-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathProxy.sol
65 lines (55 loc) · 2.01 KB
/
Proxy.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
pragma solidity ^0.4.18;
import './Proxied.sol';
import './Upgradeable.sol';
/*
* @title Proxy v0.5
* @author Jack Tanner
* @notice The Proxy contract forwards all calls to a target with delegate call and thus create an upgradeable
* stateful contract
*/
contract Proxy is Proxied {
/*
* @notice Constructor sets the target and emmits an event with the first target
* @param _target - The target Upgradeable contracts address
*/
constructor(address _target) public {
upgradeTo(_target);
}
/*
* @notice Upgrades the contract to a different target that has a changed logic.
* @dev See https://github.com/jackandtheblockstalk/upgradeable-proxy for what can and cannot be done in Upgradeable
* contracts
* @param _target - The target Upgradeable contracts address
*/
function upgradeTo(address _target) public {
assert(target != _target);
address oldTarget = target;
target = _target;
emit EventUpgrade(_target, oldTarget, msg.sender);
}
/*
* @notice Performs an upgrade and then executes a transaction. Intended use to upgrade and initialize atomically
*/
function upgradeTo(address _target, bytes _data) public {
upgradeTo(_target);
assert(target.delegatecall(_data));
}
/*
* @notice Fallback function that will execute code from the target contract to process a function call.
* @dev Will use the delegatecall opcode to retain the current state of the Proxy contract and use the logic
* from the target contract to process it.
*/
function () payable public {
bytes memory data = msg.data;
address impl = target;
assembly {
let result := delegatecall(gas, impl, add(data, 0x20), mload(data), 0, 0)
let size := returndatasize
let ptr := mload(0x40)
returndatacopy(ptr, 0, size)
switch result
case 0 { revert(ptr, size) }
default { return(ptr, size) }
}
}
}