Created
March 11, 2018 08:34
-
-
Save Perseverance/2100df9b1b3c2315a7500898e62cb036 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity 0.4.15; | |
contract SharedStorage { | |
address public contractImplementation; | |
} | |
contract Forwardable { | |
/** | |
* @dev Performs a delegatecall and returns whatever the delegatecall returned (entire context execution will return!) | |
* @param _dst Destination address to perform the delegatecall | |
* @param _calldata Calldata for the delegatecall | |
*/ | |
function delegatedFwd(address _dst, bytes _calldata) internal { | |
assembly { | |
switch extcodesize(_dst) case 0 { revert(0, 0) } | |
let result := delegatecall(sub(gas, 10000), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0) | |
let size := returndatasize | |
let ptr := mload(0x40) | |
returndatacopy(ptr, 0, size) | |
// revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas. | |
// if the call returned error data, forward it | |
switch result case 0 { revert(ptr, size) } | |
default { return(ptr, size) } | |
} | |
} | |
} | |
contract UpgradeableProxy is SharedStorage, Forwardable { | |
/** | |
* @dev UpgradeableProxy is a proxy contract to a contract implementation. The implementation | |
* can update the reference, which effectively upgrades the contract | |
* @param _contractImpl Address of the contract used as implementation | |
*/ | |
function UpgradeableProxy(address _contractImpl) public { | |
contractImplementation = _contractImpl; | |
} | |
/** | |
* @dev All calls made to the proxy are forwarded to the contract implementation via a delegatecall | |
* @return Any bytes32 value the implementation returns | |
*/ | |
function () payable public { | |
delegatedFwd(contractImplementation, msg.data); | |
} | |
} | |
contract UpgradeableImplementation is SharedStorage { | |
event UpgradedContract(address indexed _newImpl); | |
function upgradeImplementation(address _newImpl) public { | |
contractImplementation = _newImpl; | |
UpgradedContract(_newImpl); | |
} | |
} | |
contract TestProxy is UpgradeableProxy { | |
function TestProxy(address initialImplementation) UpgradeableProxy(initialImplementation) {} | |
} | |
contract ITestImpl { | |
function rate() public constant returns(uint); | |
function setRate(uint r) public; | |
function getRate() public constant returns(uint); | |
} | |
contract TestImpl is ITestImpl, UpgradeableImplementation { | |
uint public rate; | |
function rate() public constant returns(uint) { | |
return rate; | |
} | |
function setRate(uint r) public { | |
rate = r; | |
} | |
function getRate() public constant returns(uint) { | |
return 1000; | |
} | |
} | |
let impl = await TestImpl1.new(); | |
let proxy = await TestProxy.new(impl.address); | |
let implementedContract = await ITestImpl.at(proxy.address); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment