Privacy
1. 题目要求
1.1 这个合约的制作者非常小心的保护了敏感区域的 storage.解开这个合约来完成这一关.这些可能有帮助:
- 理解 storage 的原理
- 理解 parameter parsing 的原理
- 理解 casting 的原理
1.2 题目代码:
1 | // SPDX-License-Identifier: MIT |
2. 分析
2.1 目标:将locked修改为false
bool public locked
初始化为 true 并保存必须设置为 false 才能赢得挑战的值bytes32[3] private data
是存储我们的密钥的变量。我们需要找出data[2]
解决挑战的价值
2.2 我们可以将所有其他变量仅视为“存储填充”,以达到我们想要读取的内容 (
data[2]
) 以解决挑战。constructor(bytes32[3] memory _data)
初始化data
变量的值- 然后我们只需检查我们传递的输入
unlock(bytes16 _key)
是否与值匹配。如果比较返回 true,我们就解锁了合约,通过了挑战。byte16 _key``data[2]``true
2.3
data
首先,必须检索变量中的数据。这可以通过从区块链上的合约存储中提取数据来完成。在 brownie 中,这可以使用 来完成web3.eth.getStorageAt()
,第一个参数是合约的地址,以及要查看的合约存储槽的方向。每个槽的容量为 32 字节(256 位),这意味着实际填满 32 字节槽的数据类型将占用整个槽,因此后续数据类型将滚动到下一个槽。如果数据类型声明为uint256
或bytes32
,它将始终占用一个完整的存储槽,因为这些类型的大小已经是 32 字节。在隐私合约的情况下,我们知道相关数据是数组的最后一个元素
data
。因此,要提取这个,我们必须确定这条数据在哪里,在什么存储槽中。2.4 参考博客
2.5 在浏览器控制台依次执行 web3.eth.getStorageAt() ** ,data.slice(0,34)** 命令
3 .解题
3.1 获取关卡实例地址:0xb6b2910033C8934D4eBf2FBb72EF87cbC09BE4d0
3.2 依次执行如下代码得到 data[2]
addr = "0xb6b2910033C8934D4eBf2FBb72EF87cbC09BE4d0" '0xb6b2910033C8934D4eBf2FBb72EF87cbC09BE4d0' await web3.eth.getStorageAt(addr, 5) '0xa9cbb829703de0df913fc95cc78d10df15dc54270f501657492c89ceec732fb2' data = "0xa9cbb829703de0df913fc95cc78d10df15dc54270f501657492c89ceec732fb2" '0xa9cbb829703de0df913fc95cc78d10df15dc54270f501657492c89ceec732fb2' data.slice(0,34) '0xa9cbb829703de0df913fc95cc78d10df'
3.3 调用实例部署的合约,并查看locked 的值为true
3.4 将执行data.slice(0,34) 得到的值传入unlock的形参中,并调用unlock() 函数
3.5 查看locked的值,值由true 变成 false
3.6 提交实例
3.7 成功!!!!