/ contracts / deployment / Deployer.sol
Deployer.sol
  1  pragma solidity >=0.6.0;
  2  pragma experimental ABIEncoderV2;
  3  
  4  import "./ManagedContract.sol";
  5  import "./Proxy.sol";
  6  
  7  contract Deployer {
  8  
  9      struct ContractData {
 10          string key;
 11          address origAddr;
 12          bool upgradeable;
 13      }
 14  
 15      mapping(string => address) private contractMap;
 16      mapping(string => string) private aliases;
 17  
 18      address private owner;
 19      ContractData[] private contracts;
 20      bool private deployed;
 21  
 22      constructor(address _owner) public {
 23  
 24          owner = _owner;
 25      }
 26  
 27      function hasKey(string memory key) public view returns (bool) {
 28          
 29          return contractMap[key] != address(0) || contractMap[aliases[key]] != address(0);
 30      }
 31  
 32      function setContractAddress(string memory key, address addr) public {
 33  
 34          setContractAddress(key, addr, true);
 35      }
 36  
 37      function setContractAddress(string memory key, address addr, bool upgradeable) public {
 38          
 39          require(!hasKey(key), buildKeyAlreadySetMessage(key));
 40  
 41          ensureNotDeployed();
 42          ensureCaller();
 43          
 44          contracts.push(ContractData(key, addr, upgradeable));
 45          contractMap[key] = address(1);
 46      }
 47  
 48      function addAlias(string memory fromKey, string memory toKey) public {
 49          
 50          ensureNotDeployed();
 51          ensureCaller();
 52          require(contractMap[toKey] != address(0), buildAddressNotSetMessage(toKey));
 53          aliases[fromKey] = toKey;
 54      }
 55  
 56      function getContractAddress(string memory key) public view returns (address) {
 57          
 58          require(hasKey(key), buildAddressNotSetMessage(key));
 59          address addr = contractMap[key];
 60          if (addr == address(0)) {
 61              addr = contractMap[aliases[key]];
 62          }
 63          require(addr != address(1), buildProxyNotDeployedMessage(key));
 64          return addr;
 65      }
 66  
 67      function getPayableContractAddress(string memory key) public view returns (address payable) {
 68  
 69          return address(uint160(address(getContractAddress(key))));
 70      }
 71  
 72      function isDeployed() public view returns(bool) {
 73          
 74          return deployed;
 75      }
 76  
 77      function deploy() public {
 78  
 79          deploy(owner);
 80      }
 81  
 82      function deploy(address _owner) public {
 83  
 84          ensureNotDeployed();
 85          ensureCaller();
 86          deployed = true;
 87  
 88          for (uint i = contracts.length - 1; i != uint(-1); i--) {
 89              if (contractMap[contracts[i].key] == address(1)) {
 90                  if (contracts[i].upgradeable) {
 91                      Proxy p = new Proxy(_owner, contracts[i].origAddr);
 92                      contractMap[contracts[i].key] = address(p);
 93                  } else {
 94                      contractMap[contracts[i].key] = contracts[i].origAddr;
 95                  }
 96              } else {
 97                  contracts[i] = contracts[contracts.length - 1];
 98                  contracts.pop();
 99              }
100          }
101  
102          for (uint i = 0; i < contracts.length; i++) {
103              if (contracts[i].upgradeable) {
104                  address p = contractMap[contracts[i].key];
105                  ManagedContract(p).initializeAndLock(this);
106              }
107          }
108      }
109  
110      function reset() public {
111  
112          ensureCaller();
113          deployed = false;
114  
115          for (uint i = 0; i < contracts.length; i++) {
116              contractMap[contracts[i].key] = address(1);
117          }
118      }
119  
120      function ensureNotDeployed() private view {
121  
122          require(!deployed, "already deployed");
123      }
124  
125      function ensureCaller() private view {
126  
127          require(owner == address(0) || msg.sender == owner, "unallowed caller");
128      }
129  
130      function buildKeyAlreadySetMessage(string memory key) private pure returns(string memory) {
131  
132          return string(abi.encodePacked("key already set: ", key));
133      }
134  
135      function buildAddressNotSetMessage(string memory key) private pure returns(string memory) {
136  
137          return string(abi.encodePacked("contract address not set: ", key));
138      }
139  
140      function buildProxyNotDeployedMessage(string memory key) private pure returns(string memory) {
141  
142          return string(abi.encodePacked("proxy not deployed: ", key));
143      }
144  }