2021-03-22 21:47:01 +00:00
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_ ,
2021-03-22 21:47:01 +00:00
uint mintingAllowedAfter_ ,
2021-03-25 06:57:04 +00:00
uint changeImplementationAfter_ ,
bool transferPaused_
2021-03-22 21:47:01 +00:00
) {
delegateTo (
implementation_ ,
abi . encodeWithSignature (
2021-03-27 18:13:20 +00:00
" initialize(address,uint256,uint256,bool) " ,
2021-03-22 21:47:01 +00:00
account ,
2021-03-27 18:13:20 +00:00
initialSupply_ ,
2021-03-25 06:57:04 +00:00
mintingAllowedAfter_ ,
transferPaused_
2021-03-22 21:47:01 +00:00
)
) ;
2021-03-27 18:28:21 +00:00
implementation = implementation_ ;
2021-03-22 21:47:01 +00:00
changeImplementationAfter = changeImplementationAfter_ ;
2021-03-27 18:28:21 +00:00
emit NewImplementation ( address ( 0 ) , implementation ) ;
2021-03-22 21:47:01 +00:00
}
/**
* @ notice Called by the admin to update the implementation of the delegator
* @ param implementation_ The address of the new implementation for delegation
* /
2021-03-27 18:28:21 +00:00
function _setImplementation ( address implementation_ ) external isMaster {
2021-03-22 21:47:01 +00:00
require ( implementation_ != address ( 0 ) , " TokenDelegator::_setImplementation: invalid implementation address " ) ;
2021-03-27 18:28:21 +00:00
require ( block . timestamp >= changeImplementationAfter , " TokenDelegator::_setImplementation: can change implementation changeImplementationAfter time only " ) ;
2021-03-22 21:47:01 +00:00
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 ( ) ) }
}
}
}