Level 12 - Privacy ⏺⏺⏺
Level Setup
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.
Level Contract
Exploit
The data is a private
state variable, which means it's not accessible to other contracts, but can be read externally by a script.
Storage slots explained:
bool public locked
: This occupies slot 0. Each state variable takes up a single slot unless it is part of a struct or an array.bool
takes 1 byte, but an entire 32-byte slot is allocated for it.uint256 public ID
: This occupies slot 1.uint256
requires 32 bytes (1 full slot).uint8 private flattening
: This will start in slot 2.uint8
only takes 1 byte.uint8 private denomination
: Sinceuint8
also takes only 1 byte, it is packed into slot 2 along withflattening
.uint16 private awkwardness
:uint16
takes 2 bytes. Solidity packs this into slot 2 along with the otheruint8
values because they collectively fit within 32 bytes.Slot 2 looks like this (in bytes):
flattening (1) + denomination (1) + awkwardness (2) + 28 bytes padding = 32 bytes
bytes32[3] private data
: Arrays and structs are always stored in separate slots. The arraydata
has 3 elements of typebytes32
, and eachbytes32
takes 32 bytes (1 full slot).data[0]
is stored in slot 3.data[1]
is stored in slot 4.data[2]
is stored in slot 5.
Therefore, data[2]
is in slot 5 because it is the third element of the bytes32[3]
array, and each element of this array occupies its own 32-byte storage slot. The preceding variables occupy slots 0 through 2, with the array data
starting at slot 3 and extending to slots 4 and 5 for its elements.
Once found, cast it as bytes16
to truncate the packed zeros.
Submit instance... 🥳
Completion Message
Nothing in the Ethereum blockchain is private. The keyword private is merely an artificial construct of the Solidity language. Tools such as Foundry or Ethers 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
Notes
Last updated