/ contracts / deployment / Proxy.sol
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  }