题目信息
- 挑战名称: Shapeshifter
- 作者: bobface
- 目标: 获得 100 ETH 或更多
- 特殊说明: 运行在 Shanghai 硬分叉(2023)
题目背景
The gas optimizooooors have launched their latest psyop in the form of a PR stunt. They deposited 100 ETH into a contract, where the first person to solve the challenge receives the full amount. Obviously, they don't want anyone to actually win this sum, so they implemented clever protections against winning the highest possible amount.
合约分析
Stunt 合约核心逻辑
contract Stunt is IStunt {
function attempt(address target) external override onlyContract(target) {
bytes32 firstResult = ITarget(target).first();
require(firstResult == hex"deadbeef", "first failed");
bytes32 secondResult = ITarget(target).second();
require(secondResult == hex"c0ffeebabe", "second failed");
bytes32 thirdResult = ITarget(target).third();
require(thirdResult == hex"1337", "third failed");
solved[target] = true;
}
function claimReward(address target) external override onlyContract(target) {
require(solved[target], "not solved");
require(!claimed[target], "already claimed");
claimed[target] = true;
uint256 size;
assembly {
size := extcodesize(target)
}
uint256 reward;
if (size <= 3) {
// Don't worry, that is impossible.
reward = 100 ether;
} else if (size <= 10) {
reward = 1e12;
} else if (size <= 100) {
reward = 1e10;
}
(bool success, ) = target.call{value: reward}("");
require(success, "transfer failed");
}
}
奖励机制
| 代码大小 | 奖励 |
|---|---|
| ≤ 3 字节 | 100 ETH |
| ≤ 10 字节 | 0.000001 ETH |
| ≤ 100 字节 | 0.00000001 ETH |
| > 100 字节 | 0 ETH |
挑战分析
要获得 100 ETH,需要满足:
attempt()验证通过:合约必须实现first()、second()、third()三个函数claimReward()时代码大小 ≤ 3 字节
看似矛盾:一个实现三个函数的合约不可能只有 3 字节!
漏洞发现
关键洞察
代码大小检查是在 claimReward() 时进行的,不是在 attempt() 时!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
















暂无评论内容