Proxy.sol
1 pragma solidity ^0.6.0; 2 pragma experimental ABIEncoderV2; 3 4 // *** IMPORTANT *** 5 // "onwer" storage variable must be set to a GnosisSafe multisig wallet address: 6 // - https://github.com/gnosis/safe-contracts/blob/main/contracts/GnosisSafe.sol 7 8 contract Proxy { 9 10 // ATTENTION: storage variable alignment 11 address private owner; 12 address private pendingOwner; 13 address private implementation; 14 uint private locked; // 1 = Initialized; 2 = Non upgradable 15 // -------------------------------------------------------- 16 17 event OwnershipTransferRequested(address indexed from, address indexed to); 18 19 event OwnershipTransferred(address indexed from, address indexed to); 20 21 event SetNonUpgradable(); 22 23 event ImplementationUpdated(address indexed from, address indexed to); 24 25 constructor(address _owner, address _implementation) public { 26 27 owner = _owner; 28 implementation = _implementation; 29 } 30 31 fallback () payable external { 32 33 _fallback(); 34 } 35 36 receive () payable external { 37 38 _fallback(); 39 } 40 41 function transferOwnership(address _to) external { 42 43 require(msg.sender == owner); 44 pendingOwner = _to; 45 emit OwnershipTransferRequested(owner, _to); 46 } 47 48 function acceptOwnership() external { 49 50 require(msg.sender == pendingOwner); 51 address oldOwner = owner; 52 owner = msg.sender; 53 pendingOwner = address(0); 54 emit OwnershipTransferred(oldOwner, msg.sender); 55 } 56 57 function setNonUpgradable() public { 58 59 require(msg.sender == owner && locked == 1); 60 locked = 2; 61 emit SetNonUpgradable(); 62 } 63 64 function setImplementation(address _implementation) public { 65 66 require(msg.sender == owner && locked != 2); 67 address oldImplementation = implementation; 68 implementation = _implementation; 69 emit ImplementationUpdated(oldImplementation, _implementation); 70 } 71 72 function delegate(address _implementation) internal { 73 assembly { 74 75 calldatacopy(0, 0, calldatasize()) 76 77 let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0) 78 79 returndatacopy(0, 0, returndatasize()) 80 81 switch result 82 83 case 0 { revert(0, returndatasize()) } 84 default { return(0, returndatasize()) } 85 } 86 } 87 88 function _fallback() internal { 89 willFallback(); 90 delegate(implementation); 91 } 92 93 function willFallback() internal virtual { 94 95 } 96 }