ETH Price: $1,872.29 (+0.32%)
Gas: 0.54 Gwei

Transaction Decoder

Block:
20353390 at Jul-21-2024 07:22:47 AM +UTC
Transaction Fee:
0.000157777562198529 ETH $0.30
Gas Used:
53,781 Gas / 2.933704509 Gwei

Emitted Events:

217 GYEN.0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925( 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925, 0x000000000000000000000000ad89fd507d694993de3adb8366162e84f9fafb6c, 0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff, ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff )

Account State Difference:

  Address   Before After State Difference Code
(Titan Builder)
10.823560714869730564 Eth10.823614495869730564 Eth0.000053781
0xaD89Fd50...4f9fafb6c
0.023810358234881353 Eth
Nonce: 30
0.023652580672682824 Eth
Nonce: 31
0.000157777562198529
0xC0851292...ac6EcD911

Execution Trace

GYEN.095ea7b3( )
  • Token_v3.approve( spender=0xDef1C0ded9bec7F1a1670819833240f027b25EfF, value=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
    File 1 of 2: GYEN
    // File: @openzeppelin/upgrades/contracts/upgradeability/Proxy.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title Proxy
     * @dev Implements delegation of calls to other contracts, with proper
     * forwarding of return values and bubbling of failures.
     * It defines a fallback function that delegates all calls to the address
     * returned by the abstract _implementation() internal function.
     */
    contract Proxy {
      /**
       * @dev Fallback function.
       * Implemented entirely in `_fallback`.
       */
      function () payable external {
        _fallback();
      }
    
      /**
       * @return The Address of the implementation.
       */
      function _implementation() internal view returns (address);
    
      /**
       * @dev Delegates execution to an implementation contract.
       * This is a low level function that doesn't return to its internal call site.
       * It will return to the external caller whatever the implementation returns.
       * @param implementation Address to delegate.
       */
      function _delegate(address implementation) internal {
        assembly {
          // Copy msg.data. We take full control of memory in this inline assembly
          // block because it will not return to Solidity code. We overwrite the
          // Solidity scratch pad at memory position 0.
          calldatacopy(0, 0, calldatasize)
    
          // Call the implementation.
          // out and outsize are 0 because we don't know the size yet.
          let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
    
          // Copy the returned data.
          returndatacopy(0, 0, returndatasize)
    
          switch result
          // delegatecall returns 0 on error.
          case 0 { revert(0, returndatasize) }
          default { return(0, returndatasize) }
        }
      }
    
      /**
       * @dev Function that is run as the first thing in the fallback function.
       * Can be redefined in derived contracts to add functionality.
       * Redefinitions must call super._willFallback().
       */
      function _willFallback() internal {
      }
    
      /**
       * @dev fallback implementation.
       * Extracted to enable manual triggering.
       */
      function _fallback() internal {
        _willFallback();
        _delegate(_implementation());
      }
    }
    
    // File: @openzeppelin/upgrades/contracts/utils/Address.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * Utility library of inline functions on addresses
     *
     * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/utils/Address.sol
     * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts
     * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the
     * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version.
     */
    library OpenZeppelinUpgradesAddress {
        /**
         * Returns whether the target address is a contract
         * @dev This function will return false if invoked during the constructor of a contract,
         * as the code is not actually created until after the constructor finishes.
         * @param account address of the account to check
         * @return whether the target address is a contract
         */
        function isContract(address account) internal view returns (bool) {
            uint256 size;
            // XXX Currently there is no better way to check if there is a contract in an address
            // than to check the size of the code at that address.
            // See https://ethereum.stackexchange.com/a/14016/36603
            // for more details about how this works.
            // TODO Check this again before the Serenity release, because all addresses will be
            // contracts then.
            // solhint-disable-next-line no-inline-assembly
            assembly { size := extcodesize(account) }
            return size > 0;
        }
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @title BaseUpgradeabilityProxy
     * @dev This contract implements a proxy that allows to change the
     * implementation address to which it will delegate.
     * Such a change is called an implementation upgrade.
     */
    contract BaseUpgradeabilityProxy is Proxy {
      /**
       * @dev Emitted when the implementation is upgraded.
       * @param implementation Address of the new implementation.
       */
      event Upgraded(address indexed implementation);
    
      /**
       * @dev Storage slot with the address of the current implementation.
       * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
       * validated in the constructor.
       */
      bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    
      /**
       * @dev Returns the current implementation.
       * @return Address of the current implementation
       */
      function _implementation() internal view returns (address impl) {
        bytes32 slot = IMPLEMENTATION_SLOT;
        assembly {
          impl := sload(slot)
        }
      }
    
      /**
       * @dev Upgrades the proxy to a new implementation.
       * @param newImplementation Address of the new implementation.
       */
      function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
      }
    
      /**
       * @dev Sets the implementation address of the proxy.
       * @param newImplementation Address of the new implementation.
       */
      function _setImplementation(address newImplementation) internal {
        require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
    
        bytes32 slot = IMPLEMENTATION_SLOT;
    
        assembly {
          sstore(slot, newImplementation)
        }
      }
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/UpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title UpgradeabilityProxy
     * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing
     * implementation and init data.
     */
    contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
      /**
       * @dev Contract constructor.
       * @param _logic Address of the initial implementation.
       * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
       * It should include the signature and the parameters of the function to be called, as described in
       * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
       * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
       */
      constructor(address _logic, bytes memory _data) public payable {
        assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
        _setImplementation(_logic);
        if(_data.length > 0) {
          (bool success,) = _logic.delegatecall(_data);
          require(success);
        }
      }  
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/BaseAdminUpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title BaseAdminUpgradeabilityProxy
     * @dev This contract combines an upgradeability proxy with an authorization
     * mechanism for administrative tasks.
     * All external functions in this contract must be guarded by the
     * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
     * feature proposal that would enable this to be done automatically.
     */
    contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
      /**
       * @dev Emitted when the administration has been transferred.
       * @param previousAdmin Address of the previous admin.
       * @param newAdmin Address of the new admin.
       */
      event AdminChanged(address previousAdmin, address newAdmin);
    
      /**
       * @dev Storage slot with the admin of the contract.
       * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
       * validated in the constructor.
       */
    
      bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
    
      /**
       * @dev Modifier to check whether the `msg.sender` is the admin.
       * If it is, it will run the function. Otherwise, it will delegate the call
       * to the implementation.
       */
      modifier ifAdmin() {
        if (msg.sender == _admin()) {
          _;
        } else {
          _fallback();
        }
      }
    
      /**
       * @return The address of the proxy admin.
       */
      function admin() external ifAdmin returns (address) {
        return _admin();
      }
    
      /**
       * @return The address of the implementation.
       */
      function implementation() external ifAdmin returns (address) {
        return _implementation();
      }
    
      /**
       * @dev Changes the admin of the proxy.
       * Only the current admin can call this function.
       * @param newAdmin Address to transfer proxy administration to.
       */
      function changeAdmin(address newAdmin) external ifAdmin {
        require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
        emit AdminChanged(_admin(), newAdmin);
        _setAdmin(newAdmin);
      }
    
      /**
       * @dev Upgrade the backing implementation of the proxy.
       * Only the admin can call this function.
       * @param newImplementation Address of the new implementation.
       */
      function upgradeTo(address newImplementation) external ifAdmin {
        _upgradeTo(newImplementation);
      }
    
      /**
       * @dev Upgrade the backing implementation of the proxy and call a function
       * on the new implementation.
       * This is useful to initialize the proxied contract.
       * @param newImplementation Address of the new implementation.
       * @param data Data to send as msg.data in the low level call.
       * It should include the signature and the parameters of the function to be called, as described in
       * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
       */
      function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
        _upgradeTo(newImplementation);
        (bool success,) = newImplementation.delegatecall(data);
        require(success);
      }
    
      /**
       * @return The admin slot.
       */
      function _admin() internal view returns (address adm) {
        bytes32 slot = ADMIN_SLOT;
        assembly {
          adm := sload(slot)
        }
      }
    
      /**
       * @dev Sets the address of the proxy admin.
       * @param newAdmin Address of the new proxy admin.
       */
      function _setAdmin(address newAdmin) internal {
        bytes32 slot = ADMIN_SLOT;
    
        assembly {
          sstore(slot, newAdmin)
        }
      }
    
      /**
       * @dev Only fall back when the sender is not the admin.
       */
      function _willFallback() internal {
        require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
        super._willFallback();
      }
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/AdminUpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title AdminUpgradeabilityProxy
     * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for 
     * initializing the implementation, admin, and init data.
     */
    contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {
      /**
       * Contract constructor.
       * @param _logic address of the initial implementation.
       * @param _admin Address of the proxy administrator.
       * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
       * It should include the signature and the parameters of the function to be called, as described in
       * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
       * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
       */
      constructor(address _logic, address _admin, bytes memory _data) UpgradeabilityProxy(_logic, _data) public payable {
        assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
        _setAdmin(_admin);
      }
    }
    
    // File: contracts/GYEN.sol
    
    pragma solidity 0.5.8;
    
    
    contract GYEN is AdminUpgradeabilityProxy {
    
        constructor(address _logic, address _admin, bytes memory _data) public payable AdminUpgradeabilityProxy(_logic, _admin, _data) {}
    
    }

    File 2 of 2: Token_v3
    pragma solidity 0.5.8;
    import "./Capper.sol";
    import "./Pauser.sol";
    import "./Prohibiter.sol";
    contract Admin is Capper, Prohibiter {
        address public admin = address(0);
        event CapperChanged(address indexed oldCapper, address indexed newCapper, address indexed sender);
        event PauserChanged(address indexed oldPauser, address indexed newPauser, address indexed sender);
        event ProhibiterChanged(address indexed oldProhibiter, address indexed newProhibiter, address indexed sender);
        
        modifier onlyAdmin() {
            require(msg.sender == admin, "the sender is not the admin");
            _;
        }
        function changeCapper(address _account) public onlyAdmin whenNotPaused isNotZeroAddress(_account) {
            address old = capper;
            capper = _account;
            emit CapperChanged(old, capper, msg.sender);
        }
        /**
         * Change Pauser
         * @dev "whenNotPaused" modifier should not be used here
         */
        function changePauser(address _account) public onlyAdmin isNotZeroAddress(_account) {
            address old = pauser;
            pauser = _account;
            emit PauserChanged(old, pauser, msg.sender);
        }
        function changeProhibiter(address _account) public onlyAdmin whenNotPaused isNotZeroAddress(_account) {
            address old = prohibiter;
            prohibiter = _account;
            emit ProhibiterChanged(old, prohibiter, msg.sender);
        }
    }pragma solidity 0.5.8;
    import "./Common.sol";
    contract Capper is Common {
        uint256 public capacity = 0;
        address public capper = address(0);
        event Cap(uint256 indexed newCapacity, address indexed sender);
        modifier onlyCapper() {
            require(msg.sender == capper, "the sender is not the capper");
            _;
        }
        modifier notMoreThanCapacity(uint256 _amount) {
            require(_amount <= capacity, "this amount is more than capacity");
            _;
        }
        function _cap(uint256 _amount) internal {
            capacity = _amount;
            emit Cap(capacity, msg.sender);
        }
    }pragma solidity 0.5.8;
    contract Common {
        modifier isNotZeroAddress(address _account) {
            require(_account != address(0), "this account is the zero address");
            _;
        }
        modifier isNaturalNumber(uint256 _amount) {
            require(0 < _amount, "this amount is not a natural number");
            _;
        }
    }pragma solidity 0.5.8;
    import "./Pauser.sol";
    contract Minter is Pauser {
        address public minter = address(0);
        modifier onlyMinter() {
            require(msg.sender == minter, "the sender is not the minter");
            _;
        }
    }pragma solidity 0.5.8;
    import "./Minter.sol";
    contract MinterAdmin is Minter {
        address public minterAdmin = address(0);
        event MinterChanged(address indexed oldMinter, address indexed newMinter, address indexed sender);
        modifier onlyMinterAdmin() {
            require(msg.sender == minterAdmin, "the sender is not the minterAdmin");
            _;
        }
        function changeMinter(address _account) public onlyMinterAdmin whenNotPaused isNotZeroAddress(_account) {
            address old = minter;
            minter = _account;
            emit MinterChanged(old, minter, msg.sender);
        }
    }pragma solidity 0.5.8;
    import "./Common.sol";
    contract Operators is Common  {
        address public operator1 = address(0);
        address public operator2 = address(0);
        modifier onlyOperator() {
            require(msg.sender == operator1 || msg.sender == operator2, "the sender is not the operator");
            _;
        }
        function initializeOperators(address _account1, address _account2) internal {
            operator1 = _account1;
            operator2 = _account2;
        }
    }pragma solidity 0.5.8;
    import "./Admin.sol";
    import "./MinterAdmin.sol";
    contract Owner is Admin, MinterAdmin {
        address public owner = address(0);
        event OwnerChanged(address indexed oldOwner, address indexed newOwner, address indexed sender);
        event AdminChanged(address indexed oldAdmin, address indexed newAdmin, address indexed sender);
        event MinterAdminChanged(address indexed oldMinterAdmin, address indexed newMinterAdmin, address indexed sender);
        modifier onlyOwner() {
            require(msg.sender == owner, "the sender is not the owner");
            _;
        }
        function changeOwner(address _account) public onlyOwner whenNotPaused isNotZeroAddress(_account) {
            address old = owner;
            owner = _account;
            emit OwnerChanged(old, owner, msg.sender);
        }
        /**
         * Change Admin
         * @dev "whenNotPaused" modifier should not be used here
         */
        function changeAdmin(address _account) public onlyOwner isNotZeroAddress(_account) {
            address old = admin;
            admin = _account;
            emit AdminChanged(old, admin, msg.sender);
        }
        function changeMinterAdmin(address _account) public onlyOwner whenNotPaused isNotZeroAddress(_account) {
            address old = minterAdmin;
            minterAdmin = _account;
            emit MinterAdminChanged(old, minterAdmin, msg.sender);
        }
    }pragma solidity 0.5.8;
    import "./Common.sol";
    contract Pauser is Common {
        address public pauser = address(0);
        bool public paused = false;
        event Pause(bool status, address indexed sender);
        modifier onlyPauser() {
            require(msg.sender == pauser, "the sender is not the pauser");
            _;
        }
        modifier whenNotPaused() {
            require(!paused, "this is a paused contract");
            _;
        }
        modifier whenPaused() {
            require(paused, "this is not a paused contract");
            _;
        }
        function pause() public onlyPauser whenNotPaused {
            paused = true;
            emit Pause(paused, msg.sender);
        }
        function unpause() public onlyPauser whenPaused {
            paused = false;
            emit Pause(paused, msg.sender);
        }
    }pragma solidity 0.5.8;
    import "./Pauser.sol";
    contract Prohibiter is Pauser {
        address public prohibiter = address(0);
        mapping(address => bool) public prohibiteds;
        event Prohibition(address indexed prohibited, bool status, address indexed sender);
        modifier onlyProhibiter() {
            require(msg.sender == prohibiter, "the sender is not the prohibiter");
            _;
        }
        modifier onlyNotProhibited(address _account) {
            require(!prohibiteds[_account], "this account is prohibited");
            _;
        }
        modifier onlyProhibited(address _account) {
            require(prohibiteds[_account], "this account is not prohibited");
            _;
        }
        function prohibit(address _account) public onlyProhibiter whenNotPaused isNotZeroAddress(_account) onlyNotProhibited(_account) {
            prohibiteds[_account] = true;
            emit Prohibition(_account, prohibiteds[_account], msg.sender);
        }
        function unprohibit(address _account) public onlyProhibiter whenNotPaused isNotZeroAddress(_account) onlyProhibited(_account) {
            prohibiteds[_account] = false;
            emit Prohibition(_account, prohibiteds[_account], msg.sender);
        }
    }pragma solidity 0.5.8;
    import "./Common.sol";
    contract Rescuer is Common  {
        address public rescuer = address(0);
        modifier onlyRescuer() {
            require(msg.sender == rescuer, "the sender is not the rescuer");
            _;
        }
        function initializeRescuer(address _account) internal {
            require(rescuer == address(0), "the rescuer can only be initiated once");
            rescuer = _account;
        }
    }pragma solidity 0.5.8;
    import "./Common.sol";
    contract Wiper is Common  {
        address public wiper = address(0);
        
        modifier onlyWiper() {
            require(msg.sender == wiper, "the sender is not the wiper");
            _;
        }
        function initializeWiper(address _account) public isNotZeroAddress(_account) {
            require(wiper == address(0), "the wiper can only be initiated once");
            wiper = _account;
        }
    }pragma solidity 0.5.8;
    import "@openzeppelin/upgrades/contracts/Initializable.sol";
    import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
    import "./Roles/Owner.sol";
    contract Token_v1 is Initializable, ERC20, Owner {
        string public name;
        string public symbol;
        uint8 public decimals;
        event Mint(address indexed mintee, uint256 amount, address indexed sender);
        event Burn(address indexed burnee, uint256 amount, address indexed sender);
        function initialize(
            string memory _name,
            string memory _symbol,
            uint8 _decimals,
            address _owner,
            address _admin,
            address _capper,
            address _prohibiter,
            address _pauser,
            address _minterAdmin,
            address _minter
            ) public initializer {
                require(_owner != address(0), "_owner is the zero address");
                require(_admin != address(0), "_admin is the zero address");
                require(_capper != address(0), "_capper is the zero address");
                require(_prohibiter != address(0), "_prohibiter is the zero address");
                require(_pauser != address(0), "_pauser is the zero address");
                require(_minterAdmin != address(0), "_minterAdmin is the zero address");
                require(_minter != address(0), "_minter is the zero address");
                name = _name;
                symbol = _symbol;
                decimals = _decimals;
                owner = _owner;
                admin = _admin;
                capper = _capper;
                prohibiter = _prohibiter;
                pauser = _pauser;
                minterAdmin = _minterAdmin;
                minter = _minter;
        }
        function cap(uint256 _amount) public onlyCapper whenNotPaused isNaturalNumber(_amount) {
            require(totalSupply() <= _amount, "this amount is less than the totalySupply");
            _cap(_amount);
        }
        function mint(address _account, uint256 _amount) public onlyMinter whenNotPaused notMoreThanCapacity(totalSupply().add(_amount)) isNaturalNumber(_amount) {
            _mint(_account, _amount);
            emit Mint(_account, _amount, msg.sender);
        }
        function transfer(address _recipient, uint256 _amount) public whenNotPaused onlyNotProhibited(msg.sender) isNaturalNumber(_amount) returns (bool) {
            _transfer(msg.sender, _recipient, _amount);
            return true;
        }
        function transferFrom(address _sender, address _recipient, uint256 _amount) public whenNotPaused onlyNotProhibited(_sender) isNaturalNumber(_amount) returns (bool) {
            return super.transferFrom(_sender, _recipient, _amount);
        }
        function burn(uint256 _amount) public isNaturalNumber(_amount) {
            _burn(msg.sender, _amount);
            emit Burn(msg.sender, _amount, msg.sender);
        }
    }pragma solidity 0.5.8;
    import "./Token_v1.sol";
    import "./Roles/Wiper.sol";
    contract Token_v2 is Token_v1, Wiper {
        event Wipe(address indexed addr, uint256 amount);
        event WiperChanged(address indexed oldWiper, address indexed newWiper, address indexed sender);
        // only admin can change wiper
        function changeWiper(address _account) public onlyAdmin whenNotPaused isNotZeroAddress(_account) {
            address old = wiper;
            wiper = _account;
            emit WiperChanged(old, wiper, msg.sender);
        }
        // wipe balance of prohibited address
        function wipe(address _account) public whenNotPaused onlyWiper onlyProhibited(_account) {
            uint256 _balance = balanceOf(_account);
            _burn(_account, _balance);
            emit Wipe(_account, _balance);
        }
    }pragma solidity 0.5.8;
    import "./Token_v2.sol";
    import "./Roles/Rescuer.sol";
    import "./Roles/Operators.sol";
    import { IERC20 } from "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
    import { SafeERC20 } from "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
    contract Token_v3 is Token_v2, Rescuer, Operators {
        using SafeERC20 for IERC20;
        struct MintTransaction {
            address destination;
            uint amount;
            bool executed;
        }
        uint256 public mintTransactionCount;
        mapping (uint => mapping (address => bool)) public confirmations;
        mapping (uint => MintTransaction) public mintTransactions;
        modifier transactionExists(uint transactionId) {
            require (mintTransactions[transactionId].destination != address(0), "mint transaction does not exist.");
            _;
        }
        modifier notConfirmed(uint transactionId, address operator) {
            require (!confirmations[transactionId][operator], "mint transaction had been confirmed.");
            _;
        }
        event Rescue(IERC20 indexed tokenAddr, address indexed toAddr, uint256 amount);
        event RescuerChanged(address indexed oldRescuer, address indexed newRescuer, address indexed sender);
        event OperatorChanged(address indexed oldOperator, address indexed newOperator, uint256 index, address indexed sender);
        event Confirmation(address indexed sender, uint indexed transactionId);
        event PendingMintTransaction(uint indexed transactionId, address indexed acount, uint amount, address indexed sender);
        // only admin can change rescuer
        function changeRescuer(address _account) public onlyAdmin whenNotPaused isNotZeroAddress(_account) {
            address old = rescuer;
            rescuer = _account;
            emit RescuerChanged(old, rescuer, msg.sender);
        }
        // rescue locked ERC20 Tokens
        function rescue(IERC20 _tokenContract, address _to, uint256 _amount) public whenNotPaused onlyRescuer {
            _tokenContract.safeTransfer(_to, _amount);
            emit Rescue(_tokenContract, _to, _amount);
        }
        // only admin can change operator
        function changeOperator(address _account, uint256 _index) public onlyAdmin whenNotPaused isNotZeroAddress(_account) {
            require(_index == 1 || _index == 2, "there is only two operators.");
            address old = operator1;
            if(_index == 1){
                operator1 = _account;
            }else{
                old = operator2;
                operator2 = _account;
            }
            emit OperatorChanged(old, _account, _index, msg.sender);
        }
        function addMintTransaction(address _account, uint _amount)
            internal
            returns (uint transactionId)
        {
            transactionId = mintTransactionCount;
            mintTransactions[transactionId] = MintTransaction({
                destination: _account,
                amount: _amount,
                executed: false
            });
            mintTransactionCount += 1;
            emit PendingMintTransaction(transactionId, _account, _amount, msg.sender);
        }
        function confirmMintTransaction(uint transactionId)
            public
            onlyOperator
            whenNotPaused
            transactionExists(transactionId)
            notConfirmed(transactionId, msg.sender)
        {
            confirmations[transactionId][msg.sender] = true;
            emit Confirmation(msg.sender, transactionId);
            executeTransaction(transactionId);
        }
        function mint(address _account, uint256 _amount) public onlyMinter whenNotPaused notMoreThanCapacity(totalSupply().add(_amount)) onlyNotProhibited(_account) isNaturalNumber(_amount){
            require(_account != address(0), "mint destination is the zero address");
            addMintTransaction(_account, _amount);
        }
        function executeTransaction(uint transactionId)
            internal
        {
            if (isConfirmed(transactionId)) {
                mintTransactions[transactionId].executed = true;
                _mint(mintTransactions[transactionId].destination, mintTransactions[transactionId].amount);
                emit Mint(mintTransactions[transactionId].destination, mintTransactions[transactionId].amount, msg.sender);
            }
        }
        function isConfirmed(uint transactionId)
            public
            view
            returns (bool)
        {
            if(confirmations[transactionId][operator1] &&
                confirmations[transactionId][operator2]){
                    return true;
            }
            return false;
        }
        function initializeV3(address _rescuer, address _operator1, address _operator2) public isNotZeroAddress(_rescuer) isNotZeroAddress(_operator1) isNotZeroAddress(_operator2){
            initializeRescuer(_rescuer);
            initializeOperators(_operator1, _operator2);
        }
        function transfer(address _recipient, uint256 _amount) public whenNotPaused onlyNotProhibited(msg.sender) onlyNotProhibited(_recipient) isNaturalNumber(_amount) returns (bool) {
            _transfer(msg.sender, _recipient, _amount);
            return true;
        }
        function transferFrom(address _sender, address _recipient, uint256 _amount) public whenNotPaused onlyNotProhibited(_sender) onlyNotProhibited(_recipient) isNaturalNumber(_amount) returns (bool) {
            return super.transferFrom(_sender, _recipient, _amount);
        }
        function burn(uint256 _amount) public onlyNotProhibited(msg.sender) isNaturalNumber(_amount) {
            _burn(msg.sender, _amount);
            emit Burn(msg.sender, _amount, msg.sender);
        }
    }pragma solidity >=0.4.24 <0.6.0;
    /**
     * @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.
        uint256 cs;
        assembly { cs := extcodesize(address) }
        return cs == 0;
      }
      // Reserved storage space to allow for layout changes in the future.
      uint256[50] private ______gap;
    }
    pragma solidity ^0.5.0;
    /**
     * @dev Wrappers over Solidity's arithmetic operations with added overflow
     * checks.
     *
     * Arithmetic operations in Solidity wrap on overflow. This can easily result
     * in bugs, because programmers usually assume that an overflow raises an
     * error, which is the standard behavior in high level programming languages.
     * `SafeMath` restores this intuition by reverting the transaction when an
     * operation overflows.
     *
     * Using this library instead of the unchecked operations eliminates an entire
     * class of bugs, so it's recommended to use it always.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
            return c;
        }
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a, "SafeMath: subtraction overflow");
            uint256 c = a - b;
            return c;
        }
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
            if (a == 0) {
                return 0;
            }
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
            return c;
        }
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, "SafeMath: division by zero");
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return c;
        }
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b != 0, "SafeMath: modulo by zero");
            return a % b;
        }
    }
    pragma solidity ^0.5.0;
    import "./IERC20.sol";
    import "../../math/SafeMath.sol";
    /**
     * @dev Implementation of the `IERC20` interface.
     *
     * This implementation is agnostic to the way tokens are created. This means
     * that a supply mechanism has to be added in a derived contract using `_mint`.
     * For a generic mechanism see `ERC20Mintable`.
     *
     * *For a detailed writeup see our guide [How to implement supply
     * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
     *
     * We have followed general OpenZeppelin guidelines: functions revert instead
     * of returning `false` on failure. This behavior is nonetheless conventional
     * and does not conflict with the expectations of ERC20 applications.
     *
     * Additionally, an `Approval` event is emitted on calls to `transferFrom`.
     * This allows applications to reconstruct the allowance for all accounts just
     * by listening to said events. Other implementations of the EIP may not emit
     * these events, as it isn't required by the specification.
     *
     * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
     * functions have been added to mitigate the well-known issues around setting
     * allowances. See `IERC20.approve`.
     */
    contract ERC20 is IERC20 {
        using SafeMath for uint256;
        mapping (address => uint256) private _balances;
        mapping (address => mapping (address => uint256)) private _allowances;
        uint256 private _totalSupply;
        /**
         * @dev See `IERC20.totalSupply`.
         */
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
        /**
         * @dev See `IERC20.balanceOf`.
         */
        function balanceOf(address account) public view returns (uint256) {
            return _balances[account];
        }
        /**
         * @dev See `IERC20.transfer`.
         *
         * Requirements:
         *
         * - `recipient` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address recipient, uint256 amount) public returns (bool) {
            _transfer(msg.sender, recipient, amount);
            return true;
        }
        /**
         * @dev See `IERC20.allowance`.
         */
        function allowance(address owner, address spender) public view returns (uint256) {
            return _allowances[owner][spender];
        }
        /**
         * @dev See `IERC20.approve`.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 value) public returns (bool) {
            _approve(msg.sender, spender, value);
            return true;
        }
        /**
         * @dev See `IERC20.transferFrom`.
         *
         * Emits an `Approval` event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of `ERC20`;
         *
         * Requirements:
         * - `sender` and `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `value`.
         * - the caller must have allowance for `sender`'s tokens of at least
         * `amount`.
         */
        function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
            return true;
        }
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to `approve` that can be used as a mitigation for
         * problems described in `IERC20.approve`.
         *
         * Emits an `Approval` event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
            return true;
        }
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to `approve` that can be used as a mitigation for
         * problems described in `IERC20.approve`.
         *
         * Emits an `Approval` event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
            return true;
        }
        /**
         * @dev Moves tokens `amount` from `sender` to `recipient`.
         *
         * This is internal function is equivalent to `transfer`, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a `Transfer` event.
         *
         * Requirements:
         *
         * - `sender` cannot be the zero address.
         * - `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         */
        function _transfer(address sender, address recipient, uint256 amount) internal {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
            _balances[sender] = _balances[sender].sub(amount);
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a `Transfer` event with `from` set to the zero address.
         *
         * Requirements
         *
         * - `to` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: mint to the zero address");
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
         /**
         * @dev Destoys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a `Transfer` event with `to` set to the zero address.
         *
         * Requirements
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 value) internal {
            require(account != address(0), "ERC20: burn from the zero address");
            _totalSupply = _totalSupply.sub(value);
            _balances[account] = _balances[account].sub(value);
            emit Transfer(account, address(0), value);
        }
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
         *
         * This is internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an `Approval` event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 value) internal {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
            _allowances[owner][spender] = value;
            emit Approval(owner, spender, value);
        }
        /**
         * @dev Destoys `amount` tokens from `account`.`amount` is then deducted
         * from the caller's allowance.
         *
         * See `_burn` and `_approve`.
         */
        function _burnFrom(address account, uint256 amount) internal {
            _burn(account, amount);
            _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
        }
    }
    pragma solidity ^0.5.0;
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
     * the optional functions; to access them see `ERC20Detailed`.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a `Transfer` event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through `transferFrom`. This is
         * zero by default.
         *
         * This value changes when `approve` or `transferFrom` are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * > Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an `Approval` event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a `Transfer` event.
         */
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to `approve`. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    pragma solidity ^0.5.0;
    import "./IERC20.sol";
    import "../../math/SafeMath.sol";
    import "../../utils/Address.sol";
    /**
     * @title SafeERC20
     * @dev Wrappers around ERC20 operations that throw on failure (when the token
     * contract returns false). Tokens that return no value (and instead revert or
     * throw on failure) are also supported, non-reverting calls are assumed to be
     * successful.
     * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
     * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
     */
    library SafeERC20 {
        using SafeMath for uint256;
        using Address for address;
        function safeTransfer(IERC20 token, address to, uint256 value) internal {
            callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
        }
        function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
            callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
        }
        function safeApprove(IERC20 token, address spender, uint256 value) internal {
            // safeApprove should only be called when setting an initial allowance,
            // or when resetting it to zero. To increase and decrease it, use
            // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
            // solhint-disable-next-line max-line-length
            require((value == 0) || (token.allowance(address(this), spender) == 0),
                "SafeERC20: approve from non-zero to non-zero allowance"
            );
            callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
        }
        function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
            uint256 newAllowance = token.allowance(address(this), spender).add(value);
            callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
        function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
            uint256 newAllowance = token.allowance(address(this), spender).sub(value);
            callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
        /**
         * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
         * on the return value: the return value is optional (but if data is returned, it must not be false).
         * @param token The token targeted by the call.
         * @param data The call data (encoded using abi.encode or one of its variants).
         */
        function callOptionalReturn(IERC20 token, bytes memory data) private {
            // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
            // we're implementing it ourselves.
            // A Solidity high level call has three parts:
            //  1. The target address is checked to verify it contains contract code
            //  2. The call itself is made, and success asserted
            //  3. The return value is decoded, which in turn checks the size of the returned data.
            // solhint-disable-next-line max-line-length
            require(address(token).isContract(), "SafeERC20: call to non-contract");
            // solhint-disable-next-line avoid-low-level-calls
            (bool success, bytes memory returndata) = address(token).call(data);
            require(success, "SafeERC20: low-level call failed");
            if (returndata.length > 0) { // Return data is optional
                // solhint-disable-next-line max-line-length
                require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
            }
        }
    }
    pragma solidity ^0.5.0;
    /**
     * @dev Collection of functions related to the address type,
     */
    library Address {
        /**
         * @dev Returns true if `account` is a contract.
         *
         * This test is non-exhaustive, and there may be false-negatives: during the
         * execution of a contract's constructor, its address will be reported as
         * not containing a contract.
         *
         * > It is unsafe to assume that an address for which this function returns
         * false is an externally-owned account (EOA) and not a contract.
         */
        function isContract(address account) internal view returns (bool) {
            // This method relies in extcodesize, which returns 0 for contracts in
            // construction, since the code is only stored at the end of the
            // constructor execution.
            uint256 size;
            // solhint-disable-next-line no-inline-assembly
            assembly { size := extcodesize(account) }
            return size > 0;
        }
    }