creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/PermittableToken.sol": {
        "content": "\n// File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol\n\npragma solidity ^0.4.24;\n\n\n/**\n * @title ERC20Basic\n * @dev Simpler version of ERC20 interface\n * See https://github.com/ethereum/EIPs/issues/179\n */\ncontract ERC20Basic {\n  function totalSupply() public view returns (uint256);\n  function balanceOf(address _who) public view returns (uint256);\n  function transfer(address _to, uint256 _value) public returns (bool);\n  event Transfer(address indexed from, address indexed to, uint256 value);\n}\n\n// File: openzeppelin-solidity/contracts/math/SafeMath.sol\n\npragma solidity ^0.4.24;\n\n\n/**\n * @title SafeMath\n * @dev Math operations with safety checks that throw on error\n */\nlibrary SafeMath {\n\n  /**\n  * @dev Multiplies two numbers, throws on overflow.\n  */\n  function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {\n    // Gas optimization: this is cheaper than asserting 'a' not being zero, but the\n    // benefit is lost if 'b' is also tested.\n    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n    if (_a == 0) {\n      return 0;\n    }\n\n    c = _a * _b;\n    assert(c / _a == _b);\n    return c;\n  }\n\n  /**\n  * @dev Integer division of two numbers, truncating the quotient.\n  */\n  function div(uint256 _a, uint256 _b) internal pure returns (uint256) {\n    // assert(_b > 0); // Solidity automatically throws when dividing by 0\n    // uint256 c = _a / _b;\n    // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold\n    return _a / _b;\n  }\n\n  /**\n  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).\n  */\n  function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {\n    assert(_b <= _a);\n    return _a - _b;\n  }\n\n  /**\n  * @dev Adds two numbers, throws on overflow.\n  */\n  function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {\n    c = _a + _b;\n    assert(c >= _a);\n    return c;\n  }\n}\n\n// File: openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol\n\npragma solidity ^0.4.24;\n\n\n\n\n/**\n * @title Basic token\n * @dev Basic version of StandardToken, with no allowances.\n */\ncontract BasicToken is ERC20Basic {\n  using SafeMath for uint256;\n\n  mapping(address => uint256) internal balances;\n\n  uint256 internal totalSupply_;\n\n  /**\n  * @dev Total number of tokens in existence\n  */\n  function totalSupply() public view returns (uint256) {\n    return totalSupply_;\n  }\n\n  /**\n  * @dev Transfer token for a specified address\n  * @param _to The address to transfer to.\n  * @param _value The amount to be transferred.\n  */\n  function transfer(address _to, uint256 _value) public returns (bool) {\n    require(_value <= balances[msg.sender]);\n    require(_to != address(0));\n\n    balances[msg.sender] = balances[msg.sender].sub(_value);\n    balances[_to] = balances[_to].add(_value);\n    emit Transfer(msg.sender, _to, _value);\n    return true;\n  }\n\n  /**\n  * @dev Gets the balance of the specified address.\n  * @param _owner The address to query the the balance of.\n  * @return An uint256 representing the amount owned by the passed address.\n  */\n  function balanceOf(address _owner) public view returns (uint256) {\n    return balances[_owner];\n  }\n\n}\n\n// File: openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol\n\npragma solidity ^0.4.24;\n\n\n\n/**\n * @title Burnable Token\n * @dev Token that can be irreversibly burned (destroyed).\n */\ncontract BurnableToken is BasicToken {\n\n  event Burn(address indexed burner, uint256 value);\n\n  /**\n   * @dev Burns a specific amount of tokens.\n   * @param _value The amount of token to be burned.\n   */\n  function burn(uint256 _value) public {\n    _burn(msg.sender, _value);\n  }\n\n  function _burn(address _who, uint256 _value) internal {\n    require(_value <= balances[_who]);\n    // no need to require value <= totalSupply, since that would imply the\n    // sender's balance is greater than the totalSupply, which *should* be an assertion failure\n\n    balances[_who] = balances[_who].sub(_value);\n    totalSupply_ = totalSupply_.sub(_value);\n    emit Burn(_who, _value);\n    emit Transfer(_who, address(0), _value);\n  }\n}\n\n// File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol\n\npragma solidity ^0.4.24;\n\n\n\n/**\n * @title ERC20 interface\n * @dev see https://github.com/ethereum/EIPs/issues/20\n */\ncontract ERC20 is ERC20Basic {\n  function allowance(address _owner, address _spender)\n    public view returns (uint256);\n\n  function transferFrom(address _from, address _to, uint256 _value)\n    public returns (bool);\n\n  function approve(address _spender, uint256 _value) public returns (bool);\n  event Approval(\n    address indexed owner,\n    address indexed spender,\n    uint256 value\n  );\n}\n\n// File: openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol\n\npragma solidity ^0.4.24;\n\n\n\n\n/**\n * @title Standard ERC20 token\n *\n * @dev Implementation of the basic standard token.\n * https://github.com/ethereum/EIPs/issues/20\n * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol\n */\ncontract StandardToken is ERC20, BasicToken {\n\n  mapping (address => mapping (address => uint256)) internal allowed;\n\n\n  /**\n   * @dev Transfer tokens from one address to another\n   * @param _from address The address which you want to send tokens from\n   * @param _to address The address which you want to transfer to\n   * @param _value uint256 the amount of tokens to be transferred\n   */\n  function transferFrom(\n    address _from,\n    address _to,\n    uint256 _value\n  )\n    public\n    returns (bool)\n  {\n    require(_value <= balances[_from]);\n    require(_value <= allowed[_from][msg.sender]);\n    require(_to != address(0));\n\n    balances[_from] = balances[_from].sub(_value);\n    balances[_to] = balances[_to].add(_value);\n    allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);\n    emit Transfer(_from, _to, _value);\n    return true;\n  }\n\n  /**\n   * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.\n   * Beware that changing an allowance with this method brings the risk that someone may use both the old\n   * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this\n   * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:\n   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n   * @param _spender The address which will spend the funds.\n   * @param _value The amount of tokens to be spent.\n   */\n  function approve(address _spender, uint256 _value) public returns (bool) {\n    allowed[msg.sender][_spender] = _value;\n    emit Approval(msg.sender, _spender, _value);\n    return true;\n  }\n\n  /**\n   * @dev Function to check the amount of tokens that an owner allowed to a spender.\n   * @param _owner address The address which owns the funds.\n   * @param _spender address The address which will spend the funds.\n   * @return A uint256 specifying the amount of tokens still available for the spender.\n   */\n  function allowance(\n    address _owner,\n    address _spender\n   )\n    public\n    view\n    returns (uint256)\n  {\n    return allowed[_owner][_spender];\n  }\n\n  /**\n   * @dev Increase the amount of tokens that an owner allowed to a spender.\n   * approve should be called when allowed[_spender] == 0. To increment\n   * allowed value is better to use this function to avoid 2 calls (and wait until\n   * the first transaction is mined)\n   * From MonolithDAO Token.sol\n   * @param _spender The address which will spend the funds.\n   * @param _addedValue The amount of tokens to increase the allowance by.\n   */\n  function increaseApproval(\n    address _spender,\n    uint256 _addedValue\n  )\n    public\n    returns (bool)\n  {\n    allowed[msg.sender][_spender] = (\n      allowed[msg.sender][_spender].add(_addedValue));\n    emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);\n    return true;\n  }\n\n  /**\n   * @dev Decrease the amount of tokens that an owner allowed to a spender.\n   * approve should be called when allowed[_spender] == 0. To decrement\n   * allowed value is better to use this function to avoid 2 calls (and wait until\n   * the first transaction is mined)\n   * From MonolithDAO Token.sol\n   * @param _spender The address which will spend the funds.\n   * @param _subtractedValue The amount of tokens to decrease the allowance by.\n   */\n  function decreaseApproval(\n    address _spender,\n    uint256 _subtractedValue\n  )\n    public\n    returns (bool)\n  {\n    uint256 oldValue = allowed[msg.sender][_spender];\n    if (_subtractedValue >= oldValue) {\n      allowed[msg.sender][_spender] = 0;\n    } else {\n      allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);\n    }\n    emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);\n    return true;\n  }\n\n}\n\n// File: openzeppelin-solidity/contracts/ownership/Ownable.sol\n\npragma solidity ^0.4.24;\n\n\n/**\n * @title Ownable\n * @dev The Ownable contract has an owner address, and provides basic authorization control\n * functions, this simplifies the implementation of \"user permissions\".\n */\ncontract Ownable {\n  address public owner;\n\n\n  event OwnershipRenounced(address indexed previousOwner);\n  event OwnershipTransferred(\n    address indexed previousOwner,\n    address indexed newOwner\n  );\n\n\n  /**\n   * @dev The Ownable constructor sets the original `owner` of the contract to the sender\n   * account.\n   */\n  constructor() public {\n    owner = msg.sender;\n  }\n\n  /**\n   * @dev Throws if called by any account other than the owner.\n   */\n  modifier onlyOwner() {\n    require(msg.sender == owner);\n    _;\n  }\n\n  /**\n   * @dev Allows the current owner to relinquish control of the contract.\n   * @notice Renouncing to ownership will leave the contract without an owner.\n   * It will not be possible to call the functions with the `onlyOwner`\n   * modifier anymore.\n   */\n  function renounceOwnership() public onlyOwner {\n    emit OwnershipRenounced(owner);\n    owner = address(0);\n  }\n\n  /**\n   * @dev Allows the current owner to transfer control of the contract to a newOwner.\n   * @param _newOwner The address to transfer ownership to.\n   */\n  function transferOwnership(address _newOwner) public onlyOwner {\n    _transferOwnership(_newOwner);\n  }\n\n  /**\n   * @dev Transfers control of the contract to a newOwner.\n   * @param _newOwner The address to transfer ownership to.\n   */\n  function _transferOwnership(address _newOwner) internal {\n    require(_newOwner != address(0));\n    emit OwnershipTransferred(owner, _newOwner);\n    owner = _newOwner;\n  }\n}\n\n// File: openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol\n\npragma solidity ^0.4.24;\n\n\n\n\n/**\n * @title Mintable token\n * @dev Simple ERC20 Token example, with mintable token creation\n * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol\n */\ncontract MintableToken is StandardToken, Ownable {\n  event Mint(address indexed to, uint256 amount);\n  event MintFinished();\n\n  bool public mintingFinished = false;\n\n\n  modifier canMint() {\n    require(!mintingFinished);\n    _;\n  }\n\n  modifier hasMintPermission() {\n    require(msg.sender == owner);\n    _;\n  }\n\n  /**\n   * @dev Function to mint tokens\n   * @param _to The address that will receive the minted tokens.\n   * @param _amount The amount of tokens to mint.\n   * @return A boolean that indicates if the operation was successful.\n   */\n  function mint(\n    address _to,\n    uint256 _amount\n  )\n    public\n    hasMintPermission\n    canMint\n    returns (bool)\n  {\n    totalSupply_ = totalSupply_.add(_amount);\n    balances[_to] = balances[_to].add(_amount);\n    emit Mint(_to, _amount);\n    emit Transfer(address(0), _to, _amount);\n    return true;\n  }\n\n  /**\n   * @dev Function to stop minting new tokens.\n   * @return True if the operation was successful.\n   */\n  function finishMinting() public onlyOwner canMint returns (bool) {\n    mintingFinished = true;\n    emit MintFinished();\n    return true;\n  }\n}\n\n// File: openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol\n\npragma solidity ^0.4.24;\n\n\n\n/**\n * @title DetailedERC20 token\n * @dev The decimals are only for visualization purposes.\n * All the operations are done using the smallest and indivisible token unit,\n * just as on Ethereum all the operations are done in wei.\n */\ncontract DetailedERC20 is ERC20 {\n  string public name;\n  string public symbol;\n  uint8 public decimals;\n\n  constructor(string _name, string _symbol, uint8 _decimals) public {\n    name = _name;\n    symbol = _symbol;\n    decimals = _decimals;\n  }\n}\n\n// File: openzeppelin-solidity/contracts/AddressUtils.sol\n\npragma solidity ^0.4.24;\n\n\n/**\n * Utility library of inline functions on addresses\n */\nlibrary AddressUtils {\n\n  /**\n   * Returns whether the target address is a contract\n   * @dev This function will return false if invoked during the constructor of a contract,\n   * as the code is not actually created until after the constructor finishes.\n   * @param _addr address to check\n   * @return whether the target address is a contract\n   */\n  function isContract(address _addr) internal view returns (bool) {\n    uint256 size;\n    // XXX Currently there is no better way to check if there is a contract in an address\n    // than to check the size of the code at that address.\n    // See https://ethereum.stackexchange.com/a/14016/36603\n    // for more details about how this works.\n    // TODO Check this again before the Serenity release, because all addresses will be\n    // contracts then.\n    // solium-disable-next-line security/no-inline-assembly\n    assembly { size := extcodesize(_addr) }\n    return size > 0;\n  }\n\n}\n\n// File: contracts/interfaces/ERC677.sol\n\npragma solidity 0.4.24;\n\n\ncontract ERC677 is ERC20 {\n    event Transfer(address indexed from, address indexed to, uint256 value, bytes data);\n\n    function transferAndCall(address, uint256, bytes) external payable returns (bool);\n\n    function increaseAllowance(address spender, uint256 addedValue) public returns (bool);\n    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool);\n}\n\ncontract LegacyERC20 {\n    function transfer(address _spender, uint256 _value) public; // returns (bool);\n    function transferFrom(address _owner, address _spender, uint256 _value) public; // returns (bool);\n}\n\n// File: contracts/interfaces/IBurnableMintableERC677Token.sol\n\npragma solidity 0.4.24;\n\n\ncontract IBurnableMintableERC677Token is ERC677 {\n    function mint(address _to, uint256 _amount) public returns (bool);\n    function burn(uint256 _value) public;\n    function claimTokens(address _token, address _to) external;\n}\n\n// File: contracts/upgradeable_contracts/Sacrifice.sol\n\npragma solidity 0.4.24;\n\ncontract Sacrifice {\n    constructor(address _recipient) public payable {\n        selfdestruct(_recipient);\n    }\n}\n\n// File: contracts/libraries/Address.sol\n\npragma solidity 0.4.24;\n\n\n/**\n * @title Address\n * @dev Helper methods for Address type.\n */\nlibrary Address {\n    /**\n    * @dev Try to send native tokens to the address. If it fails, it will force the transfer by creating a selfdestruct contract\n    * @param _receiver address that will receive the native tokens\n    * @param _value the amount of native tokens to send\n    */\n    function safeSendValue(address _receiver, uint256 _value) internal {\n        if (!_receiver.send(_value)) {\n            (new Sacrifice).value(_value)(_receiver);\n        }\n    }\n}\n\n// File: contracts/libraries/SafeERC20.sol\n\npragma solidity 0.4.24;\n\n\n\n/**\n * @title SafeERC20\n * @dev Helper methods for safe token transfers.\n * Functions perform additional checks to be sure that token transfer really happened.\n */\nlibrary SafeERC20 {\n    using SafeMath for uint256;\n\n    /**\n    * @dev Same as ERC20.transfer(address,uint256) but with extra consistency checks.\n    * @param _token address of the token contract\n    * @param _to address of the receiver\n    * @param _value amount of tokens to send\n    */\n    function safeTransfer(address _token, address _to, uint256 _value) internal {\n        LegacyERC20(_token).transfer(_to, _value);\n        assembly {\n            if returndatasize {\n                returndatacopy(0, 0, 32)\n                if iszero(mload(0)) {\n                    revert(0, 0)\n                }\n            }\n        }\n    }\n\n    /**\n    * @dev Same as ERC20.transferFrom(address,address,uint256) but with extra consistency checks.\n    * @param _token address of the token contract\n    * @param _from address of the sender\n    * @param _value amount of tokens to send\n    */\n    function safeTransferFrom(address _token, address _from, uint256 _value) internal {\n        LegacyERC20(_token).transferFrom(_from, address(this), _value);\n        assembly {\n            if returndatasize {\n                returndatacopy(0, 0, 32)\n                if iszero(mload(0)) {\n                    revert(0, 0)\n                }\n            }\n        }\n    }\n}\n\n// File: contracts/upgradeable_contracts/Claimable.sol\n\npragma solidity 0.4.24;\n\n\n\n/**\n * @title Claimable\n * @dev Implementation of the claiming utils that can be useful for withdrawing accidentally sent tokens that are not used in bridge operations.\n */\ncontract Claimable {\n    using SafeERC20 for address;\n\n    /**\n     * Throws if a given address is equal to address(0)\n     */\n    modifier validAddress(address _to) {\n        require(_to != address(0));\n        /* solcov ignore next */\n        _;\n    }\n\n    /**\n     * @dev Withdraws the erc20 tokens or native coins from this contract.\n     * Caller should additionally check that the claimed token is not a part of bridge operations (i.e. that token != erc20token()).\n     * @param _token address of the claimed token or address(0) for native coins.\n     * @param _to address of the tokens/coins receiver.\n     */\n    function claimValues(address _token, address _to) internal validAddress(_to) {\n        if (_token == address(0)) {\n            claimNativeCoins(_to);\n        } else {\n            claimErc20Tokens(_token, _to);\n        }\n    }\n\n    /**\n     * @dev Internal function for withdrawing all native coins from the contract.\n     * @param _to address of the coins receiver.\n     */\n    function claimNativeCoins(address _to) internal {\n        uint256 value = address(this).balance;\n        Address.safeSendValue(_to, value);\n    }\n\n    /**\n     * @dev Internal function for withdrawing all tokens of ssome particular ERC20 contract from this contract.\n     * @param _token address of the claimed ERC20 token.\n     * @param _to address of the tokens receiver.\n     */\n    function claimErc20Tokens(address _token, address _to) internal {\n        ERC20Basic token = ERC20Basic(_token);\n        uint256 balance = token.balanceOf(this);\n        _token.safeTransfer(_to, balance);\n    }\n}\n\n// File: contracts/ERC677BridgeToken.sol\n\npragma solidity 0.4.24;\n\n\n\n\n\n\n\n/**\n* @title ERC677BridgeToken\n* @dev The basic implementation of a bridgeable ERC677-compatible token\n*/\ncontract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, BurnableToken, MintableToken, Claimable {\n    bytes4 internal constant ON_TOKEN_TRANSFER = 0xa4c0ed36; // onTokenTransfer(address,uint256,bytes)\n\n    address internal bridgeContractAddr;\n    address internal bridgeFeeAddr;\n    uint256 internal bridgeFeeAmount;\n\n    constructor(string _name, string _symbol, uint8 _decimals) public DetailedERC20(_name, _symbol, _decimals) {\n        // solhint-disable-previous-line no-empty-blocks\n    }\n\n    function bridgeContract() external view returns (address) {\n        return bridgeContractAddr;\n    }\n\n    function setBridgeContract(address _bridgeContract) external onlyOwner {\n        require(AddressUtils.isContract(_bridgeContract));\n        bridgeContractAddr = _bridgeContract;\n    }\n\n    function transferFeeAddress() external view returns (address) {\n        return bridgeFeeAddr;\n    }\n\n    function settransferFeeAddress(address _bridgeFeeAddr) external onlyOwner {\n        bridgeFeeAddr = _bridgeFeeAddr;\n    }\n\n    function transferFeeAmount() external view returns (uint256) {\n        return bridgeFeeAmount;\n    }\n\n    function settransferFeeAmount(uint256 _bridgeFeeAmount) external onlyOwner {\n        bridgeFeeAmount = _bridgeFeeAmount;\n    }\n\n    modifier validRecipient(address _recipient) {\n        require(_recipient != address(0) && _recipient != address(this));\n        /* solcov ignore next */\n        _;\n    }\n\n    function transferAndCall(address _to, uint256 _value, bytes _data) external payable validRecipient(_to) returns (bool) {\n        if (!AddressUtils.isContract(msg.sender)) {\n          require(msg.value >= bridgeFeeAmount);\n\n          require(bridgeFeeAddr.send(bridgeFeeAmount));\n          if (msg.value > bridgeFeeAmount) {\n              require(msg.sender.send(msg.value-bridgeFeeAmount));            \n          }\n        }\n        \n        require(superTransfer(_to, _value));\n        emit Transfer(msg.sender, _to, _value, _data);\n\n        if (AddressUtils.isContract(_to)) {\n            require(contractFallback(msg.sender, _to, _value, _data));\n        }\n        return true;\n    }\n\n    function getTokenInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {\n        return (2, 5, 0);\n    }\n\n    function superTransfer(address _to, uint256 _value) internal returns (bool) {\n        return super.transfer(_to, _value);\n    }\n\n    function transfer(address _to, uint256 _value) public returns (bool) {\n        require(superTransfer(_to, _value));\n        callAfterTransfer(msg.sender, _to, _value);\n        return true;\n    }\n\n    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {\n        require(super.transferFrom(_from, _to, _value));\n        callAfterTransfer(_from, _to, _value);\n        return true;\n    }\n\n    /**\n     * @dev Internal function that calls onTokenTransfer callback on the receiver after the successful transfer.\n     * Since it is not present in the original ERC677 standard, the callback is only called on the bridge contract,\n     * in order to simplify UX. In other cases, this token complies with the ERC677/ERC20 standard.\n     * @param _from tokens sender address.\n     * @param _to tokens receiver address.\n     * @param _value amount of sent tokens.\n     */\n    function callAfterTransfer(address _from, address _to, uint256 _value) internal {\n        if (isBridge(_to)) {\n            require(contractFallback(_from, _to, _value, new bytes(0)));\n        }\n    }\n\n    function isBridge(address _address) public view returns (bool) {\n        return _address == bridgeContractAddr;\n    }\n\n    /**\n     * @dev call onTokenTransfer fallback on the token recipient contract\n     * @param _from tokens sender\n     * @param _to tokens recipient\n     * @param _value amount of tokens that was sent\n     * @param _data set of extra bytes that can be passed to the recipient\n     */\n    function contractFallback(address _from, address _to, uint256 _value, bytes _data) private returns (bool) {\n        return _to.call(abi.encodeWithSelector(ON_TOKEN_TRANSFER, _from, _value, _data));\n    }\n\n    function finishMinting() public returns (bool) {\n        revert();\n    }\n\n    function renounceOwnership() public onlyOwner {\n        revert();\n    }\n\n    /**\n     * @dev Withdraws the erc20 tokens or native coins from this contract.\n     * @param _token address of the claimed token or address(0) for native coins.\n     * @param _to address of the tokens/coins receiver.\n     */\n    function claimTokens(address _token, address _to) external onlyOwner {\n        claimValues(_token, _to);\n    }\n\n    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {\n        return super.increaseApproval(spender, addedValue);\n    }\n\n    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {\n        return super.decreaseApproval(spender, subtractedValue);\n    }\n}\n\n// File: contracts/PermittableToken.sol\n\npragma solidity 0.4.24;\n\n\ncontract PermittableToken is ERC677BridgeToken {\n    string public constant version = \"1\";\n\n    // EIP712 niceties\n    bytes32 public DOMAIN_SEPARATOR;\n    // bytes32 public constant PERMIT_TYPEHASH_LEGACY = keccak256(\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\");\n    bytes32 public constant PERMIT_TYPEHASH_LEGACY = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;\n    // bytes32 public constant PERMIT_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n    bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n    mapping(address => uint256) public nonces;\n    mapping(address => mapping(address => uint256)) public expirations;\n\n    constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _chainId)\n        public\n        ERC677BridgeToken(_name, _symbol, _decimals)\n    {\n        require(_chainId != 0);\n        DOMAIN_SEPARATOR = keccak256(\n            abi.encode(\n                keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                keccak256(bytes(_name)),\n                keccak256(bytes(version)),\n                _chainId,\n                address(this)\n            )\n        );\n    }\n\n    /// @dev transferFrom in this contract works in a slightly different form than the generic\n    /// transferFrom function. This contract allows for \"unlimited approval\".\n    /// Should the user approve an address for the maximum uint256 value,\n    /// then that address will have unlimited approval until told otherwise.\n    /// @param _sender The address of the sender.\n    /// @param _recipient The address of the recipient.\n    /// @param _amount The value to transfer.\n    /// @return Success status.\n    function transferFrom(address _sender, address _recipient, uint256 _amount) public returns (bool) {\n        require(_sender != address(0));\n        require(_recipient != address(0));\n\n        balances[_sender] = balances[_sender].sub(_amount);\n        balances[_recipient] = balances[_recipient].add(_amount);\n        emit Transfer(_sender, _recipient, _amount);\n\n        if (_sender != msg.sender) {\n            uint256 allowedAmount = allowance(_sender, msg.sender);\n\n            if (allowedAmount != uint256(-1)) {\n                // If allowance is limited, adjust it.\n                // In this case `transferFrom` works like the generic\n                allowed[_sender][msg.sender] = allowedAmount.sub(_amount);\n                emit Approval(_sender, msg.sender, allowed[_sender][msg.sender]);\n            } else {\n                // If allowance is unlimited by `permit`, `approve`, or `increaseAllowance`\n                // function, don't adjust it. But the expiration date must be empty or in the future\n                require(expirations[_sender][msg.sender] == 0 || expirations[_sender][msg.sender] >= now);\n            }\n        } else {\n            // If `_sender` is `msg.sender`,\n            // the function works just like `transfer()`\n        }\n\n        callAfterTransfer(_sender, _recipient, _amount);\n        return true;\n    }\n\n    /// @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.\n    /// @param _to The address which will spend the funds.\n    /// @param _value The amount of tokens to be spent.\n    function approve(address _to, uint256 _value) public returns (bool result) {\n        _approveAndResetExpirations(msg.sender, _to, _value);\n        return true;\n    }\n\n    /// @dev Atomically increases the allowance granted to spender by the caller.\n    /// @param _to The address which will spend the funds.\n    /// @param _addedValue The amount of tokens to increase the allowance by.\n    function increaseAllowance(address _to, uint256 _addedValue) public returns (bool result) {\n        _approveAndResetExpirations(msg.sender, _to, allowed[msg.sender][_to].add(_addedValue));\n        return true;\n    }\n\n    /// @dev An alias for `transfer` function.\n    /// @param _to The address of the recipient.\n    /// @param _amount The value to transfer.\n    function push(address _to, uint256 _amount) public {\n        transferFrom(msg.sender, _to, _amount);\n    }\n\n    /// @dev Makes a request to transfer the specified amount\n    /// from the specified address to the caller's address.\n    /// @param _from The address of the holder.\n    /// @param _amount The value to transfer.\n    function pull(address _from, uint256 _amount) public {\n        transferFrom(_from, msg.sender, _amount);\n    }\n\n    /// @dev An alias for `transferFrom` function.\n    /// @param _from The address of the sender.\n    /// @param _to The address of the recipient.\n    /// @param _amount The value to transfer.\n    function move(address _from, address _to, uint256 _amount) public {\n        transferFrom(_from, _to, _amount);\n    }\n\n    /// @dev Allows to spend holder's unlimited amount by the specified spender.\n    /// The function can be called by anyone, but requires having allowance parameters\n    /// signed by the holder according to EIP712.\n    /// @param _holder The holder's address.\n    /// @param _spender The spender's address.\n    /// @param _nonce The nonce taken from `nonces(_holder)` public getter.\n    /// @param _expiry The allowance expiration date (unix timestamp in UTC).\n    /// Can be zero for no expiration. Forced to zero if `_allowed` is `false`.\n    /// Note that timestamps are not precise, malicious miner/validator can manipulate them to some extend.\n    /// Assume that there can be a 900 seconds time delta between the desired timestamp and the actual expiration.\n    /// @param _allowed True to enable unlimited allowance for the spender by the holder. False to disable.\n    /// @param _v A final byte of signature (ECDSA component).\n    /// @param _r The first 32 bytes of signature (ECDSA component).\n    /// @param _s The second 32 bytes of signature (ECDSA component).\n    function permit(\n        address _holder,\n        address _spender,\n        uint256 _nonce,\n        uint256 _expiry,\n        bool _allowed,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) external {\n        require(_expiry == 0 || now <= _expiry);\n\n        bytes32 digest = _digest(abi.encode(PERMIT_TYPEHASH_LEGACY, _holder, _spender, _nonce, _expiry, _allowed));\n\n        require(_holder == _recover(digest, _v, _r, _s));\n        require(_nonce == nonces[_holder]++);\n\n        uint256 amount = _allowed ? uint256(-1) : 0;\n\n        expirations[_holder][_spender] = _allowed ? _expiry : 0;\n\n        _approve(_holder, _spender, amount);\n    }\n\n    /** @dev Allows to spend holder's unlimited amount by the specified spender according to EIP2612.\n     * The function can be called by anyone, but requires having allowance parameters\n     * signed by the holder according to EIP712.\n     * @param _holder The holder's address.\n     * @param _spender The spender's address.\n     * @param _value Allowance value to set as a result of the call.\n     * @param _deadline The deadline timestamp to call the permit function. Must be a timestamp in the future.\n     * Note that timestamps are not precise, malicious miner/validator can manipulate them to some extend.\n     * Assume that there can be a 900 seconds time delta between the desired timestamp and the actual expiration.\n     * @param _v A final byte of signature (ECDSA component).\n     * @param _r The first 32 bytes of signature (ECDSA component).\n     * @param _s The second 32 bytes of signature (ECDSA component).\n     */\n    function permit(\n        address _holder,\n        address _spender,\n        uint256 _value,\n        uint256 _deadline,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) external {\n        require(now <= _deadline);\n\n        uint256 nonce = nonces[_holder]++;\n        bytes32 digest = _digest(abi.encode(PERMIT_TYPEHASH, _holder, _spender, _value, nonce, _deadline));\n\n        require(_holder == _recover(digest, _v, _r, _s));\n\n        _approveAndResetExpirations(_holder, _spender, _value);\n    }\n\n    /**\n     * @dev Sets a new allowance value for the given owner and spender addresses.\n     * Resets expiration timestamp in case of unlimited approval.\n     * @param _owner address tokens holder.\n     * @param _spender address of tokens spender.\n     * @param _amount amount of approved tokens.\n     */\n    function _approveAndResetExpirations(address _owner, address _spender, uint256 _amount) internal {\n        _approve(_owner, _spender, _amount);\n\n        // it is not necessary to reset _expirations in other cases, since it is only used together with infinite allowance\n        if (_amount == uint256(-1)) {\n            delete expirations[_owner][_spender];\n        }\n    }\n\n    /**\n     * @dev Internal function for issuing an allowance.\n     * @param _owner address of the tokens owner.\n     * @param _spender address of the approved tokens spender.\n     * @param _amount amount of the approved tokens.\n     */\n    function _approve(address _owner, address _spender, uint256 _amount) internal {\n        require(_owner != address(0), \"ERC20: approve from the zero address\");\n        require(_spender != address(0), \"ERC20: approve to the zero address\");\n\n        allowed[_owner][_spender] = _amount;\n        emit Approval(_owner, _spender, _amount);\n    }\n\n    /**\n     * @dev Calculates the message digest for encoded EIP712 typed struct.\n     * @param _typedStruct encoded payload.\n     */\n    function _digest(bytes memory _typedStruct) internal view returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", DOMAIN_SEPARATOR, keccak256(_typedStruct)));\n    }\n\n    /**\n     * @dev Derives the signer address for the given message digest and ECDSA signature params.\n     * @param _digest signed message digest.\n     * @param _v a final byte of signature (ECDSA component).\n     * @param _r the first 32 bytes of the signature (ECDSA component).\n     * @param _s the second 32 bytes of the signature (ECDSA component).\n     */\n    function _recover(bytes32 _digest, uint8 _v, bytes32 _r, bytes32 _s) internal pure returns (address) {\n        require(_v == 27 || _v == 28, \"ECDSA: invalid signature 'v' value\");\n        require(\n            uint256(_s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,\n            \"ECDSA: invalid signature 's' value\"\n        );\n\n        address signer = ecrecover(_digest, _v, _r, _s);\n        require(signer != address(0), \"ECDSA: invalid signature\");\n\n        return signer;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}