ETH Price: $3,579.38 (+0.63%)
Gas: 69 Gwei

Contract

0xba3Ed686cC32FfA8664628b1E96D8022e40543dE
 

Overview

ETH Balance

5.553170497988678327 ETH

Eth Value

$19,876.90 (@ $3,579.38/ETH)

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Emergency Withdr...87193542019-10-11 8:36:071630 days ago1570782967IN
Switcheo Exchange
0 ETH0.000235599
Slow Withdraw87153472019-10-10 17:21:171630 days ago1570728077IN
Switcheo Exchange
0 ETH0.000025521
Announce Withdra...87153432019-10-10 17:20:311630 days ago1570728031IN
Switcheo Exchange
0 ETH0.000065421
Emergency Withdr...87133662019-10-10 9:55:251631 days ago1570701325IN
Switcheo Exchange
0 ETH0.0003125812
Emergency Withdr...87133552019-10-10 9:52:501631 days ago1570701170IN
Switcheo Exchange
0 ETH0.036312.1
Emergency Withdr...87133082019-10-10 9:41:431631 days ago1570700503IN
Switcheo Exchange
0 ETH0.03612
Set Cancel Annou...87130942019-10-10 8:52:051631 days ago1570697525IN
Switcheo Exchange
0 ETH0.000027381
Set Withdraw Ann...87130852019-10-10 8:50:331631 days ago1570697433IN
Switcheo Exchange
0 ETH0.0002767110
Emergency Withdr...87130852019-10-10 8:50:331631 days ago1570697433IN
Switcheo Exchange
0 ETH0.0003420813.1
Emergency Withdr...87130852019-10-10 8:50:331631 days ago1570697433IN
Switcheo Exchange
0 ETH0.0003420813.1
Emergency Withdr...87130852019-10-10 8:50:331631 days ago1570697433IN
Switcheo Exchange
0 ETH0.0003420813.1
Emergency Withdr...87130852019-10-10 8:50:331631 days ago1570697433IN
Switcheo Exchange
0 ETH0.0003420813.1
Emergency Withdr...87130852019-10-10 8:50:331631 days ago1570697433IN
Switcheo Exchange
0 ETH0.0003429113.1
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0002872411
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0002879411
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0006382711
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0004732711
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0002879411
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0002872411
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0002879411
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0002879411
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0005632111
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.0002872411
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.000253919.7
Emergency Withdr...87130812019-10-10 8:49:401631 days ago1570697380IN
Switcheo Exchange
0 ETH0.000253299.7
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Txn Hash Block From To Value
87193542019-10-11 8:36:071630 days ago1570782967
Switcheo Exchange
0.29550857 ETH
87153472019-10-10 17:21:171630 days ago1570728077
Switcheo Exchange
0.31523836 ETH
87133662019-10-10 9:55:251631 days ago1570701325
Switcheo Exchange
1.7 ETH
87130852019-10-10 8:50:331631 days ago1570697433
Switcheo Exchange
0.0035254 ETH
87130852019-10-10 8:50:331631 days ago1570697433
Switcheo Exchange
0.00352685 ETH
87130852019-10-10 8:50:331631 days ago1570697433
Switcheo Exchange
0.00354463 ETH
87130852019-10-10 8:50:331631 days ago1570697433
Switcheo Exchange
0.0035508 ETH
87130852019-10-10 8:50:331631 days ago1570697433
Switcheo Exchange
0.00355773 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.0035832 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.00359558 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.00369952 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.00371477 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.00372872 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.0037363 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.00375099 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.00375524 ETH
87130812019-10-10 8:49:401631 days ago1570697380
Switcheo Exchange
0.00376479 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.00377342 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.00387809 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.00389939 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.00390792 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.00391 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.00399429 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.004 ETH
87130762019-10-10 8:47:211631 days ago1570697241
Switcheo Exchange
0.004018 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Broker

Compiler Version
v0.4.25+commit.59dbf8f1

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-11-08
*/

pragma solidity ^0.4.25;


/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;


  event OwnershipRenounced(address indexed previousOwner);
  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  constructor() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to relinquish control of the contract.
   * @notice Renouncing to ownership will leave the contract without an owner.
   * It will not be possible to call the functions with the `onlyOwner`
   * modifier anymore.
   */
  function renounceOwnership() public onlyOwner {
    emit OwnershipRenounced(owner);
    owner = address(0);
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function transferOwnership(address _newOwner) public onlyOwner {
    _transferOwnership(_newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address _newOwner) internal {
    require(_newOwner != address(0));
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }
}


/**
 * @title Claimable
 * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
 * This allows the new owner to accept the transfer.
 */
contract Claimable is Ownable {
  address public pendingOwner;

  /**
   * @dev Modifier throws if called by any account other than the pendingOwner.
   */
  modifier onlyPendingOwner() {
    require(msg.sender == pendingOwner);
    _;
  }

  /**
   * @dev Allows the current owner to set the pendingOwner address.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    pendingOwner = newOwner;
  }

  /**
   * @dev Allows the pendingOwner address to finalize the transfer.
   */
  function claimOwnership() public onlyPendingOwner {
    emit OwnershipTransferred(owner, pendingOwner);
    owner = pendingOwner;
    pendingOwner = address(0);
  }
}
/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (_a == 0) {
      return 0;
    }

    c = _a * _b;
    assert(c / _a == _b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  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 _a / _b;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    assert(_b <= _a);
    return _a - _b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    c = _a + _b;
    assert(c >= _a);
    return c;
  }
}

/// @title The Broker + Vault contract for Switcheo Exchange
/// @author Switcheo Network
/// @notice This contract faciliates Ethereum and ERC-20 trades
/// between users. Users can trade with each other by making
/// and taking offers without giving up custody of their tokens.
/// Users should first deposit tokens, then communicate off-chain
/// with the exchange coordinator, in order to place orders
/// (make / take offers). This allows trades to be confirmed
/// immediately by the coordinator, and settled on-chain through
/// this contract at a later time.
contract Broker is Claimable {
    using SafeMath for uint256;

    struct Offer {
        address maker;
        address offerAsset;
        address wantAsset;
        uint64 nonce;
        uint256 offerAmount;
        uint256 wantAmount;
        uint256 availableAmount; // the remaining offer amount
    }

    struct AnnouncedWithdrawal {
        uint256 amount;
        uint256 canWithdrawAt;
    }

    // Exchange states
    enum State { Active, Inactive }
    State public state;

    // The maximum announce delay in seconds
    // (7 days * 60 mins * 60 seconds)
    uint32 constant maxAnnounceDelay = 604800;
    // Ether token "address" is set as the constant 0x00
    address constant etherAddr = address(0);

    // deposits
    uint8 constant ReasonDeposit = 0x01;
    // making an offer
    uint8 constant ReasonMakerGive = 0x02;
    uint8 constant ReasonMakerFeeGive = 0x10;
    uint8 constant ReasonMakerFeeReceive = 0x11;
    // filling an offer
    uint8 constant ReasonFillerGive = 0x03;
    uint8 constant ReasonFillerFeeGive = 0x04;
    uint8 constant ReasonFillerReceive = 0x05;
    uint8 constant ReasonMakerReceive = 0x06;
    uint8 constant ReasonFillerFeeReceive = 0x07;
    // cancelling an offer
    uint8 constant ReasonCancel = 0x08;
    uint8 constant ReasonCancelFeeGive = 0x12;
    uint8 constant ReasonCancelFeeReceive = 0x13;
    // withdrawals
    uint8 constant ReasonWithdraw = 0x09;
    uint8 constant ReasonWithdrawFeeGive = 0x14;
    uint8 constant ReasonWithdrawFeeReceive = 0x15;

    // The coordinator sends trades (balance transitions) to the exchange
    address public coordinator;
    // The operator receives fees
    address public operator;
    // The time required to wait after a cancellation is announced
    // to let the operator detect it in non-byzantine conditions
    uint32 public cancelAnnounceDelay;
    // The time required to wait after a withdrawal is announced
    // to let the operator detect it in non-byzantine conditions
    uint32 public withdrawAnnounceDelay;

    // User balances by: userAddress => assetHash => balance
    mapping(address => mapping(address => uint256)) public balances;
    // Offers by the creation transaction hash: transactionHash => offer
    mapping(bytes32 => Offer) public offers;
    // A record of which hashes have been used before
    mapping(bytes32 => bool) public usedHashes;
    // Set of whitelisted spender addresses allowed by the owner
    mapping(address => bool) public whitelistedSpenders;
    // Spenders which have been approved by individual user as: userAddress => spenderAddress => true
    mapping(address => mapping(address => bool)) public approvedSpenders;
    // Announced withdrawals by: userAddress => assetHash => data
    mapping(address => mapping(address => AnnouncedWithdrawal)) public announcedWithdrawals;
    // Announced cancellations by: offerHash => data
    mapping(bytes32 => uint256) public announcedCancellations;

    // Emitted when new offers made
    event Make(address indexed maker, bytes32 indexed offerHash);
    // Emitted when offers are filled
    event Fill(address indexed filler, bytes32 indexed offerHash, uint256 amountFilled, uint256 amountTaken, address indexed maker);
    // Emitted when offers are cancelled
    event Cancel(address indexed maker, bytes32 indexed offerHash);
    // Emitted on any balance state transition (+ve)
    event BalanceIncrease(address indexed user, address indexed token, uint256 amount, uint8 indexed reason);
    // Emitted on any balance state transition (-ve)
    event BalanceDecrease(address indexed user, address indexed token, uint256 amount, uint8 indexed reason);
    // Emitted when a withdrawal is annnounced
    event WithdrawAnnounce(address indexed user, address indexed token, uint256 amount, uint256 canWithdrawAt);
    // Emitted when a cancellation is annnounced
    event CancelAnnounce(address indexed user, bytes32 indexed offerHash, uint256 canCancelAt);
    // Emitted when a user approved a spender
    event SpenderApprove(address indexed user, address indexed spender);
    // Emitted when a user rescinds approval for a spender
    event SpenderRescind(address indexed user, address indexed spender);

    /// @notice Initializes the Broker contract
    /// @dev The coordinator and operator is initialized
    /// to be the address of the sender. The Broker is immediately
    /// put into an active state, with maximum exit delays set.
    constructor()
        public
    {
        coordinator = msg.sender;
        operator = msg.sender;
        cancelAnnounceDelay = maxAnnounceDelay;
        withdrawAnnounceDelay = maxAnnounceDelay;
        state = State.Active;
    }

    modifier onlyCoordinator() {
        require(
            msg.sender == coordinator,
            "Invalid sender"
        );
        _;
    }

    modifier onlyActiveState() {
        require(
            state == State.Active,
            "Invalid state"
        );
        _;
    }

    modifier onlyInactiveState() {
        require(
            state == State.Inactive,
            "Invalid state"
        );
        _;
    }

    modifier notMoreThanMaxDelay(uint32 _delay) {
        require(
            _delay <= maxAnnounceDelay,
            "Invalid delay"
        );
        _;
    }

    modifier unusedReasonCode(uint8 _reasonCode) {
        require(
            _reasonCode > ReasonWithdrawFeeReceive,
            "Invalid reason code"
        );
        _;
    }

    /// @notice Sets the Broker contract state
    /// @dev There are only two states - Active & Inactive.
    ///
    /// The Active state is the normal operating state for the contract -
    /// deposits, trading and withdrawals can be carried out.
    ///
    /// In the Inactive state, the coordinator can invoke additional
    /// emergency methods such as emergencyCancel and emergencyWithdraw,
    /// without the cooperation of users. However, deposits and trading
    /// methods cannot be invoked at that time. This state is meant
    /// primarily to terminate and upgrade the contract, or to be used
    /// in the event that the contract is considered no longer viable
    /// to continue operation, and held tokens should be immediately
    /// withdrawn to their respective owners.
    /// @param _state The state to transition the contract into
    function setState(State _state) external onlyOwner { state = _state; }

    /// @notice Sets the coordinator address.
    /// @dev All standard operations (except `depositEther`)
    /// must be invoked by the coordinator.
    /// @param _coordinator The address to set as the coordinator
    function setCoordinator(address _coordinator) external onlyOwner {
        _validateAddress(_coordinator);
        coordinator = _coordinator;
    }

    /// @notice Sets the operator address.
    /// @dev All fees are paid to the operator.
    /// @param _operator The address to set as the operator
    function setOperator(address _operator) external onlyOwner {
        _validateAddress(operator);
        operator = _operator;
    }

    /// @notice Sets the delay between when a cancel
    /// intention must be announced, and when the cancellation
    /// can actually be executed on-chain
    /// @dev This delay exists so that the coordinator has time to
    /// respond when a user is attempting to bypass it and cancel
    /// offers directly on-chain.
    /// Note that this is an direct on-chain cancellation
    /// is an atypical operation - see `slowCancel`
    /// for more details.
    /// @param _delay The delay in seconds
    function setCancelAnnounceDelay(uint32 _delay)
        external
        onlyOwner
        notMoreThanMaxDelay(_delay)
    {
        cancelAnnounceDelay = _delay;
    }

    /// @notice Sets the delay (in seconds) between when a withdrawal
    /// intention must be announced, and when the withdrawal
    /// can actually be executed on-chain.
    /// @dev This delay exists so that the coordinator has time to
    /// respond when a user is attempting to bypass it and cancel
    /// offers directly on-chain. See `announceWithdraw` and
    /// `slowWithdraw` for more details.
    /// @param _delay The delay in seconds
    function setWithdrawAnnounceDelay(uint32 _delay)
        external
        onlyOwner
        notMoreThanMaxDelay(_delay)
    {
        withdrawAnnounceDelay = _delay;
    }

    /// @notice Adds an address to the set of allowed spenders.
    /// @dev Spenders are meant to be additional EVM contracts that
    /// will allow adding or upgrading of trading functionality, without
    /// having to cancel all offers and withdraw all tokens for all users.
    /// This whitelist ensures that all approved spenders are contracts
    /// that have been verified by the owner. Note that each user also
    /// has to invoke `approveSpender` to actually allow the `_spender`
    /// to spend his/her balance, so that they can examine / verify
    /// the new spender contract first.
    /// @param _spender The address to add as a whitelisted spender
    function addSpender(address _spender)
        external
        onlyOwner
    {
        _validateAddress(_spender);
        whitelistedSpenders[_spender] = true;
    }

    /// @notice Removes an address from the set of allowed spenders.
    /// @dev Note that removing a spender from the whitelist will not
    /// prevent already approved spenders from spending a user's balance.
    /// This is to ensure that the spender contracts can be certain that once
    /// an approval is done, the owner cannot rescient spending priviledges,
    /// and cause tokens to be withheld or locked in the spender contract.
    /// Users must instead manually rescind approvals using `rescindApproval`
    /// after the `_spender` has been removed from the whitelist.
    /// @param _spender The address to remove as a whitelisted spender
    function removeSpender(address _spender)
        external
        onlyOwner
    {
        _validateAddress(_spender);
        delete whitelistedSpenders[_spender];
    }

    /// @notice Deposits Ethereum tokens under the `msg.sender`'s balance
    /// @dev Allows sending ETH to the contract, and increasing
    /// the user's contract balance by the amount sent in.
    /// This operation is only usable in an Active state to prevent
    /// a terminated contract from receiving tokens.
    function depositEther()
        external
        payable
        onlyActiveState
    {
        require(
            msg.value > 0,
            'Invalid value'
        );
        balances[msg.sender][etherAddr] = balances[msg.sender][etherAddr].add(msg.value);
        emit BalanceIncrease(msg.sender, etherAddr, msg.value, ReasonDeposit);
    }

    /// @notice Deposits ERC20 tokens under the `_user`'s balance
    /// @dev Allows sending ERC20 tokens to the contract, and increasing
    /// the user's contract balance by the amount sent in. This operation
    /// can only be used after an ERC20 `approve` operation for a
    /// sufficient amount has been carried out.
    ///
    /// Note that this operation does not require user signatures as
    /// a valid ERC20 `approve` call is considered as intent to deposit
    /// the tokens. This is as there is no other ERC20 methods that this
    /// contract can call.
    ///
    /// This operation can only be called by the coordinator,
    /// and should be autoamtically done so whenever an `approve` event
    /// from a ERC20 token (that the coordinator deems valid)
    /// approving this contract to spend tokens on behalf of a user is seen.
    ///
    /// This operation is only usable in an Active state to prevent
    /// a terminated contract from receiving tokens.
    /// @param _user The address of the user that is depositing tokens
    /// @param _token The address of the ERC20 token to deposit
    /// @param _amount The (approved) amount to deposit
    function depositERC20(
        address _user,
        address _token,
        uint256 _amount
    )
        external
        onlyCoordinator
        onlyActiveState
    {
        require(
            _amount > 0,
            'Invalid value'
        );
        balances[_user][_token] = balances[_user][_token].add(_amount);

        _validateIsContract(_token);
        require(
            _token.call(
                bytes4(keccak256("transferFrom(address,address,uint256)")),
                _user, address(this), _amount
            ),
            "transferFrom call failed"
        );
        require(
            _getSanitizedReturnValue(),
            "transferFrom failed."
        );

        emit BalanceIncrease(_user, _token, _amount, ReasonDeposit);
    }

    /// @notice Withdraws `_amount` worth of `_token`s to the `_withdrawer`
    /// @dev This is the standard withdraw operation. Tokens can only be
    /// withdrawn directly to the token balance owner's address.
    /// Fees can be paid to cover network costs, as the operation must
    /// be invoked by the coordinator. The hash of all parameters, prefixed
    /// with the operation name "withdraw" must be signed by the withdrawer
    /// to validate the withdrawal request. A nonce that is issued by the
    /// coordinator is used to prevent replay attacks.
    /// See `slowWithdraw` for withdrawing without requiring the coordinator's
    /// involvement.
    /// @param _withdrawer The address of the user that is withdrawing tokens
    /// @param _token The address of the token to withdraw
    /// @param _amount The number of tokens to withdraw
    /// @param _feeAsset The address of the token to use for fee payment
    /// @param _feeAmount The amount of tokens to pay as fees to the operator
    /// @param _nonce The nonce to prevent replay attacks
    /// @param _v The `v` component of the `_withdrawer`'s signature
    /// @param _r The `r` component of the `_withdrawer`'s signature
    /// @param _s The `s` component of the `_withdrawer`'s signature
    function withdraw(
        address _withdrawer,
        address _token,
        uint256 _amount,
        address _feeAsset,
        uint256 _feeAmount,
        uint64 _nonce,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    )
        external
        onlyCoordinator
    {
        bytes32 msgHash = keccak256(abi.encodePacked(
            "withdraw",
            _withdrawer,
            _token,
            _amount,
            _feeAsset,
            _feeAmount,
            _nonce
        ));

        require(
            _recoverAddress(msgHash, _v, _r, _s) == _withdrawer,
            "Invalid signature"
        );

        _validateAndAddHash(msgHash);

        _withdraw(_withdrawer, _token, _amount, _feeAsset, _feeAmount);
    }

    /// @notice Announces intent to withdraw tokens using `slowWithdraw`
    /// @dev Allows a user to invoke `slowWithdraw` after a minimum of
    /// `withdrawAnnounceDelay` seconds has passed.
    /// This announcement and delay is necessary so that the operator has time
    /// to respond if a user attempts to invoke a `slowWithdraw` even though
    /// the exchange is operating normally. In that case, the coordinator would respond
    /// by not allowing the announced amount of tokens to be used in future trades
    /// the moment a `WithdrawAnnounce` is seen.
    /// @param _token The address of the token to withdraw after the required exit delay
    /// @param _amount The number of tokens to withdraw after the required exit delay
    function announceWithdraw(
        address _token,
        uint256 _amount
    )
        external
    {
        require(
            _amount <= balances[msg.sender][_token],
            "Amount too high"
        );

        AnnouncedWithdrawal storage announcement = announcedWithdrawals[msg.sender][_token];
        uint256 canWithdrawAt = now + withdrawAnnounceDelay;

        announcement.canWithdrawAt = canWithdrawAt;
        announcement.amount = _amount;

        emit WithdrawAnnounce(msg.sender, _token, _amount, canWithdrawAt);
    }

    /// @notice Withdraw tokens without requiring the coordinator
    /// @dev This operation is meant to be used if the operator becomes "byzantine",
    /// so that users can still exit tokens locked in this contract.
    /// The `announceWithdraw` operation has to be invoked first, and a minimum time of
    /// `withdrawAnnounceDelay` seconds have to pass, before this operation can be carried out.
    /// Note that this direct on-chain withdrawal is an atypical operation, and
    /// the normal `withdraw` operation should be used in non-byzantine states.
    /// @param _withdrawer The address of the user that is withdrawing tokens
    /// @param _token The address of the token to withdraw
    /// @param _amount The number of tokens to withdraw
    function slowWithdraw(
        address _withdrawer,
        address _token,
        uint256 _amount
    )
        external
    {
        AnnouncedWithdrawal memory announcement = announcedWithdrawals[_withdrawer][_token];

        require(
            announcement.canWithdrawAt != 0 && announcement.canWithdrawAt <= now,
            "Insufficient delay"
        );

        require(
            announcement.amount == _amount,
            "Invalid amount"
        );

        delete announcedWithdrawals[_withdrawer][_token];

        _withdraw(_withdrawer, _token, _amount, etherAddr, 0);
    }

    /// @notice Withdraws tokens to the owner without requiring the owner's signature
    /// @dev Can only be invoked in an Inactive state by the coordinator.
    /// This operation is meant to be used in emergencies only.
    /// @param _withdrawer The address of the user that should have tokens withdrawn
    /// @param _token The address of the token to withdraw
    /// @param _amount The number of tokens to withdraw
    function emergencyWithdraw(
        address _withdrawer,
        address _token,
        uint256 _amount
    )
        external
        onlyCoordinator
        onlyInactiveState
    {
        _withdraw(_withdrawer, _token, _amount, etherAddr, 0);
    }

    /// @notice Makes an offer which can be filled by other users.
    /// @dev Makes an offer for `_offerAmount` of `offerAsset` tokens
    /// for `wantAmount` of `wantAsset` tokens, that can be filled later
    /// by one or more counterparties using `fillOffer` or `fillOffers`.
    /// The offer can be later cancelled using `cancel` or `slowCancel` as long
    /// as it has not completely been filled.
    /// A fee of `_feeAmount` of `_feeAsset` tokens can be paid to the operator
    /// to cover orderbook maintenance and network costs.
    /// The hash of all parameters, prefixed with the operation name "makeOffer"
    /// must be signed by the `_maker` to validate the offer request.
    /// A nonce that is issued by the coordinator is used to prevent replay attacks.
    /// This operation can only be invoked by the coordinator in an Active state.
    /// @param _maker The address of the user that is making the offer
    /// @param _offerAsset The address of the token being offered
    /// @param _wantAsset The address of the token asked in return
    /// @param _offerAmount The number of tokens being offered
    /// @param _wantAmount The number of tokens asked for in return
    /// @param _feeAsset The address of the token to use for fee payment
    /// @param _feeAmount The amount of tokens to pay as fees to the operator
    /// @param _nonce The nonce to prevent replay attacks
    /// @param _v The `v` component of the `_maker`'s signature
    /// @param _r The `r` component of the `_maker`'s signature
    /// @param _s The `s` component of the `_maker`'s signature
    function makeOffer(
        address _maker,
        address _offerAsset,
        address _wantAsset,
        uint256 _offerAmount,
        uint256 _wantAmount,
        address _feeAsset,
        uint256 _feeAmount,
        uint64 _nonce,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    )
        external
        onlyCoordinator
        onlyActiveState
    {
        require(
            _offerAmount > 0 && _wantAmount > 0,
            "Invalid amounts"
        );

        require(
            _offerAsset != _wantAsset,
            "Invalid assets"
        );

        bytes32 offerHash = keccak256(abi.encodePacked(
            "makeOffer",
            _maker,
            _offerAsset,
            _wantAsset,
            _offerAmount,
            _wantAmount,
            _feeAsset,
            _feeAmount,
            _nonce
        ));

        require(
            _recoverAddress(offerHash, _v, _r, _s) == _maker,
            "Invalid signature"
        );

        _validateAndAddHash(offerHash);

        // Reduce maker's balance
        _decreaseBalanceAndPayFees(
            _maker,
            _offerAsset,
            _offerAmount,
            _feeAsset,
            _feeAmount,
            ReasonMakerGive,
            ReasonMakerFeeGive,
            ReasonMakerFeeReceive
        );

        // Store the offer
        Offer storage offer = offers[offerHash];
        offer.maker = _maker;
        offer.offerAsset = _offerAsset;
        offer.wantAsset = _wantAsset;
        offer.offerAmount = _offerAmount;
        offer.wantAmount = _wantAmount;
        offer.availableAmount = _offerAmount;
        offer.nonce = _nonce;

        emit Make(_maker, offerHash);
    }

    /// @notice Fills a offer that has been previously made using `makeOffer`.
    /// @dev Fill an offer with `_offerHash` by giving `_amountToTake` of
    /// the offers' `wantAsset` tokens.
    /// A fee of `_feeAmount` of `_feeAsset` tokens can be paid to the operator
    /// to cover orderbook maintenance and network costs.
    /// The hash of all parameters, prefixed with the operation name "fillOffer"
    /// must be signed by the `_filler` to validate the fill request.
    /// A nonce that is issued by the coordinator is used to prevent replay attacks.
    /// This operation can only be invoked by the coordinator in an Active state.
    /// @param _filler The address of the user that is filling the offer
    /// @param _offerHash The hash of the offer to fill
    /// @param _amountToTake The number of tokens to take from the offer
    /// @param _feeAsset The address of the token to use for fee payment
    /// @param _feeAmount The amount of tokens to pay as fees to the operator
    /// @param _nonce The nonce to prevent replay attacks
    /// @param _v The `v` component of the `_filler`'s signature
    /// @param _r The `r` component of the `_filler`'s signature
    /// @param _s The `s` component of the `_filler`'s signature
    function fillOffer(
        address _filler,
        bytes32 _offerHash,
        uint256 _amountToTake,
        address _feeAsset,
        uint256 _feeAmount,
        uint64 _nonce,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    )
        external
        onlyCoordinator
        onlyActiveState
    {
        bytes32 msgHash = keccak256(
            abi.encodePacked(
                "fillOffer",
                _filler,
                _offerHash,
                _amountToTake,
                _feeAsset,
                _feeAmount,
                _nonce
            )
        );

        require(
            _recoverAddress(msgHash, _v, _r, _s) == _filler,
            "Invalid signature"
        );

        _validateAndAddHash(msgHash);

        _fill(_filler, _offerHash, _amountToTake, _feeAsset, _feeAmount);
    }

    /// @notice Fills multiple offers that have been previously made using `makeOffer`.
    /// @dev Fills multiple offers with hashes in `_offerHashes` for amounts in
    /// `_amountsToTake`. This method allows conserving of the base gas cost.
    /// A fee of `_feeAmount` of `_feeAsset`  tokens can be paid to the operator
    /// to cover orderbook maintenance and network costs.
    /// The hash of all parameters, prefixed with the operation name "fillOffers"
    /// must be signed by the maker to validate the fill request.
    /// A nonce that is issued by the coordinator is used to prevent replay attacks.
    /// This operation can only be invoked by the coordinator in an Active state.
    /// @param _filler The address of the user that is filling the offer
    /// @param _offerHashes The hashes of the offers to fill
    /// @param _amountsToTake The number of tokens to take for each offer
    /// (each index corresponds to the entry with the same index in _offerHashes)
    /// @param _feeAsset The address of the token to use for fee payment
    /// @param _feeAmount The amount of tokens to pay as fees to the operator
    /// @param _nonce The nonce to prevent replay attacks
    /// @param _v The `v` component of the `_filler`'s signature
    /// @param _r The `r` component of the `_filler`'s signature
    /// @param _s The `s` component of the `_filler`'s signature
    function fillOffers(
        address _filler,
        bytes32[] _offerHashes,
        uint256[] _amountsToTake,
        address _feeAsset,
        uint256 _feeAmount,
        uint64 _nonce,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    )
        external
        onlyCoordinator
        onlyActiveState
    {
        require(
            _offerHashes.length > 0,
            'Invalid input'
        );
        require(
            _offerHashes.length == _amountsToTake.length,
            'Invalid inputs'
        );

        bytes32 msgHash = keccak256(
            abi.encodePacked(
                "fillOffers",
                _filler,
                _offerHashes,
                _amountsToTake,
                _feeAsset,
                _feeAmount,
                _nonce
            )
        );

        require(
            _recoverAddress(msgHash, _v, _r, _s) == _filler,
            "Invalid signature"
        );

        _validateAndAddHash(msgHash);

        for (uint32 i = 0; i < _offerHashes.length; i++) {
            _fill(_filler, _offerHashes[i], _amountsToTake[i], etherAddr, 0);
        }

        _paySeparateFees(
            _filler,
            _feeAsset,
            _feeAmount,
            ReasonFillerFeeGive,
            ReasonFillerFeeReceive
        );
    }

    /// @notice Cancels an offer that was preivously made using `makeOffer`.
    /// @dev Cancels the offer with `_offerHash`. An `_expectedAvailableAmount`
    /// is provided to allow the coordinator to ensure that the offer is not accidentally
    /// cancelled ahead of time (where there is a pending fill that has not been settled).
    /// The hash of the _offerHash, _feeAsset, `_feeAmount` prefixed with the
    /// operation name "cancel" must be signed by the offer maker to validate
    /// the cancellation request. Only the coordinator can invoke this operation.
    /// See `slowCancel` for cancellation without requiring the coordinator's
    /// involvement.
    /// @param _offerHash The hash of the offer to cancel
    /// @param _expectedAvailableAmount The number of tokens that should be present when cancelling
    /// @param _feeAsset The address of the token to use for fee payment
    /// @param _feeAmount The amount of tokens to pay as fees to the operator
    /// @param _v The `v` component of the offer maker's signature
    /// @param _r The `r` component of the offer maker's signature
    /// @param _s The `s` component of the offer maker's signature
    function cancel(
        bytes32 _offerHash,
        uint256 _expectedAvailableAmount,
        address _feeAsset,
        uint256 _feeAmount,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    )
        external
        onlyCoordinator
    {
        require(
            _recoverAddress(keccak256(abi.encodePacked(
                "cancel",
                _offerHash,
                _feeAsset,
                _feeAmount
            )), _v, _r, _s) == offers[_offerHash].maker,
            "Invalid signature"
        );

        _cancel(_offerHash, _expectedAvailableAmount, _feeAsset, _feeAmount);
    }

    /// @notice Announces intent to cancel tokens using `slowCancel`
    /// @dev Allows a user to invoke `slowCancel` after a minimum of
    /// `cancelAnnounceDelay` seconds has passed.
    /// This announcement and delay is necessary so that the operator has time
    /// to respond if a user attempts to invoke a `slowCancel` even though
    /// the exchange is operating normally.
    /// In that case, the coordinator would simply stop matching the offer to
    /// viable counterparties the moment the `CancelAnnounce` is seen.
    /// @param _offerHash The hash of the offer that will be cancelled
    function announceCancel(bytes32 _offerHash)
        external
    {
        Offer memory offer = offers[_offerHash];

        require(
            offer.maker == msg.sender,
            "Invalid sender"
        );

        require(
            offer.availableAmount > 0,
            "Offer already cancelled"
        );

        uint256 canCancelAt = now + cancelAnnounceDelay;
        announcedCancellations[_offerHash] = canCancelAt;

        emit CancelAnnounce(offer.maker, _offerHash, canCancelAt);
    }

    /// @notice Cancel an offer without requiring the coordinator
    /// @dev This operation is meant to be used if the operator becomes "byzantine",
    /// so that users can still cancel offers in this contract, and withdraw tokens
    /// using `slowWithdraw`.
    /// The `announceCancel` operation has to be invoked first, and a minimum time of
    /// `cancelAnnounceDelay` seconds have to pass, before this operation can be carried out.
    /// Note that this direct on-chain cancellation is an atypical operation, and
    /// the normal `cancel` operation should be used in non-byzantine states.
    /// @param _offerHash The hash of the offer to cancel
    function slowCancel(bytes32 _offerHash)
        external
    {
        require(
            announcedCancellations[_offerHash] != 0 && announcedCancellations[_offerHash] <= now,
            "Insufficient delay"
        );

        delete announcedCancellations[_offerHash];

        Offer memory offer = offers[_offerHash];
        _cancel(_offerHash, offer.availableAmount, etherAddr, 0);
    }

    /// @notice Cancels an offer immediately once cancellation intent
    /// has been announced.
    /// @dev Can only be invoked by the coordinator. This allows
    /// the coordinator to quickly remove offers that it has already
    /// acknowledged, and move its offer book into a consistent state.
    function fastCancel(bytes32 _offerHash, uint256 _expectedAvailableAmount)
        external
        onlyCoordinator
    {
        require(
            announcedCancellations[_offerHash] != 0,
            "Missing annoncement"
        );

        delete announcedCancellations[_offerHash];

        _cancel(_offerHash, _expectedAvailableAmount, etherAddr, 0);
    }

    /// @notice Cancels an offer requiring the owner's signature,
    /// so that the tokens can be withdrawn using `emergencyWithdraw`.
    /// @dev Can only be invoked in an Inactive state by the coordinator.
    /// This operation is meant to be used in emergencies only.
    function emergencyCancel(bytes32 _offerHash, uint256 _expectedAvailableAmount)
        external
        onlyCoordinator
        onlyInactiveState
    {
        _cancel(_offerHash, _expectedAvailableAmount, etherAddr, 0);
    }

    /// @notice Approve an address for spending any amount of
    /// any token from the `msg.sender`'s balances
    /// @dev Analogous to ERC-20 `approve`, with the following differences:
    ///     - `_spender` must be whitelisted by owner
    ///     - approval can be rescinded at a later time by the user
    ///       iff it has been removed from the whitelist
    ///     - spending amount is unlimited
    /// @param _spender The address to approve spending
    function approveSpender(address _spender)
        external
    {
        require(
            whitelistedSpenders[_spender],
            "Spender is not whitelisted"
        );

        approvedSpenders[msg.sender][_spender] = true;
        emit SpenderApprove(msg.sender, _spender);
    }

    /// @notice Rescinds a previous approval for spending the `msg.sender`'s contract balance.
    /// @dev Rescinds approval for a spender, after it has been removed from
    /// the `whitelistedSpenders` set. This allows an approval to be removed
    /// if both the owner and user agrees that the previously approved spender
    /// contract should no longer be used.
    /// @param _spender The address to rescind spending approval
    function rescindApproval(address _spender)
        external
    {
        require(
            approvedSpenders[msg.sender][_spender],
            "Spender has not been approved"
        );

        require(
            whitelistedSpenders[_spender] != true,
            "Spender must be removed from the whitelist"
        );

        delete approvedSpenders[msg.sender][_spender];
        emit SpenderRescind(msg.sender, _spender);
    }

    /// @notice Transfers tokens from one address to another
    /// @dev Analogous to ERC-20 `transferFrom`, with the following differences:
    ///     - the address of the token to transfer must be specified
    ///     - any amount of token can be transferred, as long as it is less or equal
    ///       to `_from`'s balance
    ///     - reason codes can be attached and they must not use reasons specified in
    ///       this contract
    /// @param _from The address to transfer tokens from
    /// @param _to The address to transfer tokens to
    /// @param _amount The number of tokens to transfer
    /// @param _token The address of the token to transfer
    /// @param _decreaseReason A reason code to emit in the `BalanceDecrease` event
    /// @param _increaseReason A reason code to emit in the `BalanceIncrease` event
    function spendFrom(
        address _from,
        address _to,
        uint256 _amount,
        address _token,
        uint8 _decreaseReason,
        uint8 _increaseReason
    )
        external
        unusedReasonCode(_decreaseReason)
        unusedReasonCode(_increaseReason)
    {
        require(
            approvedSpenders[_from][msg.sender],
            "Spender has not been approved"
        );

        _validateAddress(_to);

        balances[_from][_token] = balances[_from][_token].sub(_amount);
        emit BalanceDecrease(_from, _token, _amount, _decreaseReason);

        balances[_to][_token] = balances[_to][_token].add(_amount);
        emit BalanceIncrease(_to, _token, _amount, _increaseReason);
    }

    /// @dev Overrides ability to renounce ownership as this contract is
    /// meant to always have an owner.
    function renounceOwnership() public { require(false, "Cannot have no owner"); }

    /// @dev The actual withdraw logic that is used internally by multiple operations.
    function _withdraw(
        address _withdrawer,
        address _token,
        uint256 _amount,
        address _feeAsset,
        uint256 _feeAmount
    )
        private
    {
        // SafeMath.sub checks that balance is sufficient already
        _decreaseBalanceAndPayFees(
            _withdrawer,
            _token,
            _amount,
            _feeAsset,
            _feeAmount,
            ReasonWithdraw,
            ReasonWithdrawFeeGive,
            ReasonWithdrawFeeReceive
        );

        if (_token == etherAddr) // ether
        {
            _withdrawer.transfer(_amount);
        }
        else
        {
            _validateIsContract(_token);
            require(
                _token.call(
                    bytes4(keccak256("transfer(address,uint256)")), _withdrawer, _amount
                ),
                "transfer call failed"
            );
            require(
                _getSanitizedReturnValue(),
                "transfer failed"
            );
        }
    }

    /// @dev The actual fill logic that is used internally by multiple operations.
    function _fill(
        address _filler,
        bytes32 _offerHash,
        uint256 _amountToTake,
        address _feeAsset,
        uint256 _feeAmount
    )
        private
    {
        require(
            _amountToTake > 0,
            "Invalid input"
        );

        Offer storage offer = offers[_offerHash];
        require(
            offer.maker != _filler,
            "Invalid filler"
        );

        require(
            offer.availableAmount != 0,
            "Offer already filled"
        );

        uint256 amountToFill = (_amountToTake.mul(offer.wantAmount)).div(offer.offerAmount);

        // transfer amountToFill in fillAsset from filler to maker
        balances[_filler][offer.wantAsset] = balances[_filler][offer.wantAsset].sub(amountToFill);
        emit BalanceDecrease(_filler, offer.wantAsset, amountToFill, ReasonFillerGive);

        balances[offer.maker][offer.wantAsset] = balances[offer.maker][offer.wantAsset].add(amountToFill);
        emit BalanceIncrease(offer.maker, offer.wantAsset, amountToFill, ReasonMakerReceive);

        // deduct amountToTake in takeAsset from offer
        offer.availableAmount = offer.availableAmount.sub(_amountToTake);
        _increaseBalanceAndPayFees(
            _filler,
            offer.offerAsset,
            _amountToTake,
            _feeAsset,
            _feeAmount,
            ReasonFillerReceive,
            ReasonFillerFeeGive,
            ReasonFillerFeeReceive
        );
        emit Fill(_filler, _offerHash, amountToFill, _amountToTake, offer.maker);

        if (offer.availableAmount == 0)
        {
            delete offers[_offerHash];
        }
    }

    /// @dev The actual cancellation logic that is used internally by multiple operations.
    function _cancel(
        bytes32 _offerHash,
        uint256 _expectedAvailableAmount,
        address _feeAsset,
        uint256 _feeAmount
    )
        private
    {
        Offer memory offer = offers[_offerHash];

        require(
            offer.availableAmount > 0,
            "Offer already cancelled"
        );

        require(
            offer.availableAmount == _expectedAvailableAmount,
            "Invalid input"
        );

        delete offers[_offerHash];

        _increaseBalanceAndPayFees(
            offer.maker,
            offer.offerAsset,
            offer.availableAmount,
            _feeAsset,
            _feeAmount,
            ReasonCancel,
            ReasonCancelFeeGive,
            ReasonCancelFeeReceive
        );

        emit Cancel(offer.maker, _offerHash);
    }

    /// @dev Performs an `ecrecover` operation for signed message hashes
    /// in accordance to EIP-191.
    function _recoverAddress(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s)
        private
        pure
        returns (address)
    {
        bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, _hash));
        return ecrecover(prefixedHash, _v, _r, _s);
    }

    /// @dev Decreases a user's balance while adding a cut from the decrement
    /// to be paid as fees to the operator. Reason codes should be provided
    /// to be emitted with events for tracking.
    function _decreaseBalanceAndPayFees(
        address _user,
        address _token,
        uint256 _amount,
        address _feeAsset,
        uint256 _feeAmount,
        uint8 _reason,
        uint8 _feeGiveReason,
        uint8 _feeReceiveReason
    )
        private
    {
        uint256 totalAmount = _amount;

        if (_feeAsset == _token) {
            totalAmount = _amount.add(_feeAmount);
        }

        balances[_user][_token] = balances[_user][_token].sub(totalAmount);
        emit BalanceDecrease(_user, _token, totalAmount, _reason);

        _payFees(_user, _token, _feeAsset, _feeAmount, _feeGiveReason, _feeReceiveReason);
    }

    /// @dev Increases a user's balance while deducting a cut from the increment
    /// to be paid as fees to the operator. Reason codes should be provided
    /// to be emitted with events for tracking.
    function _increaseBalanceAndPayFees(
        address _user,
        address _token,
        uint256 _amount,
        address _feeAsset,
        uint256 _feeAmount,
        uint8 _reason,
        uint8 _feeGiveReason,
        uint8 _feeReceiveReason
    )
        private
    {
        uint256 totalAmount = _amount;

        if (_feeAsset == _token) {
            totalAmount = _amount.sub(_feeAmount);
        }

        balances[_user][_token] = balances[_user][_token].add(totalAmount);
        emit BalanceIncrease(_user, _token, totalAmount, _reason);

        _payFees(_user, _token, _feeAsset, _feeAmount, _feeGiveReason, _feeReceiveReason);
    }

    /// @dev Pays fees to the operator, attaching the specified reason codes
    /// to the emitted event, only deducting from the `_user` balance if the
    /// `_token` does not match `_feeAsset`.
    /// IMPORTANT: In the event that the `_token` matches `_feeAsset`,
    /// there should a reduction in balance increment carried out separately,
    /// to ensure balance consistency.
    function _payFees(
        address _user,
        address _token,
        address _feeAsset,
        uint256 _feeAmount,
        uint8 _feeGiveReason,
        uint8 _feeReceiveReason
    )
        private
    {
        if (_feeAmount == 0) {
            return;
        }

        // if the feeAsset does not match the token then the feeAmount needs to be separately deducted
        if (_feeAsset != _token) {
            balances[_user][_feeAsset] = balances[_user][_feeAsset].sub(_feeAmount);
            emit BalanceDecrease(_user, _feeAsset, _feeAmount, _feeGiveReason);
        }

        balances[operator][_feeAsset] = balances[operator][_feeAsset].add(_feeAmount);
        emit BalanceIncrease(operator, _feeAsset, _feeAmount, _feeReceiveReason);
    }

    /// @dev Pays fees to the operator, attaching the specified reason codes to the emitted event.
    function _paySeparateFees(
        address _user,
        address _feeAsset,
        uint256 _feeAmount,
        uint8 _feeGiveReason,
        uint8 _feeReceiveReason
    )
        private
    {
        if (_feeAmount == 0) {
            return;
        }

        balances[_user][_feeAsset] = balances[_user][_feeAsset].sub(_feeAmount);
        emit BalanceDecrease(_user, _feeAsset, _feeAmount, _feeGiveReason);

        balances[operator][_feeAsset] = balances[operator][_feeAsset].add(_feeAmount);
        emit BalanceIncrease(operator, _feeAsset, _feeAmount, _feeReceiveReason);
    }

    /// @dev Ensures that the address is a valid user address.
    function _validateAddress(address _address)
        private
        pure
    {
        require(
            _address != address(0),
            'Invalid address'
        );
    }

    /// @dev Ensures a hash hasn't been already used, which would mean
    /// a repeated set of arguments and nonce was used. This prevents
    /// replay attacks.
    function _validateAndAddHash(bytes32 _hash)
        private
    {
        require(
            usedHashes[_hash] != true,
            "hash already used"
        );

        usedHashes[_hash] = true;
    }

    /// @dev Ensure that the address is a deployed contract
    function _validateIsContract(address addr) private view {
        assembly {
            if iszero(extcodesize(addr)) { revert(0, 0) }
        }
    }

    /// @dev Fix for ERC-20 tokens that do not have proper return type
    /// See: https://github.com/ethereum/solidity/issues/4116
    /// https://medium.com/loopring-protocol/an-incompatibility-in-smart-contract-threatening-dapp-ecosystem-72b8ca5db4da
    /// https://github.com/sec-bit/badERC20Fix/blob/master/badERC20Fix.sol
    function _getSanitizedReturnValue()
        private
        pure
        returns (bool)
    {
        uint256 result = 0;
        assembly {
            switch returndatasize
            case 0 {    // this is an non-standard ERC-20 token
                result := 1 // assume success on no revert
            }
            case 32 {   // this is a standard ERC-20 token
                returndatacopy(0, 0, 32)
                result := mload(0)
            }
            default {   // this is not an ERC-20 token
                revert(0, 0) // revert for safety
            }
        }
        return result != 0;
    }
}

Contract Security Audit

Contract ABI

[{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"announceWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"approveSpender","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"coordinator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_delay","type":"uint32"}],"name":"setCancelAnnounceDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_user","type":"address"},{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"depositERC20","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawer","type":"address"},{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"slowWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"announcedCancellations","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cancelAnnounceDelay","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"rescindApproval","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"offers","outputs":[{"name":"maker","type":"address"},{"name":"offerAsset","type":"address"},{"name":"wantAsset","type":"address"},{"name":"nonce","type":"uint64"},{"name":"offerAmount","type":"uint256"},{"name":"wantAmount","type":"uint256"},{"name":"availableAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_offerHash","type":"bytes32"}],"name":"announceCancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"claimOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_state","type":"uint8"}],"name":"setState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"operator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawer","type":"address"},{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_feeAsset","type":"address"},{"name":"_feeAmount","type":"uint256"},{"name":"_nonce","type":"uint64"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"approvedSpenders","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_delay","type":"uint32"}],"name":"setWithdrawAnnounceDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"announcedWithdrawals","outputs":[{"name":"amount","type":"uint256"},{"name":"canWithdrawAt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_token","type":"address"},{"name":"_decreaseReason","type":"uint8"},{"name":"_increaseReason","type":"uint8"}],"name":"spendFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_offerHash","type":"bytes32"},{"name":"_expectedAvailableAmount","type":"uint256"},{"name":"_feeAsset","type":"address"},{"name":"_feeAmount","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"cancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_filler","type":"address"},{"name":"_offerHash","type":"bytes32"},{"name":"_amountToTake","type":"uint256"},{"name":"_feeAsset","type":"address"},{"name":"_feeAmount","type":"uint256"},{"name":"_nonce","type":"uint64"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"fillOffer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maker","type":"address"},{"name":"_offerAsset","type":"address"},{"name":"_wantAsset","type":"address"},{"name":"_offerAmount","type":"uint256"},{"name":"_wantAmount","type":"uint256"},{"name":"_feeAsset","type":"address"},{"name":"_feeAmount","type":"uint256"},{"name":"_nonce","type":"uint64"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"makeOffer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"removeSpender","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_coordinator","type":"address"}],"name":"setCoordinator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_offerHash","type":"bytes32"}],"name":"slowCancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_offerHash","type":"bytes32"},{"name":"_expectedAvailableAmount","type":"uint256"}],"name":"fastCancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_offerHash","type":"bytes32"},{"name":"_expectedAvailableAmount","type":"uint256"}],"name":"emergencyCancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"depositEther","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"whitelistedSpenders","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"usedHashes","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_operator","type":"address"}],"name":"setOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_filler","type":"address"},{"name":"_offerHashes","type":"bytes32[]"},{"name":"_amountsToTake","type":"uint256[]"},{"name":"_feeAsset","type":"address"},{"name":"_feeAmount","type":"uint256"},{"name":"_nonce","type":"uint64"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"fillOffers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"pendingOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawer","type":"address"},{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawAnnounceDelay","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"addSpender","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"maker","type":"address"},{"indexed":true,"name":"offerHash","type":"bytes32"}],"name":"Make","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"filler","type":"address"},{"indexed":true,"name":"offerHash","type":"bytes32"},{"indexed":false,"name":"amountFilled","type":"uint256"},{"indexed":false,"name":"amountTaken","type":"uint256"},{"indexed":true,"name":"maker","type":"address"}],"name":"Fill","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"maker","type":"address"},{"indexed":true,"name":"offerHash","type":"bytes32"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":true,"name":"reason","type":"uint8"}],"name":"BalanceIncrease","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":true,"name":"reason","type":"uint8"}],"name":"BalanceDecrease","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"canWithdrawAt","type":"uint256"}],"name":"WithdrawAnnounce","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"offerHash","type":"bytes32"},{"indexed":false,"name":"canCancelAt","type":"uint256"}],"name":"CancelAnnounce","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"spender","type":"address"}],"name":"SpenderApprove","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"spender","type":"address"}],"name":"SpenderRescind","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]

608060405234801561001057600080fd5b506000805433600160a060020a03199182168117835560028054831682179055600380549092161760a060020a63ffffffff02191676093a8000000000000000000000000000000000000000001760c060020a63ffffffff0219167a093a800000000000000000000000000000000000000000000000001790556001805460a060020a60ff02191674010000000000000000000000000000000000000000830217905550613a9d806100c36000396000f3006080604052600436106101df5763ffffffff60e060020a6000350416630929162381146101e4578063099a0aae1461020a5780630a0090971461022b578063109952b91461025c5780631cad5a401461027a5780631da72f4a146102a457806320e4b639146102ce5780632a40aa90146102f857806335bd17c114610326578063474d3ff0146103475780634822954a146103af5780634e71e0c8146103c757806356de96db146103dc578063570ca735146103f757806358efd2931461040c5780635a975a8c1461045a5780635b5e3355146104955780635da5064d146104b357806366acab4c146104f3578063715018a614610530578063715058c11461054557806373241b631461057b57806381d0f02e146105c75780638ce5877c146106215780638da5cb5b146106425780638ea98117146106575780638eff84061461067857806390908dde1461069057806397152a26146106ab57806398ea5fca146106c6578063aa72d9e7146106ce578063aef18bf7146106ef578063b3ab15fb14610707578063c19d93fb14610728578063c23f001f14610761578063d9b6e0a614610788578063e30c3978146107e5578063e63ea408146107fa578063e6d6896114610824578063e7e31e7a14610839578063f2fde38b1461085a575b600080fd5b3480156101f057600080fd5b50610208600160a060020a036004351660243561087b565b005b34801561021657600080fd5b50610208600160a060020a036004351661097f565b34801561023757600080fd5b50610240610a4a565b60408051600160a060020a039092168252519081900360200190f35b34801561026857600080fd5b5061020863ffffffff60043516610a59565b34801561028657600080fd5b50610208600160a060020a0360043581169060243516604435610b0a565b3480156102b057600080fd5b50610208600160a060020a0360043581169060243516604435610e17565b3480156102da57600080fd5b506102e6600435610f64565b60408051918252519081900360200190f35b34801561030457600080fd5b5061030d610f76565b6040805163ffffffff9092168252519081900360200190f35b34801561033257600080fd5b50610208600160a060020a0360043516610f89565b34801561035357600080fd5b5061035f6004356110f8565b60408051600160a060020a0398891681529688166020880152949096168585015267ffffffffffffffff9092166060850152608084015260a083015260c082019290925290519081900360e00190f35b3480156103bb57600080fd5b50610208600435611150565b3480156103d357600080fd5b506102086112e4565b3480156103e857600080fd5b5061020860ff6004351661136c565b34801561040357600080fd5b506102406113ba565b34801561041857600080fd5b50610208600160a060020a03600435811690602435811690604435906064351660843567ffffffffffffffff60a4351660ff60c4351660e435610104356113c9565b34801561046657600080fd5b50610481600160a060020a036004358116906024351661158a565b604080519115158252519081900360200190f35b3480156104a157600080fd5b5061020863ffffffff600435166115aa565b3480156104bf57600080fd5b506104da600160a060020a0360043581169060243516611662565b6040805192835260208301919091528051918290030190f35b3480156104ff57600080fd5b50610208600160a060020a03600435811690602435811690604435906064351660ff60843581169060a43516611686565b34801561053c57600080fd5b506102086118d8565b34801561055157600080fd5b50610208600435602435600160a060020a036044351660643560ff6084351660a43560c435611928565b34801561058757600080fd5b50610208600160a060020a0360043581169060243590604435906064351660843567ffffffffffffffff60a4351660ff60c4351660e43561010435611ab6565b3480156105d357600080fd5b50610208600160a060020a03600435811690602435811690604435811690606435906084359060a4351660c43567ffffffffffffffff60e4351660ff61010435166101243561014435611cc5565b34801561062d57600080fd5b50610208600160a060020a036004351661213f565b34801561064e57600080fd5b50610240612180565b34801561066357600080fd5b50610208600160a060020a036004351661218f565b34801561068457600080fd5b506102086004356121de565b34801561069c57600080fd5b50610208600435602435612301565b3480156106b757600080fd5b506102086004356024356123d5565b61020861248e565b3480156106da57600080fd5b50610481600160a060020a03600435166125b2565b3480156106fb57600080fd5b506104816004356125c7565b34801561071357600080fd5b50610208600160a060020a03600435166125dc565b34801561073457600080fd5b5061073d612637565b6040518082600181111561074d57fe5b60ff16815260200191505060405180910390f35b34801561076d57600080fd5b506102e6600160a060020a0360043581169060243516612647565b34801561079457600080fd5b5061020860048035600160a060020a039081169160248035808201939083013592604435928301920135906064351660843560a43567ffffffffffffffff1660c43560ff1660e43561010435612664565b3480156107f157600080fd5b506102406129d5565b34801561080657600080fd5b50610208600160a060020a03600435811690602435166044356129e4565b34801561083057600080fd5b5061030d612aa3565b34801561084557600080fd5b50610208600160a060020a0360043516612ab6565b34801561086657600080fd5b50610208600160a060020a0360043516612afa565b336000908152600460209081526040808320600160a060020a038616845290915281205481908311156108f8576040805160e560020a62461bcd02815260206004820152600f60248201527f416d6f756e7420746f6f20686967680000000000000000000000000000000000604482015290519081900360640190fd5b5050336000818152600960209081526040808320600160a060020a0387168085529083529281902060035460c060020a900463ffffffff1642016001820181905586825582518781529384018190528251919590949390927ff8721275b3a50a37f692c7ba70c878e6cb3e44c23967756a3f712fe1ccc0377992918290030190a350505050565b600160a060020a03811660009081526007602052604090205460ff1615156109f1576040805160e560020a62461bcd02815260206004820152601a60248201527f5370656e646572206973206e6f742077686974656c6973746564000000000000604482015290519081900360640190fd5b336000818152600860209081526040808320600160a060020a0386168085529252808320805460ff19166001179055519092917f052c513b128416028f181f8d2c76eee59572b251fc379accba39533b40b3e86d91a350565b600254600160a060020a031681565b600054600160a060020a03163314610a7057600080fd5b8062093a8063ffffffff82161115610ad2576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642064656c617900000000000000000000000000000000000000604482015290519081900360640190fd5b506003805463ffffffff90921660a060020a0277ffffffff000000000000000000000000000000000000000019909216919091179055565b600254600160a060020a03163314610b5a576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff1690811115610b7457fe5b14610bb7576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60008111610c0f576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642076616c756500000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03808416600090815260046020908152604080832093861683529290522054610c45908263ffffffff612b4016565b600160a060020a03808516600090815260046020908152604080832093871683529290522055610c7482612b53565b604080517f7472616e7366657246726f6d28616464726573732c616464726573732c75696e81527f74323536290000000000000000000000000000000000000000000000000000006020820152815190819003602501812063ffffffff60e060020a918290049081169091028252600160a060020a038681166004840152306024840152604483018590529251928516929091606480820192600092909190829003018183875af1925050501515610d76576040805160e560020a62461bcd02815260206004820152601860248201527f7472616e7366657246726f6d2063616c6c206661696c65640000000000000000604482015290519081900360640190fd5b610d7e612b63565b1515610dd4576040805160e560020a62461bcd02815260206004820152601460248201527f7472616e7366657246726f6d206661696c65642e000000000000000000000000604482015290519081900360640190fd5b600160ff1682600160a060020a031684600160a060020a03166000805160206139d2833981519152846040518082815260200191505060405180910390a4505050565b610e1f61397e565b50600160a060020a0380841660009081526009602090815260408083209386168352928152908290208251808401909352805483526001015490820181905215801590610e70575042816020015111155b1515610ec6576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742064656c61790000000000000000000000000000604482015290519081900360640190fd5b80518214610f1e576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c696420616d6f756e74000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0380851660009081526009602090815260408083209387168352929052908120818155600101819055610f5e9085908590859080612b97565b50505050565b600a6020526000908152604090205481565b60035460a060020a900463ffffffff1681565b336000908152600860209081526040808320600160a060020a038516845290915290205460ff161515611006576040805160e560020a62461bcd02815260206004820152601d60248201527f5370656e64657220686173206e6f74206265656e20617070726f766564000000604482015290519081900360640190fd5b600160a060020a03811660009081526007602052604090205460ff161515600114156110a2576040805160e560020a62461bcd02815260206004820152602a60248201527f5370656e646572206d7573742062652072656d6f7665642066726f6d2074686560448201527f2077686974656c69737400000000000000000000000000000000000000000000606482015290519081900360840190fd5b336000818152600860209081526040808320600160a060020a0386168085529252808320805460ff19169055519092917f4524ec10cbd92d9466126e9af13eba34a4176c2cc2a74d0dee145087b67f5e0491a350565b6005602081905260009182526040909120805460018201546002830154600384015460048501549490950154600160a060020a0393841695928416949382169360a060020a90920467ffffffffffffffff1692919087565b611158613995565b506000818152600560208181526040808420815160e0810183528154600160a060020a03908116808352600184015482169583019590955260028301549081169382019390935260a060020a90920467ffffffffffffffff16606083015260038101546080830152600481015460a08301529092015460c0830152909190331461121a576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60c0820151600010611276576040805160e560020a62461bcd02815260206004820152601760248201527f4f6666657220616c72656164792063616e63656c6c6564000000000000000000604482015290519081900360640190fd5b506003546000838152600a602090815260409182902060a060020a90930463ffffffff164201928390558351825184815292518693600160a060020a03909216927f5a4fb258356f60bc7302795f48ccdc1ca92d9bd3322ddd4c1c93cc1a27f72672928290030190a3505050565b600154600160a060020a031633146112fb57600080fd5b60015460008054604051600160a060020a0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b600054600160a060020a0316331461138357600080fd5b6001805482919074ff0000000000000000000000000000000000000000191660a060020a83838111156113b257fe5b021790555050565b600354600160a060020a031681565b600254600090600160a060020a0316331461141c576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b604080517f7769746864726177000000000000000000000000000000000000000000000000602080830191909152606060020a600160a060020a03808f1682026028850152808e168202603c850152605084018d90528b160260708301526084820189905260c060020a67ffffffffffffffff89160260a48301528251608c81840301815260ac90920192839052815191929182918401908083835b602083106114d75780518252601f1990920191602091820191016114b8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905089600160a060020a031661151c82868686612d4d565b600160a060020a031614611568576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b61157181612eae565b61157e8a8a8a8a8a612b97565b50505050505050505050565b600860209081526000928352604080842090915290825290205460ff1681565b600054600160a060020a031633146115c157600080fd5b8062093a8063ffffffff82161115611623576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642064656c617900000000000000000000000000000000000000604482015290519081900360640190fd5b506003805463ffffffff90921660c060020a027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055565b60096020908152600092835260408084209091529082529020805460019091015482565b81601560ff8216116116e2576040805160e560020a62461bcd02815260206004820152601360248201527f496e76616c696420726561736f6e20636f646500000000000000000000000000604482015290519081900360640190fd5b81601560ff82161161173e576040805160e560020a62461bcd02815260206004820152601360248201527f496e76616c696420726561736f6e20636f646500000000000000000000000000604482015290519081900360640190fd5b600160a060020a038816600090815260086020908152604080832033845290915290205460ff1615156117bb576040805160e560020a62461bcd02815260206004820152601d60248201527f5370656e64657220686173206e6f74206265656e20617070726f766564000000604482015290519081900360640190fd5b6117c487612f35565b600160a060020a038089166000908152600460209081526040808320938916835292905220546117fa908763ffffffff612f9516565b600160a060020a03808a166000818152600460209081526040808320948b16808452948252918290209490945580518a8152905160ff891694600080516020613a52833981519152928290030190a4600160a060020a0380881660009081526004602090815260408083209389168352929052205461187f908763ffffffff612b4016565b600160a060020a038089166000818152600460209081526040808320948b16808452948252918290209490945580518a8152905160ff8816946000805160206139d2833981519152928290030190a45050505050505050565b6040805160e560020a62461bcd02815260206004820152601460248201527f43616e6e6f742068617665206e6f206f776e6572000000000000000000000000604482015290519081900360640190fd5b600254600160a060020a03163314611978576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b6000878152600560209081526040918290205482517f63616e63656c000000000000000000000000000000000000000000000000000081840152602681018b9052600160a060020a03898116606060020a026046830152605a8083018a905285518084039091018152607a909201948590528151921693611a5593919290918291908401908083835b60208310611a205780518252601f199092019160209182019101611a01565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020858585612d4d565b600160a060020a031614611aa1576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b611aad87878787612fa7565b50505050505050565b600254600090600160a060020a03163314611b09576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff1690811115611b2357fe5b14611b66576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b604080517f66696c6c4f666665720000000000000000000000000000000000000000000000602080830191909152606060020a600160a060020a03808f1682026029850152603d84018e9052605d84018d90528b1602607d8301526091820189905260c060020a67ffffffffffffffff89160260b18301528251609981840301815260b990920192839052815191929182918401908083835b60208310611c1e5780518252601f199092019160209182019101611bff565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905089600160a060020a0316611c6382868686612d4d565b600160a060020a031614611caf576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b611cb881612eae565b61157e8a8a8a8a8a6131ac565b6002546000908190600160a060020a03163314611d1a576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff1690811115611d3457fe5b14611d77576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60008a118015611d875750600089115b1515611ddd576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616d6f756e74730000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038c8116908c161415611e41576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c696420617373657473000000000000000000000000000000000000604482015290519081900360640190fd5b8c8c8c8c8c8c8c8c60405160200180807f6d616b654f66666572000000000000000000000000000000000000000000000081525060090189600160a060020a0316600160a060020a0316606060020a02815260140188600160a060020a0316600160a060020a0316606060020a02815260140187600160a060020a0316600160a060020a0316606060020a02815260140186815260200185815260200184600160a060020a0316600160a060020a0316606060020a0281526014018381526020018267ffffffffffffffff1667ffffffffffffffff1660c060020a028152600801985050505050505050506040516020818303038152906040526040518082805190602001908083835b60208310611f6a5780518252601f199092019160209182019101611f4b565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091508c600160a060020a0316611faf83878787612d4d565b600160a060020a031614611ffb576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b61200482612eae565b6120178d8d8c8b8b60026010601161354b565b60056000836000191660001916815260200190815260200160002090508c8160000160006101000a815481600160a060020a030219169083600160a060020a031602179055508b8160010160006101000a815481600160a060020a030219169083600160a060020a031602179055508a8160020160006101000a815481600160a060020a030219169083600160a060020a03160217905550898160030181905550888160040181905550898160050181905550858160020160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600019168d600160a060020a03167f1fa192562e5fbdce807069b18275dc0d672cacd78576602b47d21730975635a160405160405180910390a350505050505050505050505050565b600054600160a060020a0316331461215657600080fd5b61215f81612f35565b600160a060020a03166000908152600760205260409020805460ff19169055565b600054600160a060020a031681565b600054600160a060020a031633146121a657600080fd5b6121af81612f35565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6121e6613995565b6000828152600a60205260409020541580159061221157506000828152600a60205260409020544210155b1515612267576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742064656c61790000000000000000000000000000604482015290519081900360640190fd5b506000818152600a602090815260408083208390556005808352818420825160e0810184528154600160a060020a039081168252600183015481169582019590955260028201549485169381019390935260a060020a90930467ffffffffffffffff16606083015260038301546080830152600483015460a0830152919091015460c0820181905290916122fd91849180612fa7565b5050565b600254600160a060020a03163314612351576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b6000828152600a602052604090205415156123b6576040805160e560020a62461bcd02815260206004820152601360248201527f4d697373696e6720616e6e6f6e63656d656e7400000000000000000000000000604482015290519081900360640190fd5b6000828152600a602052604081208190556122fd908390839080612fa7565b600254600160a060020a03163314612425576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b600180805460a060020a900460ff169081111561243e57fe5b14612481576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b6122fd8282600080612fa7565b60006001805460a060020a900460ff16908111156124a857fe5b146124eb576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60003411612543576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642076616c756500000000000000000000000000000000000000604482015290519081900360640190fd5b33600090815260046020908152604080832083805290915290205461256e903463ffffffff612b4016565b336000818152600460209081526040808320838052825280832094909455835134815293516001949293926000805160206139d283398151915292908290030190a4565b60076020526000908152604090205460ff1681565b60066020526000908152604090205460ff1681565b600054600160a060020a031633146125f357600080fd5b60035461260890600160a060020a0316612f35565b6003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60015460a060020a900460ff1681565b600460209081526000928352604080842090915290825290205481565b6002546000908190600160a060020a031633146126b9576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff16908111156126d357fe5b14612716576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60008b1161276e576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c696420696e70757400000000000000000000000000000000000000604482015290519081900360640190fd5b8a89146127c5576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c696420696e70757473000000000000000000000000000000000000604482015290519081900360640190fd5b8c8c8c8c8c8c8c8c60405160200180807f66696c6c4f666665727300000000000000000000000000000000000000000000815250600a0189600160a060020a0316600160a060020a0316606060020a0281526014018888602002808284378201915050868660200280828437820191505084600160a060020a0316600160a060020a0316606060020a0281526014018381526020018267ffffffffffffffff1667ffffffffffffffff1660c060020a028152600801985050505050505050506040516020818303038152906040526040518082805190602001908083835b602083106128c25780518252601f1990920191602091820191016128a3565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091508c600160a060020a031661290783878787612d4d565b600160a060020a031614612953576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b61295c82612eae565b5060005b63ffffffff81168b11156129b7576129af8d8d8d63ffffffff851681811061298457fe5b602002919091013590508c8c63ffffffff86168181106129a057fe5b905060200201356000806131ac565b600101612960565b6129c68d898960046007613611565b50505050505050505050505050565b600154600160a060020a031681565b600254600160a060020a03163314612a34576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b600180805460a060020a900460ff1690811115612a4d57fe5b14612a90576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b612a9e838383600080612b97565b505050565b60035460c060020a900463ffffffff1681565b600054600160a060020a03163314612acd57600080fd5b612ad681612f35565b600160a060020a03166000908152600760205260409020805460ff19166001179055565b600054600160a060020a03163314612b1157600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b81810182811015612b4d57fe5b92915050565b803b1515612b6057600080fd5b50565b6000803d8015612b7a5760208114612b8357600080fd5b60019150612b8f565b60206000803e60005191505b501515919050565b612baa858585858560096014601561354b565b600160a060020a0384161515612bf657604051600160a060020a0386169084156108fc029085906000818181858888f19350505050158015612bf0573d6000803e3d6000fd5b50612d46565b612bff84612b53565b83600160a060020a031660405180807f7472616e7366657228616464726573732c75696e7432353629000000000000008152506019019050604051809103902060e060020a900486856040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a03168152602001828152602001925050506000604051808303816000875af1925050501515612ce8576040805160e560020a62461bcd02815260206004820152601460248201527f7472616e736665722063616c6c206661696c6564000000000000000000000000604482015290519081900360640190fd5b612cf0612b63565b1515612d46576040805160e560020a62461bcd02815260206004820152600f60248201527f7472616e73666572206661696c65640000000000000000000000000000000000604482015290519081900360640190fd5b5050505050565b604080518082018252601c8082527f19457468657265756d205369676e6564204d6573736167653a0a33320000000060208084019182529351600094859385938b939092019182918083835b60208310612db85780518252601f199092019160209182019101612d99565b51815160209384036101000a600019018019909216911617905292019384525060408051808503815293820190819052835193945092839250908401908083835b60208310612e185780518252601f199092019160209182019101612df9565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080845283830180875282905260ff8e1684870152606084018d9052608084018c905294519097506001965060a080840196509194601f19820194509281900390910191865af1158015612e98573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b60008181526006602052604090205460ff16151560011415612f1a576040805160e560020a62461bcd02815260206004820152601160248201527f6861736820616c72656164792075736564000000000000000000000000000000604482015290519081900360640190fd5b6000908152600660205260409020805460ff19166001179055565b600160a060020a0381161515612b60576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b600082821115612fa157fe5b50900390565b612faf613995565b506000848152600560208181526040808420815160e0810183528154600160a060020a039081168252600183015481169482019490945260028201549384169281019290925260a060020a90920467ffffffffffffffff16606082015260038201546080820152600482015460a082015291015460c08201819052909110613081576040805160e560020a62461bcd02815260206004820152601760248201527f4f6666657220616c72656164792063616e63656c6c6564000000000000000000604482015290519081900360640190fd5b60c081015184146130dc576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c696420696e70757400000000000000000000000000000000000000604482015290519081900360640190fd5b60008581526005602081815260408320805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690556002810180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916905560038101849055600481018490559091019190915581519082015160c083015161316e9291908686600860126013613740565b80516040518691600160a060020a0316907fdb2b33dd6349739e1f3cd6dc90cf093af6a3dfb1838aced380528b0aefe6093c90600090a35050505050565b600080808511613206576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c696420696e70757400000000000000000000000000000000000000604482015290519081900360640190fd5b60008681526005602052604090208054909250600160a060020a038881169116141561327c576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c69642066696c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b600582015415156132d7576040805160e560020a62461bcd02815260206004820152601460248201527f4f6666657220616c72656164792066696c6c6564000000000000000000000000604482015290519081900360640190fd5b61330282600301546132f68460040154886137fb90919063ffffffff16565b9063ffffffff61382416565b600160a060020a038089166000908152600460209081526040808320600288015490941683529290522054909150613340908263ffffffff612f9516565b600160a060020a0380891660008181526004602090815260408083206002890180548716855290835292819020959095559054845186815294516003959190941693600080516020613a52833981519152929181900390910190a48154600160a060020a0390811660009081526004602090815260408083206002870154909416835292905220546133d8908263ffffffff612b4016565b8254600160a060020a03908116600090815260046020908152604080832060028801805486168552908352928190209490945590548554845186815294516006959285169491909116926000805160206139d2833981519152928290030190a4600582015461344d908663ffffffff612f9516565b600580840191909155600183015461347a918991600160a060020a03169088908890889060046007613740565b815460408051838152602081018890528151600160a060020a03938416938a93908c16927fc587d1c5cbeb2dc01ea21c77c1c9232f39962a50cf2d6ce8d02dd09356e05b85929081900390910190a460058201541515611aad57505050600092835250506005602081905260408220805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690556002810180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690556003810183905560048101839055015550565b85600160a060020a03868116908916141561357357613570878663ffffffff612b4016565b90505b600160a060020a03808a166000908152600460209081526040808320938c16835292905220546135a9908263ffffffff612f9516565b600160a060020a03808b166000818152600460209081526040808320948e1680845294825291829020949094558051858152905160ff891694600080516020613a52833981519152928290030190a4613606898988888787613839565b505050505050505050565b82151561361d57612d46565b600160a060020a03808616600090815260046020908152604080832093881683529290522054613653908463ffffffff612f9516565b600160a060020a038087166000818152600460209081526040808320948a1680845294825291829020949094558051878152905160ff871694600080516020613a52833981519152928290030190a4600354600160a060020a039081166000908152600460209081526040808320938816835292905220546136db908463ffffffff612b4016565b60038054600160a060020a0390811660009081526004602090815260408083208a8516808552908352928190209590955592548451888152945160ff871695929491909316926000805160206139d28339815191529281900390910190a45050505050565b85600160a060020a03868116908916141561376857613765878663ffffffff612f9516565b90505b600160a060020a03808a166000908152600460209081526040808320938c168352929052205461379e908263ffffffff612b4016565b600160a060020a03808b166000818152600460209081526040808320948e1680845294825291829020949094558051858152905160ff8916946000805160206139d2833981519152928290030190a4613606898988888787613839565b600082151561380c57506000612b4d565b5081810281838281151561381c57fe5b0414612b4d57fe5b6000818381151561383157fe5b049392505050565b82151561384557613976565b600160a060020a03848116908616146138de57600160a060020a0380871660009081526004602090815260408083209388168352929052205461388e908463ffffffff612f9516565b600160a060020a038088166000818152600460209081526040808320948a1680845294825291829020949094558051878152905160ff871694600080516020613a52833981519152928290030190a45b600354600160a060020a03908116600090815260046020908152604080832093881683529290522054613917908463ffffffff612b4016565b60038054600160a060020a0390811660009081526004602090815260408083208a8516808552908352928190209590955592548451888152945160ff871695929491909316926000805160206139d28339815191529281900390910190a45b505050505050565b604080518082019091526000808252602082015290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091529056004a52a947455663fbd6ddcc61a4d3a18a7e387c418de430ea8a191956cc53ec79496e76616c69642073656e646572000000000000000000000000000000000000496e76616c6964207369676e6174757265000000000000000000000000000000496e76616c696420737461746500000000000000000000000000000000000000a3bbf8b09a42177fa9310281fb7f2fc8803d7c6df09a82093ea047cb6a222aa3a165627a7a72305820eedc0304d51bd7a039c150363cfd0f3abd3ae51b32404275ae0be012f46225780029

Deployed Bytecode

0x6080604052600436106101df5763ffffffff60e060020a6000350416630929162381146101e4578063099a0aae1461020a5780630a0090971461022b578063109952b91461025c5780631cad5a401461027a5780631da72f4a146102a457806320e4b639146102ce5780632a40aa90146102f857806335bd17c114610326578063474d3ff0146103475780634822954a146103af5780634e71e0c8146103c757806356de96db146103dc578063570ca735146103f757806358efd2931461040c5780635a975a8c1461045a5780635b5e3355146104955780635da5064d146104b357806366acab4c146104f3578063715018a614610530578063715058c11461054557806373241b631461057b57806381d0f02e146105c75780638ce5877c146106215780638da5cb5b146106425780638ea98117146106575780638eff84061461067857806390908dde1461069057806397152a26146106ab57806398ea5fca146106c6578063aa72d9e7146106ce578063aef18bf7146106ef578063b3ab15fb14610707578063c19d93fb14610728578063c23f001f14610761578063d9b6e0a614610788578063e30c3978146107e5578063e63ea408146107fa578063e6d6896114610824578063e7e31e7a14610839578063f2fde38b1461085a575b600080fd5b3480156101f057600080fd5b50610208600160a060020a036004351660243561087b565b005b34801561021657600080fd5b50610208600160a060020a036004351661097f565b34801561023757600080fd5b50610240610a4a565b60408051600160a060020a039092168252519081900360200190f35b34801561026857600080fd5b5061020863ffffffff60043516610a59565b34801561028657600080fd5b50610208600160a060020a0360043581169060243516604435610b0a565b3480156102b057600080fd5b50610208600160a060020a0360043581169060243516604435610e17565b3480156102da57600080fd5b506102e6600435610f64565b60408051918252519081900360200190f35b34801561030457600080fd5b5061030d610f76565b6040805163ffffffff9092168252519081900360200190f35b34801561033257600080fd5b50610208600160a060020a0360043516610f89565b34801561035357600080fd5b5061035f6004356110f8565b60408051600160a060020a0398891681529688166020880152949096168585015267ffffffffffffffff9092166060850152608084015260a083015260c082019290925290519081900360e00190f35b3480156103bb57600080fd5b50610208600435611150565b3480156103d357600080fd5b506102086112e4565b3480156103e857600080fd5b5061020860ff6004351661136c565b34801561040357600080fd5b506102406113ba565b34801561041857600080fd5b50610208600160a060020a03600435811690602435811690604435906064351660843567ffffffffffffffff60a4351660ff60c4351660e435610104356113c9565b34801561046657600080fd5b50610481600160a060020a036004358116906024351661158a565b604080519115158252519081900360200190f35b3480156104a157600080fd5b5061020863ffffffff600435166115aa565b3480156104bf57600080fd5b506104da600160a060020a0360043581169060243516611662565b6040805192835260208301919091528051918290030190f35b3480156104ff57600080fd5b50610208600160a060020a03600435811690602435811690604435906064351660ff60843581169060a43516611686565b34801561053c57600080fd5b506102086118d8565b34801561055157600080fd5b50610208600435602435600160a060020a036044351660643560ff6084351660a43560c435611928565b34801561058757600080fd5b50610208600160a060020a0360043581169060243590604435906064351660843567ffffffffffffffff60a4351660ff60c4351660e43561010435611ab6565b3480156105d357600080fd5b50610208600160a060020a03600435811690602435811690604435811690606435906084359060a4351660c43567ffffffffffffffff60e4351660ff61010435166101243561014435611cc5565b34801561062d57600080fd5b50610208600160a060020a036004351661213f565b34801561064e57600080fd5b50610240612180565b34801561066357600080fd5b50610208600160a060020a036004351661218f565b34801561068457600080fd5b506102086004356121de565b34801561069c57600080fd5b50610208600435602435612301565b3480156106b757600080fd5b506102086004356024356123d5565b61020861248e565b3480156106da57600080fd5b50610481600160a060020a03600435166125b2565b3480156106fb57600080fd5b506104816004356125c7565b34801561071357600080fd5b50610208600160a060020a03600435166125dc565b34801561073457600080fd5b5061073d612637565b6040518082600181111561074d57fe5b60ff16815260200191505060405180910390f35b34801561076d57600080fd5b506102e6600160a060020a0360043581169060243516612647565b34801561079457600080fd5b5061020860048035600160a060020a039081169160248035808201939083013592604435928301920135906064351660843560a43567ffffffffffffffff1660c43560ff1660e43561010435612664565b3480156107f157600080fd5b506102406129d5565b34801561080657600080fd5b50610208600160a060020a03600435811690602435166044356129e4565b34801561083057600080fd5b5061030d612aa3565b34801561084557600080fd5b50610208600160a060020a0360043516612ab6565b34801561086657600080fd5b50610208600160a060020a0360043516612afa565b336000908152600460209081526040808320600160a060020a038616845290915281205481908311156108f8576040805160e560020a62461bcd02815260206004820152600f60248201527f416d6f756e7420746f6f20686967680000000000000000000000000000000000604482015290519081900360640190fd5b5050336000818152600960209081526040808320600160a060020a0387168085529083529281902060035460c060020a900463ffffffff1642016001820181905586825582518781529384018190528251919590949390927ff8721275b3a50a37f692c7ba70c878e6cb3e44c23967756a3f712fe1ccc0377992918290030190a350505050565b600160a060020a03811660009081526007602052604090205460ff1615156109f1576040805160e560020a62461bcd02815260206004820152601a60248201527f5370656e646572206973206e6f742077686974656c6973746564000000000000604482015290519081900360640190fd5b336000818152600860209081526040808320600160a060020a0386168085529252808320805460ff19166001179055519092917f052c513b128416028f181f8d2c76eee59572b251fc379accba39533b40b3e86d91a350565b600254600160a060020a031681565b600054600160a060020a03163314610a7057600080fd5b8062093a8063ffffffff82161115610ad2576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642064656c617900000000000000000000000000000000000000604482015290519081900360640190fd5b506003805463ffffffff90921660a060020a0277ffffffff000000000000000000000000000000000000000019909216919091179055565b600254600160a060020a03163314610b5a576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff1690811115610b7457fe5b14610bb7576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60008111610c0f576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642076616c756500000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03808416600090815260046020908152604080832093861683529290522054610c45908263ffffffff612b4016565b600160a060020a03808516600090815260046020908152604080832093871683529290522055610c7482612b53565b604080517f7472616e7366657246726f6d28616464726573732c616464726573732c75696e81527f74323536290000000000000000000000000000000000000000000000000000006020820152815190819003602501812063ffffffff60e060020a918290049081169091028252600160a060020a038681166004840152306024840152604483018590529251928516929091606480820192600092909190829003018183875af1925050501515610d76576040805160e560020a62461bcd02815260206004820152601860248201527f7472616e7366657246726f6d2063616c6c206661696c65640000000000000000604482015290519081900360640190fd5b610d7e612b63565b1515610dd4576040805160e560020a62461bcd02815260206004820152601460248201527f7472616e7366657246726f6d206661696c65642e000000000000000000000000604482015290519081900360640190fd5b600160ff1682600160a060020a031684600160a060020a03166000805160206139d2833981519152846040518082815260200191505060405180910390a4505050565b610e1f61397e565b50600160a060020a0380841660009081526009602090815260408083209386168352928152908290208251808401909352805483526001015490820181905215801590610e70575042816020015111155b1515610ec6576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742064656c61790000000000000000000000000000604482015290519081900360640190fd5b80518214610f1e576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c696420616d6f756e74000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0380851660009081526009602090815260408083209387168352929052908120818155600101819055610f5e9085908590859080612b97565b50505050565b600a6020526000908152604090205481565b60035460a060020a900463ffffffff1681565b336000908152600860209081526040808320600160a060020a038516845290915290205460ff161515611006576040805160e560020a62461bcd02815260206004820152601d60248201527f5370656e64657220686173206e6f74206265656e20617070726f766564000000604482015290519081900360640190fd5b600160a060020a03811660009081526007602052604090205460ff161515600114156110a2576040805160e560020a62461bcd02815260206004820152602a60248201527f5370656e646572206d7573742062652072656d6f7665642066726f6d2074686560448201527f2077686974656c69737400000000000000000000000000000000000000000000606482015290519081900360840190fd5b336000818152600860209081526040808320600160a060020a0386168085529252808320805460ff19169055519092917f4524ec10cbd92d9466126e9af13eba34a4176c2cc2a74d0dee145087b67f5e0491a350565b6005602081905260009182526040909120805460018201546002830154600384015460048501549490950154600160a060020a0393841695928416949382169360a060020a90920467ffffffffffffffff1692919087565b611158613995565b506000818152600560208181526040808420815160e0810183528154600160a060020a03908116808352600184015482169583019590955260028301549081169382019390935260a060020a90920467ffffffffffffffff16606083015260038101546080830152600481015460a08301529092015460c0830152909190331461121a576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60c0820151600010611276576040805160e560020a62461bcd02815260206004820152601760248201527f4f6666657220616c72656164792063616e63656c6c6564000000000000000000604482015290519081900360640190fd5b506003546000838152600a602090815260409182902060a060020a90930463ffffffff164201928390558351825184815292518693600160a060020a03909216927f5a4fb258356f60bc7302795f48ccdc1ca92d9bd3322ddd4c1c93cc1a27f72672928290030190a3505050565b600154600160a060020a031633146112fb57600080fd5b60015460008054604051600160a060020a0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180546000805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a03841617909155169055565b600054600160a060020a0316331461138357600080fd5b6001805482919074ff0000000000000000000000000000000000000000191660a060020a83838111156113b257fe5b021790555050565b600354600160a060020a031681565b600254600090600160a060020a0316331461141c576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b604080517f7769746864726177000000000000000000000000000000000000000000000000602080830191909152606060020a600160a060020a03808f1682026028850152808e168202603c850152605084018d90528b160260708301526084820189905260c060020a67ffffffffffffffff89160260a48301528251608c81840301815260ac90920192839052815191929182918401908083835b602083106114d75780518252601f1990920191602091820191016114b8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905089600160a060020a031661151c82868686612d4d565b600160a060020a031614611568576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b61157181612eae565b61157e8a8a8a8a8a612b97565b50505050505050505050565b600860209081526000928352604080842090915290825290205460ff1681565b600054600160a060020a031633146115c157600080fd5b8062093a8063ffffffff82161115611623576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642064656c617900000000000000000000000000000000000000604482015290519081900360640190fd5b506003805463ffffffff90921660c060020a027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055565b60096020908152600092835260408084209091529082529020805460019091015482565b81601560ff8216116116e2576040805160e560020a62461bcd02815260206004820152601360248201527f496e76616c696420726561736f6e20636f646500000000000000000000000000604482015290519081900360640190fd5b81601560ff82161161173e576040805160e560020a62461bcd02815260206004820152601360248201527f496e76616c696420726561736f6e20636f646500000000000000000000000000604482015290519081900360640190fd5b600160a060020a038816600090815260086020908152604080832033845290915290205460ff1615156117bb576040805160e560020a62461bcd02815260206004820152601d60248201527f5370656e64657220686173206e6f74206265656e20617070726f766564000000604482015290519081900360640190fd5b6117c487612f35565b600160a060020a038089166000908152600460209081526040808320938916835292905220546117fa908763ffffffff612f9516565b600160a060020a03808a166000818152600460209081526040808320948b16808452948252918290209490945580518a8152905160ff891694600080516020613a52833981519152928290030190a4600160a060020a0380881660009081526004602090815260408083209389168352929052205461187f908763ffffffff612b4016565b600160a060020a038089166000818152600460209081526040808320948b16808452948252918290209490945580518a8152905160ff8816946000805160206139d2833981519152928290030190a45050505050505050565b6040805160e560020a62461bcd02815260206004820152601460248201527f43616e6e6f742068617665206e6f206f776e6572000000000000000000000000604482015290519081900360640190fd5b600254600160a060020a03163314611978576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b6000878152600560209081526040918290205482517f63616e63656c000000000000000000000000000000000000000000000000000081840152602681018b9052600160a060020a03898116606060020a026046830152605a8083018a905285518084039091018152607a909201948590528151921693611a5593919290918291908401908083835b60208310611a205780518252601f199092019160209182019101611a01565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020858585612d4d565b600160a060020a031614611aa1576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b611aad87878787612fa7565b50505050505050565b600254600090600160a060020a03163314611b09576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff1690811115611b2357fe5b14611b66576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b604080517f66696c6c4f666665720000000000000000000000000000000000000000000000602080830191909152606060020a600160a060020a03808f1682026029850152603d84018e9052605d84018d90528b1602607d8301526091820189905260c060020a67ffffffffffffffff89160260b18301528251609981840301815260b990920192839052815191929182918401908083835b60208310611c1e5780518252601f199092019160209182019101611bff565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905089600160a060020a0316611c6382868686612d4d565b600160a060020a031614611caf576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b611cb881612eae565b61157e8a8a8a8a8a6131ac565b6002546000908190600160a060020a03163314611d1a576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff1690811115611d3457fe5b14611d77576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60008a118015611d875750600089115b1515611ddd576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616d6f756e74730000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038c8116908c161415611e41576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c696420617373657473000000000000000000000000000000000000604482015290519081900360640190fd5b8c8c8c8c8c8c8c8c60405160200180807f6d616b654f66666572000000000000000000000000000000000000000000000081525060090189600160a060020a0316600160a060020a0316606060020a02815260140188600160a060020a0316600160a060020a0316606060020a02815260140187600160a060020a0316600160a060020a0316606060020a02815260140186815260200185815260200184600160a060020a0316600160a060020a0316606060020a0281526014018381526020018267ffffffffffffffff1667ffffffffffffffff1660c060020a028152600801985050505050505050506040516020818303038152906040526040518082805190602001908083835b60208310611f6a5780518252601f199092019160209182019101611f4b565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091508c600160a060020a0316611faf83878787612d4d565b600160a060020a031614611ffb576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b61200482612eae565b6120178d8d8c8b8b60026010601161354b565b60056000836000191660001916815260200190815260200160002090508c8160000160006101000a815481600160a060020a030219169083600160a060020a031602179055508b8160010160006101000a815481600160a060020a030219169083600160a060020a031602179055508a8160020160006101000a815481600160a060020a030219169083600160a060020a03160217905550898160030181905550888160040181905550898160050181905550858160020160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600019168d600160a060020a03167f1fa192562e5fbdce807069b18275dc0d672cacd78576602b47d21730975635a160405160405180910390a350505050505050505050505050565b600054600160a060020a0316331461215657600080fd5b61215f81612f35565b600160a060020a03166000908152600760205260409020805460ff19169055565b600054600160a060020a031681565b600054600160a060020a031633146121a657600080fd5b6121af81612f35565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6121e6613995565b6000828152600a60205260409020541580159061221157506000828152600a60205260409020544210155b1515612267576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742064656c61790000000000000000000000000000604482015290519081900360640190fd5b506000818152600a602090815260408083208390556005808352818420825160e0810184528154600160a060020a039081168252600183015481169582019590955260028201549485169381019390935260a060020a90930467ffffffffffffffff16606083015260038301546080830152600483015460a0830152919091015460c0820181905290916122fd91849180612fa7565b5050565b600254600160a060020a03163314612351576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b6000828152600a602052604090205415156123b6576040805160e560020a62461bcd02815260206004820152601360248201527f4d697373696e6720616e6e6f6e63656d656e7400000000000000000000000000604482015290519081900360640190fd5b6000828152600a602052604081208190556122fd908390839080612fa7565b600254600160a060020a03163314612425576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b600180805460a060020a900460ff169081111561243e57fe5b14612481576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b6122fd8282600080612fa7565b60006001805460a060020a900460ff16908111156124a857fe5b146124eb576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60003411612543576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c69642076616c756500000000000000000000000000000000000000604482015290519081900360640190fd5b33600090815260046020908152604080832083805290915290205461256e903463ffffffff612b4016565b336000818152600460209081526040808320838052825280832094909455835134815293516001949293926000805160206139d283398151915292908290030190a4565b60076020526000908152604090205460ff1681565b60066020526000908152604090205460ff1681565b600054600160a060020a031633146125f357600080fd5b60035461260890600160a060020a0316612f35565b6003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60015460a060020a900460ff1681565b600460209081526000928352604080842090915290825290205481565b6002546000908190600160a060020a031633146126b9576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b60006001805460a060020a900460ff16908111156126d357fe5b14612716576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b60008b1161276e576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c696420696e70757400000000000000000000000000000000000000604482015290519081900360640190fd5b8a89146127c5576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c696420696e70757473000000000000000000000000000000000000604482015290519081900360640190fd5b8c8c8c8c8c8c8c8c60405160200180807f66696c6c4f666665727300000000000000000000000000000000000000000000815250600a0189600160a060020a0316600160a060020a0316606060020a0281526014018888602002808284378201915050868660200280828437820191505084600160a060020a0316600160a060020a0316606060020a0281526014018381526020018267ffffffffffffffff1667ffffffffffffffff1660c060020a028152600801985050505050505050506040516020818303038152906040526040518082805190602001908083835b602083106128c25780518252601f1990920191602091820191016128a3565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091508c600160a060020a031661290783878787612d4d565b600160a060020a031614612953576040805160e560020a62461bcd0281526020600482015260116024820152600080516020613a12833981519152604482015290519081900360640190fd5b61295c82612eae565b5060005b63ffffffff81168b11156129b7576129af8d8d8d63ffffffff851681811061298457fe5b602002919091013590508c8c63ffffffff86168181106129a057fe5b905060200201356000806131ac565b600101612960565b6129c68d898960046007613611565b50505050505050505050505050565b600154600160a060020a031681565b600254600160a060020a03163314612a34576040805160e560020a62461bcd02815260206004820152600e60248201526000805160206139f2833981519152604482015290519081900360640190fd5b600180805460a060020a900460ff1690811115612a4d57fe5b14612a90576040805160e560020a62461bcd02815260206004820152600d6024820152600080516020613a32833981519152604482015290519081900360640190fd5b612a9e838383600080612b97565b505050565b60035460c060020a900463ffffffff1681565b600054600160a060020a03163314612acd57600080fd5b612ad681612f35565b600160a060020a03166000908152600760205260409020805460ff19166001179055565b600054600160a060020a03163314612b1157600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b81810182811015612b4d57fe5b92915050565b803b1515612b6057600080fd5b50565b6000803d8015612b7a5760208114612b8357600080fd5b60019150612b8f565b60206000803e60005191505b501515919050565b612baa858585858560096014601561354b565b600160a060020a0384161515612bf657604051600160a060020a0386169084156108fc029085906000818181858888f19350505050158015612bf0573d6000803e3d6000fd5b50612d46565b612bff84612b53565b83600160a060020a031660405180807f7472616e7366657228616464726573732c75696e7432353629000000000000008152506019019050604051809103902060e060020a900486856040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a03168152602001828152602001925050506000604051808303816000875af1925050501515612ce8576040805160e560020a62461bcd02815260206004820152601460248201527f7472616e736665722063616c6c206661696c6564000000000000000000000000604482015290519081900360640190fd5b612cf0612b63565b1515612d46576040805160e560020a62461bcd02815260206004820152600f60248201527f7472616e73666572206661696c65640000000000000000000000000000000000604482015290519081900360640190fd5b5050505050565b604080518082018252601c8082527f19457468657265756d205369676e6564204d6573736167653a0a33320000000060208084019182529351600094859385938b939092019182918083835b60208310612db85780518252601f199092019160209182019101612d99565b51815160209384036101000a600019018019909216911617905292019384525060408051808503815293820190819052835193945092839250908401908083835b60208310612e185780518252601f199092019160209182019101612df9565b51815160209384036101000a600019018019909216911617905260408051929094018290038220600080845283830180875282905260ff8e1684870152606084018d9052608084018c905294519097506001965060a080840196509194601f19820194509281900390910191865af1158015612e98573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b60008181526006602052604090205460ff16151560011415612f1a576040805160e560020a62461bcd02815260206004820152601160248201527f6861736820616c72656164792075736564000000000000000000000000000000604482015290519081900360640190fd5b6000908152600660205260409020805460ff19166001179055565b600160a060020a0381161515612b60576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b600082821115612fa157fe5b50900390565b612faf613995565b506000848152600560208181526040808420815160e0810183528154600160a060020a039081168252600183015481169482019490945260028201549384169281019290925260a060020a90920467ffffffffffffffff16606082015260038201546080820152600482015460a082015291015460c08201819052909110613081576040805160e560020a62461bcd02815260206004820152601760248201527f4f6666657220616c72656164792063616e63656c6c6564000000000000000000604482015290519081900360640190fd5b60c081015184146130dc576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c696420696e70757400000000000000000000000000000000000000604482015290519081900360640190fd5b60008581526005602081815260408320805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690556002810180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916905560038101849055600481018490559091019190915581519082015160c083015161316e9291908686600860126013613740565b80516040518691600160a060020a0316907fdb2b33dd6349739e1f3cd6dc90cf093af6a3dfb1838aced380528b0aefe6093c90600090a35050505050565b600080808511613206576040805160e560020a62461bcd02815260206004820152600d60248201527f496e76616c696420696e70757400000000000000000000000000000000000000604482015290519081900360640190fd5b60008681526005602052604090208054909250600160a060020a038881169116141561327c576040805160e560020a62461bcd02815260206004820152600e60248201527f496e76616c69642066696c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b600582015415156132d7576040805160e560020a62461bcd02815260206004820152601460248201527f4f6666657220616c72656164792066696c6c6564000000000000000000000000604482015290519081900360640190fd5b61330282600301546132f68460040154886137fb90919063ffffffff16565b9063ffffffff61382416565b600160a060020a038089166000908152600460209081526040808320600288015490941683529290522054909150613340908263ffffffff612f9516565b600160a060020a0380891660008181526004602090815260408083206002890180548716855290835292819020959095559054845186815294516003959190941693600080516020613a52833981519152929181900390910190a48154600160a060020a0390811660009081526004602090815260408083206002870154909416835292905220546133d8908263ffffffff612b4016565b8254600160a060020a03908116600090815260046020908152604080832060028801805486168552908352928190209490945590548554845186815294516006959285169491909116926000805160206139d2833981519152928290030190a4600582015461344d908663ffffffff612f9516565b600580840191909155600183015461347a918991600160a060020a03169088908890889060046007613740565b815460408051838152602081018890528151600160a060020a03938416938a93908c16927fc587d1c5cbeb2dc01ea21c77c1c9232f39962a50cf2d6ce8d02dd09356e05b85929081900390910190a460058201541515611aad57505050600092835250506005602081905260408220805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690556002810180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690556003810183905560048101839055015550565b85600160a060020a03868116908916141561357357613570878663ffffffff612b4016565b90505b600160a060020a03808a166000908152600460209081526040808320938c16835292905220546135a9908263ffffffff612f9516565b600160a060020a03808b166000818152600460209081526040808320948e1680845294825291829020949094558051858152905160ff891694600080516020613a52833981519152928290030190a4613606898988888787613839565b505050505050505050565b82151561361d57612d46565b600160a060020a03808616600090815260046020908152604080832093881683529290522054613653908463ffffffff612f9516565b600160a060020a038087166000818152600460209081526040808320948a1680845294825291829020949094558051878152905160ff871694600080516020613a52833981519152928290030190a4600354600160a060020a039081166000908152600460209081526040808320938816835292905220546136db908463ffffffff612b4016565b60038054600160a060020a0390811660009081526004602090815260408083208a8516808552908352928190209590955592548451888152945160ff871695929491909316926000805160206139d28339815191529281900390910190a45050505050565b85600160a060020a03868116908916141561376857613765878663ffffffff612f9516565b90505b600160a060020a03808a166000908152600460209081526040808320938c168352929052205461379e908263ffffffff612b4016565b600160a060020a03808b166000818152600460209081526040808320948e1680845294825291829020949094558051858152905160ff8916946000805160206139d2833981519152928290030190a4613606898988888787613839565b600082151561380c57506000612b4d565b5081810281838281151561381c57fe5b0414612b4d57fe5b6000818381151561383157fe5b049392505050565b82151561384557613976565b600160a060020a03848116908616146138de57600160a060020a0380871660009081526004602090815260408083209388168352929052205461388e908463ffffffff612f9516565b600160a060020a038088166000818152600460209081526040808320948a1680845294825291829020949094558051878152905160ff871694600080516020613a52833981519152928290030190a45b600354600160a060020a03908116600090815260046020908152604080832093881683529290522054613917908463ffffffff612b4016565b60038054600160a060020a0390811660009081526004602090815260408083208a8516808552908352928190209590955592548451888152945160ff871695929491909316926000805160206139d28339815191529281900390910190a45b505050505050565b604080518082019091526000808252602082015290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091529056004a52a947455663fbd6ddcc61a4d3a18a7e387c418de430ea8a191956cc53ec79496e76616c69642073656e646572000000000000000000000000000000000000496e76616c6964207369676e6174757265000000000000000000000000000000496e76616c696420737461746500000000000000000000000000000000000000a3bbf8b09a42177fa9310281fb7f2fc8803d7c6df09a82093ea047cb6a222aa3a165627a7a72305820eedc0304d51bd7a039c150363cfd0f3abd3ae51b32404275ae0be012f46225780029

Swarm Source

bzzr://eedc0304d51bd7a039c150363cfd0f3abd3ae51b32404275ae0be012f4622578

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

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
Chain Token Portfolio % Price Amount Value
ETH
Ether (ETH)
98.30%$3,579.385.5532$19,876.9
ETH0.68%$22.975.9532$136.75
ETH0.36%$0.0000362,000,000$71.8
ETH0.23%$586.580.0787$46.18
ETH0.08%$6.092.5688$15.64
ETH0.05%$0.16896861.2935$10.36
ETH0.05%$0.23959143$10.3
ETH0.04%$3,497.680.00216926$7.59
ETH0.03%$0.59655111.0271$6.58
ETH0.03%$0.9083356.6082$6
ETH0.03%$0.07644273.1522$5.59
ETH0.02%$19.30.1711$3.3
ETH0.01%$1.352.167$2.93
ETH0.01%$1.032.5975$2.68
ETH0.01%$0.4096016.3797$2.61
ETH0.01%$138.90.0169$2.35
ETH0.01%$0.6615833.1631$2.09
ETH0.01%$0.5033664.0805$2.05
ETH<0.01%$0.00341507.3932$1.73
ETH<0.01%$0.3368975.026$1.69
ETH<0.01%$0.003935232.3591$0.9142
ETH<0.01%$0.000992845.2584$0.8383
ETH<0.01%$0.1031147.9233$0.8169
ETH<0.01%$1.090.5977$0.649
ETH<0.01%$0.1549344.0763$0.6315
ETH<0.01%$0.0005751,053.3652$0.606
ETH<0.01%$10.4898$0.4897
ETH<0.01%$0.04009611.4916$0.4607
ETH<0.01%$0.00698563.9901$0.4469
ETH<0.01%$0.002321100$0.2321
ETH<0.01%$0.000751260.389$0.1956
ETH<0.01%$0.00239680.009$0.1916
[ 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.