ETH Price: $2,554.85 (+0.80%)
Gas: 0.53 Gwei

Transaction Decoder

Block:
21652820 at Jan-18-2025 05:18:35 PM +UTC
Transaction Fee:
0.001395346993091172 ETH $3.56
Gas Used:
53,724 Gas / 25.972507503 Gwei

Emitted Events:

245 TokenProxy.0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925( 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925, 0x000000000000000000000000a152ba5c481be9a479179f12b4c300fad2a62917, 0x000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3, ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff )

Account State Difference:

  Address   Before After State Difference Code
0x3496B523...b234c3079
(Titan Builder)
6.685802467243696402 Eth6.685923989489797966 Eth0.000121522246101564
0xA152ba5C...ad2A62917
17.471310202934032378 Eth
Nonce: 147
17.469914855940941206 Eth
Nonce: 148
0.001395346993091172

Execution Trace

TokenProxy.095ea7b3( )
  • ERC677InitializableTokenV2.approve( spender=0x000000000022D473030F116dDEE9F6B43aC78BA3, value=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
    File 1 of 2: TokenProxy
    pragma solidity 0.4.24;
    import "zos-lib/contracts/upgradeability/AdminUpgradeabilityProxy.sol";
    contract TokenProxy is AdminUpgradeabilityProxy {
        constructor(address _implementation, address _admin, bytes memory _data)
            AdminUpgradeabilityProxy(_implementation, _admin, _data) public payable {
        }
    }
    pragma solidity ^0.4.24;
    /**
     * Utility library of inline functions on addresses
     *
     * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.0.0/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 ZOSLibAddress {
      /**
       * 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.
        // solium-disable-next-line security/no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
      }
    }pragma solidity ^0.4.24;
    import './Proxy.sol';
    import '../utils/Address.sol';
    /**
     * @title UpgradeabilityProxy
     * @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 UpgradeabilityProxy 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 "org.zeppelinos.proxy.implementation", and is
       * validated in the constructor.
       */
      bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;
      /**
       * @dev Contract constructor.
       * @param _implementation 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 _implementation, bytes _data) public payable {
        assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation"));
        _setImplementation(_implementation);
        if(_data.length > 0) {
          require(_implementation.delegatecall(_data));
        }
      }
      /**
       * @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) private {
        require(ZOSLibAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
        bytes32 slot = IMPLEMENTATION_SLOT;
        assembly {
          sstore(slot, newImplementation)
        }
      }
    }
    pragma solidity ^0.4.24;
    /**
     * @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());
      }
    }
    pragma solidity ^0.4.24;
    import './UpgradeabilityProxy.sol';
    /**
     * @title AdminUpgradeabilityProxy
     * @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 AdminUpgradeabilityProxy is UpgradeabilityProxy {
      /**
       * @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 "org.zeppelinos.proxy.admin", and is
       * validated in the constructor.
       */
      bytes32 private constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b;
      /**
       * @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();
        }
      }
      /**
       * Contract constructor.
       * @param _implementation 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 _implementation, address _admin, bytes _data) UpgradeabilityProxy(_implementation, _data) public payable {
        assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin"));
        _setAdmin(_admin);
      }
      /**
       * @return The address of the proxy admin.
       */
      function admin() external view ifAdmin returns (address) {
        return _admin();
      }
      /**
       * @return The address of the implementation.
       */
      function implementation() external view 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 data) payable external ifAdmin {
        _upgradeTo(newImplementation);
        require(newImplementation.delegatecall(data));
      }
      /**
       * @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 2 of 2: ERC677InitializableTokenV2
    pragma solidity 0.4.24;
    
    
    /**
     * @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 wasInitializing = initializing;
        initializing = true;
        initialized = true;
    
        _;
    
        initializing = wasInitializing;
      }
    
      /// @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;
    }
    
    /**
     * @title ERC20 interface
     * @dev see https://github.com/ethereum/EIPs/issues/20
     */
    interface IERC20 {
      function totalSupply() external view returns (uint256);
    
      function balanceOf(address who) external view returns (uint256);
    
      function allowance(address owner, address spender)
        external view returns (uint256);
    
      function transfer(address to, uint256 value) external returns (bool);
    
      function approve(address spender, uint256 value)
        external returns (bool);
    
      function transferFrom(address from, address to, uint256 value)
        external returns (bool);
    
      event Transfer(
        address indexed from,
        address indexed to,
        uint256 value
      );
    
      event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
      );
    }
    
    /**
     * @title SafeMath
     * @dev Math operations with safety checks that revert on error
     */
    library SafeMath {
    
      /**
      * @dev Multiplies two numbers, reverts on 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);
    
        return c;
      }
    
      /**
      * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
      */
      function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0); // Solidity only automatically asserts when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
        return c;
      }
    
      /**
      * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
      */
      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;
    
        return c;
      }
    
      /**
      * @dev Adds two numbers, reverts on overflow.
      */
      function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);
    
        return c;
      }
    
      /**
      * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
      * reverts when dividing by zero.
      */
      function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
      }
    }
    
    /**
     * @title Standard ERC20 token
     *
     * @dev Implementation of the basic standard token.
     * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
     * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
     */
    contract ERC20 is Initializable, IERC20 {
      using SafeMath for uint256;
    
      mapping (address => uint256) private _balances;
    
      mapping (address => mapping (address => uint256)) private _allowed;
    
      uint256 private _totalSupply;
    
      /**
      * @dev Total number of tokens in existence
      */
      function totalSupply() public view returns (uint256) {
        return _totalSupply;
      }
    
      /**
      * @dev Gets the balance of the specified address.
      * @param owner The address to query the the balance of.
      * @return An uint256 representing the amount owned by the passed address.
      */
      function balanceOf(address owner) public view returns (uint256) {
        return _balances[owner];
      }
    
      /**
       * @dev Function to check the amount of tokens that an owner allowed to a spender.
       * @param owner address The address which owns the funds.
       * @param spender address The address which will spend the funds.
       * @return A uint256 specifying the amount of tokens still available for the spender.
       */
      function allowance(
        address owner,
        address spender
       )
        public
        view
        returns (uint256)
      {
        return _allowed[owner][spender];
      }
    
      /**
      * @dev Transfer token for a specified address
      * @param to The address to transfer to.
      * @param value The amount to be transferred.
      */
      function transfer(address to, uint256 value) public returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
      }
    
      /**
       * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
       * 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
       * @param spender The address which will spend the funds.
       * @param value The amount of tokens to be spent.
       */
      function approve(address spender, uint256 value) public returns (bool) {
        require(spender != address(0));
    
        _allowed[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
      }
    
      /**
       * @dev Transfer tokens from one address to another
       * @param from address The address which you want to send tokens from
       * @param to address The address which you want to transfer to
       * @param value uint256 the amount of tokens to be transferred
       */
      function transferFrom(
        address from,
        address to,
        uint256 value
      )
        public
        returns (bool)
      {
        require(value <= _allowed[from][msg.sender]);
    
        _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
        _transfer(from, to, value);
        return true;
      }
    
      /**
       * @dev Increase the amount of tokens that an owner allowed to a spender.
       * approve should be called when allowed_[_spender] == 0. To increment
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param spender The address which will spend the funds.
       * @param addedValue The amount of tokens to increase the allowance by.
       */
      function increaseAllowance(
        address spender,
        uint256 addedValue
      )
        public
        returns (bool)
      {
        require(spender != address(0));
    
        _allowed[msg.sender][spender] = (
          _allowed[msg.sender][spender].add(addedValue));
        emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
        return true;
      }
    
      /**
       * @dev Decrease the amount of tokens that an owner allowed to a spender.
       * approve should be called when allowed_[_spender] == 0. To decrement
       * allowed value is better to use this function to avoid 2 calls (and wait until
       * the first transaction is mined)
       * From MonolithDAO Token.sol
       * @param spender The address which will spend the funds.
       * @param subtractedValue The amount of tokens to decrease the allowance by.
       */
      function decreaseAllowance(
        address spender,
        uint256 subtractedValue
      )
        public
        returns (bool)
      {
        require(spender != address(0));
    
        _allowed[msg.sender][spender] = (
          _allowed[msg.sender][spender].sub(subtractedValue));
        emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
        return true;
      }
    
      /**
      * @dev Transfer token for a specified addresses
      * @param from The address to transfer from.
      * @param to The address to transfer to.
      * @param value The amount to be transferred.
      */
      function _transfer(address from, address to, uint256 value) internal {
        require(value <= _balances[from]);
        require(to != address(0));
    
        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Transfer(from, to, value);
      }
    
      /**
       * @dev Internal function that mints an amount of the token and assigns it to
       * an account. This encapsulates the modification of balances such that the
       * proper events are emitted.
       * @param account The account that will receive the created tokens.
       * @param amount The amount that will be created.
       */
      function _mint(address account, uint256 amount) internal {
        require(account != 0);
        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
      }
    
      /**
       * @dev Internal function that burns an amount of the token of a given
       * account.
       * @param account The account whose tokens will be burnt.
       * @param amount The amount that will be burnt.
       */
      function _burn(address account, uint256 amount) internal {
        require(account != 0);
        require(amount <= _balances[account]);
    
        _totalSupply = _totalSupply.sub(amount);
        _balances[account] = _balances[account].sub(amount);
        emit Transfer(account, address(0), amount);
      }
    
      /**
       * @dev Internal function that burns an amount of the token of a given
       * account, deducting from the sender's allowance for said account. Uses the
       * internal burn function.
       * @param account The account whose tokens will be burnt.
       * @param amount The amount that will be burnt.
       */
      function _burnFrom(address account, uint256 amount) internal {
        require(amount <= _allowed[account][msg.sender]);
    
        // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
        // this function needs to emit an event with the updated approval.
        _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(
          amount);
        _burn(account, amount);
      }
    
      uint256[50] private ______gap;
    }
    
    /**
     * @title Burnable Token
     * @dev Token that can be irreversibly burned (destroyed).
     */
    contract ERC20Burnable is Initializable, ERC20 {
    
      /**
       * @dev Burns a specific amount of tokens.
       * @param value The amount of token to be burned.
       */
      function burn(uint256 value) public {
        _burn(msg.sender, value);
      }
    
      /**
       * @dev Burns a specific amount of tokens from the target address and decrements allowance
       * @param from address The address which you want to send tokens from
       * @param value uint256 The amount of token to be burned
       */
      function burnFrom(address from, uint256 value) public {
        _burnFrom(from, value);
      }
    
      uint256[50] private ______gap;
    }
    
    /**
     * @title Ownable
     * @dev The Ownable contract has an owner address, and provides basic authorization control
     * functions, this simplifies the implementation of "user permissions".
     */
    contract Ownable is Initializable {
      address private _owner;
    
    
      event OwnershipRenounced(address indexed previousOwner);
      event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
      );
    
    
      /**
       * @dev The Ownable constructor sets the original `owner` of the contract to the sender
       * account.
       */
      function initialize(address sender) public initializer {
        _owner = sender;
      }
    
      /**
       * @return the address of the owner.
       */
      function owner() public view returns(address) {
        return _owner;
      }
    
      /**
       * @dev Throws if called by any account other than the owner.
       */
      modifier onlyOwner() {
        require(isOwner());
        _;
      }
    
      /**
       * @return true if `msg.sender` is the owner of the contract.
       */
      function isOwner() public view returns(bool) {
        return msg.sender == _owner;
      }
    
      /**
       * @dev Allows the current owner to relinquish control of the contract.
       * @notice Renouncing to ownership will leave the contract without an owner.
       * It will not be possible to call the functions with the `onlyOwner`
       * modifier anymore.
       */
      function renounceOwnership() public onlyOwner {
        emit OwnershipRenounced(_owner);
        _owner = address(0);
      }
    
      /**
       * @dev Allows the current owner to transfer control of the contract to a newOwner.
       * @param newOwner The address to transfer ownership to.
       */
      function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
      }
    
      /**
       * @dev Transfers control of the contract to a newOwner.
       * @param newOwner The address to transfer ownership to.
       */
      function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0));
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
      }
    
      uint256[50] private ______gap;
    }
    
    /**
     * @title ERC20Mintable
     * @dev ERC20 minting logic
     */
    contract ERC20Mintable is Initializable, ERC20, Ownable {
      function initialize(address sender) public initializer {
        Ownable.initialize(sender);
      }
    
      /**
       * @dev Function to mint tokens
       * @param to The address that will receive the minted tokens.
       * @param amount The amount of tokens to mint.
       * @return A boolean that indicates if the operation was successful.
       */
      function mint(
        address to,
        uint256 amount
      )
        public
        onlyOwner
        returns (bool)
      {
        _mint(to, amount);
        return true;
      }
    
    
      modifier hasMintPermission() {
        require(msg.sender == owner());
        _;
      }
    
      uint256[50] private ______gap;
    }
    
    /**
     * @title ERC20Detailed token
     * @dev The decimals are only for visualization purposes.
     * All the operations are done using the smallest and indivisible token unit,
     * just as on Ethereum all the operations are done in wei.
     */
    contract ERC20Detailed is Initializable, IERC20 {
      string private _name;
      string private _symbol;
      uint8 private _decimals;
    
      function initialize(string name, string symbol, uint8 decimals) public initializer {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
      }
    
      /**
       * @return the name of the token.
       */
      function name() public view returns(string) {
        return _name;
      }
    
      /**
       * @return the symbol of the token.
       */
      function symbol() public view returns(string) {
        return _symbol;
      }
    
      /**
       * @return the number of decimals of the token.
       */
      function decimals() public view returns(uint8) {
        return _decimals;
      }
    
      uint256[50] private ______gap;
    }
    
    contract ERC677Receiver {
      function onTokenTransfer(address _from, uint _value, bytes _data) external returns(bool);
    }
    
    //import "openzeppelin-eth/contracts/token/ERC20/ERC20Mintable.sol";
    //import "openzeppelin-eth/contracts/ownership/Ownerable.sol";
    contract ERC677 is ERC20 {
        event Transfer(address indexed from, address indexed to, uint value, bytes data);
    
        function transferAndCall(address, uint, bytes) external returns (bool);
    
    
    }
    
    contract ERC677InitializableTokenV2 is
        ERC677,
        ERC20Detailed,
        ERC20Burnable,
        ERC20Mintable {
    
        event ContractFallbackCallFailed(address from, address to, uint value);
    
        address public bridgeContract;
    
        uint256 lastFundingPeriod = 0;
        uint256 totalPeriodFundedAmount = 0;
    
        FundingRules fundingRules;
    
        struct FundingRules {
            uint256 periodLength; // refresh period for next funding round in blocks
            uint256 maxPeriodFunds; // max amount to fund in a period
            uint256 threshold; // amount below which a funding event happens
            uint256 amount; // amount to fund
        }
    
        function initialize(string _name, string _symbol, uint8 _decimals, address _owner) external initializer {
            ERC20Mintable.initialize(_owner);
            ERC20Detailed.initialize(_name, _symbol, _decimals);
        }
    
    
        function () payable {
            revert();
        }
    
        function setFundingRules(uint256 _periodLength, uint256 _maxPeriodFunds, uint256 _threshold, uint256 _amount) onlyOwner public {
            fundingRules.periodLength = _periodLength;
            fundingRules.maxPeriodFunds = _maxPeriodFunds;
            fundingRules.threshold = _threshold;
            fundingRules.amount = _amount;
        }
    
        function getFundingRules() public view returns(uint256, uint256, uint256, uint256){
            return (fundingRules.periodLength,
            fundingRules.maxPeriodFunds,
            fundingRules.threshold,
            fundingRules.amount);
        }
    
        function fundReceiver(address _to) internal {
            // reset funding period
            if(block.number > fundingRules.periodLength + lastFundingPeriod) {
                lastFundingPeriod = block.number;
                totalPeriodFundedAmount = 0;
            }
            // transfer receiver money only if limits are not met and they are below the threshold
            if(address(_to).balance < fundingRules.threshold && fundingRules.amount + totalPeriodFundedAmount <= fundingRules.maxPeriodFunds) {
                if(address(_to).send(fundingRules.amount)){
                    totalPeriodFundedAmount += fundingRules.amount;
                }
            }
        }
    
        function setBridgeContract(address _bridgeContract) onlyOwner public {
            require(_bridgeContract != address(0) && isContract(_bridgeContract));
            bridgeContract = _bridgeContract;
        }
    
        modifier validRecipient(address _recipient) {
            require(_recipient != address(0) && _recipient != address(this));
            _;
        }
    
        function transferAndCall(address _to, uint _value, bytes _data)
            external validRecipient(_to) returns (bool)
        {
            require(superTransfer(_to, _value));
            fundReceiver(_to);
            emit Transfer(msg.sender, _to, _value, _data);
    
            if (isContract(_to)) {
                require(contractFallback(_to, _value, _data));
            }
            return true;
        }
    
        function getTokenInterfacesVersion() public pure returns(uint64 major, uint64 minor, uint64 patch) {
            return (2, 0, 0);
        }
    
        function superTransfer(address _to, uint256 _value) internal returns(bool)
        {
            return super.transfer(_to, _value);
        }
    
        function transfer(address _to, uint256 _value) public returns (bool)
        {
            require(superTransfer(_to, _value), "failed superTransfer");
            fundReceiver(_to);
            if (isContract(_to) && !contractFallback(_to, _value, new bytes(0))) {
                if (_to == bridgeContract) {
                    revert("reverted here");
                } else {
                    emit ContractFallbackCallFailed(msg.sender, _to, _value);
                }
            }
            return true;
        }
    
        function contractFallback(address _to, uint _value, bytes _data)
            private
            returns(bool)
        {
            return _to.call(abi.encodeWithSignature("onTokenTransfer(address,uint256,bytes)",  msg.sender, _value, _data));
        }
    
        function isContract(address _addr)
            private
            view
            returns (bool)
        {
            uint length;
            assembly { length := extcodesize(_addr) }
            return length > 0;
        }
    
        function mint(
            address _to,
            uint256 _amount
        )
        public
        hasMintPermission
        returns (bool)
        {
            fundReceiver(_to);
            return super.mint(_to, _amount);
        }
    
        function finishMinting() public returns (bool) {
            revert();
        }
    
        function renounceOwnership() public onlyOwner {
            revert();
        }
    
        function claimTokens(address _token, address _to) public onlyOwner {
            require(_to != address(0));
            if (_token == address(0)) {
                _to.transfer(address(this).balance);
                return;
            }
    
            ERC20Detailed token = ERC20Detailed(_token);
            uint256 balance = token.balanceOf(address(this));
            require(token.transfer(_to, balance));
        }
    
    }