在以太坊官网发现了这个 wargame,项目已经比较老了(solidity 版本为 0.4.21)。做完之后发现题目质量是相当高的,比起 Ethernaut 更综合也更有趣~
Warmup
这个部分都是熟悉环境用的,略过
Lotteries
Guess the number
目标合约
1 | pragma solidity ^0.4.21; |
通关条件
猜中合约的 answer 的值
题目分析
答案就在代码里,42
Guess the secret number
目标合约
1 | pragma solidity ^0.4.21; |
通关条件
猜中合约的 answer 的值
题目分析
代码里只有答案的 keccak-sha3 hash 值了。但是注意到答案的数据类型是 uint8,范围非常小,所以遍历一下就出来了,170
Guess the random number
目标合约
1 | pragma solidity ^0.4.21; |
通关条件
猜中合约的 answer 的值
题目分析
回顾一下 Ethernaut 第八题的题解,从 Storage 的存储布局可知答案在 Storage 的第一个 slot 中, web3.eth.getStorageAt('contractAddr', 0)
即可获得答案
Guess the new number
目标合约
1 | pragma solidity ^0.4.21; |
通关条件
猜中合约的 answer 的值
题目分析
答案是在 guess 的时候使用 block.blockhash(block.number - 1)
和 now
这些公开的区块信息生成,所以部署一个攻击合约去 guess 就好。合约如下:
1 | contract GuessTheNewNumberChallengeHack { |
Predict the future
目标合约
1 | pragma solidity ^0.4.21; |
通关说明
此题使用了一种延迟开奖的机制。在 guess 之后,需要再过至少两个块才能开奖(settle()),开奖之后 guesser 会被重置,所以每次 guess 只能开奖一次。
题目分析
由于这题的答案也是由区块信息生成的,所以我们可以知道每个块会公布的答案是什么,这也就意味着我们可以在答案和我们 guess 的值相同的时候再去开奖。合约如下:
1 | contract PredictTheFutureChallengeHack { |
尽管如此,每次操作成功猜中的概率也只有 1 / 10,还是写个脚本处理方便(事实上,我猜了三十几次才猜中 T^T)。
Predict the block hash
目标合约
1 | pragma solidity ^0.4.21; |
通关条件
猜中未来的 block.blockhash
题目分析
没做出来,看了这篇题解,确实是没想到这个思路(其实还是对文档不熟悉)。核心在于 block.blockhash 只对最近的 256 个区块有效,超出 256 个区块则一律返回 0x0000000000000000000000000000000000000000000000000000000000000000
。我们可以将这个值作为答案,然后等过了 256 个区块再 settle() 即可。