pragmasolidity 0.5.7;import"./UpgradeabilityProxy.sol";
/**
* @title OwnedUpgradeabilityProxy
* @dev This contract combines an upgradeability proxy with basic authorization control functionalities
*/contractOwnedUpgradeabilityProxyisUpgradeabilityProxy{
/**
* @dev Event to show ownership has been transferred
* @param previousOwner representing the address of the previous owner
* @param newOwner representing the address of the new owner
*/eventProxyOwnershipTransferred(address previousOwner, address newOwner);
// Storage position of the owner of the contractbytes32privateconstant PROXY_OWNER_POSITION =keccak256("org.govblocks.proxy.owner");
/**
* @dev the constructor sets the original owner of the contract to the sender account.
*/constructor(address _implementation) public{
_setUpgradeabilityOwner(msg.sender);
_upgradeTo(_implementation);
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyProxyOwner() {
require(msg.sender== proxyOwner());
_;
}
/**
* @dev Tells the address of the owner
* @return the address of the owner
*/functionproxyOwner() publicviewreturns (address owner) {
bytes32 position = PROXY_OWNER_POSITION;
assembly {
owner :=sload(position)
}
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/functiontransferProxyOwnership(address _newOwner) publiconlyProxyOwner{
require(_newOwner !=address(0));
_setUpgradeabilityOwner(_newOwner);
emit ProxyOwnershipTransferred(proxyOwner(), _newOwner);
}
/**
* @dev Allows the proxy owner to upgrade the current version of the proxy.
* @param _implementation representing the address of the new implementation to be set.
*/functionupgradeTo(address _implementation) publiconlyProxyOwner{
_upgradeTo(_implementation);
}
/**
* @dev Sets the address of the owner
*/function_setUpgradeabilityOwner(address _newProxyOwner) internal{
bytes32 position = PROXY_OWNER_POSITION;
assembly {
sstore(position, _newProxyOwner)
}
}
}
Contract Source Code
File 2 of 3: Proxy.sol
pragmasolidity 0.5.7;/**
* @title Proxy
* @dev Gives the possibility to delegate any call to a foreign implementation.
*/contractProxy{
/**
* @dev Fallback function allowing to perform a delegatecall to the given implementation.
* This function will return whatever the implementation call returns
*/function () externalpayable{
address _impl = implementation();
require(_impl !=address(0));
assembly {
let ptr :=mload(0x40)
calldatacopy(ptr, 0, calldatasize)
let result :=delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
let size :=returndatasizereturndatacopy(ptr, 0, size)
switch result
case0 { revert(ptr, size) }
default { return(ptr, size) }
}
}
/**
* @dev Tells the address of the implementation where every call will be delegated.
* @return address of the implementation to which it will be delegated
*/functionimplementation() publicviewreturns (address);
}
Contract Source Code
File 3 of 3: UpgradeabilityProxy.sol
pragmasolidity 0.5.7;import"./Proxy.sol";
/**
* @title UpgradeabilityProxy
* @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded
*/contractUpgradeabilityProxyisProxy{
/**
* @dev This event will be emitted every time the implementation gets upgraded
* @param implementation representing the address of the upgraded implementation
*/eventUpgraded(addressindexed implementation);
// Storage position of the address of the current implementationbytes32privateconstant IMPLEMENTATION_POSITION =keccak256("org.govblocks.proxy.implementation");
/**
* @dev Constructor function
*/constructor() public{}
/**
* @dev Tells the address of the current implementation
* @return address of the current implementation
*/functionimplementation() publicviewreturns (address impl) {
bytes32 position = IMPLEMENTATION_POSITION;
assembly {
impl :=sload(position)
}
}
/**
* @dev Sets the address of the current implementation
* @param _newImplementation address representing the new implementation to be set
*/function_setImplementation(address _newImplementation) internal{
bytes32 position = IMPLEMENTATION_POSITION;
assembly {
sstore(position, _newImplementation)
}
}
/**
* @dev Upgrades the implementation address
* @param _newImplementation representing the address of the new implementation to be set
*/function_upgradeTo(address _newImplementation) internal{
address currentImplementation = implementation();
require(currentImplementation != _newImplementation);
_setImplementation(_newImplementation);
emit Upgraded(_newImplementation);
}
}