ETH Price: $2,919.51 (-8.66%)
 

Overview

ETH Balance

0.058 ETH

Eth Value

$169.33 (@ $2,919.51/ETH)

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Add New User154471082022-08-31 14:20:24886 days ago1661955624IN
0x0e41113a...87208Bf5F
0 ETH0.0140308318
Add New User153671542022-08-18 20:40:58898 days ago1660855258IN
0x0e41113a...87208Bf5F
0 ETH0.0077949110
Add New User153080212022-08-09 12:34:57908 days ago1660048497IN
0x0e41113a...87208Bf5F
0 ETH0.004676876
Add New User151868082022-07-21 15:49:58927 days ago1658418598IN
0x0e41113a...87208Bf5F
0 ETH0.0194872725
Add New User151853312022-07-21 10:18:54927 days ago1658398734IN
0x0e41113a...87208Bf5F
0 ETH0.0077949110
Add New User150954982022-07-07 12:39:26941 days ago1657197566IN
0x0e41113a...87208Bf5F
0 ETH0.0163693121
Add New User150691342022-07-03 10:51:39945 days ago1656845499IN
0x0e41113a...87208Bf5F
0 ETH0.005456437
Add New User150070532022-06-22 9:53:21956 days ago1655891601IN
0x0e41113a...87208Bf5F
0 ETH0.0109128714
Add New User146950562022-05-02 0:09:491007 days ago1651450189IN
0x0e41113a...87208Bf5F
0 ETH0.04287255
Add New User145180402022-04-04 6:59:151035 days ago1649055555IN
0x0e41113a...87208Bf5F
0 ETH0.0288411637
Add New User144874992022-03-30 12:13:391040 days ago1648642419IN
0x0e41113a...87208Bf5F
0 ETH0.0280616736
Add New User144109562022-03-18 14:21:041052 days ago1647613264IN
0x0e41113a...87208Bf5F
0 ETH0.0452104758
Add New User143792732022-03-13 16:12:491057 days ago1647187969IN
0x0e41113a...87208Bf5F
0 ETH0.0350770945
Add New User143729302022-03-12 16:11:201058 days ago1647101480IN
0x0e41113a...87208Bf5F
0 ETH0.025723233
Add New User143594012022-03-10 13:41:221060 days ago1646919682IN
0x0e41113a...87208Bf5F
0 ETH0.0202667626
Add New User142854752022-02-27 2:14:381071 days ago1645928078IN
0x0e41113a...87208Bf5F
0 ETH0.0413130253
Add New User141783502022-02-10 12:29:021088 days ago1644496142IN
0x0e41113a...87208Bf5F
0 ETH0.0545643770
Add New User138930622021-12-28 9:59:281132 days ago1640685568IN
0x0e41113a...87208Bf5F
0 ETH0.0522250967
Add New User138663342021-12-24 6:38:481136 days ago1640327928IN
0x0e41113a...87208Bf5F
0 ETH0.060020877
Add New User138484422021-12-21 12:10:581139 days ago1640088658IN
0x0e41113a...87208Bf5F
0 ETH0.0436514956
Add New User137635782021-12-08 7:42:511152 days ago1638949371IN
0x0e41113a...87208Bf5F
0 ETH0.0639182682
Add New User136411052021-11-18 19:12:081171 days ago1637262728IN
0x0e41113a...87208Bf5F
0 ETH0.14576481187
Add New User135656422021-11-06 22:28:281183 days ago1636237708IN
0x0e41113a...87208Bf5F
0 ETH0.08886197114
Add New User135454402021-11-03 18:18:571187 days ago1635963537IN
0x0e41113a...87208Bf5F
0 ETH0.15355972197
Add New User134443182021-10-18 21:59:041202 days ago1634594344IN
0x0e41113a...87208Bf5F
0 ETH0.09977484128
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
115412032020-12-28 8:09:291497 days ago1609142969
0x0e41113a...87208Bf5F
0.029 ETH
115412032020-12-28 8:09:291497 days ago1609142969
0x0e41113a...87208Bf5F
0.029 ETH
115411972020-12-28 8:08:311497 days ago1609142911
0x0e41113a...87208Bf5F
0.041 ETH
115411972020-12-28 8:08:311497 days ago1609142911
0x0e41113a...87208Bf5F
0.041 ETH
115411972020-12-28 8:08:311497 days ago1609142911
0x0e41113a...87208Bf5F
0.041 ETH
115411972020-12-28 8:08:311497 days ago1609142911
0x0e41113a...87208Bf5F
0.041 ETH
115411932020-12-28 8:07:071497 days ago1609142827
0x0e41113a...87208Bf5F
0.041 ETH
115411932020-12-28 8:07:071497 days ago1609142827
0x0e41113a...87208Bf5F
0.041 ETH
115411932020-12-28 8:07:071497 days ago1609142827
0x0e41113a...87208Bf5F
0.041 ETH
115411932020-12-28 8:07:071497 days ago1609142827
0x0e41113a...87208Bf5F
0.041 ETH
115411882020-12-28 8:06:041497 days ago1609142764
0x0e41113a...87208Bf5F
0.074 ETH
115411882020-12-28 8:06:041497 days ago1609142764
0x0e41113a...87208Bf5F
0.074 ETH
115411882020-12-28 8:06:041497 days ago1609142764
0x0e41113a...87208Bf5F
0.074 ETH
115411882020-12-28 8:06:041497 days ago1609142764
0x0e41113a...87208Bf5F
0.074 ETH
115411882020-12-28 8:06:041497 days ago1609142764
0x0e41113a...87208Bf5F
0.074 ETH
115411882020-12-28 8:06:041497 days ago1609142764
0x0e41113a...87208Bf5F
0.074 ETH
115363252020-12-27 14:23:381498 days ago1609079018
0x0e41113a...87208Bf5F
0.03333406 ETH
115363252020-12-27 14:23:381498 days ago1609079018
0x0e41113a...87208Bf5F
0.03333406 ETH
115043602020-12-22 16:26:081503 days ago1608654368
0x0e41113a...87208Bf5F
0.42131904 ETH
115043602020-12-22 16:26:081503 days ago1608654368
0x0e41113a...87208Bf5F
0.42131904 ETH
114548422020-12-15 2:14:051510 days ago1607998445
0x0e41113a...87208Bf5F
0.03333406 ETH
114548422020-12-15 2:14:051510 days ago1607998445
0x0e41113a...87208Bf5F
0.03333406 ETH
112512872020-11-13 19:42:381541 days ago1605296558
0x0e41113a...87208Bf5F
0.045 ETH
112512872020-11-13 19:42:381541 days ago1605296558
0x0e41113a...87208Bf5F
0.045 ETH
112066742020-11-06 23:08:521548 days ago1604704132
0x0e41113a...87208Bf5F
0.052 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ExchangeV3

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-06-30
*/

// File: contracts/utils/LoggingErrors.sol

pragma solidity ^0.4.11;

/**
 * @title Log Various Error Types
 * @author Adam Lemmon <[email protected]>
 * @dev Inherit this contract and your may now log errors easily
 * To support various error types, params, etc.
 */
contract LoggingErrors {
  /**
  * Events
  */
  event LogErrorString(string errorString);

  /**
  * Error cases
  */

  /**
   * @dev Default error to simply log the error message and return
   * @param _errorMessage The error message to log
   * @return ALWAYS false
   */
  function error(string _errorMessage) internal returns(bool) {
    emit LogErrorString(_errorMessage);
    return false;
  }
}

// File: contracts/wallet/WalletConnector.sol

pragma solidity ^0.4.15;


/**
 * @title Wallet Connector
 * @dev Connect the wallet contract to the correct Wallet Logic version
 */
contract WalletConnector is LoggingErrors {
  /**
   * Storage
   */
  address public owner_;
  address public latestLogic_;
  uint256 public latestVersion_;
  mapping(uint256 => address) public logicVersions_;
  uint256 public birthBlock_;

  /**
   * Events
   */
  event LogLogicVersionAdded(uint256 version);
  event LogLogicVersionRemoved(uint256 version);

  /**
   * @dev Constructor to set the latest logic address
   * @param _latestVersion Latest version of the wallet logic
   * @param _latestLogic Latest address of the wallet logic contract
   */
  function WalletConnector (
    uint256 _latestVersion,
    address _latestLogic
  ) public {
    owner_ = msg.sender;
    latestLogic_ = _latestLogic;
    latestVersion_ = _latestVersion;
    logicVersions_[_latestVersion] = _latestLogic;
    birthBlock_ = block.number;
  }

  /**
   * Add a new version of the logic contract
   * @param _version The version to be associated with the new contract.
   * @param _logic New logic contract.
   * @return Success of the transaction.
   */
  function addLogicVersion (
    uint256 _version,
    address _logic
  ) external
    returns(bool)
  {
    if (msg.sender != owner_)
      return error('msg.sender != owner, WalletConnector.addLogicVersion()');

    if (logicVersions_[_version] != 0)
      return error('Version already exists, WalletConnector.addLogicVersion()');

    // Update latest if this is the latest version
    if (_version > latestVersion_) {
      latestLogic_ = _logic;
      latestVersion_ = _version;
    }

    logicVersions_[_version] = _logic;
    LogLogicVersionAdded(_version);

    return true;
  }

  /**
   * @dev Remove a version. Cannot remove the latest version.
   * @param  _version The version to remove.
   */
  function removeLogicVersion(uint256 _version) external {
    require(msg.sender == owner_);
    require(_version != latestVersion_);
    delete logicVersions_[_version];
    LogLogicVersionRemoved(_version);
  }

  /**
   * Constants
   */

  /**
   * Called from user wallets in order to upgrade their logic.
   * @param _version The version to upgrade to. NOTE pass in 0 to upgrade to latest.
   * @return The address of the logic contract to upgrade to.
   */
  function getLogic(uint256 _version)
    external
    constant
    returns(address)
  {
    if (_version == 0)
      return latestLogic_;
    else
      return logicVersions_[_version];
  }
}

// File: contracts/token/ERC20Interface.sol

pragma solidity ^0.4.11;

interface Token {
  /// @return total amount of tokens
  function totalSupply() external constant returns (uint256 supply);

  /// @param _owner The address from which the balance will be retrieved
  /// @return The balance
  function balanceOf(address _owner) external constant returns (uint256 balance);

  /// @notice send `_value` token to `_to` from `msg.sender`
  /// @param _to The address of the recipient
  /// @param _value The amount of token to be transferred
  /// @return Whether the transfer was successful or not
  function transfer(address _to, uint256 _value) external returns (bool success);

  /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
  /// @param _from The address of the sender
  /// @param _to The address of the recipient
  /// @param _value The amount of token to be transferred
  /// @return Whether the transfer was successful or not
  function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);

  /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
  /// @param _spender The address of the account able to transfer the tokens
  /// @param _value The amount of wei to be approved for transfer
  /// @return Whether the approval was successful or not
  function approve(address _spender, uint256 _value) external returns (bool success);

  /// @param _owner The address of the account owning tokens
  /// @param _spender The address of the account able to transfer the tokens
  /// @return Amount of remaining tokens allowed to spent
  function allowance(address _owner, address _spender) external constant returns (uint256 remaining);

  event Transfer(address indexed _from, address indexed _to, uint256 _value);
  event Approval(address indexed _owner, address indexed _spender, uint256 _value);

  function decimals() external constant returns(uint);
  function name() external constant returns(string);
}

// File: contracts/wallet/WalletV3.sol

pragma solidity ^0.4.15;




/**
 * @title Wallet to hold and trade ERC20 tokens and ether
 * @dev User wallet to interact with the exchange.
 * all tokens and ether held in this wallet, 1 to 1 mapping to user EOAs.
 */
contract WalletV3 is LoggingErrors {
  /**
   * Storage
   */
  // Vars included in wallet logic "lib", the order must match between Wallet and Logic
  address public owner_;
  address public exchange_;
  mapping(address => uint256) public tokenBalances_;

  address public logic_; // storage location 0x3 loaded for delegatecalls so this var must remain at index 3
  uint256 public birthBlock_;

  WalletConnector private connector_;

  /**
   * Events
   */
  event LogDeposit(address token, uint256 amount, uint256 balance);
  event LogWithdrawal(address token, uint256 amount, uint256 balance);

  /**
   * @dev Contract constructor. Set user as owner and connector address.
   * @param _owner The address of the user's EOA, wallets created from the exchange
   * so must past in the owner address, msg.sender == exchange.
   * @param _connector The wallet connector to be used to retrieve the wallet logic
   */
  constructor(address _owner, address _connector, address _exchange) public {
    owner_ = _owner;
    connector_ = WalletConnector(_connector);
    exchange_ = _exchange;
    logic_ = connector_.latestLogic_();
    birthBlock_ = block.number;
  }

  function () external payable {}

  /**
  * External
  */

  /**
   * @dev Deposit ether into this wallet, default to address 0 for consistent token lookup.
   */
  function depositEther()
    external
    payable
  {
    require(
      logic_.delegatecall(abi.encodeWithSignature('deposit(address,uint256)', 0, msg.value)),
      "depositEther() failed"
    );
  }

  /**
   * @dev Deposit any ERC20 token into this wallet.
   * @param _token The address of the existing token contract.
   * @param _amount The amount of tokens to deposit.
   * @return Bool if the deposit was successful.
   */
  function depositERC20Token (
    address _token,
    uint256 _amount
  ) external
    returns(bool)
  {
    // ether
    if (_token == 0)
      return error('Cannot deposit ether via depositERC20, Wallet.depositERC20Token()');

    require(
      logic_.delegatecall(abi.encodeWithSignature('deposit(address,uint256)', _token, _amount)),
      "depositERC20Token() failed"
    );
    return true;
  }

  /**
   * @dev The result of an order, update the balance of this wallet.
   * param _token The address of the token balance to update.
   * param _amount The amount to update the balance by.
   * param _subtractionFlag If true then subtract the token amount else add.
   * @return Bool if the update was successful.
   */
  function updateBalance (
    address /*_token*/,
    uint256 /*_amount*/,
    bool /*_subtractionFlag*/
  ) external
    returns(bool)
  {
    assembly {
      calldatacopy(0x40, 0, calldatasize)
      delegatecall(gas, sload(0x3), 0x40, calldatasize, 0, 32)
      return(0, 32)
      pop
    }
  }

  /**
   * User may update to the latest version of the exchange contract.
   * Note that multiple versions are NOT supported at this time and therefore if a
   * user does not wish to update they will no longer be able to use the exchange.
   * @param _exchange The new exchange.
   * @return Success of this transaction.
   */
  function updateExchange(address _exchange)
    external
    returns(bool)
  {
    if (msg.sender != owner_)
      return error('msg.sender != owner_, Wallet.updateExchange()');

    // If subsequent messages are not sent from this address all orders will fail
    exchange_ = _exchange;

    return true;
  }

  /**
   * User may update to a new or older version of the logic contract.
   * @param _version The versin to update to.
   * @return Success of this transaction.
   */
  function updateLogic(uint256 _version)
    external
    returns(bool)
  {
    if (msg.sender != owner_)
      return error('msg.sender != owner_, Wallet.updateLogic()');

    address newVersion = connector_.getLogic(_version);

    // Invalid version as defined by connector
    if (newVersion == 0)
      return error('Invalid version, Wallet.updateLogic()');

    logic_ = newVersion;
    return true;
  }

  /**
   * @dev Verify an order that the Exchange has received involving this wallet.
   * Internal checks and then authorize the exchange to move the tokens.
   * If sending ether will transfer to the exchange to broker the trade.
   * param _token The address of the token contract being sold.
   * param _amount The amount of tokens the order is for.
   * param _fee The fee for the current trade.
   * param _feeToken The token of which the fee is to be paid in.
   * @return If the order was verified or not.
   */
  function verifyOrder (
    address /*_token*/,
    uint256 /*_amount*/,
    uint256 /*_fee*/,
    address /*_feeToken*/
  ) external
    returns(bool)
  {
    assembly {
      calldatacopy(0x40, 0, calldatasize)
      delegatecall(gas, sload(0x3), 0x40, calldatasize, 0, 32)
      return(0, 32)
      pop
    }
  }

  /**
   * @dev Withdraw any token, including ether from this wallet to an EOA.
   * param _token The address of the token to withdraw.
   * param _amount The amount to withdraw.
   * @return Success of the withdrawal.
   */
  function withdraw(address /*_token*/, uint256 /*_amount*/)
    external
    returns(bool)
  {
    if(msg.sender != owner_)
      return error('msg.sender != owner, Wallet.withdraw()');

    assembly {
      calldatacopy(0x40, 0, calldatasize)
      delegatecall(gas, sload(0x3), 0x40, calldatasize, 0, 32)
      return(0, 32)
      pop
    }
  }

  /**
   * Constants
   */

  /**
   * @dev Get the balance for a specific token.
   * @param _token The address of the token contract to retrieve the balance of.
   * @return The current balance within this contract.
   */
  function balanceOf(address _token)
    public
    view
    returns(uint)
  {
    if (_token == address(0)) {
      return address(this).balance;
    } else {
      return Token(_token).balanceOf(this);
    }
  }

  function walletVersion() external pure returns(uint){
    return 3;
  }
}

// File: contracts/wallet/WalletBuilderInterface.sol

pragma solidity ^0.4.15;



/**
 * @title Wallet to hold and trade ERC20 tokens and ether
 */
interface WalletBuilderInterface {

  /**
   * @dev build a new trading wallet and returns its address
   * @param _owner user EOA of the created trading wallet
   * @param _exchange exchange address
   */
  function buildWallet(address _owner, address _exchange) external returns(address);
}

// File: contracts/utils/Ownable.sol

pragma solidity ^0.4.24;

contract Ownable {
  address public owner;

  function Ownable() public {
    owner = msg.sender;
  }

  modifier onlyOwner() {
    require(msg.sender == owner, "msg.sender != owner");
    _;
  }

  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0), "newOwner == 0");
    owner = newOwner;
  }

}

// File: contracts/utils/SafeMath.sol

pragma solidity ^0.4.11;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws 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;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

// File: contracts/UsersManager.sol

pragma solidity ^0.4.24;







interface RetrieveWalletInterface {
  function retrieveWallet(address userAccount) external returns(address walletAddress);
}

contract UsersManager is Ownable, RetrieveWalletInterface {
  mapping(address => address) public userAccountToWallet_; // User EOA to wallet addresses
  WalletBuilderInterface public walletBuilder;
  RetrieveWalletInterface public previousMapping;

  event LogUserAdded(address indexed user, address walletAddress);
  event LogWalletUpgraded(address indexed user, address oldWalletAddress, address newWalletAddress);
  event LogWalletBuilderChanged(address newWalletBuilder);

  constructor (
    address _previousMappingAddress,
    address _walletBuilder
  ) public {
    require(_walletBuilder != address (0), "WalletConnector address == 0");
    previousMapping = RetrieveWalletInterface(_previousMappingAddress);
    walletBuilder = WalletBuilderInterface(_walletBuilder);
  }

  /**
   * External
   */

  /**
   * @dev Returns the Wallet contract address associated to a user account. If the user account is not known, try to
   * migrate the wallet address from the old exchange instance. This function is equivalent to getWallet(), in addition
   * it stores the wallet address fetched from old the exchange instance.
   * @param userAccount The user account address
   * @return The address of the Wallet instance associated to the user account
   */
  function retrieveWallet(address userAccount)
    public
    returns(address walletAddress)
  {
    walletAddress = userAccountToWallet_[userAccount];
    if (walletAddress == address(0) && address(previousMapping) != address(0)) {
      // Retrieve the wallet address from the old exchange.
      walletAddress = previousMapping.retrieveWallet(userAccount);

      if (walletAddress != address(0)) {
        userAccountToWallet_[userAccount] = walletAddress;
      }
    }
  }

  /**
 * @dev Private implementation for addNewUser function. Add a new user
 * into the exchange, create a wallet for them.
 * Map their account address to the wallet contract for lookup.
 * @param userExternalOwnedAccount The address of the user"s EOA.
 * @param exchangeAddress The address of the exchange smart contract.
 * @return the created trading wallet address.
 */
  function __addNewUser(address userExternalOwnedAccount, address exchangeAddress)
    private
    returns (address)
  {
    address userTradingWallet = walletBuilder.buildWallet(userExternalOwnedAccount, exchangeAddress);
    userAccountToWallet_[userExternalOwnedAccount] = userTradingWallet;
    emit LogUserAdded(userExternalOwnedAccount, userTradingWallet);
    return userTradingWallet;
  }

  /**
   * @dev Add a new user to the exchange, create a wallet for them.
   * Map their account address to the wallet contract for lookup.
   * @param userExternalOwnedAccount The address of the user"s EOA.
   * @return Success of the transaction, false if error condition met.
   */
  function addNewUser(address userExternalOwnedAccount)
    public
    returns (bool)
  {
    require (
      retrieveWallet(userExternalOwnedAccount) == address(0),
      "User already exists, Exchange.addNewUser()"
    );

    // Create a new wallet passing EOA for owner and msg.sender for exchange. If the caller of this function is not the
    // exchange, the trading wallet is not operable and requires an updateExchange()
    __addNewUser(userExternalOwnedAccount, msg.sender);
    return true;
  }

  /**
   * @dev Recreate the trading wallet for the user calling the function.
   */
  function upgradeWallet() external
  {
    address oldWallet = retrieveWallet(msg.sender);
    require(
      oldWallet != address(0),
      "User does not exists yet, Exchange.upgradeWallet()"
    );
    address exchange = WalletV3(oldWallet).exchange_();
    address userTradingWallet = __addNewUser(msg.sender, exchange);
    emit LogWalletUpgraded(msg.sender, oldWallet, userTradingWallet);
  }

  /**
   * @dev Administratively changes the wallet address for a specific EOA.
   */
  function adminSetWallet(address userExternalOwnedAccount, address userTradingWallet)
    onlyOwner
    external
  {
    address oldWallet = retrieveWallet(userExternalOwnedAccount);
    userAccountToWallet_[userExternalOwnedAccount] = userTradingWallet;
    emit LogUserAdded(userExternalOwnedAccount, userTradingWallet);
    if (oldWallet != address(0)) {
      emit LogWalletUpgraded(userExternalOwnedAccount, oldWallet, userTradingWallet);
    }
  }

  /**
   * @dev Add a new user to the exchange, create a wallet for them.
   * Map their account address to the wallet contract for lookup.
   * @param newWalletBuilder The address of the new wallet builder
   * @return Success of the transaction, false if error condition met.
   */
  function setWalletBuilder(address newWalletBuilder)
    public
    onlyOwner
    returns (bool)
  {
    require(newWalletBuilder != address(0), "setWalletBuilder(): newWalletBuilder == 0");
    walletBuilder = WalletBuilderInterface(newWalletBuilder);
    emit LogWalletBuilderChanged(walletBuilder);
    return true;
  }
}

// File: contracts/utils/SafeERC20.sol

pragma solidity ^0.4.11;


interface BadERC20 {
  function transfer(address to, uint value) external;
  function transferFrom(address from, address to, uint256 value) external;
  function approve(address spender, uint value) external;
}

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeERC20 {

  event LogWarningNonZeroAllowance(address token, address spender, uint256 allowance);

  /**
   * @dev Wrapping the ERC20 transfer function to avoid missing returns.
   * @param _token The address of bad formed ERC20 token.
   * @param _to Transfer receiver.
   * @param _amount Amount to be transfered.
   * @return Success of the safeTransfer.
   */

  function safeTransfer(
    address _token,
    address _to,
    uint _amount
  )
  internal
  returns (bool result)
  {
    BadERC20(_token).transfer(_to, _amount);

    assembly {
      switch returndatasize()
      case 0 {                      // This is our BadToken
        result := not(0)            // result is true
      }
      case 32 {                     // This is our GoodToken
        returndatacopy(0, 0, 32)
        result := mload(0)          // result == returndata of external call
      }
      default {                     // This is not an ERC20 token
        revert(0, 0)
      }
    }
  }


  /**
   * @dev Wrapping the ERC20 transferFrom function to avoid missing returns.
   * @param _token The address of bad formed ERC20 token.
   * @param _from Transfer sender.
   * @param _to Transfer receiver.
   * @param _value Amount to be transfered.
   * @return Success of the safeTransferFrom.
   */

  function safeTransferFrom(
    address _token,
    address _from,
    address _to,
    uint256 _value
  )
  internal
  returns (bool result)
  {
    BadERC20(_token).transferFrom(_from, _to, _value);

    assembly {
      switch returndatasize()
      case 0 {                      // This is our BadToken
        result := not(0)            // result is true
      }
      case 32 {                     // This is our GoodToken
        returndatacopy(0, 0, 32)
        result := mload(0)          // result == returndata of external call
      }
      default {                     // This is not an ERC20 token
        revert(0, 0)
      }
    }
  }

  function checkAndApprove(
    address _token,
    address _spender,
    uint256 _value
  )
  internal
  returns (bool result)
  {
    uint currentAllowance = Token(_token).allowance(this, _spender);
    if (currentAllowance > 0) {
      emit LogWarningNonZeroAllowance(_token, _spender, currentAllowance);
      // no check required for approve because it eventually will fail in the second approve
      safeApprove(_token, _spender, 0);
    }
    return safeApprove(_token, _spender, _value);
  }
  /**
   * @dev Wrapping the ERC20 approve function to avoid missing returns.
   * @param _token The address of bad formed ERC20 token.
   * @param _spender Spender address.
   * @param _value Amount allowed to be spent.
   * @return Success of the safeApprove.
   */

  function safeApprove(
    address _token,
    address _spender,
    uint256 _value
  )
  internal
  returns (bool result)
  {
    BadERC20(_token).approve(_spender, _value);

    assembly {
      switch returndatasize()
      case 0 {                      // This is our BadToken
        result := not(0)            // result is true
      }
      case 32 {                     // This is our GoodToken
        returndatacopy(0, 0, 32)
        result := mload(0)          // result == returndata of external call
      }
      default {                     // This is not an ERC20 token
        revert(0, 0)
      }
    }
  }
}

// File: contracts/ExchangeV3.sol

pragma solidity ^0.4.24;






/**
 * @title Decentralized exchange for ether and ERC20 tokens.
 * @author Eidoo SAGL.
 * @dev All trades brokered by this contract.
 * Orders submitted by off chain order book and this contract handles
 * verification and execution of orders.
 * All value between parties is transferred via this exchange.
 * Methods arranged by visibility; external, public, internal, private and alphabatized within.
 *
 * New Exchange SC with eventually no fee and ERC20 tokens as quote
 */
contract ExchangeV3 {

  using SafeMath for uint256;

  /**
   * Data Structures
   */
  struct Order {
    address offerToken_;
    uint256 offerTokenTotal_;
    uint256 offerTokenRemaining_;  // Amount left to give
    address wantToken_;
    uint256 wantTokenTotal_;
    uint256 wantTokenReceived_;  // Amount received, note this may exceed want total
  }

  struct OrderStatus {
    uint256 expirationBlock_;
    uint256 wantTokenReceived_;    // Amount received, note this may exceed want total
    uint256 offerTokenRemaining_;  // Amount left to give
  }

  struct Orders {
    Order makerOrder;
    Order takerOrder;
    bool isMakerBuy;
  }

  struct FeeRate {
    uint256 edoPerQuote;
    uint256 edoPerQuoteDecimals;
  }

  struct Balances {
    uint256 makerWantTokenBalance;
    uint256 makerOfferTokenBalance;
    uint256 takerWantTokenBalance;
    uint256 takerOfferTokenBalance;
  }

  struct TradingWallets {
    WalletV3 maker;
    WalletV3 taker;
  }

  struct TradingAmounts {
    uint256 toTaker;
    uint256 toMaker;
    uint256 fee;
  }

  struct OrdersHashes {
    bytes32 makerOrder;
    bytes32 takerOrder;
  }

  /**
   * Storage
   */
  address private orderBookAccount_;
  address public owner_;
  address public feeManager_;
  uint256 public birthBlock_;
  address public edoToken_;
  uint256 public dustLimit = 100;

  mapping (address => uint256) public feeEdoPerQuote;
  mapping (address => uint256) public feeEdoPerQuoteDecimals;

  address public eidooWallet_;

  // Define if fee calculation must be skipped for a given trade. By default (false) fee must not be skipped.
  mapping(address => mapping(address => FeeRate)) public customFee;
  // whitelist of EOA that should not pay fee
  mapping(address => bool) public feeTakersWhitelist;

  /**
   * @dev Define in a trade who is the quote using a priority system:
   * values example
   *   0: not used as quote
   *  >0: used as quote
   *  if wanted and offered tokens have value > 0 the quote is the token with the bigger value
   */
  mapping(address => uint256) public quotePriority;

  mapping(bytes32 => OrderStatus) public orders_; // Map order hashes to order data struct
  UsersManager public users;

  /**
   * Events
   */
  event LogFeeRateSet(address indexed token, uint256 rate, uint256 decimals);
  event LogQuotePrioritySet(address indexed quoteToken, uint256 priority);
  event LogCustomFeeSet(address indexed base, address indexed quote, uint256 edoPerQuote, uint256 edoPerQuoteDecimals);
  event LogFeeTakersWhitelistSet(address takerEOA, bool value);
  event LogWalletDeposit(address indexed walletAddress, address token, uint256 amount, uint256 balance);
  event LogWalletWithdrawal(address indexed walletAddress, address token, uint256 amount, uint256 balance);
  event LogWithdraw(address recipient, address token, uint256 amount);

  event LogOrderExecutionSuccess(
    bytes32 indexed makerOrderId,
    bytes32 indexed takerOrderId,
    uint256 toMaker,
    uint256 toTaker
  );
  event LogBatchOrderExecutionFailed(
    bytes32 indexed makerOrderId,
    bytes32 indexed takerOrderId,
    uint256 position
  );
  event LogOrderFilled(bytes32 indexed orderId, uint256 totalOfferRemaining, uint256 totalWantReceived);

  /**
   * @dev Contract constructor - CONFIRM matches contract name.  Set owner and addr of order book.
   * @param _bookAccount The EOA address for the order book, will submit ALL orders.
   * @param _edoToken Deployed edo token.
   * @param _edoPerWei Rate of edo tokens per wei.
   * @param _edoPerWeiDecimals Decimlas carried in edo rate.
   * @param _eidooWallet Wallet to pay fees to.
   * @param _usersMapperAddress Previous exchange smart contract address.
   */
  constructor (
    address _bookAccount,
    address _edoToken,
    uint256 _edoPerWei,
    uint256 _edoPerWeiDecimals,
    address _eidooWallet,
    address _usersMapperAddress
  ) public {
    orderBookAccount_ = _bookAccount;
    owner_ = msg.sender;
    birthBlock_ = block.number;
    edoToken_ = _edoToken;
    feeEdoPerQuote[address(0)] = _edoPerWei;
    feeEdoPerQuoteDecimals[address(0)] = _edoPerWeiDecimals;
    eidooWallet_ = _eidooWallet;
    quotePriority[address(0)] = 10;
    setUsersMapper(_usersMapperAddress);
  }

  /**
   * @dev Fallback. wallets utilize to send ether in order to broker trade.
   */
  function () external payable { }

  modifier onlyOwner() {
    require (
      msg.sender == owner_,
      "msg.sender != owner"
    );
    _;
  }

  function setUsersMapper(address _userMapperAddress)
    public
    onlyOwner
    returns (bool)
  {
    require(_userMapperAddress != address(0), "_userMapperAddress == 0");
    users = UsersManager(_userMapperAddress);
    return true;
  }

  function setFeeManager(address feeManager)
    public
    onlyOwner
  {
    feeManager_ = feeManager;
  }

  function setDustLimit(uint limit)
    public
    onlyOwner
  {
    dustLimit = limit;
  }

  /**
   * @dev Add a new user to the exchange, create a wallet for them.
   * Map their account address to the wallet contract for lookup.
   * @param userExternalOwnedAccount The address of the user"s EOA.
   * @return Success of the transaction, false if error condition met.
   */
  function addNewUser(address userExternalOwnedAccount)
    external
    returns (bool)
  {
    return users.addNewUser(userExternalOwnedAccount);
  }

  /**
   * @dev For backward compatibility.
   * @param userExternalOwnedAccount The address of the user's EOA.
   * @return The address of the trading wallet
   */
  function userAccountToWallet_(address userExternalOwnedAccount) external returns(address)
  {
    return users.retrieveWallet(userExternalOwnedAccount);
  }

  function retrieveWallet(address userExternalOwnedAccount)
    external
    returns(address)
  {
    return users.retrieveWallet(userExternalOwnedAccount);
  }

  /**
   * Execute orders in batches.
   * @param ownedExternalAddressesAndTokenAddresses Tokan and user addresses.
   * @param amountsExpirationsAndSalts Offer and want token amount and expiration and salt values.
   * @param vSignatures All order signature v values.
   * @param rAndSsignatures All order signature r and r values.
   * @return The success of this transaction.
   */
  function batchExecuteOrder(
    address[4][] ownedExternalAddressesAndTokenAddresses,
    uint256[8][] amountsExpirationsAndSalts, // Packing to save stack size
    uint8[2][] vSignatures,
    bytes32[4][] rAndSsignatures
  ) external
    returns(bool)
  {
    require(
      msg.sender == orderBookAccount_,
      "msg.sender != orderBookAccount, Exchange.batchExecuteOrder()"
    );

    for (uint256 i = 0; i < amountsExpirationsAndSalts.length; i++) {
      // TODO: the following 3 lines requires solc 0.5.0
//      bytes memory payload = abi.encodeWithSignature("executeOrder(address[4],uint256[8],uint8[2],bytes32[4])",
//        ownedExternalAddressesAndTokenAddresses[i],
//        amountsExpirationsAndSalts[i],
//        vSignatures[i],
//        rAndSsignatures[i]
//      );
//      (bool success, bytes memory returnData) = address(this).call(payload);
//      if (!success || !bool(returnData)) {
      bool success = address(this).call(abi.encodeWithSignature("executeOrder(address[4],uint256[8],uint8[2],bytes32[4])",
        ownedExternalAddressesAndTokenAddresses[i],
        amountsExpirationsAndSalts[i],
        vSignatures[i],
        rAndSsignatures[i]
      ));
      if (!success) {
        OrdersHashes memory hashes = __generateOrderHashes__(
          ownedExternalAddressesAndTokenAddresses[i],
          amountsExpirationsAndSalts[i]
        );
        emit LogBatchOrderExecutionFailed(hashes.makerOrder, hashes.takerOrder, i);
      }
    }

    return true;
  }

  /**
   * @dev Execute an order that was submitted by the external order book server.
   * The order book server believes it to be a match.
   * There are components for both orders, maker and taker, 2 signatures as well.
   * @param ownedExternalAddressesAndTokenAddresses The maker and taker external owned accounts addresses and offered tokens contracts.
   * [
   *   makerEOA
   *   makerOfferToken
   *   takerEOA
   *   takerOfferToken
   * ]
   * @param amountsExpirationsAndSalts The amount of tokens and the block number at which this order expires and a random number to mitigate replay.
   * [
   *   makerOffer
   *   makerWant
   *   takerOffer
   *   takerWant
   *   makerExpiry
   *   makerSalt
   *   takerExpiry
   *   takerSalt
   * ]
   * @param vSignatures ECDSA signature parameter.
   * [
   *   maker V
   *   taker V
   * ]
   * @param rAndSsignatures ECDSA signature parameters r ans s, maker 0, 1 and taker 2, 3.
   * [
   *   maker R
   *   maker S
   *   taker R
   *   taker S
   * ]
   * @return Success of the transaction, false if error condition met.
   * Like types grouped to eliminate stack depth error.
   */
  function executeOrder (
    address[4] ownedExternalAddressesAndTokenAddresses,
    uint256[8] amountsExpirationsAndSalts, // Packing to save stack size
    uint8[2] vSignatures,
    bytes32[4] rAndSsignatures
  ) public
    returns(bool)
  {
    // get users trading wallets and check if they exist
    TradingWallets memory wallets =
      getMakerAndTakerTradingWallets(ownedExternalAddressesAndTokenAddresses);

    // Basic pre-conditions, return if any input data is invalid
    __executeOrderInputIsValid__(
      ownedExternalAddressesAndTokenAddresses,
      amountsExpirationsAndSalts
    );

    // Verify Maker and Taker signatures
    OrdersHashes memory hashes = __generateOrderHashes__(
      ownedExternalAddressesAndTokenAddresses,
      amountsExpirationsAndSalts
    );

    // Check maker order signature
    require(
      __signatureIsValid__(
      ownedExternalAddressesAndTokenAddresses[0],
        hashes.makerOrder,
        vSignatures[0],
        rAndSsignatures[0],
        rAndSsignatures[1]
      ),
      "Maker signature is invalid, Exchange.executeOrder()"
    );

    // Check taker order signature
    require(__signatureIsValid__(
        ownedExternalAddressesAndTokenAddresses[2],
        hashes.takerOrder,
        vSignatures[1],
        rAndSsignatures[2],
        rAndSsignatures[3]
      ),
      "Taker signature is invalid, Exchange.executeOrder()"
    );

    // Exchange Order Verification and matching
    Orders memory orders = __getOrders__(ownedExternalAddressesAndTokenAddresses, amountsExpirationsAndSalts, hashes);

    // Trade amounts and fee
    TradingAmounts memory amounts = __getTradeAmounts__(orders, ownedExternalAddressesAndTokenAddresses[2]);

    require(
      amounts.toTaker > 0 && amounts.toMaker > 0,
      "Token amount < 1, price ratio is invalid! Token value < 1, Exchange.executeOrder()"
    );

    // Update orders status
    orders.makerOrder.offerTokenRemaining_ = orders.makerOrder.offerTokenRemaining_.sub(amounts.toTaker);
    orders.makerOrder.wantTokenReceived_ = orders.makerOrder.wantTokenReceived_.add(amounts.toMaker);

    orders.takerOrder.offerTokenRemaining_ = orders.takerOrder.offerTokenRemaining_.sub(amounts.toMaker);
    orders.takerOrder.wantTokenReceived_ = orders.takerOrder.wantTokenReceived_.add(amounts.toTaker);

    // Write orders status to storage. If the remaining to trade in the order is below the limit,
    // cleanup the storage marking the order as completed.
    uint limit = dustLimit;
    if ((orders.makerOrder.offerTokenRemaining_ <= limit) ||
        (orders.isMakerBuy && (orders.makerOrder.wantTokenReceived_ + limit) >= orders.makerOrder.wantTokenTotal_)
    ) {
      orders_[hashes.makerOrder].offerTokenRemaining_ = 0;
      orders_[hashes.makerOrder].wantTokenReceived_ = 0;
    } else {
      orders_[hashes.makerOrder].offerTokenRemaining_ = orders.makerOrder.offerTokenRemaining_;
      orders_[hashes.makerOrder].wantTokenReceived_ = orders.makerOrder.wantTokenReceived_;
    }

    if ((orders.takerOrder.offerTokenRemaining_ <= limit) ||
        (!orders.isMakerBuy && (orders.takerOrder.wantTokenReceived_ + limit) >= orders.takerOrder.wantTokenTotal_)
    ) {
      orders_[hashes.takerOrder].offerTokenRemaining_ = 0;
      orders_[hashes.takerOrder].wantTokenReceived_ = 0;
    } else {
      orders_[hashes.takerOrder].offerTokenRemaining_ = orders.takerOrder.offerTokenRemaining_;
      orders_[hashes.takerOrder].wantTokenReceived_ = orders.takerOrder.wantTokenReceived_;
    }

    // Transfer the external value, ether <> tokens
    __executeTokenTransfer__(
      ownedExternalAddressesAndTokenAddresses,
      amounts,
      wallets
    );

    // Log the order id(hash), amount of offer given, amount of offer remaining
    emit LogOrderFilled(hashes.makerOrder, orders.makerOrder.offerTokenRemaining_, orders.makerOrder.wantTokenReceived_);
    emit LogOrderFilled(hashes.takerOrder, orders.takerOrder.offerTokenRemaining_, orders.takerOrder.wantTokenReceived_);
    emit LogOrderExecutionSuccess(hashes.makerOrder, hashes.takerOrder, amounts.toMaker, amounts.toTaker);

    return true;
  }

  /**
   * @dev Set the fee rate for a specific quote
   * @param _quoteToken Quote token.
   * @param _edoPerQuote EdoPerQuote.
   * @param _edoPerQuoteDecimals EdoPerQuoteDecimals.
   * @return Success of the transaction.
   */
  function setFeeRate(
    address _quoteToken,
    uint256 _edoPerQuote,
    uint256 _edoPerQuoteDecimals
  ) external
    returns(bool)
  {
    require(
      msg.sender == owner_ || msg.sender == feeManager_,
      "msg.sender != owner, Exchange.setFeeRate()"
    );

    require(
      quotePriority[_quoteToken] != 0,
      "quotePriority[_quoteToken] == 0, Exchange.setFeeRate()"
    );

    feeEdoPerQuote[_quoteToken] = _edoPerQuote;
    feeEdoPerQuoteDecimals[_quoteToken] = _edoPerQuoteDecimals;

    emit LogFeeRateSet(_quoteToken, _edoPerQuote, _edoPerQuoteDecimals);

    return true;
  }

  /**
   * @dev Set the wallet for fees to be paid to.
   * @param eidooWallet Wallet to pay fees to.
   * @return Success of the transaction.
   */
  function setEidooWallet(
    address eidooWallet
  ) external
    returns(bool)
  {
    require(
      msg.sender == owner_,
      "msg.sender != owner, Exchange.setEidooWallet()"
    );
    eidooWallet_ = eidooWallet;
    return true;
  }

  /**
   * @dev Set a new order book account.
   * @param account The new order book account.
   */
  function setOrderBookAcount (
    address account
  ) external
    returns(bool)
  {
    require(
      msg.sender == owner_,
      "msg.sender != owner, Exchange.setOrderBookAcount()"
    );
    orderBookAccount_ = account;
    return true;
  }

  /**
   * @dev Set custom fee for a pair. If both _edoPerQuote and _edoPerQuoteDecimals are 0 there is no custom fee.
   *      If _edoPerQuote is 0 and _edoPerQuoteDecimals is greater than 0 the resulting fee rate is 0 (disable fee for the pair).
   * @param _baseTokenAddress The trade base token address that must skip fee calculation.
   * @param _quoteTokenAddress The trade quote token address that must skip fee calculation.
   * @param _edoPerQuote Rate
   * @param _edoPerQuoteDecimals Rate decimals
   */
  function setCustomFee (
    address _baseTokenAddress,
    address _quoteTokenAddress,
    uint256 _edoPerQuote,
    uint256 _edoPerQuoteDecimals
  ) external
    returns(bool)
  {
    // Preserving same owner check style
    require(
      msg.sender == owner_ || msg.sender == feeManager_,
      "msg.sender != owner, Exchange.setCustomFee()"
    );
    if (_edoPerQuote == 0 && _edoPerQuoteDecimals == 0) {
      delete customFee[_baseTokenAddress][_quoteTokenAddress];
    } else {
      customFee[_baseTokenAddress][_quoteTokenAddress] = FeeRate({
        edoPerQuote: _edoPerQuote,
        edoPerQuoteDecimals: _edoPerQuoteDecimals
      });
    }
    emit LogCustomFeeSet(_baseTokenAddress, _quoteTokenAddress, _edoPerQuote, _edoPerQuoteDecimals);
    return true;
  }

  /**
   *  For backward compatibility
   */
  function mustSkipFee(address base, address quote) external view returns(bool) {
    FeeRate storage rate = customFee[base][quote];
    return rate.edoPerQuote == 0 && rate.edoPerQuoteDecimals != 0;
  }

  /**
   * @dev Set a taker EOA in the fees whitelist
   * @param _takerEOA EOA address of the taker
   * @param _value true if the take should not pay fees
   *
   */
  function setFeeTakersWhitelist(
    address _takerEOA,
    bool _value
  ) external
    returns(bool)
  {
    require(
      msg.sender == owner_,
      "msg.sender != owner, Exchange.setFeeTakersWhitelist()"
    );
    feeTakersWhitelist[_takerEOA] = _value;
    emit LogFeeTakersWhitelistSet(_takerEOA, _value);
    return true;
  }

  /**
   * @dev Set quote priority token.
   * Set the sorting of token quote based on a priority.
   * @param _token The address of the token that was deposited.
   * @param _priority The amount of the token that was deposited.
   * @return Operation success.
   */

  function setQuotePriority(address _token, uint256 _priority)
    external
    returns(bool)
  {
    require(
      msg.sender == owner_,
      "msg.sender != owner, Exchange.setQuotePriority()"
    );
    quotePriority[_token] = _priority;
    emit LogQuotePrioritySet(_token, _priority);
    return true;
  }

  /*
   Methods to catch events from external contracts, user wallets primarily
   */

  /**
   * @dev DEPRECATED!
   * Simply log the event to track wallet interaction off-chain.
   * @param tokenAddress The address of the token that was deposited.
   * @param amount The amount of the token that was deposited.
   * @param tradingWalletBalance The updated balance of the wallet after deposit.
   */
  function walletDeposit(
    address tokenAddress,
    uint256 amount,
    uint256 tradingWalletBalance
  ) external
  {
    emit LogWalletDeposit(msg.sender, tokenAddress, amount, tradingWalletBalance);
  }

  /**
   * @dev DEPRECATED!
   * Simply log the event to track wallet interaction off-chain.
   * @param tokenAddress The address of the token that was deposited.
   * @param amount The amount of the token that was deposited.
   * @param tradingWalletBalance The updated balance of the wallet after deposit.
   */
  function walletWithdrawal(
    address tokenAddress,
    uint256 amount,
    uint256 tradingWalletBalance
  ) external
  {
    emit LogWalletWithdrawal(msg.sender, tokenAddress, amount, tradingWalletBalance);
  }

  /**
   * Private
   */

  /**
   * @dev Convenient function to resolve call stack size error in ExchangeV3
   * @param ownedExternalAddressesAndTokenAddresses -
   */
  function getMakerAndTakerTradingWallets(address[4] ownedExternalAddressesAndTokenAddresses)
    private
    returns (TradingWallets wallets)
  {
    wallets = TradingWallets(
      WalletV3(users.retrieveWallet(ownedExternalAddressesAndTokenAddresses[0])), // maker
      WalletV3(users.retrieveWallet(ownedExternalAddressesAndTokenAddresses[2])) // taker
    );

    // Operating on existing tradingWallets
    require(
      wallets.maker != address(0),
      "Maker wallet does not exist, Exchange.getMakerAndTakerTradingWallets()"
    );

    require(
      wallets.taker != address(0),
      "Taker wallet does not exist, Exchange.getMakerAndTakerTradingWallets()"
    );
  }

  function calculateFee(
    address base,
    address quote,
    uint256 quoteAmount,
    address takerEOA
  ) public
    view
    returns(uint256)
  {
    require(quotePriority[quote] > quotePriority[base], "Invalid pair");
    return __calculateFee__(base, quote, quoteAmount, takerEOA);
  }

  function __calculateFee__(
    address base,
    address quote,
    uint256 quoteAmount,
    address takerEOA
  )
    internal view returns(uint256)
  {
    FeeRate memory fee;
    if (feeTakersWhitelist[takerEOA]) {
      return 0;
    }

    // weiAmount * (fee %) * (EDO/Wei) / (decimals in edo/wei) / (decimals in percentage)
      fee = customFee[base][quote];
      if (fee.edoPerQuote == 0 && fee.edoPerQuoteDecimals == 0) {
        // no custom fee
        fee.edoPerQuote = feeEdoPerQuote[quote];
        fee.edoPerQuoteDecimals = feeEdoPerQuoteDecimals[quote];
      }
      return quoteAmount.mul(fee.edoPerQuote).div(10**fee.edoPerQuoteDecimals);
  }

  /**
   * @dev Verify the input to order execution is valid.
   * @param ownedExternalAddressesAndTokenAddresses The maker and taker external owned accounts addresses and offered tokens contracts.
   * [
   *   makerEOA
   *   makerOfferToken
   *   takerEOA
   *   takerOfferToken
   * ]
   * @param amountsExpirationsAndSalts The amount of tokens and the block number at which this order expires and a random number to mitigate replay.
   * [
   *   makerOffer
   *   makerWant
   *   takerOffer
   *   takerWant
   *   makerExpiry
   *   makerSalt
   *   takerExpiry
   *   takerSalt
   * ]
   * @return Success if all checks pass.
   */
  function __executeOrderInputIsValid__(
    address[4] ownedExternalAddressesAndTokenAddresses,
    uint256[8] amountsExpirationsAndSalts
  ) private view
  {
    // msg.send needs to be the orderBookAccount
    require(
      msg.sender == orderBookAccount_ || msg.sender == address(this),
      "msg.sender != orderBookAccount, Exchange.__executeOrderInputIsValid__()"
    );

    // Check expirations base on the block number
    require (
      block.number <= amountsExpirationsAndSalts[4],
      "Maker order has expired, Exchange.__executeOrderInputIsValid__()"
    );

    require(
      block.number <= amountsExpirationsAndSalts[6],
      "Taker order has expired, Exchange.__executeOrderInputIsValid__()"
    );

    require(
      quotePriority[ownedExternalAddressesAndTokenAddresses[1]] != quotePriority[ownedExternalAddressesAndTokenAddresses[3]],
      "Quote token is omitted! Is not offered by either the Taker or Maker, Exchange.__executeOrderInputIsValid__()"
    );

    // Check that none of the amounts is = to 0
    if (
        amountsExpirationsAndSalts[0] == 0 ||
        amountsExpirationsAndSalts[1] == 0 ||
        amountsExpirationsAndSalts[2] == 0 ||
        amountsExpirationsAndSalts[3] == 0
      )
    {
      revert("May not execute an order where token amount == 0, Exchange.__executeOrderInputIsValid__()");
    }
  }

  function __getBalance__(address token, address owner) private view returns(uint256) {
    if (token == address(0)) {
      return owner.balance;
    } else {
      return Token(token).balanceOf(owner);
    }
  }

  /**
   * @dev Execute the external transfer of tokens.
   * @param ownedExternalAddressesAndTokenAddresses The maker and taker external owned accounts addresses and offered tokens contracts.
   * [
   *   makerEOA
   *   makerOfferToken
   *   takerEOA
   *   takerOfferToken
   * ]
   * @param amounts The amount of tokens to transfer.
   * @return Success if both wallets verify the order.
   */
  function __executeTokenTransfer__(
    address[4] ownedExternalAddressesAndTokenAddresses,
    TradingAmounts amounts,
    TradingWallets wallets
  ) private
  {

    // Get balances. Must be taken before trading wallet verifyOrder() call because it can transfer ethers
    Balances memory initialBalances;
    initialBalances.takerOfferTokenBalance = __getBalance__(ownedExternalAddressesAndTokenAddresses[3], wallets.taker);
    initialBalances.makerOfferTokenBalance = __getBalance__(ownedExternalAddressesAndTokenAddresses[1], wallets.maker);
    initialBalances.takerWantTokenBalance = __getBalance__(ownedExternalAddressesAndTokenAddresses[1], wallets.taker);
    initialBalances.makerWantTokenBalance = __getBalance__(ownedExternalAddressesAndTokenAddresses[3], wallets.maker);
    //    initialBalances.takerFeeTokenBalance = __getBalance__(edoToken_, wallets.taker);


    // Wallet Order Verification, reach out to the maker and taker wallets. Approve the tokens and transfer ethers
    // to the exchange contract
    require(
      wallets.maker.verifyOrder(
        ownedExternalAddressesAndTokenAddresses[1],
        amounts.toTaker,
        0,
        0
      ),
      "Maker wallet could not prepare the transfer, Exchange.__executeTokenTransfer__()"
    );

    require(
      wallets.taker.verifyOrder(
        ownedExternalAddressesAndTokenAddresses[3],
        amounts.toMaker,
        amounts.fee,
        edoToken_
      ),
      "Taker wallet could not prepare the transfer, Exchange.__executeTokenTransfer__()"
    );

    // Wallet mapping balances
    address makerOfferTokenAddress = ownedExternalAddressesAndTokenAddresses[1];
    address takerOfferTokenAddress = ownedExternalAddressesAndTokenAddresses[3];

    WalletV3 makerTradingWallet = wallets.maker;
    WalletV3 takerTradingWallet = wallets.taker;

    // Taker to pay fee before trading
    if(amounts.fee != 0) {
      uint256 takerInitialFeeTokenBalance = Token(edoToken_).balanceOf(takerTradingWallet);

      require(
        Token(edoToken_).transferFrom(takerTradingWallet, eidooWallet_, amounts.fee),
        "Cannot transfer fees from taker trading wallet to eidoo wallet, Exchange.__executeTokenTransfer__()"
      );
      require(
        Token(edoToken_).balanceOf(takerTradingWallet) == takerInitialFeeTokenBalance.sub(amounts.fee),
        "Wrong fee token balance after transfer, Exchange.__executeTokenTransfer__()"
      );
    }

    // Ether to the taker and tokens to the maker
    if (makerOfferTokenAddress == address(0)) {
      address(takerTradingWallet).transfer(amounts.toTaker);
    } else {
      require(
        SafeERC20.safeTransferFrom(makerOfferTokenAddress, makerTradingWallet, takerTradingWallet, amounts.toTaker),
        "Token transfership from makerTradingWallet to takerTradingWallet failed, Exchange.__executeTokenTransfer__()"
      );
    }

    if (takerOfferTokenAddress == address(0)) {
      address(makerTradingWallet).transfer(amounts.toMaker);
    } else {
      require(
        SafeERC20.safeTransferFrom(takerOfferTokenAddress, takerTradingWallet, makerTradingWallet, amounts.toMaker),
        "Token transfership from takerTradingWallet to makerTradingWallet failed, Exchange.__executeTokenTransfer__()"
      );
    }

    // Check balances
    Balances memory expected;
    if (takerTradingWallet != makerTradingWallet) {
      expected.makerWantTokenBalance = initialBalances.makerWantTokenBalance.add(amounts.toMaker);
      expected.makerOfferTokenBalance = initialBalances.makerOfferTokenBalance.sub(amounts.toTaker);
      expected.takerWantTokenBalance = edoToken_ == makerOfferTokenAddress
        ? initialBalances.takerWantTokenBalance.add(amounts.toTaker).sub(amounts.fee)
        : initialBalances.takerWantTokenBalance.add(amounts.toTaker);
      expected.takerOfferTokenBalance = edoToken_ == takerOfferTokenAddress
        ? initialBalances.takerOfferTokenBalance.sub(amounts.toMaker).sub(amounts.fee)
        : initialBalances.takerOfferTokenBalance.sub(amounts.toMaker);
    } else {
      expected.makerWantTokenBalance = expected.takerOfferTokenBalance =
        edoToken_ == takerOfferTokenAddress
        ? initialBalances.takerOfferTokenBalance.sub(amounts.fee)
        : initialBalances.takerOfferTokenBalance;
      expected.makerOfferTokenBalance = expected.takerWantTokenBalance =
        edoToken_ == makerOfferTokenAddress
        ? initialBalances.takerWantTokenBalance.sub(amounts.fee)
        : initialBalances.takerWantTokenBalance;
    }

    require(
      expected.takerOfferTokenBalance == __getBalance__(takerOfferTokenAddress, takerTradingWallet),
      "Wrong taker offer token balance after transfer, Exchange.__executeTokenTransfer__()"
    );
    require(
      expected.makerOfferTokenBalance == __getBalance__(makerOfferTokenAddress, makerTradingWallet),
      "Wrong maker offer token balance after transfer, Exchange.__executeTokenTransfer__()"
    );
    require(
      expected.takerWantTokenBalance == __getBalance__(makerOfferTokenAddress, takerTradingWallet),
      "Wrong taker want token balance after transfer, Exchange.__executeTokenTransfer__()"
    );
    require(
      expected.makerWantTokenBalance == __getBalance__(takerOfferTokenAddress, makerTradingWallet),
      "Wrong maker want token balance after transfer, Exchange.__executeTokenTransfer__()"
    );
  }

  /**
   * @dev Calculates Keccak-256 hash of order with specified parameters.
   * @param ownedExternalAddressesAndTokenAddresses The orders maker EOA and current exchange address.
   * @param amountsExpirationsAndSalts The orders offer and want amounts and expirations with salts.
   * @return Keccak-256 hash of the passed order.
   */
  function generateOrderHashes(
    address[4] ownedExternalAddressesAndTokenAddresses,
    uint256[8] amountsExpirationsAndSalts
  ) public
    view
    returns (bytes32[2])
  {
    OrdersHashes memory hashes = __generateOrderHashes__(
      ownedExternalAddressesAndTokenAddresses,
      amountsExpirationsAndSalts
    );
    return [hashes.makerOrder, hashes.takerOrder];
  }

  function __generateOrderHashes__(
    address[4] ownedExternalAddressesAndTokenAddresses,
    uint256[8] amountsExpirationsAndSalts
  ) internal
    view
    returns (OrdersHashes)
  {
    bytes32 makerOrderHash = keccak256(abi.encodePacked(
      address(this),
      ownedExternalAddressesAndTokenAddresses[0], // _makerEOA
      ownedExternalAddressesAndTokenAddresses[1], // offerToken
      amountsExpirationsAndSalts[0],  // offerTokenAmount
      ownedExternalAddressesAndTokenAddresses[3], // wantToken
      amountsExpirationsAndSalts[1],  // wantTokenAmount
      amountsExpirationsAndSalts[4], // expiry
      amountsExpirationsAndSalts[5] // salt
    ));

    bytes32 takerOrderHash = keccak256(abi.encodePacked(
      address(this),
      ownedExternalAddressesAndTokenAddresses[2], // _makerEOA
      ownedExternalAddressesAndTokenAddresses[3], // offerToken
      amountsExpirationsAndSalts[2],  // offerTokenAmount
      ownedExternalAddressesAndTokenAddresses[1], // wantToken
      amountsExpirationsAndSalts[3],  // wantTokenAmount
      amountsExpirationsAndSalts[6], // expiry
      amountsExpirationsAndSalts[7] // salt
    ));

    return OrdersHashes(makerOrderHash, takerOrderHash);
  }

  function __getOrders__(
    address[4] ownedExternalAddressesAndTokenAddresses,
    uint256[8] amountsExpirationsAndSalts,
    OrdersHashes hashes
  ) private
    returns(Orders orders)
  {
    OrderStatus storage makerOrderStatus = orders_[hashes.makerOrder];
    OrderStatus storage takerOrderStatus = orders_[hashes.takerOrder];

    orders.makerOrder.offerToken_ = ownedExternalAddressesAndTokenAddresses[1];
    orders.makerOrder.offerTokenTotal_ = amountsExpirationsAndSalts[0];
    orders.makerOrder.wantToken_ = ownedExternalAddressesAndTokenAddresses[3];
    orders.makerOrder.wantTokenTotal_ = amountsExpirationsAndSalts[1];

    if (makerOrderStatus.expirationBlock_ > 0) {  // Check for existence
      // Orders still active
      require(
        makerOrderStatus.offerTokenRemaining_ != 0,
        "Maker order is inactive, Exchange.executeOrder()"
      );
      orders.makerOrder.offerTokenRemaining_ = makerOrderStatus.offerTokenRemaining_; // Amount to give
      orders.makerOrder.wantTokenReceived_ = makerOrderStatus.wantTokenReceived_; // Amount received
    } else {
      makerOrderStatus.expirationBlock_ = amountsExpirationsAndSalts[4]; // maker order expiration block, persist order on storage
      orders.makerOrder.offerTokenRemaining_ = amountsExpirationsAndSalts[0]; // Amount to give
      orders.makerOrder.wantTokenReceived_ = 0; // Amount received
    }

    orders.takerOrder.offerToken_ = ownedExternalAddressesAndTokenAddresses[3];
    orders.takerOrder.offerTokenTotal_ = amountsExpirationsAndSalts[2];
    orders.takerOrder.wantToken_ = ownedExternalAddressesAndTokenAddresses[1];
    orders.takerOrder.wantTokenTotal_ = amountsExpirationsAndSalts[3];

    if (takerOrderStatus.expirationBlock_ > 0) {  // Check for existence
      require(
        takerOrderStatus.offerTokenRemaining_ != 0,
        "Taker order is inactive, Exchange.executeOrder()"
      );
      orders.takerOrder.offerTokenRemaining_ = takerOrderStatus.offerTokenRemaining_;  // Amount to give
      orders.takerOrder.wantTokenReceived_ = takerOrderStatus.wantTokenReceived_; // Amount received
    } else {
      takerOrderStatus.expirationBlock_ = amountsExpirationsAndSalts[6]; // taker order expiration block, persist order on storage
      orders.takerOrder.offerTokenRemaining_ = amountsExpirationsAndSalts[2];  // Amount to give
      orders.takerOrder.wantTokenReceived_ = 0; // Amount received
    }

    orders.isMakerBuy = __isSell__(orders.takerOrder);
  }

  /**
   * @dev Returns a bool representing a SELL or BUY order based on quotePriority.
   * @param _order The maker order data structure.
   * @return The bool indicating if the order is a SELL or BUY.
   */
  function __isSell__(Order _order) internal view returns (bool) {
    return quotePriority[_order.offerToken_] < quotePriority[_order.wantToken_];
  }

  /**
   * @dev Compute the tradeable amounts of the two verified orders.
   * Token amount is the __min__ remaining between want and offer of the two orders that isn"t ether.
   * Ether amount is then: etherAmount = tokenAmount * priceRatio, as ratio = eth / token.
   * @param orders The maker and taker orders data structure.
   * @return The amount moving from makerOfferRemaining to takerWantRemaining and vice versa.
   */
  function __getTradeAmounts__(
    Orders memory orders,
    address takerEOA
  ) internal
    view
    returns (TradingAmounts)
  {
    Order memory makerOrder = orders.makerOrder;
    Order memory takerOrder = orders.takerOrder;
    bool isMakerBuy = orders.isMakerBuy;  // maker buy = taker sell
    uint256 priceRatio;
    uint256 makerAmountLeftToReceive;
    uint256 takerAmountLeftToReceive;

    uint toTakerAmount;
    uint toMakerAmount;

    if (makerOrder.offerTokenTotal_ >= makerOrder.wantTokenTotal_) {
      priceRatio = makerOrder.offerTokenTotal_.mul(2**128).div(makerOrder.wantTokenTotal_);
      require(
        priceRatio >= takerOrder.wantTokenTotal_.mul(2**128).div(takerOrder.offerTokenTotal_),
        "Taker price is greater than maker price, Exchange.__getTradeAmounts__()"
      );
      if (isMakerBuy) {
        // MP > 1
        makerAmountLeftToReceive = makerOrder.wantTokenTotal_.sub(makerOrder.wantTokenReceived_);
        toMakerAmount = __min__(takerOrder.offerTokenRemaining_, makerAmountLeftToReceive);
        // add 2**128-1 in order to obtain a round up
        toTakerAmount = toMakerAmount.mul(priceRatio).div(2**128);
      } else {
        // MP < 1
        takerAmountLeftToReceive = takerOrder.wantTokenTotal_.sub(takerOrder.wantTokenReceived_);
        toTakerAmount = __min__(makerOrder.offerTokenRemaining_, takerAmountLeftToReceive);
        toMakerAmount = toTakerAmount.mul(2**128).div(priceRatio);
      }
    } else {
      priceRatio = makerOrder.wantTokenTotal_.mul(2**128).div(makerOrder.offerTokenTotal_);
      require(
        priceRatio <= takerOrder.offerTokenTotal_.mul(2**128).div(takerOrder.wantTokenTotal_),
        "Taker price is less than maker price, Exchange.__getTradeAmounts__()"
      );
      if (isMakerBuy) {
        // MP < 1
        makerAmountLeftToReceive = makerOrder.wantTokenTotal_.sub(makerOrder.wantTokenReceived_);
        toMakerAmount = __min__(takerOrder.offerTokenRemaining_, makerAmountLeftToReceive);
        toTakerAmount = toMakerAmount.mul(2**128).div(priceRatio);
      } else {
        // MP > 1
        takerAmountLeftToReceive = takerOrder.wantTokenTotal_.sub(takerOrder.wantTokenReceived_);
        toTakerAmount = __min__(makerOrder.offerTokenRemaining_, takerAmountLeftToReceive);
        // add 2**128-1 in order to obtain a round up
        toMakerAmount = toTakerAmount.mul(priceRatio).div(2**128);
      }
    }

    uint fee = isMakerBuy
      ? __calculateFee__(makerOrder.wantToken_, makerOrder.offerToken_, toTakerAmount, takerEOA)
      : __calculateFee__(makerOrder.offerToken_, makerOrder.wantToken_, toMakerAmount, takerEOA);

    return TradingAmounts(toTakerAmount, toMakerAmount, fee);
  }

  /**
   * @dev Return the maximum of two uints
   * @param a Uint 1
   * @param b Uint 2
   * @return The grater value or a if equal
   */
  function __max__(uint256 a, uint256 b)
    private
    pure
    returns (uint256)
  {
    return a < b
      ? b
      : a;
  }

  /**
   * @dev Return the minimum of two uints
   * @param a Uint 1
   * @param b Uint 2
   * @return The smallest value or b if equal
   */
  function __min__(uint256 a, uint256 b)
    private
    pure
    returns (uint256)
  {
    return a < b
      ? a
      : b;
  }

  /**
   * @dev On chain verification of an ECDSA ethereum signature.
   * @param signer The EOA address of the account that supposedly signed the message.
   * @param orderHash The on-chain generated hash for the order.
   * @param v ECDSA signature parameter v.
   * @param r ECDSA signature parameter r.
   * @param s ECDSA signature parameter s.
   * @return Bool if the signature is valid or not.
   */
  function __signatureIsValid__(
    address signer,
    bytes32 orderHash,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) private
    pure
    returns (bool)
  {
    address recoveredAddr = ecrecover(
      keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", orderHash)),
      v,
      r,
      s
    );

    return recoveredAddr == signer;
  }

  /**
   * @dev Confirm wallet local balances and token balances match.
   * @param makerTradingWallet  Maker wallet address.
   * @param takerTradingWallet  Taker wallet address.
   * @param token  Token address to confirm balances match.
   * @return If the balances do match.
   */
  function __tokenAndWalletBalancesMatch__(
    address makerTradingWallet,
    address takerTradingWallet,
    address token
  ) private
    view
    returns(bool)
  {
    if (Token(token).balanceOf(makerTradingWallet) != WalletV3(makerTradingWallet).balanceOf(token)) {
      return false;
    }

    if (Token(token).balanceOf(takerTradingWallet) != WalletV3(takerTradingWallet).balanceOf(token)) {
      return false;
    }

    return true;
  }

  /**
 * @dev Withdraw asset.
 * @param _tokenAddress Asset to be withdrawed.
 * @return bool.
 */
  function withdraw(address _tokenAddress)
    public
    onlyOwner
  returns(bool)
  {
    uint tokenBalance;
    if (_tokenAddress == address(0)) {
      tokenBalance = address(this).balance;
      msg.sender.transfer(tokenBalance);
    } else {
      tokenBalance = Token(_tokenAddress).balanceOf(address(this));
      require(
        Token(_tokenAddress).transfer(msg.sender, tokenBalance),
        "withdraw transfer failed"
      );
    }
    emit LogWithdraw(msg.sender, _tokenAddress, tokenBalance);
    return true;
  }

}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"base","type":"address"},{"name":"quote","type":"address"},{"name":"quoteAmount","type":"uint256"},{"name":"takerEOA","type":"address"}],"name":"calculateFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"eidooWallet","type":"address"}],"name":"setEidooWallet","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"quotePriority","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_userMapperAddress","type":"address"}],"name":"setUsersMapper","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"userExternalOwnedAccount","type":"address"}],"name":"retrieveWallet","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"ownedExternalAddressesAndTokenAddresses","type":"address[4]"},{"name":"amountsExpirationsAndSalts","type":"uint256[8]"}],"name":"generateOrderHashes","outputs":[{"name":"","type":"bytes32[2]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"feeManager","type":"address"}],"name":"setFeeManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"ownedExternalAddressesAndTokenAddresses","type":"address[4][]"},{"name":"amountsExpirationsAndSalts","type":"uint256[8][]"},{"name":"vSignatures","type":"uint8[2][]"},{"name":"rAndSsignatures","type":"bytes32[4][]"}],"name":"batchExecuteOrder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"setOrderBookAcount","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenAddress","type":"address"}],"name":"withdraw","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"},{"name":"tradingWalletBalance","type":"uint256"}],"name":"walletWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_takerEOA","type":"address"},{"name":"_value","type":"bool"}],"name":"setFeeTakersWhitelist","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_priority","type":"uint256"}],"name":"setQuotePriority","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_baseTokenAddress","type":"address"},{"name":"_quoteTokenAddress","type":"address"},{"name":"_edoPerQuote","type":"uint256"},{"name":"_edoPerQuoteDecimals","type":"uint256"}],"name":"setCustomFee","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"edoToken_","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"birthBlock_","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"orders_","outputs":[{"name":"expirationBlock_","type":"uint256"},{"name":"wantTokenReceived_","type":"uint256"},{"name":"offerTokenRemaining_","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeManager_","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"base","type":"address"},{"name":"quote","type":"address"}],"name":"mustSkipFee","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"feeEdoPerQuote","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"limit","type":"uint256"}],"name":"setDustLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"userExternalOwnedAccount","type":"address"}],"name":"userAccountToWallet_","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"eidooWallet_","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"userExternalOwnedAccount","type":"address"}],"name":"addNewUser","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"ownedExternalAddressesAndTokenAddresses","type":"address[4]"},{"name":"amountsExpirationsAndSalts","type":"uint256[8]"},{"name":"vSignatures","type":"uint8[2]"},{"name":"rAndSsignatures","type":"bytes32[4]"}],"name":"executeOrder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"customFee","outputs":[{"name":"edoPerQuote","type":"uint256"},{"name":"edoPerQuoteDecimals","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dustLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"},{"name":"tradingWalletBalance","type":"uint256"}],"name":"walletDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"feeTakersWhitelist","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"feeEdoPerQuoteDecimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner_","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"users","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_quoteToken","type":"address"},{"name":"_edoPerQuote","type":"uint256"},{"name":"_edoPerQuoteDecimals","type":"uint256"}],"name":"setFeeRate","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_bookAccount","type":"address"},{"name":"_edoToken","type":"address"},{"name":"_edoPerWei","type":"uint256"},{"name":"_edoPerWeiDecimals","type":"uint256"},{"name":"_eidooWallet","type":"address"},{"name":"_usersMapperAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"rate","type":"uint256"},{"indexed":false,"name":"decimals","type":"uint256"}],"name":"LogFeeRateSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"quoteToken","type":"address"},{"indexed":false,"name":"priority","type":"uint256"}],"name":"LogQuotePrioritySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"base","type":"address"},{"indexed":true,"name":"quote","type":"address"},{"indexed":false,"name":"edoPerQuote","type":"uint256"},{"indexed":false,"name":"edoPerQuoteDecimals","type":"uint256"}],"name":"LogCustomFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"takerEOA","type":"address"},{"indexed":false,"name":"value","type":"bool"}],"name":"LogFeeTakersWhitelistSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"walletAddress","type":"address"},{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"LogWalletDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"walletAddress","type":"address"},{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"LogWalletWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LogWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"makerOrderId","type":"bytes32"},{"indexed":true,"name":"takerOrderId","type":"bytes32"},{"indexed":false,"name":"toMaker","type":"uint256"},{"indexed":false,"name":"toTaker","type":"uint256"}],"name":"LogOrderExecutionSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"makerOrderId","type":"bytes32"},{"indexed":true,"name":"takerOrderId","type":"bytes32"},{"indexed":false,"name":"position","type":"uint256"}],"name":"LogBatchOrderExecutionFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderId","type":"bytes32"},{"indexed":false,"name":"totalOfferRemaining","type":"uint256"},{"indexed":false,"name":"totalWantReceived","type":"uint256"}],"name":"LogOrderFilled","type":"event"}]

608060405260646005553480156200001657600080fd5b5060405160c080620040818339810160409081528151602080840151928401516060850151608086015160a09096015160008054600160a060020a03808816600160a060020a0319928316178355600180548316331790554360035560048054828b169084161790559180527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f88590557f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df84905560088054928a1692909116919091179055600b909352600a7fdf7de25b7f1fd6d0b5205f0e18f1f35bd7b8d84cce336588d184533ce43a6f765592949092916200011d816401000000006200012a810204565b5050505050505062000244565b600154600090600160a060020a03163314620001a757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f6d73672e73656e64657220213d206f776e657200000000000000000000000000604482015290519081900360640190fd5b600160a060020a03821615156200021f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5f757365724d617070657241646472657373203d3d2030000000000000000000604482015290519081900360640190fd5b50600d8054600160a060020a038316600160a060020a03199091161790556001919050565b613e2d80620002546000396000f3006080604052600436106101875763ffffffff60e060020a6000350416630ac6ab9a81146101895780631d2627bb146101cc5780631e57bc4a146102015780632a5f5a6d146102225780632e16cf541461024357806341832bed14610280578063472d35b9146103245780634983542e146103455780634a8ef4bd1461038957806351cff8d9146103aa57806357b394bf146103cb5780635d79925c146103f257806360bf46ea146104185780636296dd601461043c57806363a3d3831461046957806369820a801461047e5780636e3706f4146104935780637b11b44c146104c95780637fa86906146104de57806384b96e04146105055780639de03baa14610526578063b5f9b5cc14610243578063bd09f1171461053e578063c1d5e84f14610553578063c825ec9714610574578063cd0b302d14610626578063cf71efa914610666578063cfbe2cb31461067b578063defab0a3146106a2578063dff0fae7146106c3578063e7663079146106e4578063f2020275146106f9578063f3182d6c1461070e575b005b34801561019557600080fd5b506101ba600160a060020a036004358116906024358116906044359060643516610735565b60408051918252519081900360200190f35b3480156101d857600080fd5b506101ed600160a060020a03600435166107c4565b604080519115158252519081900360200190f35b34801561020d57600080fd5b506101ba600160a060020a036004351661086e565b34801561022e57600080fd5b506101ed600160a060020a0360043516610880565b34801561024f57600080fd5b50610264600160a060020a0360043516610965565b60408051600160a060020a039092168252519081900360200190f35b34801561028c57600080fd5b506040805160808181019092526102e99136916004916084919083908190839082908082843750506040805161010081810190925294979695818101959450925060089150839083908082843750939650610a0295505050505050565b6040518082600260200280838360005b838110156103115781810151838201526020016102f9565b5050505090500191505060405180910390f35b34801561033057600080fd5b50610187600160a060020a0360043516610a3f565b34801561035157600080fd5b506101ed6024600480358281019290820135918135808301929082013591604435808301929082013591606435918201910135610abe565b34801561039557600080fd5b506101ed600160a060020a0360043516610d91565b3480156103b657600080fd5b506101ed600160a060020a0360043516610e3c565b3480156103d757600080fd5b50610187600160a060020a03600435166024356044356110a4565b3480156103fe57600080fd5b506101ed600160a060020a036004351660243515156110f5565b34801561042457600080fd5b506101ed600160a060020a03600435166024356111d8565b34801561044857600080fd5b506101ed600160a060020a03600435811690602435166044356064356112aa565b34801561047557600080fd5b5061026461141e565b34801561048a57600080fd5b506101ba61142d565b34801561049f57600080fd5b506104ab600435611433565b60408051938452602084019290925282820152519081900360600190f35b3480156104d557600080fd5b50610264611454565b3480156104ea57600080fd5b506101ed600160a060020a0360043581169060243516611463565b34801561051157600080fd5b506101ba600160a060020a03600435166114a4565b34801561053257600080fd5b506101876004356114b6565b34801561054a57600080fd5b5061026461150b565b34801561055f57600080fd5b506101ed600160a060020a036004351661151a565b34801561058057600080fd5b506040805160808181019092526101ed91369160049160849190839081908390829080828437505060408051610100818101909252949796958181019594509250600891508390839080828437505060408051808201825294979695818101959450925060029150839083908082843750506040805160808181019092529497969581810195945092506004915083908390808284375093965061158595505050505050565b34801561063257600080fd5b5061064d600160a060020a0360043581169060243516611a84565b6040805192835260208301919091528051918290030190f35b34801561067257600080fd5b506101ba611aa8565b34801561068757600080fd5b50610187600160a060020a0360043516602435604435611aae565b3480156106ae57600080fd5b506101ed600160a060020a0360043516611aff565b3480156106cf57600080fd5b506101ba600160a060020a0360043516611b14565b3480156106f057600080fd5b50610264611b26565b34801561070557600080fd5b50610264611b35565b34801561071a57600080fd5b506101ed600160a060020a0360043516602435604435611b44565b600160a060020a038085166000908152600b60205260408082205492861682528120549091106107af576040805160e560020a62461bcd02815260206004820152600c60248201527f496e76616c696420706169720000000000000000000000000000000000000000604482015290519081900360640190fd5b6107bb85858585611cd4565b95945050505050565b600154600090600160a060020a0316331461083d576040805160e560020a62461bcd02815260206004820152602e6024820152600080516020613dc283398151915260448201527f744569646f6f57616c6c65742829000000000000000000000000000000000000606482015290519081900360840190fd5b506008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03831617905560015b919050565b600b6020526000908152604090205481565b600154600090600160a060020a031633146108d3576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b600160a060020a0382161515610933576040805160e560020a62461bcd02815260206004820152601760248201527f5f757365724d617070657241646472657373203d3d2030000000000000000000604482015290519081900360640190fd5b50600d8054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff199091161790556001919050565b600d54604080517f2e16cf54000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015291516000939290921691632e16cf549160248082019260209290919082900301818787803b1580156109d057600080fd5b505af11580156109e4573d6000803e3d6000fd5b505050506040513d60208110156109fa57600080fd5b505192915050565b610a0a613ccc565b610a12613ce7565b610a1c8484611dc5565b604080518082019091528151815260208083015190820152925090505092915050565b600154600160a060020a03163314610a8f576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000806000610acb613ce7565b600054600160a060020a03163314610b53576040805160e560020a62461bcd02815260206004820152603c60248201527f6d73672e73656e64657220213d206f72646572426f6f6b4163636f756e742c2060448201527f45786368616e67652e6261746368457865637574654f72646572282900000000606482015290519081900360840190fd5b600092505b88831015610d7f57308c8c85818110610b6d57fe5b9050608002018b8b868181101515610b8157fe5b905061010002018a8a878181101515610b9657fe5b9050604002018989888181101515610baa57fe5b9050608002016040516024018085600460200280828437909101905084610100808284379091019050836040808284379091019050826080808284376040805193909101838103601f1901845281526020830180517fc825ec97000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091161781529051835193985096508695509350909150819050838360005b83811015610c74578181015183820152602001610c5c565b50505050905090810190601f168015610ca15780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af193505050811515610d7457610d338c8c85818110610ccd57fe5b9050608002016004806020026040519081016040528092919082600460200280828437508f93508e925088915050818110610d0457fe5b90506101000201600880602002604051908101604052809291908260086020028082843750611dc59350505050565b6020808201518251604080518881529051949550919390927fa5257066aa244148645c1d43997cb8433b8b4a8b2dfd313a887445a0641c578d928290030190a35b600190920191610b58565b5060019b9a5050505050505050505050565b600154600090600160a060020a03163314610e0a576040805160e560020a62461bcd0281526020600482015260326024820152600080516020613dc283398151915260448201527f744f72646572426f6f6b41636f756e7428290000000000000000000000000000606482015290519081900360840190fd5b5060008054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff199091161790556001919050565b6001546000908190600160a060020a03163314610e91576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b600160a060020a0383161515610ed85750604051303190339082156108fc029083906000818181858888f19350505050158015610ed2573d6000803e3d6000fd5b50611053565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a038516916370a082319160248083019260209291908290030181600087803b158015610f3957600080fd5b505af1158015610f4d573d6000803e3d6000fd5b505050506040513d6020811015610f6357600080fd5b5051604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018390529051919250600160a060020a0385169163a9059cbb916044808201926020929091908290030181600087803b158015610fd157600080fd5b505af1158015610fe5573d6000803e3d6000fd5b505050506040513d6020811015610ffb57600080fd5b50511515611053576040805160e560020a62461bcd02815260206004820152601860248201527f7769746864726177207472616e73666572206661696c65640000000000000000604482015290519081900360640190fd5b60408051338152600160a060020a038516602082015280820183905290517f9207361cc2a04b9c7a06691df1eb87c6a63957ae88bf01d0d18c81e3d12720999181900360600190a150600192915050565b60408051600160a060020a038516815260208101849052808201839052905133917fe8d885fd2147a6ac7d644cd3c3a5f2413dbd8e515b61702b1cc1551188176b3c919081900360600190a2505050565b600154600090600160a060020a0316331461116e576040805160e560020a62461bcd0281526020600482015260356024820152600080516020613dc283398151915260448201527f7446656554616b65727357686974656c69737428290000000000000000000000606482015290519081900360840190fd5b600160a060020a0383166000818152600a6020908152604091829020805460ff191686151590811790915582519384529083015280517f7b31b9a94f09da1a1b9b7d74096a88704ffd866e63238327d00ae478b6d1f8ec9281900390910190a15060015b92915050565b600154600090600160a060020a03163314611251576040805160e560020a62461bcd0281526020600482015260306024820152600080516020613dc283398151915260448201527f7451756f74655072696f72697479282900000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0383166000818152600b6020908152604091829020859055815185815291517fadba5bc51f565bc23062c2968481f023e22fd162f18b0146ff7e9393ffd2ed409281900390910190a250600192915050565b600154600090600160a060020a03163314806112d05750600254600160a060020a031633145b151561133a576040805160e560020a62461bcd02815260206004820152602c6024820152600080516020613dc283398151915260448201527f74437573746f6d46656528290000000000000000000000000000000000000000606482015290519081900360840190fd5b82158015611346575081155b1561137e57600160a060020a0380861660009081526009602090815260408083209388168352929052908120818155600101556113c0565b6040805180820182528481526020808201858152600160a060020a03808a16600090815260098452858120918a16815292529290209051815590516001909101555b83600160a060020a031685600160a060020a03167fe0bfbb0947e78f22a90164fbc34fe2b8660310f8a17ab2e225a63ef706a95ba38585604051808381526020018281526020019250505060405180910390a3506001949350505050565b600454600160a060020a031681565b60035481565b600c6020526000908152604090208054600182015460029092015490919083565b600254600160a060020a031681565b600160a060020a0380831660009081526009602090815260408083209385168352929052908120805415801561149c5750600181015415155b949350505050565b60066020526000908152604090205481565b600154600160a060020a03163314611506576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b600555565b600854600160a060020a031681565b600d54604080517fc1d5e84f000000000000000000000000000000000000000000000000000000008152600160a060020a0384811660048301529151600093929092169163c1d5e84f9160248082019260209290919082900301818787803b1580156109d057600080fd5b600061158f613ce7565b611597613ce7565b61159f613cfe565b6115a7613d2d565b60006115b28a61203b565b94506115be8a8a6122e1565b6115c88a8a611dc5565b8a5181518a518a519397506115e5938b60015b6020020151612665565b1515611661576040805160e560020a62461bcd02815260206004820152603360248201527f4d616b6572207369676e617475726520697320696e76616c69642c204578636860448201527f616e67652e657865637574654f72646572282900000000000000000000000000606482015290519081900360840190fd5b60408a0151602085015161168591908a6001602002015160408b01518b60036115db565b1515611701576040805160e560020a62461bcd02815260206004820152603360248201527f54616b6572207369676e617475726520697320696e76616c69642c204578636860448201527f616e67652e657865637574654f72646572282900000000000000000000000000606482015290519081900360840190fd5b61170c8a8a8661278b565b925061171f838b600260200201516129c9565b915060008260000151118015611739575060008260200151115b15156117db576040805160e560020a62461bcd02815260206004820152605260248201527f546f6b656e20616d6f756e74203c20312c20707269636520726174696f20697360448201527f20696e76616c69642120546f6b656e2076616c7565203c20312c20457863686160648201527f6e67652e657865637574654f7264657228290000000000000000000000000000608482015290519081900360a40190fd5b81518351604001516117f29163ffffffff612d7616565b8351604001526020820151835160a001516118129163ffffffff612d8816565b835160a0015260208083015190840151604001516118359163ffffffff612d7616565b602084018051604001919091528251905160a001516118599163ffffffff612d8816565b602084015160a00152506005548251604001518110158061189357508260400151801561189357508251608081015160a090910151820110155b156118be5783516000908152600c6020526040808220600201829055855182528120600101556118ee565b825160409081015185516000908152600c60205282812060020191909155845160a0015186518252919020600101555b808360200151604001511115806119225750826040015115801561192257506020830151608081015160a090910151820110155b1561195257602080850180516000908152600c90925260408083206002018390559051825281206001015561198a565b6020808401805160409081015187840180516000908152600c90955282852060020191909155915160a0015191518352909120600101555b6119958a8387612d9e565b8351835160408082015160a0909201518151928352602083015280517fbc99ec61d80589c90dda14a2b09b9d0ddcdd61292e3745b9967c10bdd131d9529281900390910190a26020808501518482015160408082015160a090920151815192835293820193909352825191927fbc99ec61d80589c90dda14a2b09b9d0ddcdd61292e3745b9967c10bdd131d95292918290030190a2602080850151855184830151855160408051928352948201528351929391927f33f1634e907a90025026a538736ad65b4c862890df9e35a35c67cd55b0cfc8d0929181900390910190a35060019998505050505050505050565b60096020908152600092835260408084209091529082529020805460019091015482565b60055481565b60408051600160a060020a038516815260208101849052808201839052905133917f0ecba04e3ac59da620bc63359f7754b6504cf198bac1987a1ac5123c47cf2a36919081900360600190a2505050565b600a6020526000908152604090205460ff1681565b60076020526000908152604090205481565b600154600160a060020a031681565b600d54600160a060020a031681565b600154600090600160a060020a0316331480611b6a5750600254600160a060020a031633145b1515611bd4576040805160e560020a62461bcd02815260206004820152602a6024820152600080516020613dc283398151915260448201527f7446656552617465282900000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0384166000908152600b60205260409020541515611c69576040805160e560020a62461bcd02815260206004820152603660248201527f71756f74655072696f726974795b5f71756f7465546f6b656e5d203d3d20302c60448201527f2045786368616e67652e73657446656552617465282900000000000000000000606482015290519081900360840190fd5b600160a060020a03841660008181526006602090815260408083208790556007825291829020859055815186815290810185905281517f4087c0a471bb6f7904a5b325dccb8fdfe192681804f34182e0d7b17610a9871f929181900390910190a25060019392505050565b6000611cde613ce7565b600160a060020a0383166000908152600a602052604090205460ff1615611d085760009150611dbc565b50600160a060020a0380861660009081526009602090815260408083209388168352928152908290208251808401909352805480845260019091015491830191909152158015611d5a57506020810151155b15611d8d57600160a060020a03851660008181526006602090815260408083205485529282526007815291902054908201525b60208101518151611db991600a0a90611dad90879063ffffffff613adf16565b9063ffffffff613b0316565b91505b50949350505050565b611dcd613ce7565b82516020808501518451606087015186840151608088015160a0890151604080516c01000000000000000000000000308102828b0152600160a060020a039a8b1681026034830152978a1688026048820152605c81019690965297909316909402607c840152609083015260b082019290925260d0808201929092528351808203909201825260f0019283905280516000938493909182918401908083835b60208310611e8b5780518252601f199092019160209182019101611e6c565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209450309250879150600290506020020151866003602002015186600260200201518860016020020151886003602002015189600660200201518a600760200201516040516020018089600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140188600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140187600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140186815260200185600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401848152602001838152602001828152602001985050505050505050506040516020818303038152906040526040518082805190602001908083835b60208310611ff85780518252601f199092019160209182019101611fd9565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208285019094529681529586019190915250929695505050505050565b612043613ce7565b60408051808201808352600d5485517f2e16cf5400000000000000000000000000000000000000000000000000000000909252600160a060020a039182166044840152925191928392911690632e16cf54906064808501916020918187030181600087803b1580156120b457600080fd5b505af11580156120c8573d6000803e3d6000fd5b505050506040513d60208110156120de57600080fd5b5051600160a060020a039081168252600d5460209092019116632e16cf5485600260200201516040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561214f57600080fd5b505af1158015612163573d6000803e3d6000fd5b505050506040513d602081101561217957600080fd5b5051600160a060020a039081169091528151919250161515612231576040805160e560020a62461bcd02815260206004820152604660248201527f4d616b65722077616c6c657420646f6573206e6f742065786973742c2045786360448201527f68616e67652e6765744d616b6572416e6454616b657254726164696e6757616c60648201527f6c65747328290000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b6020810151600160a060020a03161515610869576040805160e560020a62461bcd02815260206004820152604660248201527f54616b65722077616c6c657420646f6573206e6f742065786973742c2045786360448201527f68616e67652e6765744d616b6572416e6454616b657254726164696e6757616c60648201527f6c65747328290000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b600054600160a060020a03163314806122f957503330145b151561239b576040805160e560020a62461bcd02815260206004820152604760248201527f6d73672e73656e64657220213d206f72646572426f6f6b4163636f756e742c2060448201527f45786368616e67652e5f5f657865637574654f72646572496e7075744973566160648201527f6c69645f5f282900000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b608081015143111561241d576040805160e560020a62461bcd02815260206004820152602481018290527f4d616b6572206f726465722068617320657870697265642c2045786368616e6760448201527f652e5f5f657865637574654f72646572496e707574497356616c69645f5f2829606482015290519081900360840190fd5b60c081015143111561249f576040805160e560020a62461bcd02815260206004820152602481018290527f54616b6572206f726465722068617320657870697265642c2045786368616e6760448201527f652e5f5f657865637574654f72646572496e707574497356616c69645f5f2829606482015290519081900360840190fd5b6060820151600160a060020a039081166000908152600b6020908152604080832054918601519093168252919020541415612596576040805160e560020a62461bcd02815260206004820152606c60248201527f51756f746520746f6b656e206973206f6d697474656421204973206e6f74206f60448201527f66666572656420627920656974686572207468652054616b6572206f72204d6160648201527f6b65722c2045786368616e67652e5f5f657865637574654f72646572496e707560848201527f74497356616c69645f5f2829000000000000000000000000000000000000000060a482015290519081900360c40190fd5b805115806125a657506020810151155b806125b357506040810151155b806125c057506060810151155b15612661576040805160e560020a62461bcd02815260206004820152605960248201527f4d6179206e6f74206578656375746520616e206f72646572207768657265207460448201527f6f6b656e20616d6f756e74203d3d20302c2045786368616e67652e5f5f65786560648201527f637574654f72646572496e707574497356616c69645f5f282900000000000000608482015290519081900360a40190fd5b5050565b60008060018660405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106126e95780518252601f1990920191602091820191016126ca565b51815160209384036101000a60001901801990921691161790526040805192909401829003822060008084528383018087529190915260ff8d1683860152606083018c9052608083018b9052935160a08084019750919550601f1981019492819003909101925090865af1158015612765573d6000803e3d6000fd5b5050604051601f190151600160a060020a03908116981697909714979650505050505050565b612793613cfe565b81516000908152600c60209081526040808320828601518452908320878301518551600160a060020a039182169052875186518501526060808a01518751921691015291860151845160800152805490921015612886576002820154151561286b576040805160e560020a62461bcd02815260206004820152603060248201527f4d616b6572206f7264657220697320696e6163746976652c2045786368616e6760448201527f652e657865637574654f72646572282900000000000000000000000000000000606482015290519081900360840190fd5b60028201548351604001526001820154835160a001526128a0565b6080850151825584518351604001528251600060a0909101525b60608087015160208581018051600160a060020a039384169052604089015181518301529089015181519216918301919091529086015190516080015280546000101561298a5760028101541515612968576040805160e560020a62461bcd02815260206004820152603060248201527f54616b6572206f7264657220697320696e6163746976652c2045786368616e6760448201527f652e657865637574654f72646572282900000000000000000000000000000000606482015290519081900360840190fd5b6002810154602084018051604001919091526001820154905160a001526129ab565b60c085015181556040808601516020850180519092015251600060a0909101525b6129b88360200151613b1a565b151560408401525090949350505050565b6129d1613d2d565b6129d9613d4f565b6129e1613d4f565b60008060008060008060008b6000015198508b6020015197508b60400151965088608001518960200151101515612b9857612a358960800151611dad608060020a8c60200151613adf90919063ffffffff16565b9550612a5a8860200151611dad608060020a8b60800151613adf90919063ffffffff16565b861015612afd576040805160e560020a62461bcd02815260206004820152604760248201527f54616b65722070726963652069732067726561746572207468616e206d616b6560448201527f722070726963652c2045786368616e67652e5f5f6765745472616465416d6f7560648201527f6e74735f5f282900000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b8615612b4d5760a089015160808a0151612b1c9163ffffffff612d7616565b9450612b2c886040015186613b47565b9150612b46608060020a611dad848963ffffffff613adf16565b9250612b93565b60a08801516080890151612b669163ffffffff612d7616565b9350612b76896040015185613b47565b9250612b9086611dad85608060020a63ffffffff613adf16565b91505b612d1a565b612bbb8960200151611dad608060020a8c60800151613adf90919063ffffffff16565b9550612be08860800151611dad608060020a8b60200151613adf90919063ffffffff16565b861115612c84576040805160e560020a62461bcd028152602060048201526044602482018190527f54616b6572207072696365206973206c657373207468616e206d616b65722070908201527f726963652c2045786368616e67652e5f5f6765745472616465416d6f756e747360648201527f5f5f282900000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b8615612cd45760a089015160808a0151612ca39163ffffffff612d7616565b9450612cb3886040015186613b47565b9150612ccd86611dad84608060020a63ffffffff613adf16565b9250612d1a565b60a08801516080890151612ced9163ffffffff612d7616565b9350612cfd896040015185613b47565b9250612d17608060020a611dad858963ffffffff613adf16565b91505b86612d3857612d3389600001518a60600151848e611cd4565b612d4c565b612d4c89606001518a60000151858e611cd4565b60408051606081018252948552602085019390935291830191909152509998505050505050505050565b600082821115612d8257fe5b50900390565b600082820183811015612d9757fe5b9392505050565b612da6613d98565b6000806000806000612db6613d98565b612dcc8a60035b60200201518960200151613b5d565b6060880152612de48a60015b60200201518951613b5d565b6020880152612df48a6001612dbd565b6040880152612e048a6003612dd8565b87528751600160a060020a0316634e7343ea8b600160200201518b600001516000806040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183815260200182600160a060020a03168152602001945050505050602060405180830381600087803b158015612e8f57600080fd5b505af1158015612ea3573d6000803e3d6000fd5b505050506040513d6020811015612eb957600080fd5b50511515612f5d576040805160e560020a62461bcd02815260206004820152605060248201527f4d616b65722077616c6c657420636f756c64206e6f742070726570617265207460448201527f6865207472616e736665722c2045786368616e67652e5f5f657865637574655460648201527f6f6b656e5472616e736665725f5f282900000000000000000000000000000000608482015290519081900360a40190fd5b60208881015160608c01518b8301516040808e01516004805483517f4e7343ea000000000000000000000000000000000000000000000000000000008152600160a060020a0396871692810192909252602482019490945260448101919091529183166064830152519190921692634e7343ea92608480820193918290030181600087803b158015612fee57600080fd5b505af1158015613002573d6000803e3d6000fd5b505050506040513d602081101561301857600080fd5b505115156130bc576040805160e560020a62461bcd02815260206004820152605060248201527f54616b65722077616c6c657420636f756c64206e6f742070726570617265207460448201527f6865207472616e736665722c2045786368616e67652e5f5f657865637574655460648201527f6f6b656e5472616e736665725f5f282900000000000000000000000000000000608482015290519081900360a40190fd5b6020808b015160608c01518a51928b015160408d01519299509097509195509093501561343e5760048054604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a0387811694820194909452905192909116916370a08231916024808201926020929091908290030181600087803b15801561314f57600080fd5b505af1158015613163573d6000803e3d6000fd5b505050506040513d602081101561317957600080fd5b5051600480546008546040808e015181517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038a81169682019690965292851660248401526044830152519395509116916323b872dd916064808201926020929091908290030181600087803b1580156131fb57600080fd5b505af115801561320f573d6000803e3d6000fd5b505050506040513d602081101561322557600080fd5b505115156132ef576040805160e560020a62461bcd02815260206004820152606360248201527f43616e6e6f74207472616e7366657220666565732066726f6d2074616b65722060448201527f74726164696e672077616c6c657420746f206569646f6f2077616c6c65742c2060648201527f45786368616e67652e5f5f65786563757465546f6b656e5472616e736665725f60848201527f5f2829000000000000000000000000000000000000000000000000000000000060a482015290519081900360c40190fd5b604089015161330590839063ffffffff612d7616565b60048054604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a0388811694820194909452905192909116916370a08231916024808201926020929091908290030181600087803b15801561337157600080fd5b505af1158015613385573d6000803e3d6000fd5b505050506040513d602081101561339b57600080fd5b50511461343e576040805160e560020a62461bcd02815260206004820152604b60248201527f57726f6e672066656520746f6b656e2062616c616e636520616674657220747260448201527f616e736665722c2045786368616e67652e5f5f65786563757465546f6b656e5460648201527f72616e736665725f5f2829000000000000000000000000000000000000000000608482015290519081900360a40190fd5b600160a060020a038616151561348a578851604051600160a060020a0385169180156108fc02916000818181858888f19350505050158015613484573d6000803e3d6000fd5b50613562565b61349a8685858c60000151613c0e565b1515613562576040805160e560020a62461bcd02815260206004820152606c60248201527f546f6b656e207472616e73666572736869702066726f6d206d616b657254726160448201527f64696e6757616c6c657420746f2074616b657254726164696e6757616c6c657460648201527f206661696c65642c2045786368616e67652e5f5f65786563757465546f6b656e60848201527f5472616e736665725f5f2829000000000000000000000000000000000000000060a482015290519081900360c40190fd5b600160a060020a03851615156135b1576020890151604051600160a060020a0386169180156108fc02916000818181858888f193505050501580156135ab573d6000803e3d6000fd5b50613689565b6135c18584868c60200151613c0e565b1515613689576040805160e560020a62461bcd02815260206004820152606c60248201527f546f6b656e207472616e73666572736869702066726f6d2074616b657254726160448201527f64696e6757616c6c657420746f206d616b657254726164696e6757616c6c657460648201527f206661696c65642c2045786368616e67652e5f5f65786563757465546f6b656e60848201527f5472616e736665725f5f2829000000000000000000000000000000000000000060a482015290519081900360c40190fd5b600160a060020a038381169085161461379057602089015187516136b29163ffffffff612d8816565b8152885160208801516136ca9163ffffffff612d7616565b6020820152600454600160a060020a038781169116146136ff57885160408801516136fa9163ffffffff612d8816565b61372b565b6040808a01518a519189015161372b9261371f919063ffffffff612d8816565b9063ffffffff612d7616565b6040820152600454600160a060020a03868116911614613763576020890151606088015161375e9163ffffffff612d7616565b613786565b613786896040015161371f8b602001518a60600151612d7690919063ffffffff16565b6060820152613816565b600454600160a060020a038681169116146137af5786606001516137c8565b604089015160608801516137c89163ffffffff612d7616565b606082018190528152600454600160a060020a038781169116146137f0578660400151613809565b6040808a0151908801516138099163ffffffff612d7616565b6040820181905260208201525b6138208584613b5d565b6060820151146138c6576040805160e560020a62461bcd02815260206004820152605360248201527f57726f6e672074616b6572206f6666657220746f6b656e2062616c616e63652060448201527f6166746572207472616e736665722c2045786368616e67652e5f5f657865637560648201527f7465546f6b656e5472616e736665725f5f282900000000000000000000000000608482015290519081900360a40190fd5b6138d08685613b5d565b602082015114613976576040805160e560020a62461bcd02815260206004820152605360248201527f57726f6e67206d616b6572206f6666657220746f6b656e2062616c616e63652060448201527f6166746572207472616e736665722c2045786368616e67652e5f5f657865637560648201527f7465546f6b656e5472616e736665725f5f282900000000000000000000000000608482015290519081900360a40190fd5b6139808684613b5d565b604082015114613a26576040805160e560020a62461bcd02815260206004820152605260248201527f57726f6e672074616b65722077616e7420746f6b656e2062616c616e6365206160448201527f66746572207472616e736665722c2045786368616e67652e5f5f65786563757460648201527f65546f6b656e5472616e736665725f5f28290000000000000000000000000000608482015290519081900360a40190fd5b613a308585613b5d565b815114613ad3576040805160e560020a62461bcd02815260206004820152605260248201527f57726f6e67206d616b65722077616e7420746f6b656e2062616c616e6365206160448201527f66746572207472616e736665722c2045786368616e67652e5f5f65786563757460648201527f65546f6b656e5472616e736665725f5f28290000000000000000000000000000608482015290519081900360a40190fd5b50505050505050505050565b6000828202831580613afb5750828482811515613af857fe5b04145b1515612d9757fe5b6000808284811515613b1157fe5b04949350505050565b6060810151600160a060020a039081166000908152600b6020526040808220549351909216815220541090565b6000818310613b565781612d97565b5090919050565b6000600160a060020a0383161515613b805750600160a060020a038116316111d2565b82600160a060020a03166370a08231836040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015613bdb57600080fd5b505af1158015613bef573d6000803e3d6000fd5b505050506040513d6020811015613c0557600080fd5b505190506111d2565b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015284811660248301526044820184905291516000928716916323b872dd916064808301928692919082900301818387803b158015613c8157600080fd5b505af1158015613c95573d6000803e3d6000fd5b505050503d60008114613caf5760208114613cb957600080fd5b6000199150611dbc565b60206000803e5050600051949350505050565b60408051808201825290600290829080388339509192915050565b604080518082019091526000808252602082015290565b6101a060405190810160405280613d13613d4f565b8152602001613d20613d4f565b8152600060209091015290565b6060604051908101604052806000815260200160008152602001600081525090565b60c0604051908101604052806000600160a060020a0316815260200160008152602001600081526020016000600160a060020a0316815260200160008152602001600081525090565b60806040519081016040528060008152602001600081526020016000815260200160008152509056006d73672e73656e64657220213d206f776e65722c2045786368616e67652e73656d73672e73656e64657220213d206f776e657200000000000000000000000000a165627a7a72305820f90ab6cbfaddca5d65034a0df67c5ae4d8931c4be868826087a9089bdaefaf3a00290000000000000000000000008725e59eef18409273fa50662e7c1b671e368a8600000000000000000000000089ab32156e46f46d02ade3fecbe5fc4243b9aaed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006504d6f4cb6ec9cff5675c515212ebd17c3d83f000000000000000000000000b7c975bd483ba4d6c3e3a12132b1c974005ba1d7

Deployed Bytecode

0x6080604052600436106101875763ffffffff60e060020a6000350416630ac6ab9a81146101895780631d2627bb146101cc5780631e57bc4a146102015780632a5f5a6d146102225780632e16cf541461024357806341832bed14610280578063472d35b9146103245780634983542e146103455780634a8ef4bd1461038957806351cff8d9146103aa57806357b394bf146103cb5780635d79925c146103f257806360bf46ea146104185780636296dd601461043c57806363a3d3831461046957806369820a801461047e5780636e3706f4146104935780637b11b44c146104c95780637fa86906146104de57806384b96e04146105055780639de03baa14610526578063b5f9b5cc14610243578063bd09f1171461053e578063c1d5e84f14610553578063c825ec9714610574578063cd0b302d14610626578063cf71efa914610666578063cfbe2cb31461067b578063defab0a3146106a2578063dff0fae7146106c3578063e7663079146106e4578063f2020275146106f9578063f3182d6c1461070e575b005b34801561019557600080fd5b506101ba600160a060020a036004358116906024358116906044359060643516610735565b60408051918252519081900360200190f35b3480156101d857600080fd5b506101ed600160a060020a03600435166107c4565b604080519115158252519081900360200190f35b34801561020d57600080fd5b506101ba600160a060020a036004351661086e565b34801561022e57600080fd5b506101ed600160a060020a0360043516610880565b34801561024f57600080fd5b50610264600160a060020a0360043516610965565b60408051600160a060020a039092168252519081900360200190f35b34801561028c57600080fd5b506040805160808181019092526102e99136916004916084919083908190839082908082843750506040805161010081810190925294979695818101959450925060089150839083908082843750939650610a0295505050505050565b6040518082600260200280838360005b838110156103115781810151838201526020016102f9565b5050505090500191505060405180910390f35b34801561033057600080fd5b50610187600160a060020a0360043516610a3f565b34801561035157600080fd5b506101ed6024600480358281019290820135918135808301929082013591604435808301929082013591606435918201910135610abe565b34801561039557600080fd5b506101ed600160a060020a0360043516610d91565b3480156103b657600080fd5b506101ed600160a060020a0360043516610e3c565b3480156103d757600080fd5b50610187600160a060020a03600435166024356044356110a4565b3480156103fe57600080fd5b506101ed600160a060020a036004351660243515156110f5565b34801561042457600080fd5b506101ed600160a060020a03600435166024356111d8565b34801561044857600080fd5b506101ed600160a060020a03600435811690602435166044356064356112aa565b34801561047557600080fd5b5061026461141e565b34801561048a57600080fd5b506101ba61142d565b34801561049f57600080fd5b506104ab600435611433565b60408051938452602084019290925282820152519081900360600190f35b3480156104d557600080fd5b50610264611454565b3480156104ea57600080fd5b506101ed600160a060020a0360043581169060243516611463565b34801561051157600080fd5b506101ba600160a060020a03600435166114a4565b34801561053257600080fd5b506101876004356114b6565b34801561054a57600080fd5b5061026461150b565b34801561055f57600080fd5b506101ed600160a060020a036004351661151a565b34801561058057600080fd5b506040805160808181019092526101ed91369160049160849190839081908390829080828437505060408051610100818101909252949796958181019594509250600891508390839080828437505060408051808201825294979695818101959450925060029150839083908082843750506040805160808181019092529497969581810195945092506004915083908390808284375093965061158595505050505050565b34801561063257600080fd5b5061064d600160a060020a0360043581169060243516611a84565b6040805192835260208301919091528051918290030190f35b34801561067257600080fd5b506101ba611aa8565b34801561068757600080fd5b50610187600160a060020a0360043516602435604435611aae565b3480156106ae57600080fd5b506101ed600160a060020a0360043516611aff565b3480156106cf57600080fd5b506101ba600160a060020a0360043516611b14565b3480156106f057600080fd5b50610264611b26565b34801561070557600080fd5b50610264611b35565b34801561071a57600080fd5b506101ed600160a060020a0360043516602435604435611b44565b600160a060020a038085166000908152600b60205260408082205492861682528120549091106107af576040805160e560020a62461bcd02815260206004820152600c60248201527f496e76616c696420706169720000000000000000000000000000000000000000604482015290519081900360640190fd5b6107bb85858585611cd4565b95945050505050565b600154600090600160a060020a0316331461083d576040805160e560020a62461bcd02815260206004820152602e6024820152600080516020613dc283398151915260448201527f744569646f6f57616c6c65742829000000000000000000000000000000000000606482015290519081900360840190fd5b506008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03831617905560015b919050565b600b6020526000908152604090205481565b600154600090600160a060020a031633146108d3576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b600160a060020a0382161515610933576040805160e560020a62461bcd02815260206004820152601760248201527f5f757365724d617070657241646472657373203d3d2030000000000000000000604482015290519081900360640190fd5b50600d8054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff199091161790556001919050565b600d54604080517f2e16cf54000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015291516000939290921691632e16cf549160248082019260209290919082900301818787803b1580156109d057600080fd5b505af11580156109e4573d6000803e3d6000fd5b505050506040513d60208110156109fa57600080fd5b505192915050565b610a0a613ccc565b610a12613ce7565b610a1c8484611dc5565b604080518082019091528151815260208083015190820152925090505092915050565b600154600160a060020a03163314610a8f576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000806000610acb613ce7565b600054600160a060020a03163314610b53576040805160e560020a62461bcd02815260206004820152603c60248201527f6d73672e73656e64657220213d206f72646572426f6f6b4163636f756e742c2060448201527f45786368616e67652e6261746368457865637574654f72646572282900000000606482015290519081900360840190fd5b600092505b88831015610d7f57308c8c85818110610b6d57fe5b9050608002018b8b868181101515610b8157fe5b905061010002018a8a878181101515610b9657fe5b9050604002018989888181101515610baa57fe5b9050608002016040516024018085600460200280828437909101905084610100808284379091019050836040808284379091019050826080808284376040805193909101838103601f1901845281526020830180517fc825ec97000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091161781529051835193985096508695509350909150819050838360005b83811015610c74578181015183820152602001610c5c565b50505050905090810190601f168015610ca15780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af193505050811515610d7457610d338c8c85818110610ccd57fe5b9050608002016004806020026040519081016040528092919082600460200280828437508f93508e925088915050818110610d0457fe5b90506101000201600880602002604051908101604052809291908260086020028082843750611dc59350505050565b6020808201518251604080518881529051949550919390927fa5257066aa244148645c1d43997cb8433b8b4a8b2dfd313a887445a0641c578d928290030190a35b600190920191610b58565b5060019b9a5050505050505050505050565b600154600090600160a060020a03163314610e0a576040805160e560020a62461bcd0281526020600482015260326024820152600080516020613dc283398151915260448201527f744f72646572426f6f6b41636f756e7428290000000000000000000000000000606482015290519081900360840190fd5b5060008054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff199091161790556001919050565b6001546000908190600160a060020a03163314610e91576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b600160a060020a0383161515610ed85750604051303190339082156108fc029083906000818181858888f19350505050158015610ed2573d6000803e3d6000fd5b50611053565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a038516916370a082319160248083019260209291908290030181600087803b158015610f3957600080fd5b505af1158015610f4d573d6000803e3d6000fd5b505050506040513d6020811015610f6357600080fd5b5051604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018390529051919250600160a060020a0385169163a9059cbb916044808201926020929091908290030181600087803b158015610fd157600080fd5b505af1158015610fe5573d6000803e3d6000fd5b505050506040513d6020811015610ffb57600080fd5b50511515611053576040805160e560020a62461bcd02815260206004820152601860248201527f7769746864726177207472616e73666572206661696c65640000000000000000604482015290519081900360640190fd5b60408051338152600160a060020a038516602082015280820183905290517f9207361cc2a04b9c7a06691df1eb87c6a63957ae88bf01d0d18c81e3d12720999181900360600190a150600192915050565b60408051600160a060020a038516815260208101849052808201839052905133917fe8d885fd2147a6ac7d644cd3c3a5f2413dbd8e515b61702b1cc1551188176b3c919081900360600190a2505050565b600154600090600160a060020a0316331461116e576040805160e560020a62461bcd0281526020600482015260356024820152600080516020613dc283398151915260448201527f7446656554616b65727357686974656c69737428290000000000000000000000606482015290519081900360840190fd5b600160a060020a0383166000818152600a6020908152604091829020805460ff191686151590811790915582519384529083015280517f7b31b9a94f09da1a1b9b7d74096a88704ffd866e63238327d00ae478b6d1f8ec9281900390910190a15060015b92915050565b600154600090600160a060020a03163314611251576040805160e560020a62461bcd0281526020600482015260306024820152600080516020613dc283398151915260448201527f7451756f74655072696f72697479282900000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0383166000818152600b6020908152604091829020859055815185815291517fadba5bc51f565bc23062c2968481f023e22fd162f18b0146ff7e9393ffd2ed409281900390910190a250600192915050565b600154600090600160a060020a03163314806112d05750600254600160a060020a031633145b151561133a576040805160e560020a62461bcd02815260206004820152602c6024820152600080516020613dc283398151915260448201527f74437573746f6d46656528290000000000000000000000000000000000000000606482015290519081900360840190fd5b82158015611346575081155b1561137e57600160a060020a0380861660009081526009602090815260408083209388168352929052908120818155600101556113c0565b6040805180820182528481526020808201858152600160a060020a03808a16600090815260098452858120918a16815292529290209051815590516001909101555b83600160a060020a031685600160a060020a03167fe0bfbb0947e78f22a90164fbc34fe2b8660310f8a17ab2e225a63ef706a95ba38585604051808381526020018281526020019250505060405180910390a3506001949350505050565b600454600160a060020a031681565b60035481565b600c6020526000908152604090208054600182015460029092015490919083565b600254600160a060020a031681565b600160a060020a0380831660009081526009602090815260408083209385168352929052908120805415801561149c5750600181015415155b949350505050565b60066020526000908152604090205481565b600154600160a060020a03163314611506576040805160e560020a62461bcd0281526020600482015260136024820152600080516020613de2833981519152604482015290519081900360640190fd5b600555565b600854600160a060020a031681565b600d54604080517fc1d5e84f000000000000000000000000000000000000000000000000000000008152600160a060020a0384811660048301529151600093929092169163c1d5e84f9160248082019260209290919082900301818787803b1580156109d057600080fd5b600061158f613ce7565b611597613ce7565b61159f613cfe565b6115a7613d2d565b60006115b28a61203b565b94506115be8a8a6122e1565b6115c88a8a611dc5565b8a5181518a518a519397506115e5938b60015b6020020151612665565b1515611661576040805160e560020a62461bcd02815260206004820152603360248201527f4d616b6572207369676e617475726520697320696e76616c69642c204578636860448201527f616e67652e657865637574654f72646572282900000000000000000000000000606482015290519081900360840190fd5b60408a0151602085015161168591908a6001602002015160408b01518b60036115db565b1515611701576040805160e560020a62461bcd02815260206004820152603360248201527f54616b6572207369676e617475726520697320696e76616c69642c204578636860448201527f616e67652e657865637574654f72646572282900000000000000000000000000606482015290519081900360840190fd5b61170c8a8a8661278b565b925061171f838b600260200201516129c9565b915060008260000151118015611739575060008260200151115b15156117db576040805160e560020a62461bcd02815260206004820152605260248201527f546f6b656e20616d6f756e74203c20312c20707269636520726174696f20697360448201527f20696e76616c69642120546f6b656e2076616c7565203c20312c20457863686160648201527f6e67652e657865637574654f7264657228290000000000000000000000000000608482015290519081900360a40190fd5b81518351604001516117f29163ffffffff612d7616565b8351604001526020820151835160a001516118129163ffffffff612d8816565b835160a0015260208083015190840151604001516118359163ffffffff612d7616565b602084018051604001919091528251905160a001516118599163ffffffff612d8816565b602084015160a00152506005548251604001518110158061189357508260400151801561189357508251608081015160a090910151820110155b156118be5783516000908152600c6020526040808220600201829055855182528120600101556118ee565b825160409081015185516000908152600c60205282812060020191909155845160a0015186518252919020600101555b808360200151604001511115806119225750826040015115801561192257506020830151608081015160a090910151820110155b1561195257602080850180516000908152600c90925260408083206002018390559051825281206001015561198a565b6020808401805160409081015187840180516000908152600c90955282852060020191909155915160a0015191518352909120600101555b6119958a8387612d9e565b8351835160408082015160a0909201518151928352602083015280517fbc99ec61d80589c90dda14a2b09b9d0ddcdd61292e3745b9967c10bdd131d9529281900390910190a26020808501518482015160408082015160a090920151815192835293820193909352825191927fbc99ec61d80589c90dda14a2b09b9d0ddcdd61292e3745b9967c10bdd131d95292918290030190a2602080850151855184830151855160408051928352948201528351929391927f33f1634e907a90025026a538736ad65b4c862890df9e35a35c67cd55b0cfc8d0929181900390910190a35060019998505050505050505050565b60096020908152600092835260408084209091529082529020805460019091015482565b60055481565b60408051600160a060020a038516815260208101849052808201839052905133917f0ecba04e3ac59da620bc63359f7754b6504cf198bac1987a1ac5123c47cf2a36919081900360600190a2505050565b600a6020526000908152604090205460ff1681565b60076020526000908152604090205481565b600154600160a060020a031681565b600d54600160a060020a031681565b600154600090600160a060020a0316331480611b6a5750600254600160a060020a031633145b1515611bd4576040805160e560020a62461bcd02815260206004820152602a6024820152600080516020613dc283398151915260448201527f7446656552617465282900000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0384166000908152600b60205260409020541515611c69576040805160e560020a62461bcd02815260206004820152603660248201527f71756f74655072696f726974795b5f71756f7465546f6b656e5d203d3d20302c60448201527f2045786368616e67652e73657446656552617465282900000000000000000000606482015290519081900360840190fd5b600160a060020a03841660008181526006602090815260408083208790556007825291829020859055815186815290810185905281517f4087c0a471bb6f7904a5b325dccb8fdfe192681804f34182e0d7b17610a9871f929181900390910190a25060019392505050565b6000611cde613ce7565b600160a060020a0383166000908152600a602052604090205460ff1615611d085760009150611dbc565b50600160a060020a0380861660009081526009602090815260408083209388168352928152908290208251808401909352805480845260019091015491830191909152158015611d5a57506020810151155b15611d8d57600160a060020a03851660008181526006602090815260408083205485529282526007815291902054908201525b60208101518151611db991600a0a90611dad90879063ffffffff613adf16565b9063ffffffff613b0316565b91505b50949350505050565b611dcd613ce7565b82516020808501518451606087015186840151608088015160a0890151604080516c01000000000000000000000000308102828b0152600160a060020a039a8b1681026034830152978a1688026048820152605c81019690965297909316909402607c840152609083015260b082019290925260d0808201929092528351808203909201825260f0019283905280516000938493909182918401908083835b60208310611e8b5780518252601f199092019160209182019101611e6c565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209450309250879150600290506020020151866003602002015186600260200201518860016020020151886003602002015189600660200201518a600760200201516040516020018089600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140188600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140187600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140186815260200185600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401848152602001838152602001828152602001985050505050505050506040516020818303038152906040526040518082805190602001908083835b60208310611ff85780518252601f199092019160209182019101611fd9565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208285019094529681529586019190915250929695505050505050565b612043613ce7565b60408051808201808352600d5485517f2e16cf5400000000000000000000000000000000000000000000000000000000909252600160a060020a039182166044840152925191928392911690632e16cf54906064808501916020918187030181600087803b1580156120b457600080fd5b505af11580156120c8573d6000803e3d6000fd5b505050506040513d60208110156120de57600080fd5b5051600160a060020a039081168252600d5460209092019116632e16cf5485600260200201516040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561214f57600080fd5b505af1158015612163573d6000803e3d6000fd5b505050506040513d602081101561217957600080fd5b5051600160a060020a039081169091528151919250161515612231576040805160e560020a62461bcd02815260206004820152604660248201527f4d616b65722077616c6c657420646f6573206e6f742065786973742c2045786360448201527f68616e67652e6765744d616b6572416e6454616b657254726164696e6757616c60648201527f6c65747328290000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b6020810151600160a060020a03161515610869576040805160e560020a62461bcd02815260206004820152604660248201527f54616b65722077616c6c657420646f6573206e6f742065786973742c2045786360448201527f68616e67652e6765744d616b6572416e6454616b657254726164696e6757616c60648201527f6c65747328290000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b600054600160a060020a03163314806122f957503330145b151561239b576040805160e560020a62461bcd02815260206004820152604760248201527f6d73672e73656e64657220213d206f72646572426f6f6b4163636f756e742c2060448201527f45786368616e67652e5f5f657865637574654f72646572496e7075744973566160648201527f6c69645f5f282900000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b608081015143111561241d576040805160e560020a62461bcd02815260206004820152602481018290527f4d616b6572206f726465722068617320657870697265642c2045786368616e6760448201527f652e5f5f657865637574654f72646572496e707574497356616c69645f5f2829606482015290519081900360840190fd5b60c081015143111561249f576040805160e560020a62461bcd02815260206004820152602481018290527f54616b6572206f726465722068617320657870697265642c2045786368616e6760448201527f652e5f5f657865637574654f72646572496e707574497356616c69645f5f2829606482015290519081900360840190fd5b6060820151600160a060020a039081166000908152600b6020908152604080832054918601519093168252919020541415612596576040805160e560020a62461bcd02815260206004820152606c60248201527f51756f746520746f6b656e206973206f6d697474656421204973206e6f74206f60448201527f66666572656420627920656974686572207468652054616b6572206f72204d6160648201527f6b65722c2045786368616e67652e5f5f657865637574654f72646572496e707560848201527f74497356616c69645f5f2829000000000000000000000000000000000000000060a482015290519081900360c40190fd5b805115806125a657506020810151155b806125b357506040810151155b806125c057506060810151155b15612661576040805160e560020a62461bcd02815260206004820152605960248201527f4d6179206e6f74206578656375746520616e206f72646572207768657265207460448201527f6f6b656e20616d6f756e74203d3d20302c2045786368616e67652e5f5f65786560648201527f637574654f72646572496e707574497356616c69645f5f282900000000000000608482015290519081900360a40190fd5b5050565b60008060018660405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106126e95780518252601f1990920191602091820191016126ca565b51815160209384036101000a60001901801990921691161790526040805192909401829003822060008084528383018087529190915260ff8d1683860152606083018c9052608083018b9052935160a08084019750919550601f1981019492819003909101925090865af1158015612765573d6000803e3d6000fd5b5050604051601f190151600160a060020a03908116981697909714979650505050505050565b612793613cfe565b81516000908152600c60209081526040808320828601518452908320878301518551600160a060020a039182169052875186518501526060808a01518751921691015291860151845160800152805490921015612886576002820154151561286b576040805160e560020a62461bcd02815260206004820152603060248201527f4d616b6572206f7264657220697320696e6163746976652c2045786368616e6760448201527f652e657865637574654f72646572282900000000000000000000000000000000606482015290519081900360840190fd5b60028201548351604001526001820154835160a001526128a0565b6080850151825584518351604001528251600060a0909101525b60608087015160208581018051600160a060020a039384169052604089015181518301529089015181519216918301919091529086015190516080015280546000101561298a5760028101541515612968576040805160e560020a62461bcd02815260206004820152603060248201527f54616b6572206f7264657220697320696e6163746976652c2045786368616e6760448201527f652e657865637574654f72646572282900000000000000000000000000000000606482015290519081900360840190fd5b6002810154602084018051604001919091526001820154905160a001526129ab565b60c085015181556040808601516020850180519092015251600060a0909101525b6129b88360200151613b1a565b151560408401525090949350505050565b6129d1613d2d565b6129d9613d4f565b6129e1613d4f565b60008060008060008060008b6000015198508b6020015197508b60400151965088608001518960200151101515612b9857612a358960800151611dad608060020a8c60200151613adf90919063ffffffff16565b9550612a5a8860200151611dad608060020a8b60800151613adf90919063ffffffff16565b861015612afd576040805160e560020a62461bcd02815260206004820152604760248201527f54616b65722070726963652069732067726561746572207468616e206d616b6560448201527f722070726963652c2045786368616e67652e5f5f6765745472616465416d6f7560648201527f6e74735f5f282900000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b8615612b4d5760a089015160808a0151612b1c9163ffffffff612d7616565b9450612b2c886040015186613b47565b9150612b46608060020a611dad848963ffffffff613adf16565b9250612b93565b60a08801516080890151612b669163ffffffff612d7616565b9350612b76896040015185613b47565b9250612b9086611dad85608060020a63ffffffff613adf16565b91505b612d1a565b612bbb8960200151611dad608060020a8c60800151613adf90919063ffffffff16565b9550612be08860800151611dad608060020a8b60200151613adf90919063ffffffff16565b861115612c84576040805160e560020a62461bcd028152602060048201526044602482018190527f54616b6572207072696365206973206c657373207468616e206d616b65722070908201527f726963652c2045786368616e67652e5f5f6765745472616465416d6f756e747360648201527f5f5f282900000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b8615612cd45760a089015160808a0151612ca39163ffffffff612d7616565b9450612cb3886040015186613b47565b9150612ccd86611dad84608060020a63ffffffff613adf16565b9250612d1a565b60a08801516080890151612ced9163ffffffff612d7616565b9350612cfd896040015185613b47565b9250612d17608060020a611dad858963ffffffff613adf16565b91505b86612d3857612d3389600001518a60600151848e611cd4565b612d4c565b612d4c89606001518a60000151858e611cd4565b60408051606081018252948552602085019390935291830191909152509998505050505050505050565b600082821115612d8257fe5b50900390565b600082820183811015612d9757fe5b9392505050565b612da6613d98565b6000806000806000612db6613d98565b612dcc8a60035b60200201518960200151613b5d565b6060880152612de48a60015b60200201518951613b5d565b6020880152612df48a6001612dbd565b6040880152612e048a6003612dd8565b87528751600160a060020a0316634e7343ea8b600160200201518b600001516000806040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183815260200182600160a060020a03168152602001945050505050602060405180830381600087803b158015612e8f57600080fd5b505af1158015612ea3573d6000803e3d6000fd5b505050506040513d6020811015612eb957600080fd5b50511515612f5d576040805160e560020a62461bcd02815260206004820152605060248201527f4d616b65722077616c6c657420636f756c64206e6f742070726570617265207460448201527f6865207472616e736665722c2045786368616e67652e5f5f657865637574655460648201527f6f6b656e5472616e736665725f5f282900000000000000000000000000000000608482015290519081900360a40190fd5b60208881015160608c01518b8301516040808e01516004805483517f4e7343ea000000000000000000000000000000000000000000000000000000008152600160a060020a0396871692810192909252602482019490945260448101919091529183166064830152519190921692634e7343ea92608480820193918290030181600087803b158015612fee57600080fd5b505af1158015613002573d6000803e3d6000fd5b505050506040513d602081101561301857600080fd5b505115156130bc576040805160e560020a62461bcd02815260206004820152605060248201527f54616b65722077616c6c657420636f756c64206e6f742070726570617265207460448201527f6865207472616e736665722c2045786368616e67652e5f5f657865637574655460648201527f6f6b656e5472616e736665725f5f282900000000000000000000000000000000608482015290519081900360a40190fd5b6020808b015160608c01518a51928b015160408d01519299509097509195509093501561343e5760048054604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a0387811694820194909452905192909116916370a08231916024808201926020929091908290030181600087803b15801561314f57600080fd5b505af1158015613163573d6000803e3d6000fd5b505050506040513d602081101561317957600080fd5b5051600480546008546040808e015181517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038a81169682019690965292851660248401526044830152519395509116916323b872dd916064808201926020929091908290030181600087803b1580156131fb57600080fd5b505af115801561320f573d6000803e3d6000fd5b505050506040513d602081101561322557600080fd5b505115156132ef576040805160e560020a62461bcd02815260206004820152606360248201527f43616e6e6f74207472616e7366657220666565732066726f6d2074616b65722060448201527f74726164696e672077616c6c657420746f206569646f6f2077616c6c65742c2060648201527f45786368616e67652e5f5f65786563757465546f6b656e5472616e736665725f60848201527f5f2829000000000000000000000000000000000000000000000000000000000060a482015290519081900360c40190fd5b604089015161330590839063ffffffff612d7616565b60048054604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a0388811694820194909452905192909116916370a08231916024808201926020929091908290030181600087803b15801561337157600080fd5b505af1158015613385573d6000803e3d6000fd5b505050506040513d602081101561339b57600080fd5b50511461343e576040805160e560020a62461bcd02815260206004820152604b60248201527f57726f6e672066656520746f6b656e2062616c616e636520616674657220747260448201527f616e736665722c2045786368616e67652e5f5f65786563757465546f6b656e5460648201527f72616e736665725f5f2829000000000000000000000000000000000000000000608482015290519081900360a40190fd5b600160a060020a038616151561348a578851604051600160a060020a0385169180156108fc02916000818181858888f19350505050158015613484573d6000803e3d6000fd5b50613562565b61349a8685858c60000151613c0e565b1515613562576040805160e560020a62461bcd02815260206004820152606c60248201527f546f6b656e207472616e73666572736869702066726f6d206d616b657254726160448201527f64696e6757616c6c657420746f2074616b657254726164696e6757616c6c657460648201527f206661696c65642c2045786368616e67652e5f5f65786563757465546f6b656e60848201527f5472616e736665725f5f2829000000000000000000000000000000000000000060a482015290519081900360c40190fd5b600160a060020a03851615156135b1576020890151604051600160a060020a0386169180156108fc02916000818181858888f193505050501580156135ab573d6000803e3d6000fd5b50613689565b6135c18584868c60200151613c0e565b1515613689576040805160e560020a62461bcd02815260206004820152606c60248201527f546f6b656e207472616e73666572736869702066726f6d2074616b657254726160448201527f64696e6757616c6c657420746f206d616b657254726164696e6757616c6c657460648201527f206661696c65642c2045786368616e67652e5f5f65786563757465546f6b656e60848201527f5472616e736665725f5f2829000000000000000000000000000000000000000060a482015290519081900360c40190fd5b600160a060020a038381169085161461379057602089015187516136b29163ffffffff612d8816565b8152885160208801516136ca9163ffffffff612d7616565b6020820152600454600160a060020a038781169116146136ff57885160408801516136fa9163ffffffff612d8816565b61372b565b6040808a01518a519189015161372b9261371f919063ffffffff612d8816565b9063ffffffff612d7616565b6040820152600454600160a060020a03868116911614613763576020890151606088015161375e9163ffffffff612d7616565b613786565b613786896040015161371f8b602001518a60600151612d7690919063ffffffff16565b6060820152613816565b600454600160a060020a038681169116146137af5786606001516137c8565b604089015160608801516137c89163ffffffff612d7616565b606082018190528152600454600160a060020a038781169116146137f0578660400151613809565b6040808a0151908801516138099163ffffffff612d7616565b6040820181905260208201525b6138208584613b5d565b6060820151146138c6576040805160e560020a62461bcd02815260206004820152605360248201527f57726f6e672074616b6572206f6666657220746f6b656e2062616c616e63652060448201527f6166746572207472616e736665722c2045786368616e67652e5f5f657865637560648201527f7465546f6b656e5472616e736665725f5f282900000000000000000000000000608482015290519081900360a40190fd5b6138d08685613b5d565b602082015114613976576040805160e560020a62461bcd02815260206004820152605360248201527f57726f6e67206d616b6572206f6666657220746f6b656e2062616c616e63652060448201527f6166746572207472616e736665722c2045786368616e67652e5f5f657865637560648201527f7465546f6b656e5472616e736665725f5f282900000000000000000000000000608482015290519081900360a40190fd5b6139808684613b5d565b604082015114613a26576040805160e560020a62461bcd02815260206004820152605260248201527f57726f6e672074616b65722077616e7420746f6b656e2062616c616e6365206160448201527f66746572207472616e736665722c2045786368616e67652e5f5f65786563757460648201527f65546f6b656e5472616e736665725f5f28290000000000000000000000000000608482015290519081900360a40190fd5b613a308585613b5d565b815114613ad3576040805160e560020a62461bcd02815260206004820152605260248201527f57726f6e67206d616b65722077616e7420746f6b656e2062616c616e6365206160448201527f66746572207472616e736665722c2045786368616e67652e5f5f65786563757460648201527f65546f6b656e5472616e736665725f5f28290000000000000000000000000000608482015290519081900360a40190fd5b50505050505050505050565b6000828202831580613afb5750828482811515613af857fe5b04145b1515612d9757fe5b6000808284811515613b1157fe5b04949350505050565b6060810151600160a060020a039081166000908152600b6020526040808220549351909216815220541090565b6000818310613b565781612d97565b5090919050565b6000600160a060020a0383161515613b805750600160a060020a038116316111d2565b82600160a060020a03166370a08231836040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015613bdb57600080fd5b505af1158015613bef573d6000803e3d6000fd5b505050506040513d6020811015613c0557600080fd5b505190506111d2565b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015284811660248301526044820184905291516000928716916323b872dd916064808301928692919082900301818387803b158015613c8157600080fd5b505af1158015613c95573d6000803e3d6000fd5b505050503d60008114613caf5760208114613cb957600080fd5b6000199150611dbc565b60206000803e5050600051949350505050565b60408051808201825290600290829080388339509192915050565b604080518082019091526000808252602082015290565b6101a060405190810160405280613d13613d4f565b8152602001613d20613d4f565b8152600060209091015290565b6060604051908101604052806000815260200160008152602001600081525090565b60c0604051908101604052806000600160a060020a0316815260200160008152602001600081526020016000600160a060020a0316815260200160008152602001600081525090565b60806040519081016040528060008152602001600081526020016000815260200160008152509056006d73672e73656e64657220213d206f776e65722c2045786368616e67652e73656d73672e73656e64657220213d206f776e657200000000000000000000000000a165627a7a72305820f90ab6cbfaddca5d65034a0df67c5ae4d8931c4be868826087a9089bdaefaf3a0029

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000008725e59eef18409273fa50662e7c1b671e368a8600000000000000000000000089ab32156e46f46d02ade3fecbe5fc4243b9aaed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006504d6f4cb6ec9cff5675c515212ebd17c3d83f000000000000000000000000b7c975bd483ba4d6c3e3a12132b1c974005ba1d7

-----Decoded View---------------
Arg [0] : _bookAccount (address): 0x8725e59eeF18409273FA50662e7C1b671E368A86
Arg [1] : _edoToken (address): 0x89Ab32156e46F46D02ade3FEcbe5Fc4243B9AAeD
Arg [2] : _edoPerWei (uint256): 0
Arg [3] : _edoPerWeiDecimals (uint256): 0
Arg [4] : _eidooWallet (address): 0x06504D6f4Cb6EC9Cff5675C515212ebD17C3D83F
Arg [5] : _usersMapperAddress (address): 0xB7c975bd483BA4d6c3E3A12132b1c974005ba1D7

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000008725e59eef18409273fa50662e7c1b671e368a86
Arg [1] : 00000000000000000000000089ab32156e46f46d02ade3fecbe5fc4243b9aaed
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 00000000000000000000000006504d6f4cb6ec9cff5675c515212ebd17c3d83f
Arg [5] : 000000000000000000000000b7c975bd483ba4d6c3e3a12132b1c974005ba1d7


Deployed Bytecode Sourcemap

23382:39910:0:-;;;;;;;;;-1:-1:-1;;;23382:39910:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43216:303;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;43216:303:0;-1:-1:-1;;;;;43216:303:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37820:250;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;37820:250:0;-1:-1:-1;;;;;37820:250:0;;;;;;;;;;;;;;;;;;;;;;;25492:48;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;25492:48:0;-1:-1:-1;;;;;25492:48:0;;;;;28013:248;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28013:248:0;-1:-1:-1;;;;;28013:248:0;;;;;29268:163;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;29268:163:0;-1:-1:-1;;;;;29268:163:0;;;;;;;;;-1:-1:-1;;;;;29268:163:0;;;;;;;;;;;;;;52746:388;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;52746:388:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;52746:388:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;52746:388:0;-1:-1:-1;52746:388:0;;-1:-1:-1;52746:388:0;;;;;;;;-1:-1:-1;52746:388:0;;-1:-1:-1;52746:388:0;;-1:-1:-1;;;;;;52746:388:0;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;52746:388:0;;;;;;;;;;;;;;;;28267:110;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28267:110:0;-1:-1:-1;;;;;28267:110:0;;;;;29830:1534;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;29830:1534:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38180:256;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;38180:256:0;-1:-1:-1;;;;;38180:256:0;;;;;62742:545;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;62742:545:0;-1:-1:-1;;;;;62742:545:0;;;;;42109:219;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;42109:219:0;-1:-1:-1;;;;;42109:219:0;;;;;;;;;40202:347;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;40202:347:0;-1:-1:-1;;;;;40202:347:0;;;;;;;;;40831:320;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;40831:320:0;-1:-1:-1;;;;;40831:320:0;;;;;;;38966:798;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;38966:798:0;-1:-1:-1;;;;;38966:798:0;;;;;;;;;;;;;;24732:24;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24732:24:0;;;;24701:26;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24701:26:0;;;;25547:46;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;25547:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24670:26;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24670:26:0;;;;39818:204;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;39818:204:0;-1:-1:-1;;;;;39818:204:0;;;;;;;;;;24798:50;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;24798:50:0;-1:-1:-1;;;;;24798:50:0;;;;;28383:94;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28383:94:0;;;;;24918:27;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24918:27:0;;;;28774:153;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28774:153:0;-1:-1:-1;;;;;28774:153:0;;;;;32556:4239;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;32556:4239:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;32556:4239:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;32556:4239:0;-1:-1:-1;32556:4239:0;;-1:-1:-1;32556:4239:0;;;;;;;;-1:-1:-1;;32556:4239:0;;;;;;;;;;;;;;;;;-1:-1:-1;32556:4239:0;-1:-1:-1;32556:4239:0;;-1:-1:-1;32556:4239:0;;;;;;;;-1:-1:-1;;32556:4239:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;32556:4239:0;-1:-1:-1;32556:4239:0;;-1:-1:-1;32556:4239:0;;;;;;;;-1:-1:-1;32556:4239:0;;-1:-1:-1;32556:4239:0;;-1:-1:-1;;;;;;32556:4239:0;25063:64;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;25063:64:0;-1:-1:-1;;;;;25063:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24761:30;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24761:30:0;;;;41569:213;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;41569:213:0;-1:-1:-1;;;;;41569:213:0;;;;;;;;;25179:50;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;25179:50:0;-1:-1:-1;;;;;25179:50:0;;;;;24853:58;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;24853:58:0;-1:-1:-1;;;;;24853:58:0;;;;;24644:21;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24644:21:0;;;;25639:25;;8:9:-1;5:2;;;30:1;27;20:12;5:2;25639:25:0;;;;37038:622;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;37038:622:0;-1:-1:-1;;;;;37038:622:0;;;;;;;;;43216:303;-1:-1:-1;;;;;43411:19:0;;;43361:7;43411:19;;;:13;:19;;;;;;;43388:20;;;;;;;;43361:7;;-1:-1:-1;43380:67:0;;;;;-1:-1:-1;;;;;43380:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;43461:52;43478:4;43484:5;43491:11;43504:8;43461:16;:52::i;:::-;43454:59;43216:303;-1:-1:-1;;;;;43216:303:0:o;37820:250::-;37943:6;;37897:4;;-1:-1:-1;;;;;37943:6:0;37929:10;:20;37913:100;;;;;-1:-1:-1;;;;;37913:100:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37913:100:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38020:12:0;:26;;-1:-1:-1;;38020:26:0;-1:-1:-1;;;;;38020:26:0;;;;;-1:-1:-1;37820:250:0;;;;:::o;25492:48::-;;;;;;;;;;;;;:::o;28013:248::-;27950:6;;28106:4;;-1:-1:-1;;;;;27950:6:0;27936:10;:20;27919:74;;;;;-1:-1:-1;;;;;27919:74:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;27919:74:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;28130:32:0;;;;28122:68;;;;;-1:-1:-1;;;;;28122:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;28197:5:0;:40;;-1:-1:-1;;;;;28197:40:0;;-1:-1:-1;;28197:40:0;;;;;;;28013:248;;;:::o;29268:163::-;29379:5;;:46;;;;;;-1:-1:-1;;;;;29379:46:0;;;;;;;;;29353:7;;29379:5;;;;;:20;;:46;;;;;;;;;;;;;;;29353:7;29379:5;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;29379:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29379:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29379:46:0;;29268:163;-1:-1:-1;;29268:163:0:o;52746:388::-;52912:10;;:::i;:::-;52934:26;;:::i;:::-;52963:113;52995:39;53043:26;52963:23;:113::i;:::-;53083:45;;;;;;;;;53091:17;;53083:45;;;53110:17;;;;53083:45;;;;;-1:-1:-1;52934:142:0;-1:-1:-1;52746:388:0;;;;;:::o;28267:110::-;27950:6;;-1:-1:-1;;;;;27950:6:0;27936:10;:20;27919:74;;;;;-1:-1:-1;;;;;27919:74:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;27919:74:0;;;;;;;;;;;;;;;28347:11;:24;;-1:-1:-1;;28347:24:0;-1:-1:-1;;;;;28347:24:0;;;;;;;;;;28267:110::o;29830:1534::-;30083:4;30238:9;30771:12;31077:26;;:::i;:::-;30129:17;;-1:-1:-1;;;;;30129:17:0;30115:10;:31;30099:125;;;;;-1:-1:-1;;;;;30099:125:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30250:1;30238:13;;30233:1106;30253:37;;;30233:1106;;;30794:4;30897:39;;30937:1;30897:42;;;;;;;;;;;;30950:26;;30977:1;30950:29;;;;;;;;;;;;;;30990:11;;31002:1;30990:14;;;;;;;;;;;;;;31015:15;;31031:1;31015:18;;;;;;;;;;;;;;30805:237;;;;;;;;;;;;;;;;;-1:-1:-1;30805:237:0;;;;;;;;;;-1:-1:-1;30805:237:0;;;;;;;;;;-1:-1:-1;30805:237:0;;;;;;;;;;;;;26:21:-1;;;-1:-1;;22:32;6:49;;30805:237:0;;49:4:-1;25:18;;61:17;;30805:237:0;;182:15:-1;;;179:29;160:49;;30786:257:0;;;;30805:237;;-1:-1:-1;30786:257:0;-1:-1:-1;30786:257:0;;-1:-1:-1;25:18;-1:-1;30786:257:0;;-1:-1:-1;30786:257:0;;-1:-1:-1;30786:257:0;25:18:-1;-1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;30786:257:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;31056:8:0;;31052:280;;;31106:131;31142:39;;31182:1;31142:42;;;;;;;;;;;;31106:131;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31197:26:0;;-1:-1:-1;31197:26:0;;-1:-1:-1;31224:1:0;;-1:-1:-1;;31197:29:0;;;;;;;;;;;;31106:131;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31106:23:0;;-1:-1:-1;;;;31106:131:0:i;:::-;31301:17;;;;;31282;;31253:69;;;;;;;;31077:160;;-1:-1:-1;31301:17:0;;31282;;31253:69;;;;;;;;31052:280;30292:3;;;;;30233:1106;;;-1:-1:-1;31354:4:0;;29830:1534;-1:-1:-1;;;;;;;;;;;29830:1534:0:o;38180:256::-;38304:6;;38258:4;;-1:-1:-1;;;;;38304:6:0;38290:10;:20;38274:104;;;;;-1:-1:-1;;;;;38274:104:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;38274:104:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38385:17:0;:27;;-1:-1:-1;;;;;38385:27:0;;-1:-1:-1;;38385:27:0;;;;;;;38180:256;;;:::o;62742:545::-;27950:6;;62821:4;;;;-1:-1:-1;;;;;27950:6:0;27936:10;:20;27919:74;;;;;-1:-1:-1;;;;;27919:74:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;27919:74:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;62865:27:0;;;62861:339;;;-1:-1:-1;62948:33:0;;62926:4;62918:21;;62948:10;;:33;;;;;62918:21;;62948:33;;;;62918:21;62948:10;:33;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62948:33:0;62861:339;;;63019:45;;;;;;63058:4;63019:45;;;;;;-1:-1:-1;;;;;63019:30:0;;;;;:45;;;;;;;;;;;;;;-1:-1:-1;63019:30:0;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;63019:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63019:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63019:45:0;63091:55;;;;;;63121:10;63091:55;;;;;;;;;;;;63019:45;;-1:-1:-1;;;;;;63091:29:0;;;;;:55;;;;;63019:45;;63091:55;;;;;;;;-1:-1:-1;63091:29:0;:55;;;5:2:-1;;;;30:1;27;20:12;5:2;63091:55:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63091:55:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63091:55:0;63073:119;;;;;;;-1:-1:-1;;;;;63073:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;63211:52;;;63223:10;63211:52;;-1:-1:-1;;;;;63211:52:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63277:4:0;;62742:545;-1:-1:-1;;62742:545:0:o;42109:219::-;42247:75;;;-1:-1:-1;;;;;42247:75:0;;;;;;;;;;;;;;;;;;42267:10;;42247:75;;;;;;;;;;42109:219;;;:::o;40202:347::-;40348:6;;40302:4;;-1:-1:-1;;;;;40348:6:0;40334:10;:20;40318:107;;;;;-1:-1:-1;;;;;40318:107:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;40318:107:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;40432:29:0;;;;;;:18;:29;;;;;;;;;:38;;-1:-1:-1;;40432:38:0;;;;;;;;;;40482:43;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;40539:4:0;40202:347;;;;;:::o;40831:320::-;40965:6;;40919:4;;-1:-1:-1;;;;;40965:6:0;40951:10;:20;40935:102;;;;;-1:-1:-1;;;;;40935:102:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;40935:102:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;41044:21:0;;;;;;:13;:21;;;;;;;;;:33;;;41089:38;;;;;;;;;;;;;;;;;-1:-1:-1;41141:4:0;40831:320;;;;:::o;38966:798::-;39231:6;;39143:4;;-1:-1:-1;;;;;39231:6:0;39217:10;:20;;:49;;-1:-1:-1;39255:11:0;;-1:-1:-1;;;;;39255:11:0;39241:10;:25;39217:49;39201:127;;;;;;;-1:-1:-1;;;;;39201:127:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;39201:127:0;;;;;;;;;;;;;;;;;;;;39339:17;;:46;;;;-1:-1:-1;39360:25:0;;39339:46;39335:304;;;-1:-1:-1;;;;;39403:28:0;;;;;;;:9;:28;;;;;;;;:48;;;;;;;;;;;39396:55;;;;;;39335:304;;;39525:106;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39474:28:0;;;-1:-1:-1;39474:28:0;;;:9;:28;;;;;:48;;;;;;;;;;:157;;;;;;;;;;;39335:304;39685:18;-1:-1:-1;;;;;39650:90:0;39666:17;-1:-1:-1;;;;;39650:90:0;;39705:12;39719:20;39650:90;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;39754:4:0;38966:798;;;;;;:::o;24732:24::-;;;-1:-1:-1;;;;;24732:24:0;;:::o;24701:26::-;;;;:::o;25547:46::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;24670:26::-;;;-1:-1:-1;;;;;24670:26:0;;:::o;39818:204::-;-1:-1:-1;;;;;39926:15:0;;;39890:4;39926:15;;;:9;:15;;;;;;;;:22;;;;;;;;;;;39962:16;;:21;:54;;;;-1:-1:-1;39987:24:0;;;;:29;;39962:54;39955:61;39818:204;-1:-1:-1;;;;39818:204:0:o;24798:50::-;;;;;;;;;;;;;:::o;28383:94::-;27950:6;;-1:-1:-1;;;;;27950:6:0;27936:10;:20;27919:74;;;;;-1:-1:-1;;;;;27919:74:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;27919:74:0;;;;;;;;;;;;;;;28454:9;:17;28383:94::o;24918:27::-;;;-1:-1:-1;;;;;24918:27:0;;:::o;28774:153::-;28879:5;;:42;;;;;;-1:-1:-1;;;;;28879:42:0;;;;;;;;;28856:4;;28879:5;;;;;:16;;:42;;;;;;;;;;;;;;;28856:4;28879:5;:42;;;5:2:-1;;;;30:1;27;20:12;32556:4239:0;32795:4;32869:29;;:::i;:::-;33223:26;;:::i;:::-;34059:20;;:::i;:::-;34211:29;;:::i;:::-;35102:10;32908:71;32939:39;32908:30;:71::i;:::-;32869:110;;33054:118;33091:39;33139:26;33054:28;:118::i;:::-;33252:113;33284:39;33332:26;33252:23;:113::i;:::-;33455:42;;33508:17;;33536:14;;33561:18;;33223:142;;-1:-1:-1;33426:191:0;;33561:15;33606:1;33590:18;;;;;33426:20;:191::i;:::-;33410:276;;;;;;;-1:-1:-1;;;;;33410:276:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33770:42;;;;;33823:17;;;33739:193;;33770:42;33851:11;33863:1;33851:14;;;;33876:18;;;;:15;33921:1;33905:18;;33739:193;33731:270;;;;;;;-1:-1:-1;;;;;33731:270:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34082:90;34096:39;34137:26;34165:6;34082:13;:90::i;:::-;34059:113;-1:-1:-1;34243:71:0;34059:113;34271:39;34311:1;34271:42;;;;34243:19;:71::i;:::-;34211:103;;34357:1;34339:7;:15;;;:19;:42;;;;;34380:1;34362:7;:15;;;:19;34339:42;34323:158;;;;;;;-1:-1:-1;;;;;34323:158:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34603:15;;34560:17;;:38;;;:59;;;:42;:59;:::i;:::-;34519:17;;:38;;:100;34706:15;;;;34665:17;;:36;;;:57;;;:40;:57;:::i;:::-;34626:17;;:36;;:96;34815:15;;;;;34772:17;;;;:38;;;:59;;;:42;:59;:::i;:::-;34731:17;;;;;:38;;:100;;;;34918:15;;34877:17;;:36;;;:57;;;:40;:57;:::i;:::-;34838:17;;;;:36;;:96;-1:-1:-1;35115:9:0;;35136:17;;:38;;;:47;-1:-1:-1;35136:47:0;;35135:168;;;35198:6;:17;;;:104;;;;-1:-1:-1;35269:17:0;;:33;;;;35220:36;;;;;:44;;35219:83;;35198:104;35131:510;;;35328:17;;35370:1;35320:26;;;:7;:26;;;;;;:47;;:51;;;35388:17;;35380:26;;;;:45;;:49;35131:510;;;35502:17;;:38;;;;;35460:17;;35502;35452:26;;;:7;:26;;;;;:47;;:88;;;;35597:17;;:36;;;35557:17;;35549:26;;;;;:45;;:84;35131:510;35696:5;35654:6;:17;;;:38;;;:47;;35653:169;;;;35717:6;:17;;;35716:18;:105;;;;-1:-1:-1;35788:17:0;;;;:33;;;;35739:36;;;;;:44;;35738:83;;35716:105;35649:511;;;35847:17;;;;;;35889:1;35839:26;;;:7;:26;;;;;;;:47;;:51;;;35907:17;;35899:26;;;;:45;;:49;35649:511;;;36021:17;;;;;;:38;;;;;35979:17;;;;;35971:26;;;;:7;:26;;;;;;:47;;:88;;;;36116:17;;:36;;;36076:17;;36068:26;;;;;:45;;:84;35649:511;36221:111;36254:39;36302:7;36318;36221:24;:111::i;:::-;36442:17;;36461;;:38;;;;;36501:36;;;;;36427:111;;;;;;;;;;;;;;;;;;;;;36565:17;;;;;36584;;;;:38;;;;;36624:36;;;;;36550:111;;;;;;;;;;;;;;36565:17;;36550:111;;;;;;;;;36717:17;;;;;36698;;36736:15;;;;36753;;36673:96;;;;;;;;;;;;36717:17;;36698;;36673:96;;;;;;;;;;;-1:-1:-1;36785:4:0;;32556:4239;-1:-1:-1;;;;;;;;;32556:4239:0:o;25063:64::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;24761:30::-;;;;:::o;41569:213::-;41704:72;;;-1:-1:-1;;;;;41704:72:0;;;;;;;;;;;;;;;;;;41721:10;;41704:72;;;;;;;;;;41569:213;;;:::o;25179:50::-;;;;;;;;;;;;;;;:::o;24853:58::-;;;;;;;;;;;;;:::o;24644:21::-;;;-1:-1:-1;;;;;24644:21:0;;:::o;25639:25::-;;;-1:-1:-1;;;;;25639:25:0;;:::o;37038:622::-;37219:6;;37173:4;;-1:-1:-1;;;;;37219:6:0;37205:10;:20;;:49;;-1:-1:-1;37243:11:0;;-1:-1:-1;;;;;37243:11:0;37229:10;:25;37205:49;37189:125;;;;;;;-1:-1:-1;;;;;37189:125:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37189:125:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37339:26:0;;;;;;:13;:26;;;;;;:31;;37323:119;;;;;-1:-1:-1;;;;;37323:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37451:27:0;;;;;;:14;:27;;;;;;;;:42;;;37500:22;:35;;;;;;:58;;;37572:62;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;37650:4:0;37038:622;;;;;:::o;43525:683::-;43671:7;43690:18;;:::i;:::-;-1:-1:-1;;;;;43719:28:0;;;;;;:18;:28;;;;;;;;43715:59;;;43765:1;43758:8;;;;43715:59;-1:-1:-1;;;;;;43881:15:0;;;;;;;:9;:15;;;;;;;;:22;;;;;;;;;;;;43875:28;;;;;;;;;;;;;;;;;;;;;;;;;43916:20;:52;;;;-1:-1:-1;43940:23:0;;;;:28;43916:52;43912:210;;;-1:-1:-1;;;;;44025:21:0;;;;;;:14;:21;;;;;;;;;44007:39;;44083:29;;;:22;:29;;;;;;44057:23;;;:55;43912:210;44178:23;;;;44153:15;;44137:65;;44174:2;:27;;44137:32;;:11;;:32;:15;:32;:::i;:::-;:36;:65;:36;:65;:::i;:::-;44130:72;;43525:683;;;;;;;;:::o;53140:1241::-;53312:12;;:::i;:::-;53418:42;;;53482;;;;53547:29;;53606:42;;;;53670:29;;;;53728;;;;53776;;;;53371:449;;;;53404:4;53371:449;;;;;;-1:-1:-1;;;;;53371:449:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;53371:449:0;;;;;;53361:460;;53336:22;;;;53371:449;;;;53361:460;;;;53371:449;53361:460;36:153:-1;66:2;58:11;;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;;;;365:33;;53361:460:0;;;;;;;;;;;-1:-1:-1;53898:4:0;;-1:-1:-1;53912:39:0;;-1:-1:-1;53952:1:0;;-1:-1:-1;53912:42:0;;;;53976:39;54016:1;53976:42;;;;54041:26;54068:1;54041:29;;;;54100:39;54140:1;54100:42;;;;54164:26;54191:1;54164:29;;;;54222:26;54249:1;54222:29;;;;54270:26;54297:1;54270:29;;;;53865:449;;;;;;-1:-1:-1;;;;;53865:449:0;-1:-1:-1;;;;;53865:449:0;;;;;;;;-1:-1:-1;;;;;53865:449:0;-1:-1:-1;;;;;53865:449:0;;;;;;;;-1:-1:-1;;;;;53865:449:0;-1:-1:-1;;;;;53865:449:0;;;;;;;;;;;;;-1:-1:-1;;;;;53865:449:0;-1:-1:-1;;;;;53865:449:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;53865:449:0;;;53855:460;;;;;;;;;;;;;36:153:-1;66:2;58:11;;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;53855:460:0;;;;;;;;;;;;54331:44;;;;;;;;;;;;;;;;-1:-1:-1;53855:460:0;;53140:1241;-1:-1:-1;;;;;;53140:1241:0:o;42511:699::-;42630:22;;:::i;:::-;42674:205;;;;;;;;;42706:5;;42727:42;;42706:64;;;;-1:-1:-1;;;;;42706:64:0;;;;;;;;;42674:205;;;;42706:5;;;:20;;:64;;;;;42727:42;;42706:64;;;;;-1:-1:-1;42706:5:0;:64;;;5:2:-1;;;;30:1;27;20:12;5:2;42706:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;42706:64:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42706:64:0;-1:-1:-1;;;;;42674:205:0;;;;;42798:5;;42706:64;42674:205;;;;42798:5;:20;42819:39;42859:1;42819:42;;;;42798:64;;;;;-1:-1:-1;;;42798:64:0;;;;;;;-1:-1:-1;;;;;42798:64:0;-1:-1:-1;;;;;42798:64:0;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;42798:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;42798:64:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42798:64:0;-1:-1:-1;;;;;42674:205:0;;;;;;42949:13;;42664:215;;-1:-1:-1;42949:27:0;;;42933:131;;;;;-1:-1:-1;;;;;42933:131:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43089:13;;;;-1:-1:-1;;;;;43089:27:0;;;43073:131;;;;;-1:-1:-1;;;;;43073:131:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44878:1392;45125:17;;-1:-1:-1;;;;;45125:17:0;45111:10;:31;;:62;;-1:-1:-1;45146:10:0;45168:4;45146:27;45111:62;45095:167;;;;;;;-1:-1:-1;;;;;45095:167:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45355:29;;;;45339:12;:45;;45322:144;;;;;-1:-1:-1;;;;;45322:144:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45507:29;;;;45491:12;:45;;45475:143;;;;;-1:-1:-1;;;;;45475:143:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45718:42;;;;-1:-1:-1;;;;;45704:57:0;;;;;;;:13;45718:42;45704:57;;;;;;;;45657:42;;;;45643:57;;;;;;;;;:118;;45627:260;;;;;-1:-1:-1;;;;;45627:260:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45959:29;;:34;;:81;;-1:-1:-1;46006:29:0;;;;:34;45959:81;:128;;;-1:-1:-1;46053:29:0;;;;:34;45959:128;:175;;;-1:-1:-1;46100:29:0;;;;:34;45959:175;45945:320;;;46158:99;;;-1:-1:-1;;;;;46158:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45945:320;44878:1392;;:::o;61498:372::-;61656:4;61672:21;61696:129;61777:9;61724:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;61724:63:0;;;61714:74;;;;;;;;;;;;;36:153:-1;66:2;58:11;;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;61714:74:0;;;;;;;;;;;;-1:-1:-1;61696:129:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;263:2;;-1:-1;;;61696:129:0;;;;;;;;;;;-1:-1:-1;61696:129:0;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;61696:129:0;;-1:-1:-1;;61696:129:0;;-1:-1:-1;;;;;61841:23:0;;;;;;;;;;61498:372;-1:-1:-1;;;;;;;61498:372:0:o;54387:2530::-;54563:13;;:::i;:::-;54635:17;;54588:36;54627:26;;;:7;:26;;;;;;;;54707:17;;;;54699:26;;;;;54766:42;;;;54734:17;;-1:-1:-1;;;;;54734:74:0;;;;;54852:29;;54815:17;;:34;;:66;54919:42;;;;;54888:17;;:73;;:28;;:73;55004:29;;;;54968:17;;:33;;:65;55046:33;;54627:26;;-1:-1:-1;55042:762:0;;;55166:37;;;;:42;;55148:130;;;;;-1:-1:-1;;;;;55148:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55328:37;;;;55287:17;;:38;;:78;55431:35;;;;55392:17;;:36;;:74;55042:762;;;55544:29;;;;55508:65;;55681:29;;55640:17;;:38;;:70;55737:17;;55508:33;55737:36;;;;:40;55042:762;55844:42;;;;;;55812:17;;;;;-1:-1:-1;;;;;55812:74:0;;;;;55930:29;;;;55893:17;;:34;;:66;55997:42;;;;55966:17;;:73;;:28;;;:73;;;;56082:29;;;;56046:17;;:33;;:65;56124:33;;-1:-1:-1;;56120:734:0;;;56214:37;;;;:42;;56196:130;;;;;-1:-1:-1;;;;;56196:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56376:37;;;;56335:17;;;;;:38;;:78;;;;56480:35;;;;56441:17;;:36;;:74;56120:734;;;56593:29;;;;56557:65;;56730:29;;;;;56593;56689:17;;;;:38;;;:70;56787:17;-1:-1:-1;56787:36:0;;;;:40;56120:734;56882:29;56893:6;:17;;;56882:10;:29::i;:::-;56862:49;;:17;;;:49;-1:-1:-1;56862:6:0;;54387:2530;-1:-1:-1;;;;54387:2530:0:o;57730:2769::-;57847:14;;:::i;:::-;57873:23;;:::i;:::-;57923;;:::i;:::-;57973:15;58042:18;58067:32;58106;58147:18;58172;60211:8;57899:6;:17;;;57873:43;;57949:6;:17;;;57923:43;;57991:6;:17;;;57973:35;;58234:10;:26;;;58203:10;:27;;;:57;;58199:2004;;;58284:71;58328:10;:26;;;58284:39;-1:-1:-1;;;58284:10:0;:27;;;:31;;:39;;;;:::i;:71::-;58271:84;;58396:71;58439:10;:27;;;58396:38;-1:-1:-1;;;58396:10:0;:26;;;:30;;:38;;;;:::i;:71::-;58382:85;;;58364:196;;;;;-1:-1:-1;;;;;58364:196:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58573:10;58569:655;;;58673:29;;;;58642:26;;;;:61;;;:30;:61;:::i;:::-;58615:88;;58730:66;58738:10;:31;;;58771:24;58730:7;:66::i;:::-;58714:82;-1:-1:-1;58878:41:0;-1:-1:-1;;;58878:29:0;58714:82;58896:10;58878:29;:17;:29;:::i;:41::-;58862:57;;58569:655;;;59023:29;;;;58992:26;;;;:61;;;:30;:61;:::i;:::-;58965:88;;59080:66;59088:10;:31;;;59121:24;59080:7;:66::i;:::-;59064:82;-1:-1:-1;59173:41:0;59203:10;59173:25;59064:82;-1:-1:-1;;;59173:25:0;:17;:25;:::i;:41::-;59157:57;;58569:655;58199:2004;;;59259:71;59302:10;:27;;;59259:38;-1:-1:-1;;;59259:10:0;:26;;;:30;;:38;;;;:::i;:71::-;59246:84;;59371:71;59415:10;:26;;;59371:39;-1:-1:-1;;;59371:10:0;:27;;;:31;;:39;;;;:::i;:71::-;59357:85;;;59339:193;;;;;-1:-1:-1;;;;;59339:193:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59545:10;59541:655;;;59645:29;;;;59614:26;;;;:61;;;:30;:61;:::i;:::-;59587:88;;59702:66;59710:10;:31;;;59743:24;59702:7;:66::i;:::-;59686:82;-1:-1:-1;59795:41:0;59825:10;59795:25;59686:82;-1:-1:-1;;;59795:25:0;:17;:25;:::i;:41::-;59779:57;;59541:655;;;59940:29;;;;59909:26;;;;:61;;;:30;:61;:::i;:::-;59882:88;;59997:66;60005:10;:31;;;60038:24;59997:7;:66::i;:::-;59981:82;-1:-1:-1;60145:41:0;-1:-1:-1;;;60145:29:0;59981:82;60163:10;60145:29;:17;:29;:::i;:41::-;60129:57;;59541:655;60222:10;:206;;60340:88;60357:10;:22;;;60381:10;:21;;;60404:13;60419:8;60340:16;:88::i;:::-;60222:206;;;60242:88;60259:10;:21;;;60282:10;:22;;;60306:13;60321:8;60242:16;:88::i;:::-;60444:49;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;60444:49:0;57730:2769;-1:-1:-1;;;;;;;;;57730:2769:0:o;13404:113::-;13462:7;13485:6;;;;13478:14;;;;-1:-1:-1;13506:5:0;;;13404:113::o;13523:133::-;13581:7;13609:5;;;13628:6;;;;13621:14;;;;13649:1;13523:133;-1:-1:-1;;;13523:133:0:o;46911:5484::-;47193:31;;:::i;:::-;48528:30;48610;48694:27;48744;48866:35;50280:24;;:::i;:::-;47272:73;47287:39;47327:1;47287:42;;;;;47331:7;:13;;;47272:14;:73::i;:::-;47231:38;;;:114;47393:73;47408:39;47448:1;47408:42;;;;;47452:13;;47393:14;:73::i;:::-;47352:38;;;:114;47513:73;47528:39;47568:1;47528:42;;47513:73;47473:37;;;:113;47633:73;47648:39;47688:1;47648:42;;47633:73;47593:113;;47974:13;;-1:-1:-1;;;;;47974:25:0;;48010:39;48050:1;48010:42;;;;48063:7;:15;;;48089:1;48101;47974:137;;;;;-1:-1:-1;;;47974:137:0;;;;;;;-1:-1:-1;;;;;47974:137:0;-1:-1:-1;;;;;47974:137:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47974:137:0;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;47974:137:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;47974:137:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47974:137:0;47958:251;;;;;;;-1:-1:-1;;;;;47958:251:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48234:13;;;;;48270:42;;;;48323:15;;;;48349:11;;;;;48371:9;;;48234:155;;;;;-1:-1:-1;;;;;48234:155:0;;;;;;;;;;;;;;;;;;;;;;;;48371:9;;;48234:155;;;;;:25;;;;;;;:155;;;;;;;;;;;-1:-1:-1;48234:25:0;:155;;;5:2:-1;;;;30:1;27;20:12;5:2;48234:155:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48234:155:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48234:155:0;48218:269;;;;;;;-1:-1:-1;;;;;48218:269:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48561:42;;;;;48643;;;;48724:13;;48774;;;;48839:11;;;;48561:42;;-1:-1:-1;48643:42:0;;-1:-1:-1;48724:13:0;;-1:-1:-1;48774:13:0;;-1:-1:-1;48839:16:0;48836:566;;48910:9;;;48904:46;;;;;;-1:-1:-1;;;;;48904:46:0;;;;;;;;;;;;48910:9;;;;;48904:26;;:46;;;;;;;;;;;;;;;48910:9;;48904:46;;;5:2:-1;;;;30:1;27;20:12;5:2;48904:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48904:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48904:46:0;48985:9;;;49029:12;;49043:11;;;;;48979:76;;;;;-1:-1:-1;;;;;48979:76:0;;;;;;;;;;49029:12;;;48979:76;;;;;;;;;48904:46;;-1:-1:-1;48985:9:0;;;48979:29;;:76;;;;;48904:46;;48979:76;;;;;;;;48985:9;;48979:76;;;5:2:-1;;;;30:1;27;20:12;5:2;48979:76:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48979:76:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48979:76:0;48961:215;;;;;;;-1:-1:-1;;;;;48961:215:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49285:11;;;;49253:44;;:27;;:44;:31;:44;:::i;:::-;49209:9;;;49203:46;;;;;;-1:-1:-1;;;;;49203:46:0;;;;;;;;;;;;49209:9;;;;;49203:26;;:46;;;;;;;;;;;;;;;49209:9;;49203:46;;;5:2:-1;;;;30:1;27;20:12;5:2;49203:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;49203:46:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;49203:46:0;:94;49185:209;;;;;-1:-1:-1;;;;;49185:209:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49465:36:0;;;49461:390;;;49549:15;;49512:53;;-1:-1:-1;;;;;49512:36:0;;;:53;;;;;49549:15;49512:53;49549:15;49512:53;49549:15;49512:36;:53;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;49512:53:0;49461:390;;;49606:107;49633:22;49657:18;49677;49697:7;:15;;;49606:26;:107::i;:::-;49588:255;;;;;;;-1:-1:-1;;;;;49588:255:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49863:36:0;;;49859:390;;;49947:15;;;;49910:53;;-1:-1:-1;;;;;49910:36:0;;;:53;;;;;;;;;49947:15;49910:36;:53;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;49910:53:0;49859:390;;;50004:107;50031:22;50055:18;50075;50095:7;:15;;;50004:26;:107::i;:::-;49986:255;;;;;;;-1:-1:-1;;;;;49986:255:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;50315:40:0;;;;;;;50311:1213;;50441:15;;;;50399:37;;:58;;;:41;:58;:::i;:::-;50366:91;;50543:15;;50500:38;;;;:59;;;:42;:59;:::i;:::-;50466:31;;;:93;50601:9;;-1:-1:-1;;;;;50601:35:0;;;:9;;:35;:192;;50777:15;;50735:37;;;;:58;;;:41;:58;:::i;:::-;50601:192;;;50711:11;;;;;50690:15;;50648:37;;;;:75;;:58;;:37;:58;:41;:58;:::i;:::-;:62;:75;:62;:75;:::i;:::-;50568:30;;;:225;50836:9;;-1:-1:-1;;;;;50836:35:0;;;:9;;:35;:194;;51014:15;;;;50971:38;;;;:59;;;:42;:59;:::i;:::-;50836:194;;;50883:76;50947:7;:11;;;50883:59;50926:7;:15;;;50883;:38;;;:42;;:59;;;;:::i;:76::-;50802:31;;;:228;50311:1213;;;51129:9;;-1:-1:-1;;;;;51129:35:0;;;:9;;:35;:152;;51243:15;:38;;;51129:152;;;51219:11;;;;51176:38;;;;:55;;;:42;:55;:::i;:::-;51086:31;;;:195;;;51053:228;;51366:9;;-1:-1:-1;;;;;51366:35:0;;;:9;;:35;:150;;51479:15;:37;;;51366:150;;;51455:11;;;;;51413:37;;;;:54;;;:41;:54;:::i;:::-;51324:30;;;:192;;;51290:31;;;:226;50311:1213;51583:58;51598:22;51622:18;51583:14;:58::i;:::-;51548:31;;;;:93;51532:210;;;;;-1:-1:-1;;;;;51532:210:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51800:58;51815:22;51839:18;51800:14;:58::i;:::-;51765:31;;;;:93;51749:210;;;;;-1:-1:-1;;;;;51749:210:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52016:58;52031:22;52055:18;52016:14;:58::i;:::-;51982:30;;;;:92;51966:208;;;;;-1:-1:-1;;;;;51966:208:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52231:58;52246:22;52270:18;52231:14;:58::i;:::-;52197:30;;:92;52181:208;;;;;-1:-1:-1;;;;;52181:208:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46911:5484;;;;;;;;;;:::o;12975:147::-;13033:7;13061:5;;;13080:6;;;:20;;;13099:1;13094;13090;:5;;;;;;;;:10;13080:20;13073:28;;;;;13128:270;13186:7;13277:9;13293:1;13289;:5;;;;;;;;;13128:270;-1:-1:-1;;;;13128:270:0:o;57137:151::-;57264:17;;;;-1:-1:-1;;;;;57250:32:0;;;57194:4;57250:32;;;:13;:32;;;;;;;57228:18;;57214:33;;;;;;;:68;;57137:151::o;60940:135::-;61016:7;61046:1;61042;:5;:27;;61068:1;61042:27;;;-1:-1:-1;61057:1:0;;61035:34;-1:-1:-1;60940:135:0:o;46276:217::-;46351:7;-1:-1:-1;;;;;46371:19:0;;;46367:121;;;-1:-1:-1;;;;;;46408:13:0;;;46401:20;;46367:121;46457:5;-1:-1:-1;;;;;46451:22:0;;46474:5;46451:29;;;;;-1:-1:-1;;;46451:29:0;;;;;;;-1:-1:-1;;;;;46451:29:0;-1:-1:-1;;;;;46451:29:0;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46451:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46451:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46451:29:0;;-1:-1:-1;46444:36:0;;20687:675;20845:49;;;;;;-1:-1:-1;;;;;20845:49:0;;;;;;;;;;;;;;;;;;;;;;20822:11;;20845:29;;;;;:49;;;;;20822:11;;20845:49;;;;;;;20822:11;20845:29;:49;;;5:2:-1;;;;30:1;27;20:12;5:2;20845:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;20845:49:0;;;;20928:16;20957:1;20952:117;;;;21082:2;21077:175;;;;21339:1;21336;21329:12;20952:117;-1:-1:-1;;21025:6:0;-1:-1:-1;20952:117:0;;21077:175;21162:2;21159:1;21156;21141:24;-1:-1:-1;;21191:1:0;21185:8;;20912:445;-1:-1:-1;;;;20912:445:0:o;23382:39910::-;;;;;;;;;;;;;;;105:10:-1;23382:39910:0;88:34:-1;-1:-1;23382:39910:0;;;-1:-1:-1;;23382:39910:0:o;:::-;;;;;;;;;;-1:-1:-1;23382:39910:0;;;;;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;-1:-1:-1;;;;;23382:39910:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23382:39910:0;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

bzzr://f90ab6cbfaddca5d65034a0df67c5ae4d8931c4be868826087a9089bdaefaf3a

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.