题目要求:
The creator of this contract was careful enough to protect the sensitive areas of its storage.
Unlock this contract to beat the level.
Things that might help:
Understanding how storage works
Understanding how parameter parsing works
Understanding how casting works
Tips:
Remember that metamask is just a commodity. Use another tool if it is presenting problems. Advanced gameplay could involve using remix, or your own web3 provider.
项目源码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Privacy {
bool public locked = true;
uint256 public ID = block.timestamp;
uint8 private flattening = 10;
uint8 private denomination = 255;
uint16 private awkwardness = uint16(block.timestamp);
bytes32[3] private data;
constructor(bytes32[3] memory _data) {
data = _data;
}
function unlock(bytes16 _key) public {
require(_key == bytes16(data[2]));
locked = false;
}
/*
A bunch of super advanced solidity algorithms...
,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`
.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,
*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^ ,---/V\
`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*. ~|__(o.o)
^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*'^`*.,*' UU UU
*/
}
题目解析:
跟vault一样,权限privacy但是数据并不是privacy的。
拿到data[2]就行。
引用陵野
里面提到的知识点:
1. 区块中的数据没有隐私性
2. 以太坊数据存储写入的两种方式
1. strings和bytes都是大端存储,从左边开始存储数据。
2. 其他类型数据属于小端,从右边开始存储数据。
3. 以太坊数据存储位置可计算
4. 强制类型转换
可知,此合约的数据排布是:
unused(31)+locked(1) <--slot0
ID(32)<--slot1
unused(28)+awkwardness(2)+demonination(1)+flattening(1)<--slot2
data[0]<--slot3
data[1]<--slot4
data[2]<--slot5
从这里可以知道,每个数据栏32字节,uint16两字节,uint8一字节,并且同数据栏内从右到左分布。
所以这里要拿第5组数据。
因为上面的instance address是0x5455850136aBC9F62fA14C6843b8897F1b242B05,所以下面的代码执行是:
web3.eth.getStorageAt("0x5455850136aBC9F62fA14C6843b8897F1b242B05",5)
得出答案:0xfc96579069282ff7a609042377af7c975da340de5c317cd3af4d2a08207cf54b
然后执行操作(取前32位):
'0xfc96579069282ff7a609042377af7c975da340de5c317cd3af4d2a08207cf54b'.slice(0,34)
得出答案:0xfc96579069282ff7a609042377af7c97
再操作:
await contract.unlock('0xfc96579069282ff7a609042377af7c97')
确定await contract.locked()值为false后,再submit,成功!
作者后话:
Nothing in the ethereum blockchain is private. The keyword private is merely an artificial construct of the Solidity language. Web3's `getStorageAt(...)` can be used to read anything from storage. It can be tricky to read what you want though, since several optimization rules and techniques are used to compact the storage as much as possible.
It can't get much more complicated than what was exposed in this level. For more, check out this excellent article by "Darius": [How to read Ethereum contract storage](https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925)