u
u
upgradable
Search…
Break versioning with registry
You have learned the registry pattern and if you look at it closely, it has a flaw when the company is malicious, use the exploit to steal users funds or just censor a user. Here is an example implementation of the registry pattern.
1
contract Registry is Ownable {
2
3
event RegistryCreated(address addressOfRegistryContract,address from );
4
5
mapping (address => address) public addresses;
6
mapping (address => bool) public userPreferences;
7
address[] public validImplementations;
8
9
10
constructor() public {
11
emit RegistryCreated(address(this),msg.sender);
12
}
13
function setImplementationAddress(address newAddress) public {
14
require(newAddress != 0, "cant set value to 0");
15
require(checkValidImplementationAddress(newAddress), "not a valid implementation address");
16
addresses[msg.sender] = newAddress;
17
}
18
19
function checkValidImplementationAddress(address addr) internal view returns (bool) {
20
for(uint i = 0; i < validImplementations.length; ++i) {
21
if (addr == validImplementations[i]) return true;
22
}
23
return false;
24
}
25
26
function addImplementation(address toAdd) external onlyOwner {
27
require(toAdd != 0);
28
validImplementations.push(toAdd);
29
}
30
31
function updatePreference(bool newPref) public {
32
userPreferences[msg.sender] = newPref;
33
}
34
}
35
36
contract Hello {
37
address public me = 0;
38
function sayHello() public pure returns(string) {
39
return "Hello";
40
}
41
}
42
43
44
contract HelloV2 is Hello {
45
uint public abc = 1234;
46
function sayHello() public pure returns (string) {
47
return "hello v2";
48
}
49
}
50
51
contract Proxy {
52
53
bytes32 private constant REGISTRY_IMPLEMENTATION_ADDRESS_KEY = keccak256("Registry address key");
54
bytes32 private constant DEFAULT_IMPLEMENTATION_ADDRESS_KEY = keccak256("default implementation address key");
55
56
function initialize(address _defLogicContract) internal {
57
require(_defLogicContract != 0);
58
require(Address.isContract(_defLogicContract));
59
60
Registry registry = new Registry();
61
address regAddress = address(registry);
62
63
bytes32 reg = REGISTRY_IMPLEMENTATION_ADDRESS_KEY;
64
bytes32 impl = DEFAULT_IMPLEMENTATION_ADDRESS_KEY;
65
//solium-disable-next-line security/no-inline-assembly
66
assembly {
67
sstore(reg, regAddress)
68
sstore(impl, _defLogicContract)
69
}
70
71
registry.addImplementation(_defLogicContract);
72
73
}
74
75
constructor(address _log) public {
76
initialize( _log);
77
}
78
79
function upgradeDefaultImplementation(address _i) public {
80
require(_i != 0);
81
require(Address.isContract(_i));
82
bytes32 impl = DEFAULT_IMPLEMENTATION_ADDRESS_KEY;
83
bytes32 regKey = REGISTRY_IMPLEMENTATION_ADDRESS_KEY;
84
address registryImpl = 0;
85
86
//solium-disable-next-line security/no-inline-assembly
87
assembly {
88
sstore(impl, _i)
89
registryImpl := sload(regKey)
90
}
91
assert(registryImpl != 0);
92
Registry reg = Registry(registryImpl);
93
reg.addImplementation(_i);
94
}
95
96
function() public {
97
98
bytes32 regImplKey = REGISTRY_IMPLEMENTATION_ADDRESS_KEY;
99
bytes32 defImplKey = DEFAULT_IMPLEMENTATION_ADDRESS_KEY;
100
address regImplAddress = 0;
101
address defImplAddress = 0;
102
//solium-disable-next-line security/no-inline-assembly
103
assembly {
104
regImplAddress := sload(regImplKey)
105
defImplAddress := sload(defImplKey)
106
}
107
108
require(regImplAddress != 0 && defImplAddress != 0);
109
110
Registry r = Registry(regImplAddress);
111
112
if(r.userPreferences(msg.sender) == true) {
113
// means that user may have a different address for implementation
114
115
if ( r.addresses(msg.sender) != 0) {
116
// they dont have it set, lets use default one
117
defImplAddress = r.addresses(msg.sender);
118
}
119
}
120
121
// at this point defImplAddress should not be 0
122
123
assert(defImplAddress != 0);
124
125
//solium-disable-next-line security/no-inline-assembly
126
assembly {
127
let ptr := mload(0x40)
128
calldatacopy(ptr, 0, calldatasize)
129
let result := delegatecall(gas, defImplAddress, ptr, calldatasize, 0, 0)
130
let size := returndatasize
131
returndatacopy(ptr, 0, size)
132
133
switch result
134
case 0 { revert(ptr, size) }
135
default { return(ptr, size) }
136
}
137
}
138
139
}
140
141
*https://github.com/ali2251/Upgradable-contracts/blob/master/contracts/Proxy.sol
Copied!
Last modified 2yr ago
Copy link