Contract Source Code:
File 1 of 1 : DUSDProxy
pragma solidity 0.5.8;
/**
* @title Proxy
* @dev This is the proxy contract for the DUSDToken Registry
*/
contract Proxy {
/**
* @dev Tell the address of the implementation where every call will be delegated.
* @return address of the implementation to which it will be delegated
*/
function implementation() public view returns (address);
/**
* @dev Fallback function allowing to perform a delegatecall to the given implementation.
* This function will return whatever the implementation call returns.
*/
function() external payable {
address _impl = implementation();
require(_impl != address(0), "Proxy: implementation contract not set");
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize)
let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
let size := returndatasize
returndatacopy(ptr, 0, size)
switch result
case 0 { revert(ptr, size) }
default { return(ptr, size) }
}
}
}
/**
* @title UpgradeabilityProxy
* @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded.
*/
contract UpgradeabilityProxy is Proxy {
// Event, it will be emitted every time the implementation gets upgraded.
event Upgraded(address indexed currentImplementation, address indexed newImplementation);
// Storage position of the address of the current implementation
bytes32 private constant implementationPosition = keccak256("DUSD.proxy.implementation");
/**
* @dev Return to the current implementation.
*/
function implementation() public view returns (address impl) {
bytes32 position = implementationPosition;
assembly {
impl := sload(position)
}
}
/**
* @dev Set the address of the current implementation.
* @param newImplementation address representing the new implementation to be set.
*/
function _setImplementation(address newImplementation) internal {
bytes32 position = implementationPosition;
assembly {
sstore(position, newImplementation)
}
}
/**
* @dev Upgrade 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, "UpgradeabilityProxy: newImplementation is the same as currentImplementation");
emit Upgraded(currentImplementation, newImplementation);
_setImplementation(newImplementation);
}
}
/**
* @title DUSDProxy
* @dev This contract combines an upgradeability proxy with basic authorization control functionalities
*/
contract DUSDProxy is UpgradeabilityProxy {
// Event to show ownership has been transferred.
event ProxyOwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// Event to show ownership transfer is pending.
event NewPendingOwner(address currentOwner, address pendingOwner);
// Storage position of the owner and pendingOwner of the contract.
bytes32 private constant proxyOwnerPosition = keccak256("DUSD.proxy.owner");
bytes32 private constant pendingProxyOwnerPosition = keccak256("DUSD.pending.proxy.owner");
/**
* @dev The constructor sets the original owner of the contract to the sender account.
*/
constructor() public {
_setUpgradeabilityOwner(0xfe30e619cc2915C905Ca45C1BA8311109A3cBdB1);
}
/**
* @dev Throw if called by any account other than the proxy owner.
*/
modifier onlyProxyOwner() {
require(msg.sender == proxyOwner(), "DUSDProxy: the caller must be the proxy Owner");
_;
}
/**
* @dev Throw if called by any account other than the pending owner.
*/
modifier onlyPendingProxyOwner() {
require(msg.sender == pendingProxyOwner(), "DUSDProxy: the caller must be the pending proxy Owner");
_;
}
/**
* @dev Return the address of the proxy owner.
* @return The address of the proxy owner.
*/
function proxyOwner() public view returns (address owner) {
bytes32 position = proxyOwnerPosition;
assembly {
owner := sload(position)
}
}
/**
* @dev Return the address of the pending proxy owner.
* @return The address of the pending proxy owner.
*/
function pendingProxyOwner() public view returns (address pendingOwner) {
bytes32 position = pendingProxyOwnerPosition;
assembly {
pendingOwner := sload(position)
}
}
/**
* @dev Set the address of the proxy owner.
*/
function _setUpgradeabilityOwner(address newProxyOwner) internal {
bytes32 position = proxyOwnerPosition;
assembly {
sstore(position, newProxyOwner)
}
}
/**
* @dev Set the address of the pending proxy owner.
*/
function _setPendingUpgradeabilityOwner(address newPendingProxyOwner) internal {
bytes32 position = pendingProxyOwnerPosition;
assembly {
sstore(position, newPendingProxyOwner)
}
}
/**
* @dev Change the owner of the proxy.
* @param newOwner The address to transfer ownership to.
*/
function transferProxyOwnership(address newOwner) external onlyProxyOwner {
require(newOwner != address(0), "DUSDProxy: cannot transfer control of the proxy owner to the zero address");
_setPendingUpgradeabilityOwner(newOwner);
emit NewPendingOwner(proxyOwner(), newOwner);
}
/**
* @dev Allow the pendingOwner to claim ownership of the proxy.
*/
function claimProxyOwnership() external onlyPendingProxyOwner {
emit ProxyOwnershipTransferred(proxyOwner(), pendingProxyOwner());
_setUpgradeabilityOwner(pendingProxyOwner());
_setPendingUpgradeabilityOwner(address(0));
}
/**
* @dev Allow the proxy owner to upgrade the current version of the proxy.
* @param implementation representing the address of the new implementation to be set.
*/
function upgradeTo(address implementation) external onlyProxyOwner {
_upgradeTo(implementation);
}
}