pragma solidity ^0.5.16; interface IAddressResolver { function getAddress(bytes32 name) external view returns (address); } interface ISystemStatus { function setUpgrading(bool status) external; } interface IProxy { function setTarget(address target) external; } interface ISynthetix {} interface IMigration { // pass the index to handle situations where the migration takes a few transactions to process function migrate(uint256 index) external; function numOfScripts() external view returns (uint); } contract Owned { constructor(address owner) {} modifier onlyOwner { _; } } contract DelegatedMigrator is Owned { uint waitingPeriod; struct Migration { bytes32 name; IMigration target; uint acceptedTimestamp; } IAddressResolver resolver = IAddressResolver(0x00000000000000000000000000000000000000000); mapping(bytes32 => Migration) proposals; constructor(address _owner) public Owned(_owner) { waitingPeriod = 3 hours; } function setWaitingPeriod(uint _waitingPeriod) external onlyOwner { waitingPeriod = _waitingPeriod; } function propose(bytes32 version, address target) external { // Anyone can call require(proposals[version].name == bytes32(0), "Cannot modify existing proposal"); // each contract needs to confirm to IMigration // ... } function accept(bytes32 version) onlyOwner { // .. } function reject(bytes32 version) onlyOwner { // .. } function execute(bytes32 version, uint index) onlyOwner { Migration storage migration = proposals[version]; require(migration.acceptedTimestamp > 0, "Must be accepted to execute"); require(now > migration.acceptedTimestamp + waitingPeriod, "Waiting period not yet expired"); // require(index not used) // mark index as used ISystemStatus status = ISystemStatus(resolver.getAddress("SystemStatus")); if (index == 0) { // deactivate system status.setUpgrading(true); } address(migration.target).delegatecall(bytes4(keccak256("migrate(address,uint256)")), resolver, index); if (index + 1 == migration.target.numOfScripts()) { // reactivate system status.setUpgrading(false); } } } // Example Migration script contract MyMigration is IMigration { function migrate(IAddressResolver resolver, uint256 index) external { if (index == 0) { migrate0(resolver); } } function migrate0(IAddressResolver resolver) internal { IProxy synthetixProxy = IProxy(resolver.getAddress("ProxySynthetix")); synthetixProxy.setTarget(0x00000000000000000000000000000000000000000); ISynthetix synthetix = ISynthetix(resolver.getAddress("Synthetix")); // etc. } function numOfScripts() external view returns (uint) { return 1; } }
0.5.16