12. Privacy

本關跟第8關Vault十分相似,都是從區塊中直接讀取資料,但需要對以太坊數據的排列更熟悉。多了解對編寫合約節省Gas 有非常大的好處,參考官方文檔

Statically-sized variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible, according to the following rules:

  • The first item in a storage slot is stored lower-order aligned.
  • Elementary types use only as many bytes as are necessary to store them.
  • If an elementary type does not fit the remaining part of a storage slot, it is moved to the next storage slot.
  • Structs and array data always start a new slot and occupy whole slots (but items inside a struct or array are packed tightly according to these rules).

以太坊在儲存時是以32 bytes為一格順序儲存的,所以定義變量的順序會影響花費Gas的多少,這是一大特色。

回到關卡合約,我們看到裏面定義了

bool public locked = true;
uint256 public ID = block.timestamp;
uint8 private flattening = 10;
uint8 private denomination = 255;
uint16 private awkwardness = uint16(now);
bytes32[3] private data;

依32 bytes 一格,會以下劃分:

Slot 0

bool public locked = true;

Slot 1

uint256 public ID = block.timestamp;

Slot 2

uint8 private flattening = 10;
uint8 private denomination = 255;
uint16 private awkwardness = uint16(now);

Slot 3-5

bytes32[3] private data;

我們的目標位於Slot 5,打開Console,輸入

> web3.eth.getStorageAt(instance, 5).then(console.log);
< 0xf8f7b3a3483669021dc62c871bd21917dd3cba5d3f2eccfe41d59b4008e623e6

然後把前16 bytes (0x後32 字元) 拿來做key呼叫unlock函數

> contract.unlock("0xf8f7b3a3483669021dc62c871bd21917")

最後按提交,本關完成。

發表留言

%d 位部落客按了讚: