dsa-governance/contracts/TokenDelegator.sol

78 lines
2.7 KiB
Solidity
Raw Normal View History

pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
import { TokenDelegatorStorage, TokenEvents } from "./TokenInterfaces.sol";
contract TokenDelegator is TokenDelegatorStorage, TokenEvents {
constructor(
address account,
address implementation_,
2021-03-27 18:13:20 +00:00
uint initialSupply_,
uint mintingAllowedAfter_,
2021-03-25 06:57:04 +00:00
uint changeImplementationAfter_,
bool transferPaused_
) {
delegateTo(
implementation_,
abi.encodeWithSignature(
2021-03-27 18:13:20 +00:00
"initialize(address,uint256,uint256,bool)",
account,
2021-03-27 18:13:20 +00:00
initialSupply_,
2021-03-25 06:57:04 +00:00
mintingAllowedAfter_,
transferPaused_
)
);
changeImplementationAfter = changeImplementationAfter_;
_setImplementation(implementation_);
}
/**
* @notice Called by the admin to update the implementation of the delegator
* @param implementation_ The address of the new implementation for delegation
*/
2021-03-26 20:48:05 +00:00
function _setImplementation(address implementation_) public isMaster {
require(implementation_ != address(0), "TokenDelegator::_setImplementation: invalid implementation address");
require(changeImplementationAfter >= block.timestamp, "TokenDelegator::_setImplementation: can change implementation changeImplementationAfter time only");
address oldImplementation = implementation;
implementation = implementation_;
emit NewImplementation(oldImplementation, implementation);
}
/**
* @notice Internal method to delegate execution to another contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
* @param callee The contract to delegatecall
* @param data The raw data to delegatecall
*/
function delegateTo(address callee, bytes memory data) internal {
(bool success, bytes memory returnData) = callee.delegatecall(data);
assembly {
if eq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
}
/**
* @dev Delegates execution to an implementation contract.
* It returns to the external caller whatever the implementation returns
* or forwards reverts.
*/
fallback () external payable {
// delegate all other functions to current implementation
(bool success, ) = implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr := mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize())
switch success
case 0 { revert(free_mem_ptr, returndatasize()) }
default { return(free_mem_ptr, returndatasize()) }
}
}
}