damn-vulnerable-defi | Unstoppable

  • zach
  • 更新于 2023-07-02 16:26
  • 阅读 872

Challenge1-UnstoppableUnstoppable为了系统的学习solidity和foundry,我基于foundry测试框架重新编写damnvulnerable-defi的题解,欢迎交流和共建~🎉https://github.com/zach030/damnvulnerable

Challenge #1 - Unstoppable

Unstoppable

为了系统的学习solidity和foundry,我基于foundry测试框架重新编写damnvulnerable-defi的题解,欢迎交流和共建~🎉

https://github.com/zach030/damnvulnerabledefi-foundry

合约

  • ReceiverUnstoppable:继承IERC3156FlashBorrower合约,用于发起闪电贷,执行闪电贷后的回调
  • UnstoppableVault:金库合约,继承IERC3156FlashLender、ERC4626,支持闪电贷

脚本

  • 依次部署DamnValuableToken、UnstoppableVault合约
  • 存入TOKENS_IN_VAULT数量的token到金库中,转入player用户INITIAL_PLAYER_TOKEN_BALANCE数目的token
  • 部署ReceiverUnstoppable合约
  • 执行攻击脚本
  • 期望ReceiverUnstoppable执行闪电贷的交易被revert

题解

攻击目标是使得通过ReceiverUnstoppable合约发起的executeFlashLoan方法被revert,首先分析executeFlashLoan的调用流程

闪电贷的调用链路

重点在UnstoppableVault.flashLoan方法,分别会进行以下操作:

  • 计算闪电贷开始前的余额:totalAssets()
  • 计算当前的share:convertToShares(totalSupply)是否与前面计算出来的余额一致
  • 计算闪电贷手续费:flashFee
  • 转移amount个token到receiver,再调用receiver的onFlashLoan方法执行回调
  • 从receiver方转回amount+fee数目的token
  • 将fee转移给feeRecipient账户,完成本次闪电贷

若要使交易revert,关键的校验点在于使得:convertToShares(totalSupply) != totalAssets()

这两个函数都是ERC4626中的定义,关于此协议可参考下面的文章: WTF-Solidity/51_ERC4626/readme.md at main · WTFAcademy/WTF-Solidity

简单来说就是ERC20的组合:资产代币asset和份额代币share,存入资产或提取资产时都会相对应的铸造或销毁对应数目的share代币

  • totalAssets():计算的是当前金库中的资产代币数目
  • convertToShares(totalSupply):totalSupply是总的share代币数目(只有deposit或mint时才会产生),convertToShares就是计算:assets * totalSupply / totalAssets()

要想使得两者不一致,只要不通过depost或mint方法向UnstoppableVault中转入token即可,因此攻击脚本内容如下:

it('Execution', async function () {
        /** CODE YOUR SOLUTION HERE */
        const dvtForPlayer  = token.connect(player);
        await dvtForPlayer.transfer(vault.address,1);
    });
Foundry 框架合约开发测试 测试对 Foundry 开发框架的了解,主要涉及的内容有编译、测试、部署、以及如何进行代码开源验证。
开始挑战
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
zach
zach
0x4460...1dE2
江湖只有他的大名,没有他的介绍。