/*
.'''''''''''.. ..''''''''''''''''.. ..'''''''''''''''..
.;;;;;;;;;;;'. .';;;;;;;;;;;;;;;;;;,. .,;;;;;;;;;;;;;;;;;,.
.;;;;;;;;;;,. .,;;;;;;;;;;;;;;;;;;;,. .,;;;;;;;;;;;;;;;;;;,.
.;;;;;;;;;,. .,;;;;;;;;;;;;;;;;;;;;,. .;;;;;;;;;;;;;;;;;;;;,.
';;;;;;;;'. .';;;;;;;;;;;;;;;;;;;;;;,. .';;;;;;;;;;;;;;;;;;;;;,.
';;;;;,.. .';;;;;;;;;;;;;;;;;;;;;;;,..';;;;;;;;;;;;;;;;;;;;;;,.
...... .';;;;;;;;;;;;;,'''''''''''.,;;;;;;;;;;;;;,'''''''''..
.,;;;;;;;;;;;;;. .,;;;;;;;;;;;;;.
.,;;;;;;;;;;;;,. .,;;;;;;;;;;;;,.
.,;;;;;;;;;;;;,. .,;;;;;;;;;;;;,.
.,;;;;;;;;;;;;,. .;;;;;;;;;;;;;,. .....
.;;;;;;;;;;;;;'. ..';;;;;;;;;;;;;'. .',;;;;,'.
.';;;;;;;;;;;;;'. .';;;;;;;;;;;;;;'. .';;;;;;;;;;.
.';;;;;;;;;;;;;'. .';;;;;;;;;;;;;;'. .;;;;;;;;;;;,.
.,;;;;;;;;;;;;;'...........,;;;;;;;;;;;;;;. .;;;;;;;;;;;,.
.,;;;;;;;;;;;;,..,;;;;;;;;;;;;;;;;;;;;;;;,. ..;;;;;;;;;,.
.,;;;;;;;;;;;;,. .,;;;;;;;;;;;;;;;;;;;;;;,. .',;;;,,..
.,;;;;;;;;;;;;,. .,;;;;;;;;;;;;;;;;;;;;;,. ....
..',;;;;;;;;,. .,;;;;;;;;;;;;;;;;;;;;,.
..',;;;;'. .,;;;;;;;;;;;;;;;;;;;'.
...'.. .';;;;;;;;;;;;;;,,,'.
...............
*/
// https://github.com/trusttoken/smart-contracts
// Dependency file: @openzeppelin/contracts/GSN/Context.sol
// SPDX-License-Identifier: MIT
// pragma solidity ^0.6.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// Dependency file: contracts/common/Initializable.sol
// Copied from https://github.com/OpenZeppelin/openzeppelin-contracts-ethereum-package/blob/v3.0.0/contracts/Initializable.sol
// Added public isInitialized() view of private initialized bool.
// pragma solidity 0.6.10;
/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly {
cs := extcodesize(self)
}
return cs == 0;
}
/**
* @dev Return true if and only if the contract has been initialized
* @return whether the contract has been initialized
*/
function isInitialized() public view returns (bool) {
return initialized;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}
// Dependency file: contracts/common/UpgradeableClaimable.sol
// pragma solidity 0.6.10;
// import {Context} from "@openzeppelin/contracts/GSN/Context.sol";
// import {Initializable} from "contracts/common/Initializable.sol";
/**
* @title UpgradeableClaimable
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. Since
* this contract combines Claimable and UpgradableOwnable contracts, ownership
* can be later change via 2 step method {transferOwnership} and {claimOwnership}
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract UpgradeableClaimable is Initializable, Context {
address private _owner;
address private _pendingOwner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting a custom initial owner of choice.
* @param __owner Initial owner of contract to be set.
*/
function initialize(address __owner) internal initializer {
_owner = __owner;
emit OwnershipTransferred(address(0), __owner);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view returns (address) {
return _pendingOwner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Modifier throws if called by any account other than the pendingOwner.
*/
modifier onlyPendingOwner() {
require(msg.sender == _pendingOwner, "Ownable: caller is not the pending owner");
_;
}
/**
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_pendingOwner = newOwner;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() public onlyPendingOwner {
emit OwnershipTransferred(_owner, _pendingOwner);
_owner = _pendingOwner;
_pendingOwner = address(0);
}
}
// Dependency file: contracts/proxy/ImplementationReference.sol
// pragma solidity 0.6.10;
// import {UpgradeableClaimable} from "contracts/common/UpgradeableClaimable.sol";
/**
* @title ImplementationReference
* @dev This contract is made to serve a simple purpose only.
* To hold the address of the implementation contract to be used by proxy.
* The implementation address, is changeable anytime by the owner of this contract.
*/
contract ImplementationReference is UpgradeableClaimable {
address public implementation;
/**
* @dev Event to show that implementation address has been changed
* @param newImplementation New address of the implementation
*/
event ImplementationChanged(address newImplementation);
/**
* @dev Set initial ownership and implementation address
* @param _implementation Initial address of the implementation
*/
constructor(address _implementation) public {
UpgradeableClaimable.initialize(msg.sender);
implementation = _implementation;
}
/**
* @dev Function to change the implementation address, which can be called only by the owner
* @param newImplementation New address of the implementation
*/
function setImplementation(address newImplementation) external onlyOwner {
implementation = newImplementation;
emit ImplementationChanged(newImplementation);
}
}
// Root file: contracts/proxy/OwnedProxyWithReference.sol
// solhint-disable const-name-snakecase
pragma solidity 0.6.10;
// import {ImplementationReference} from "contracts/proxy/ImplementationReference.sol";
/**
* @title OwnedProxyWithReference
* @dev This contract combines an upgradeability proxy with basic authorization control functionalities
* Its structure makes it easy for a group of contracts alike, to share an implementation and to change it easily for all of them at once
*/
contract OwnedProxyWithReference {
/**
* @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
*/
event ProxyOwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Event to show ownership transfer is pending
* @param currentOwner representing the address of the current owner
* @param pendingOwner representing the address of the pending owner
*/
event NewPendingOwner(address currentOwner, address pendingOwner);
/**
* @dev Event to show implementation reference has been changed
* @param implementationReference address of the new implementation reference contract
*/
event ImplementationReferenceChanged(address implementationReference);
// Storage position of the owner and pendingOwner and implementationReference of the contract
// This is made to ensure, that memory spaces do not interfere with each other
bytes32 private constant proxyOwnerPosition = 0x6279e8199720cf3557ecd8b58d667c8edc486bd1cf3ad59ea9ebdfcae0d0dfac; //keccak256("trueUSD.proxy.owner");
bytes32 private constant pendingProxyOwnerPosition = 0x8ddbac328deee8d986ec3a7b933a196f96986cb4ee030d86cc56431c728b83f4; //keccak256("trueUSD.pending.proxy.owner");
bytes32 private constant implementationReferencePosition = keccak256("trueFiPool.implementation.reference"); //keccak256("trueFiPool.implementation.reference");
/**
* @dev the constructor sets the original owner of the contract to the sender account.
* @param _owner Initial owner of the proxy
* @param _implementationReference initial ImplementationReference address
*/
constructor(address _owner, address _implementationReference) public {
_setUpgradeabilityOwner(_owner);
_changeImplementationReference(_implementationReference);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyProxyOwner() {
require(msg.sender == proxyOwner(), "only Proxy Owner");
_;
}
/**
* @dev Throws if called by any account other than the pending owner.
*/
modifier onlyPendingProxyOwner() {
require(msg.sender == pendingProxyOwner(), "only pending Proxy Owner");
_;
}
/**
* @dev Tells the address of the owner
* @return owner the address of the owner
*/
function proxyOwner() public view returns (address owner) {
bytes32 position = proxyOwnerPosition;
assembly {
owner := sload(position)
}
}
/**
* @dev Tells the address of the owner
* @return pendingOwner the address of the pending owner
*/
function pendingProxyOwner() public view returns (address pendingOwner) {
bytes32 position = pendingProxyOwnerPosition;
assembly {
pendingOwner := sload(position)
}
}
/**
* @dev Sets the address of the owner
* @param newProxyOwner New owner to be set
*/
function _setUpgradeabilityOwner(address newProxyOwner) internal {
bytes32 position = proxyOwnerPosition;
assembly {
sstore(position, newProxyOwner)
}
}
/**
* @dev Sets the address of the owner
* @param newPendingProxyOwner New pending owner address
*/
function _setPendingUpgradeabilityOwner(address newPendingProxyOwner) internal {
bytes32 position = pendingProxyOwnerPosition;
assembly {
sstore(position, newPendingProxyOwner)
}
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* changes the pending owner to newOwner. But doesn't actually transfer
* @param newOwner The address to transfer ownership to.
*/
function transferProxyOwnership(address newOwner) external onlyProxyOwner {
require(newOwner != address(0));
_setPendingUpgradeabilityOwner(newOwner);
emit NewPendingOwner(proxyOwner(), newOwner);
}
/**
* @dev Allows the pendingOwner to claim ownership of the proxy
*/
function claimProxyOwnership() external onlyPendingProxyOwner {
emit ProxyOwnershipTransferred(proxyOwner(), pendingProxyOwner());
_setUpgradeabilityOwner(pendingProxyOwner());
_setPendingUpgradeabilityOwner(address(0));
}
/**
* @dev Allows the proxy owner to change the contract holding address of implementation.
* @param _implementationReference representing the address contract, which holds implementation.
*/
function changeImplementationReference(address _implementationReference) public virtual onlyProxyOwner {
_changeImplementationReference(_implementationReference);
}
/**
* @dev Get the address of current implementation.
* @return Returns address of implementation contract
*/
function implementation() public view returns (address) {
bytes32 position = implementationReferencePosition;
address implementationReference;
assembly {
implementationReference := sload(position)
}
return ImplementationReference(implementationReference).implementation();
}
/**
* @dev Fallback functions allowing to perform a delegatecall to the given implementation.
* This function will return whatever the implementation call returns
*/
fallback() external payable {
proxyCall();
}
/**
* @dev This fallback function gets called only when this contract is called without any calldata e.g. send(), transfer()
* This would also trigger receive() function on called implementation
*/
receive() external payable {
proxyCall();
}
/**
* @dev Performs a low level call, to the contract holding all the logic, changing state on this contract at the same time
*/
function proxyCall() internal {
address impl = implementation();
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize())
let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0)
returndatacopy(ptr, 0, returndatasize())
switch result
case 0 {
revert(ptr, returndatasize())
}
default {
return(ptr, returndatasize())
}
}
}
/**
* @dev Function to internally change the contract holding address of implementation.
* @param _implementationReference representing the address contract, which holds implementation.
*/
function _changeImplementationReference(address _implementationReference) internal virtual {
bytes32 position = implementationReferencePosition;
assembly {
sstore(position, _implementationReference)
}
emit ImplementationReferenceChanged(address(_implementationReference));
}
}
{
"compilationTarget": {
"OwnedProxyWithReference.sol": "OwnedProxyWithReference"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 20000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_implementationReference","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"implementationReference","type":"address"}],"name":"ImplementationReferenceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"currentOwner","type":"address"},{"indexed":false,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"ProxyOwnershipTransferred","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"_implementationReference","type":"address"}],"name":"changeImplementationReference","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimProxyOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingProxyOwner","outputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxyOwner","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferProxyOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]