Ethernaut 题库闯关追更, 挑战 AlienCodex 合约, 通过本挑战,我们将更深刻的理解 Solidity 的数据存储,以及如何通过写数组达到写插槽的效果。
Ethernaut 题库闯关 追更啦, 欢迎订阅专栏,本题是一个名为 AlienCodex
的合约,获取到 Ownable
权限即可通关。 难度等级:难。
本篇应该是 Ethernaut 系列最难的挑战,完成后非常有收获。
以下是合约源码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.0;
import '../helpers/Ownable-05.sol';
contract AlienCodex is Ownable {
bool public contact;
bytes32[] public codex;
modifier contacted() {
assert(contact);
_;
}
function makeContact() public {
contact = true;
}
function record(bytes32 _content) contacted public {
codex.push(_content);
}
function retract() contacted public {
codex.length--;
}
function revise(uint i, bytes32 _content) contacted public {
codex[i] = _content;
}
}
本关闯关涉及到 3 个知识点:
如果你要挑战一下,就不要往下看了....
首先我们要知道,所有 Solidity 状态变量都按顺序保存(动态数组和映射除外)。
AlienCodex
合约里有 3 个字段:
ownable
: 继承自Ownable合约(Ownable-05.sol 文件中没有其他任何内容), 占用 20 字节contact
: bool 值, 占用 8 字节codex
: bytes32 数组前 2 个字段(ownable
和 contact
)将共享第一个槽,即 0 号插槽。
关于 slot 插槽布局, 前面 Vault 闯关 和 Privacy 闯关 亦有介绍,可前往重温。
第三个属性(codex
)位于第二个槽中:1。但它是一个动态数组,因此在第二个槽中的值只是数组的长度。要注意的是,数组长度始终为 uint256,因此它始终占用一个完整的槽。
对槽的读取和写入和对变量的操作是一样的。
读取某个槽的值,可以使用RPC eth_getStorageAt
, 如:
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x2ACDe8bc8567D49CF2Fe54999d4d4A1cd1a9fFEA", "0x0", "latest"], "id": 1}' http://localhost:8547
0x0 是要读取的插槽号。
还可以使用 [cast storage](https://learnblockchain.cn/docs/foundry/i18n/zh/referenc...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!