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 }