ETH Price: $2,666.60 (-1.38%)

Contract

0x7ee7Ca6E75dE79e618e88bDf80d0B1DB136b22D0
 

Overview

ETH Balance

719.734745224989640257 ETH

Eth Value

$1,919,245.74 (@ $2,666.60/ETH)

Token Holdings

Transaction Hash
Method
Block
From
To
Slow Withdraw216749682025-01-21 19:31:3526 days ago1737487895IN
Switcheo Exchange V2
0 ETH0.000665920.94182816
Transfer Tokens ...216749282025-01-21 19:23:3526 days ago1737487415IN
Switcheo Exchange V2
0 ETH0.0005124823.03919608
Slow Withdraw207419272024-09-13 13:15:11156 days ago1726233311IN
Switcheo Exchange V2
0 ETH0.000119792.48812136
Announce Withdra...207419172024-09-13 13:13:11156 days ago1726233191IN
Switcheo Exchange V2
0 ETH0.00021482.75728499
Slow Withdraw207418002024-09-13 12:49:23156 days ago1726231763IN
Switcheo Exchange V2
0 ETH0.0001292.67883989
Announce Withdra...207417612024-09-13 12:41:35156 days ago1726231295IN
Switcheo Exchange V2
0 ETH0.000214942.7585789
Slow Withdraw201644012024-06-24 22:03:35237 days ago1719266615IN
Switcheo Exchange V2
0 ETH0.000379237.87502194
Announce Withdra...201643952024-06-24 22:02:23237 days ago1719266543IN
Switcheo Exchange V2
0 ETH0.000573727.36330612
Slow Withdraw190536492024-01-21 7:08:59392 days ago1705820939IN
Switcheo Exchange V2
0 ETH0.000475749.88098632
Announce Withdra...190536472024-01-21 7:08:35392 days ago1705820915IN
Switcheo Exchange V2
0 ETH0.000762639.78924585
Slow Withdraw186202352023-11-21 12:48:35453 days ago1700570915IN
Switcheo Exchange V2
0 ETH0.0011834224.57890131
Announce Withdra...186201672023-11-21 12:34:59453 days ago1700570099IN
Switcheo Exchange V2
0 ETH0.0019292624.76436106
Slow Withdraw184442482023-10-27 21:32:35478 days ago1698442355IN
Switcheo Exchange V2
0 ETH0.0008575317.81041184
Announce Withdra...184442462023-10-27 21:32:11478 days ago1698442331IN
Switcheo Exchange V2
0 ETH0.0014313118.37263073
Announce Withdra...178886752023-08-11 2:30:47556 days ago1691721047IN
Switcheo Exchange V2
0 ETH0.0010037512.84081834
Slow Withdraw177328502023-07-20 7:19:47577 days ago1689837587IN
Switcheo Exchange V2
0 ETH0.0009958820.679935
Announce Withdra...177328452023-07-20 7:18:47577 days ago1689837527IN
Switcheo Exchange V2
0 ETH0.0016181820.76808863
Slow Withdraw175199032023-06-20 9:04:59607 days ago1687251899IN
Switcheo Exchange V2
0 ETH0.0010933814.79209933
Announce Withdra...175198992023-06-20 9:04:11607 days ago1687251851IN
Switcheo Exchange V2
0 ETH0.0012529816.02671984
Slow Withdraw175198912023-06-20 9:02:35607 days ago1687251755IN
Switcheo Exchange V2
0 ETH0.0007278515.11422959
Announce Withdra...175198852023-06-20 9:01:23607 days ago1687251683IN
Switcheo Exchange V2
0 ETH0.0013077116.78337331
Slow Withdraw172098302023-05-07 16:24:11651 days ago1683476651IN
Switcheo Exchange V2
0 ETH0.00599302124.42176135
Announce Withdra...172098292023-05-07 16:23:59651 days ago1683476639IN
Switcheo Exchange V2
0 ETH0.00514437125.69030401
Announce Withdra...172098182023-05-07 16:21:47651 days ago1683476507IN
Switcheo Exchange V2
0 ETH0.01011012129.73503847
Slow Withdraw170374302023-04-13 8:18:59675 days ago1681373939IN
Switcheo Exchange V2
0 ETH0.0020502127.62497693
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
207419272024-09-13 13:15:11156 days ago1726233311
Switcheo Exchange V2
0.01090001 ETH
207418002024-09-13 12:49:23156 days ago1726231763
Switcheo Exchange V2
0.1005 ETH
201644012024-06-24 22:03:35237 days ago1719266615
Switcheo Exchange V2
0.54032237 ETH
190536492024-01-21 7:08:59392 days ago1705820939
Switcheo Exchange V2
0.75 ETH
186202352023-11-21 12:48:35453 days ago1700570915
Switcheo Exchange V2
0.03898908 ETH
184442482023-10-27 21:32:35478 days ago1698442355
Switcheo Exchange V2
0.05687141 ETH
177328502023-07-20 7:19:47577 days ago1689837587
Switcheo Exchange V2
0.32196164 ETH
175198912023-06-20 9:02:35607 days ago1687251755
Switcheo Exchange V2
0.11570074 ETH
172098302023-05-07 16:24:11651 days ago1683476651
Switcheo Exchange V2
0.84791373 ETH
170320862023-04-12 13:00:47676 days ago1681304447
Switcheo Exchange V2
104.49172662 ETH
160617272022-11-27 13:49:23812 days ago1669556963
Switcheo Exchange V2
0.02730392 ETH
154883092022-09-07 4:32:15894 days ago1662525135
Switcheo Exchange V2
0.03296651 ETH
153068832022-08-09 8:17:20922 days ago1660033040
Switcheo Exchange V2
0.206411 ETH
152324162022-07-28 17:45:33934 days ago1659030333
Switcheo Exchange V2
1.00324846 ETH
152322942022-07-28 17:18:03934 days ago1659028683
Switcheo Exchange V2
0.005538 ETH
150177622022-06-24 10:08:43968 days ago1656065323
Switcheo Exchange V2
0.09884383 ETH
149701612022-06-15 23:25:18977 days ago1655335518
Switcheo Exchange V2
0.076291 ETH
146604142022-04-26 13:33:281027 days ago1650980008
Switcheo Exchange V2
0.06088224 ETH
146157022022-04-19 13:13:011034 days ago1650373981
Switcheo Exchange V2
0.06189102 ETH
145859942022-04-14 21:35:441039 days ago1649972144
Switcheo Exchange V2
0.03741502 ETH
145145912022-04-03 17:53:381050 days ago1649008418
Switcheo Exchange V2
0.0402766 ETH
144959912022-03-31 20:06:121053 days ago1648757172
Switcheo Exchange V2
1.07970234 ETH
144539152022-03-25 6:51:491059 days ago1648191109
Switcheo Exchange V2
0.01241694 ETH
143482792022-03-08 20:19:271076 days ago1646770767
Switcheo Exchange V2
0.03384339 ETH
143405632022-03-07 15:38:301077 days ago1646667510
Switcheo Exchange V2
0.00635323 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BrokerV2

Compiler Version
v0.5.12+commit.7709ece9

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2019-10-09
*/

// File: contracts/lib/math/SafeMath.sol

pragma solidity 0.5.12;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

// File: contracts/lib/ownership/Ownable.sol

pragma solidity 0.5.12;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be aplied to your functions to restrict their use to
 * the owner.
 */
contract Ownable {
    address public owner;
    address public pendingOwner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        owner = msg.sender;
        emit OwnershipTransferred(address(0), owner);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == owner;
    }

    /**
    * @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);
    }
}

// File: contracts/lib/utils/ReentrancyGuard.sol

pragma solidity ^0.5.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
 * available, which can be aplied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 */
contract ReentrancyGuard {
    /// @dev counter to allow mutex lock with only one SSTORE operation
    uint256 private _guardCounter;

    constructor () internal {
        // The counter starts at one to prevent changing it from zero to a non-zero
        // value, which is a more expensive operation.
        _guardCounter = 1;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }
}

// File: contracts/Utils.sol

pragma solidity 0.5.12;


interface ERC20 {
    function balanceOf(address account) external view returns (uint256);
}

interface MarketDapp {
    // Returns the address to approve tokens for
    function tokenReceiver(address[] calldata assetIds, uint256[] calldata dataValues, address[] calldata addresses) external view returns(address);
    function trade(address[] calldata assetIds, uint256[] calldata dataValues, address[] calldata addresses, address payable recipient) external payable;
}

/// @title Util functions for the BrokerV2 contract for Switcheo Exchange
/// @author Switcheo Network
/// @notice Functions were moved from the BrokerV2 contract into this contract
/// so that the BrokerV2 contract would not exceed the maximum contract size of
/// 24 KB.
library Utils {
    using SafeMath for uint256;

    // The constants for EIP-712 are precompiled to reduce contract size,
    // the original values are left here for reference and verification.
    //
    // bytes32 public constant EIP712_DOMAIN_TYPEHASH = keccak256(abi.encodePacked(
    //     "EIP712Domain(",
    //         "string name,",
    //         "string version,",
    //         "uint256 chainId,",
    //         "address verifyingContract,",
    //         "bytes32 salt",
    //     ")"
    // ));
    // bytes32 public constant EIP712_DOMAIN_TYPEHASH = 0xd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472;
    //
    // bytes32 public constant CONTRACT_NAME = keccak256("Switcheo Exchange");
    // bytes32 public constant CONTRACT_VERSION = keccak256("2");
    // uint256 public constant CHAIN_ID = 1;
    // address public constant VERIFYING_CONTRACT = 0x7ee7Ca6E75dE79e618e88bDf80d0B1DB136b22D0;
    // bytes32 public constant SALT = keccak256("switcheo-eth-salt");

    // bytes32 public constant DOMAIN_SEPARATOR = keccak256(abi.encode(
    //     EIP712_DOMAIN_TYPEHASH,
    //     CONTRACT_NAME,
    //     CONTRACT_VERSION,
    //     CHAIN_ID,
    //     VERIFYING_CONTRACT,
    //     SALT
    // ));
    bytes32 public constant DOMAIN_SEPARATOR = 0x256c0713d13c6a01bd319a2f7edabde771b6c167d37c01778290d60b362ccc7d;

    // bytes32 public constant OFFER_TYPEHASH = keccak256(abi.encodePacked(
    //     "Offer(",
    //         "address maker,",
    //         "address offerAssetId,",
    //         "uint256 offerAmount,",
    //         "address wantAssetId,",
    //         "uint256 wantAmount,",
    //         "address feeAssetId,",
    //         "uint256 feeAmount,",
    //         "uint256 nonce",
    //     ")"
    // ));
    bytes32 public constant OFFER_TYPEHASH = 0xf845c83a8f7964bc8dd1a092d28b83573b35be97630a5b8a3b8ae2ae79cd9260;

    // bytes32 public constant CANCEL_TYPEHASH = keccak256(abi.encodePacked(
    //     "Cancel(",
    //         "bytes32 offerHash,",
    //         "address feeAssetId,",
    //         "uint256 feeAmount,",
    //     ")"
    // ));
    bytes32 public constant CANCEL_TYPEHASH = 0x46f6d088b1f0ff5a05c3f232c4567f2df96958e05457e6c0e1221dcee7d69c18;

    // bytes32 public constant FILL_TYPEHASH = keccak256(abi.encodePacked(
    //     "Fill(",
    //         "address filler,",
    //         "address offerAssetId,",
    //         "uint256 offerAmount,",
    //         "address wantAssetId,",
    //         "uint256 wantAmount,",
    //         "address feeAssetId,",
    //         "uint256 feeAmount,",
    //         "uint256 nonce",
    //     ")"
    // ));
    bytes32 public constant FILL_TYPEHASH = 0x5f59dbc3412a4575afed909d028055a91a4250ce92235f6790c155a4b2669e99;

    // The Ether token address is set as the constant 0x00 for backwards
    // compatibility
    address private constant ETHER_ADDR = address(0);

    uint256 private constant mask8 = ~(~uint256(0) << 8);
    uint256 private constant mask16 = ~(~uint256(0) << 16);
    uint256 private constant mask24 = ~(~uint256(0) << 24);
    uint256 private constant mask32 = ~(~uint256(0) << 32);
    uint256 private constant mask40 = ~(~uint256(0) << 40);
    uint256 private constant mask48 = ~(~uint256(0) << 48);
    uint256 private constant mask56 = ~(~uint256(0) << 56);
    uint256 private constant mask120 = ~(~uint256(0) << 120);
    uint256 private constant mask128 = ~(~uint256(0) << 128);
    uint256 private constant mask136 = ~(~uint256(0) << 136);
    uint256 private constant mask144 = ~(~uint256(0) << 144);

    event Trade(
        address maker,
        address taker,
        address makerGiveAsset,
        uint256 makerGiveAmount,
        address fillerGiveAsset,
        uint256 fillerGiveAmount
    );

    /// @dev Calculates the balance increments for a set of trades
    /// @param _values The _values param from the trade method
    /// @param _incrementsLength Should match the value of _addresses.length / 2
    /// from the trade method
    /// @return An array of increments
    function calculateTradeIncrements(
        uint256[] memory _values,
        uint256 _incrementsLength
    )
        public
        pure
        returns (uint256[] memory)
    {
        uint256[] memory increments = new uint256[](_incrementsLength);
        _creditFillBalances(increments, _values);
        _creditMakerBalances(increments, _values);
        _creditMakerFeeBalances(increments, _values);
        return increments;
    }

    /// @dev Calculates the balance decrements for a set of trades
    /// @param _values The _values param from the trade method
    /// @param _decrementsLength Should match the value of _addresses.length / 2
    /// from the trade method
    /// @return An array of decrements
    function calculateTradeDecrements(
        uint256[] memory _values,
        uint256 _decrementsLength
    )
        public
        pure
        returns (uint256[] memory)
    {
        uint256[] memory decrements = new uint256[](_decrementsLength);
        _deductFillBalances(decrements, _values);
        _deductMakerBalances(decrements, _values);
        return decrements;
    }

    /// @dev Calculates the balance increments for a set of network trades
    /// @param _values The _values param from the networkTrade method
    /// @param _incrementsLength Should match the value of _addresses.length / 2
    /// from the networkTrade method
    /// @return An array of increments
    function calculateNetworkTradeIncrements(
        uint256[] memory _values,
        uint256 _incrementsLength
    )
        public
        pure
        returns (uint256[] memory)
    {
        uint256[] memory increments = new uint256[](_incrementsLength);
        _creditMakerBalances(increments, _values);
        _creditMakerFeeBalances(increments, _values);
        return increments;
    }

    /// @dev Calculates the balance decrements for a set of network trades
    /// @param _values The _values param from the trade method
    /// @param _decrementsLength Should match the value of _addresses.length / 2
    /// from the networkTrade method
    /// @return An array of decrements
    function calculateNetworkTradeDecrements(
        uint256[] memory _values,
        uint256 _decrementsLength
    )
        public
        pure
        returns (uint256[] memory)
    {
        uint256[] memory decrements = new uint256[](_decrementsLength);
        _deductMakerBalances(decrements, _values);
        return decrements;
    }

    /// @dev Validates `BrokerV2.trade` parameters to ensure trade fairness,
    /// see `BrokerV2.trade` for param details.
    /// @param _values Values from `trade`
    /// @param _hashes Hashes from `trade`
    /// @param _addresses Addresses from `trade`
    function validateTrades(
        uint256[] memory _values,
        bytes32[] memory _hashes,
        address[] memory _addresses,
        address _operator
    )
        public
        returns (bytes32[] memory)
    {
        _validateTradeInputLengths(_values, _hashes);
        _validateUniqueOffers(_values);
        _validateMatches(_values, _addresses);
        _validateFillAmounts(_values);
        _validateTradeData(_values, _addresses, _operator);

        // validate signatures of all offers
        _validateTradeSignatures(
            _values,
            _hashes,
            _addresses,
            OFFER_TYPEHASH,
            0,
            _values[0] & mask8 // numOffers
        );

        // validate signatures of all fills
        _validateTradeSignatures(
            _values,
            _hashes,
            _addresses,
            FILL_TYPEHASH,
            _values[0] & mask8, // numOffers
            (_values[0] & mask8) + ((_values[0] & mask16) >> 8) // numOffers + numFills
        );

        _emitTradeEvents(_values, _addresses, new address[](0), false);

        return _hashes;
    }

    /// @dev Validates `BrokerV2.networkTrade` parameters to ensure trade fairness,
    /// see `BrokerV2.networkTrade` for param details.
    /// @param _values Values from `networkTrade`
    /// @param _hashes Hashes from `networkTrade`
    /// @param _addresses Addresses from `networkTrade`
    /// @param _operator Address of the `BrokerV2.operator`
    function validateNetworkTrades(
        uint256[] memory _values,
        bytes32[] memory _hashes,
        address[] memory _addresses,
        address _operator
    )
        public
        pure
        returns (bytes32[] memory)
    {
        _validateNetworkTradeInputLengths(_values, _hashes);
        _validateUniqueOffers(_values);
        _validateNetworkMatches(_values, _addresses, _operator);
        _validateTradeData(_values, _addresses, _operator);

        // validate signatures of all offers
        _validateTradeSignatures(
            _values,
            _hashes,
            _addresses,
            OFFER_TYPEHASH,
            0,
            _values[0] & mask8 // numOffers
        );

        return _hashes;
    }

    /// @dev Executes trades against external markets,
    /// see `BrokerV2.networkTrade` for param details.
    /// @param _values Values from `networkTrade`
    /// @param _addresses Addresses from `networkTrade`
    /// @param _marketDapps See `BrokerV2.marketDapps`
    function performNetworkTrades(
        uint256[] memory _values,
        address[] memory _addresses,
        address[] memory _marketDapps
    )
        public
        returns (uint256[] memory)
    {
        uint256[] memory increments = new uint256[](_addresses.length / 2);
        // i = 1 + numOffers * 2
        uint256 i = 1 + (_values[0] & mask8) * 2;
        uint256 end = _values.length;

        // loop matches
        for(i; i < end; i++) {
            uint256[] memory data = new uint256[](9);
            data[0] = _values[i]; // match data
            data[1] = data[0] & mask8; // offerIndex
            data[2] = (data[0] & mask24) >> 16; // operator.surplusAssetIndex
            data[3] = _values[data[1] * 2 + 1]; // offer.dataA
            data[4] = _values[data[1] * 2 + 2]; // offer.dataB
            data[5] = ((data[3] & mask16) >> 8); // maker.offerAssetIndex
            data[6] = ((data[3] & mask24) >> 16); // maker.wantAssetIndex
            // amount of offerAssetId to take from the offer is equal to the match.takeAmount
            data[7] = data[0] >> 128;
            // expected amount to receive is: matchData.takeAmount * offer.wantAmount / offer.offerAmount
            data[8] = data[7].mul(data[4] >> 128).div(data[4] & mask128);

            address[] memory assetIds = new address[](3);
            assetIds[0] = _addresses[data[5] * 2 + 1]; // offer.offerAssetId
            assetIds[1] = _addresses[data[6] * 2 + 1]; // offer.wantAssetId
            assetIds[2] = _addresses[data[2] * 2 + 1]; // surplusAssetId

            uint256[] memory dataValues = new uint256[](3);
            dataValues[0] = data[7]; // the proportion of offerAmount to offer
            dataValues[1] = data[8]; // the proportion of wantAmount to receive for the offer
            dataValues[2] = data[0]; // match data

            increments[data[2]] = _performNetworkTrade(
                assetIds,
                dataValues,
                _marketDapps,
                _addresses
            );
        }

        _emitTradeEvents(_values, _addresses, _marketDapps, true);

        return increments;
    }

    /// @dev Validates the signature of a cancel invocation
    /// @param _values The _values param from the cancel method
    /// @param _hashes The _hashes param from the cancel method
    /// @param _addresses The _addresses param from the cancel method
    function validateCancel(
        uint256[] memory _values,
        bytes32[] memory _hashes,
        address[] memory _addresses
    )
        public
        pure
    {
        bytes32 offerHash = hashOffer(_values, _addresses);

        bytes32 cancelHash = keccak256(abi.encode(
            CANCEL_TYPEHASH,
            offerHash,
            _addresses[4],
            _values[1] >> 128
        ));

        validateSignature(
            cancelHash,
            _addresses[0], // maker
            uint8((_values[2] & mask144) >> 136), // v
            _hashes[0], // r
            _hashes[1], // s
            ((_values[2] & mask136) >> 128) != 0 // prefixedSignature
        );
    }

    /// @dev Hashes an offer for the cancel method
    /// @param _values The _values param from the cancel method
    /// @param _addresses THe _addresses param from the cancel method
    /// @return The hash of the offer
    function hashOffer(
        uint256[] memory _values,
        address[] memory _addresses
    )
        public
        pure
        returns (bytes32)
    {
        return keccak256(abi.encode(
            OFFER_TYPEHASH,
            _addresses[0], // maker
            _addresses[1], // offerAssetId
            _values[0] & mask128, // offerAmount
            _addresses[2], // wantAssetId
            _values[0] >> 128, // wantAmount
            _addresses[3], // feeAssetId
            _values[1] & mask128, // feeAmount
            _values[2] >> 144 // offerNonce
        ));
    }

    /// @notice Approves a token transfer
    /// @param _assetId The address of the token to approve
    /// @param _spender The address of the spender to approve
    /// @param _amount The number of tokens to approve
    function approveTokenTransfer(
        address _assetId,
        address _spender,
        uint256 _amount
    )
        public
    {
        _validateContractAddress(_assetId);

        // Some tokens have an `approve` which returns a boolean and some do not.
        // The ERC20 interface cannot be used here because it requires specifying
        // an explicit return value, and an EVM exception would be raised when calling
        // a token with the mismatched return value.
        bytes memory payload = abi.encodeWithSignature(
            "approve(address,uint256)",
            _spender,
            _amount
        );
        bytes memory returnData = _callContract(_assetId, payload);
        // Ensure that the asset transfer succeeded
        _validateContractCallResult(returnData);
    }

    /// @notice Transfers tokens into the contract
    /// @param _user The address to transfer the tokens from
    /// @param _assetId The address of the token to transfer
    /// @param _amount The number of tokens to transfer
    /// @param _expectedAmount The number of tokens expected to be received,
    /// this may not match `_amount`, for example, tokens which have a
    /// proportion burnt on transfer will have a different amount received.
    function transferTokensIn(
        address _user,
        address _assetId,
        uint256 _amount,
        uint256 _expectedAmount
    )
        public
    {
        _validateContractAddress(_assetId);

        uint256 initialBalance = tokenBalance(_assetId);

        // Some tokens have a `transferFrom` which returns a boolean and some do not.
        // The ERC20 interface cannot be used here because it requires specifying
        // an explicit return value, and an EVM exception would be raised when calling
        // a token with the mismatched return value.
        bytes memory payload = abi.encodeWithSignature(
            "transferFrom(address,address,uint256)",
            _user,
            address(this),
            _amount
        );
        bytes memory returnData = _callContract(_assetId, payload);
        // Ensure that the asset transfer succeeded
        _validateContractCallResult(returnData);

        uint256 finalBalance = tokenBalance(_assetId);
        uint256 transferredAmount = finalBalance.sub(initialBalance);

        require(transferredAmount == _expectedAmount, "Invalid transfer");
    }

    /// @notice Transfers tokens from the contract to a user
    /// @param _receivingAddress The address to transfer the tokens to
    /// @param _assetId The address of the token to transfer
    /// @param _amount The number of tokens to transfer
    function transferTokensOut(
        address _receivingAddress,
        address _assetId,
        uint256 _amount
    )
        public
    {
        _validateContractAddress(_assetId);

        // Some tokens have a `transfer` which returns a boolean and some do not.
        // The ERC20 interface cannot be used here because it requires specifying
        // an explicit return value, and an EVM exception would be raised when calling
        // a token with the mismatched return value.
        bytes memory payload = abi.encodeWithSignature(
                                   "transfer(address,uint256)",
                                   _receivingAddress,
                                   _amount
                               );
        bytes memory returnData = _callContract(_assetId, payload);

        // Ensure that the asset transfer succeeded
        _validateContractCallResult(returnData);
    }

    /// @notice Returns the number of tokens owned by this contract
    /// @param _assetId The address of the token to query
    function externalBalance(address _assetId) public view returns (uint256) {
        if (_assetId == ETHER_ADDR) {
            return address(this).balance;
        }
        return tokenBalance(_assetId);
    }

    /// @notice Returns the number of tokens owned by this contract.
    /// @dev This will not work for Ether tokens, use `externalBalance` for
    /// Ether tokens.
    /// @param _assetId The address of the token to query
    function tokenBalance(address _assetId) public view returns (uint256) {
        return ERC20(_assetId).balanceOf(address(this));
    }

    /// @dev Validates that the specified `_hash` was signed by the specified `_user`.
    /// This method supports the EIP712 specification, the older Ethereum
    /// signed message specification is also supported for backwards compatibility.
    /// @param _hash The original hash that was signed by the user
    /// @param _user The user who signed the hash
    /// @param _v The `v` component of the `_user`'s signature
    /// @param _r The `r` component of the `_user`'s signature
    /// @param _s The `s` component of the `_user`'s signature
    /// @param _prefixed If true, the signature will be verified
    /// against the Ethereum signed message specification instead of the
    /// EIP712 specification
    function validateSignature(
        bytes32 _hash,
        address _user,
        uint8 _v,
        bytes32 _r,
        bytes32 _s,
        bool _prefixed
    )
        public
        pure
    {
        bytes32 eip712Hash = keccak256(abi.encodePacked(
            "\x19\x01",
            DOMAIN_SEPARATOR,
            _hash
        ));

        if (_prefixed) {
            bytes32 prefixedHash = keccak256(abi.encodePacked(
                "\x19Ethereum Signed Message:\n32",
                eip712Hash
            ));
            require(_user == ecrecover(prefixedHash, _v, _r, _s), "Invalid signature");
        } else {
            require(_user == ecrecover(eip712Hash, _v, _r, _s), "Invalid signature");
        }
    }

    /// @dev Ensures that `_address` is not the zero address
    /// @param _address The address to check
    function validateAddress(address _address) public pure {
        require(_address != address(0), "Invalid address");
    }

    /// @dev Credit fillers for each fill.wantAmount,and credit the operator
    /// for each fill.feeAmount. See the `trade` method for param details.
    /// @param _values Values from `trade`
    function _creditFillBalances(
        uint256[] memory _increments,
        uint256[] memory _values
    )
        private
        pure
    {
        // 1 + numOffers * 2
        uint256 i = 1 + (_values[0] & mask8) * 2;
        // i + numFills * 2
        uint256 end = i + ((_values[0] & mask16) >> 8) * 2;

        // loop fills
        for(i; i < end; i += 2) {
            uint256 fillerWantAssetIndex = (_values[i] & mask24) >> 16;
            uint256 wantAmount = _values[i + 1] >> 128;

            // credit fill.wantAmount to filler
            _increments[fillerWantAssetIndex] = _increments[fillerWantAssetIndex].add(wantAmount);

            uint256 feeAmount = _values[i] >> 128;
            if (feeAmount == 0) { continue; }

            uint256 operatorFeeAssetIndex = ((_values[i] & mask40) >> 32);
            // credit fill.feeAmount to operator
            _increments[operatorFeeAssetIndex] = _increments[operatorFeeAssetIndex].add(feeAmount);
        }
    }

    /// @dev Credit makers for each amount received through a matched fill.
    /// See the `trade` method for param details.
    /// @param _values Values from `trade`
    function _creditMakerBalances(
        uint256[] memory _increments,
        uint256[] memory _values
    )
        private
        pure
    {
        uint256 i = 1;
        // i += numOffers * 2
        i += (_values[0] & mask8) * 2;
        // i += numFills * 2
        i += ((_values[0] & mask16) >> 8) * 2;

        uint256 end = _values.length;

        // loop matches
        for(i; i < end; i++) {
            // match.offerIndex
            uint256 offerIndex = _values[i] & mask8;
            // maker.wantAssetIndex
            uint256 makerWantAssetIndex = (_values[1 + offerIndex * 2] & mask24) >> 16;

            // match.takeAmount
            uint256 amount = _values[i] >> 128;
            // receiveAmount = match.takeAmount * offer.wantAmount / offer.offerAmount
            amount = amount.mul(_values[2 + offerIndex * 2] >> 128)
                           .div(_values[2 + offerIndex * 2] & mask128);

            // credit maker for the amount received from the match
            _increments[makerWantAssetIndex] = _increments[makerWantAssetIndex].add(amount);
        }
    }

    /// @dev Credit the operator for each offer.feeAmount if the offer has not
    /// been recorded through a previous `trade` call.
    /// See the `trade` method for param details.
    /// @param _values Values from `trade`
    function _creditMakerFeeBalances(
        uint256[] memory _increments,
        uint256[] memory _values
    )
        private
        pure
    {
        uint256 i = 1;
        // i + numOffers * 2
        uint256 end = i + (_values[0] & mask8) * 2;

        // loop offers
        for(i; i < end; i += 2) {
            bool nonceTaken = ((_values[i] & mask128) >> 120) == 1;
            if (nonceTaken) { continue; }

            uint256 feeAmount = _values[i] >> 128;
            if (feeAmount == 0) { continue; }

            uint256 operatorFeeAssetIndex = (_values[i] & mask40) >> 32;

            // credit make.feeAmount to operator
            _increments[operatorFeeAssetIndex] = _increments[operatorFeeAssetIndex].add(feeAmount);
        }
    }

    /// @dev Deduct tokens from fillers for each fill.offerAmount
    /// and each fill.feeAmount.
    /// See the `trade` method for param details.
    /// @param _values Values from `trade`
    function _deductFillBalances(
        uint256[] memory _decrements,
        uint256[] memory _values
    )
        private
        pure
    {
        // 1 + numOffers * 2
        uint256 i = 1 + (_values[0] & mask8) * 2;
        // i + numFills * 2
        uint256 end = i + ((_values[0] & mask16) >> 8) * 2;

        // loop fills
        for(i; i < end; i += 2) {
            uint256 fillerOfferAssetIndex = (_values[i] & mask16) >> 8;
            uint256 offerAmount = _values[i + 1] & mask128;

            // deduct fill.offerAmount from filler
            _decrements[fillerOfferAssetIndex] = _decrements[fillerOfferAssetIndex].add(offerAmount);

            uint256 feeAmount = _values[i] >> 128;
            if (feeAmount == 0) { continue; }

            // deduct fill.feeAmount from filler
            uint256 fillerFeeAssetIndex = (_values[i] & mask32) >> 24;
            _decrements[fillerFeeAssetIndex] = _decrements[fillerFeeAssetIndex].add(feeAmount);
        }
    }

    /// @dev Deduct tokens from makers for each offer.offerAmount
    /// and each offer.feeAmount if the offer has not been recorded
    /// through a previous `trade` call.
    /// See the `trade` method for param details.
    /// @param _values Values from `trade`
    function _deductMakerBalances(
        uint256[] memory _decrements,
        uint256[] memory _values
    )
        private
        pure
    {
        uint256 i = 1;
        // i + numOffers * 2
        uint256 end = i + (_values[0] & mask8) * 2;

        // loop offers
        for(i; i < end; i += 2) {
            bool nonceTaken = ((_values[i] & mask128) >> 120) == 1;
            if (nonceTaken) { continue; }

            uint256 makerOfferAssetIndex = (_values[i] & mask16) >> 8;
            uint256 offerAmount = _values[i + 1] & mask128;

            // deduct make.offerAmount from maker
            _decrements[makerOfferAssetIndex] = _decrements[makerOfferAssetIndex].add(offerAmount);

            uint256 feeAmount = _values[i] >> 128;
            if (feeAmount == 0) { continue; }

            // deduct make.feeAmount from maker
            uint256 makerFeeAssetIndex = (_values[i] & mask32) >> 24;
            _decrements[makerFeeAssetIndex] = _decrements[makerFeeAssetIndex].add(feeAmount);
        }
    }

    /// @dev Emits trade events for easier tracking
    /// @param _values The _values param from the trade / networkTrade method
    /// @param _addresses The _addresses param from the trade / networkTrade method
    /// @param _marketDapps The _marketDapps from BrokerV2
    /// @param _forNetworkTrade Whether this is called from the networkTrade method
    function _emitTradeEvents(
        uint256[] memory _values,
        address[] memory _addresses,
        address[] memory _marketDapps,
        bool _forNetworkTrade
    )
        private
    {
        uint256 i = 1;
        // i += numOffers * 2
        i += (_values[0] & mask8) * 2;
        // i += numFills * 2
        i += ((_values[0] & mask16) >> 8) * 2;

        uint256 end = _values.length;

        // loop matches
        for(i; i < end; i++) {
            uint256[] memory data = new uint256[](7);
            data[0] = _values[i] & mask8; // match.offerIndex
            data[1] = _values[1 + data[0] * 2] & mask8; // makerIndex
            data[2] = (_values[1 + data[0] * 2] & mask16) >> 8; // makerOfferAssetIndex
            data[3] = (_values[1 + data[0] * 2] & mask24) >> 16; // makerWantAssetIndex
            data[4] = _values[i] >> 128; // match.takeAmount
            // receiveAmount = match.takeAmount * offer.wantAmount / offer.offerAmount
            data[5] = data[4].mul(_values[2 + data[0] * 2] >> 128)
                             .div(_values[2 + data[0] * 2] & mask128);
            // match.fillIndex for `trade`, marketDappIndex for `networkTrade`
            data[6] = (_values[i] & mask16) >> 8;

            address filler;
            if (_forNetworkTrade) {
                filler = _marketDapps[data[6]];
            } else {
                uint256 fillerIndex = (_values[1 + data[6] * 2] & mask8);
                filler = _addresses[fillerIndex * 2];
            }

            emit Trade(
                _addresses[data[1] * 2], // maker
                filler,
                _addresses[data[2] * 2 + 1], // makerGiveAsset
                data[4], // makerGiveAmount
                _addresses[data[3] * 2 + 1], // fillerGiveAsset
                data[5] // fillerGiveAmount
            );
        }
    }


    /// @notice Executes a trade against an external market.
    /// @dev The initial Ether or token balance is compared with the
    /// balance after the trade to ensure that the appropriate amounts of
    /// tokens were taken and an appropriate amount received.
    /// The trade will fail if the number of tokens received is less than
    /// expected. If the number of tokens received is more than expected than
    /// the excess tokens are transferred to the `BrokerV2.operator`.
    /// @param _assetIds[0] The offerAssetId of the offer
    /// @param _assetIds[1] The wantAssetId of the offer
    /// @param _assetIds[2] The surplusAssetId
    /// @param _dataValues[0] The number of tokens offerred
    /// @param _dataValues[1] The number of tokens expected to be received
    /// @param _dataValues[2] Match data
    /// @param _marketDapps See `BrokerV2.marketDapps`
    /// @param _addresses Addresses from `networkTrade`
    function _performNetworkTrade(
        address[] memory _assetIds,
        uint256[] memory _dataValues,
        address[] memory _marketDapps,
        address[] memory _addresses
    )
        private
        returns (uint256)
    {
        uint256 dappIndex = (_dataValues[2] & mask16) >> 8;
        validateAddress(_marketDapps[dappIndex]);
        MarketDapp marketDapp = MarketDapp(_marketDapps[dappIndex]);

        uint256[] memory funds = new uint256[](6);
        funds[0] = externalBalance(_assetIds[0]); // initialOfferTokenBalance
        funds[1] = externalBalance(_assetIds[1]); // initialWantTokenBalance
        if (_assetIds[2] != _assetIds[0] && _assetIds[2] != _assetIds[1]) {
            funds[2] = externalBalance(_assetIds[2]); // initialSurplusTokenBalance
        }

        uint256 ethValue = 0;
        address tokenReceiver;

        if (_assetIds[0] == ETHER_ADDR) {
            ethValue = _dataValues[0]; // offerAmount
        } else {
            tokenReceiver = marketDapp.tokenReceiver(_assetIds, _dataValues, _addresses);
            approveTokenTransfer(
                _assetIds[0], // offerAssetId
                tokenReceiver,
                _dataValues[0] // offerAmount
            );
        }

        marketDapp.trade.value(ethValue)(
            _assetIds,
            _dataValues,
            _addresses,
            // use uint160 to cast `address` to `address payable`
            address(uint160(address(this))) // destAddress
        );

        funds[3] = externalBalance(_assetIds[0]); // finalOfferTokenBalance
        funds[4] = externalBalance(_assetIds[1]); // finalWantTokenBalance
        if (_assetIds[2] != _assetIds[0] && _assetIds[2] != _assetIds[1]) {
            funds[5] = externalBalance(_assetIds[2]); // finalSurplusTokenBalance
        }

        uint256 surplusAmount = 0;

        // validate that the appropriate offerAmount was deducted
        // surplusAssetId == offerAssetId
        if (_assetIds[2] == _assetIds[0]) {
            // surplusAmount = finalOfferTokenBalance - (initialOfferTokenBalance - offerAmount)
            surplusAmount = funds[3].sub(funds[0].sub(_dataValues[0]));
        } else {
            // finalOfferTokenBalance == initialOfferTokenBalance - offerAmount
            require(funds[3] == funds[0].sub(_dataValues[0]), "Invalid offer asset balance");
        }

        // validate that the appropriate wantAmount was credited
        // surplusAssetId == wantAssetId
        if (_assetIds[2] == _assetIds[1]) {
            // surplusAmount = finalWantTokenBalance - (initialWantTokenBalance + wantAmount)
            surplusAmount = funds[4].sub(funds[1].add(_dataValues[1]));
        } else {
            // finalWantTokenBalance == initialWantTokenBalance + wantAmount
            require(funds[4] == funds[1].add(_dataValues[1]), "Invalid want asset balance");
        }

        // surplusAssetId != offerAssetId && surplusAssetId != wantAssetId
        if (_assetIds[2] != _assetIds[0] && _assetIds[2] != _assetIds[1]) {
            // surplusAmount = finalSurplusTokenBalance - initialSurplusTokenBalance
            surplusAmount = funds[5].sub(funds[2]);
        }

        // set the approved token amount back to zero
        if (_assetIds[0] != ETHER_ADDR) {
            approveTokenTransfer(
                _assetIds[0],
                tokenReceiver,
                0
            );
        }

        return surplusAmount;
    }

    /// @dev Validates input lengths based on the expected format
    /// detailed in the `trade` method.
    /// @param _values Values from `trade`
    /// @param _hashes Hashes from `trade`
    function _validateTradeInputLengths(
        uint256[] memory _values,
        bytes32[] memory _hashes
    )
        private
        pure
    {
        uint256 numOffers = _values[0] & mask8;
        uint256 numFills = (_values[0] & mask16) >> 8;
        uint256 numMatches = (_values[0] & mask24) >> 16;

        // Validate that bits(24..256) are zero
        require(_values[0] >> 24 == 0, "Invalid trade input");

        // It is enforced by other checks that if a fill is present
        // then it must be completely filled so there must be at least one offer
        // and at least one match in this case.
        // It is possible to have one offer with no matches and no fills
        // but that is blocked by this check as there is no foreseeable use
        // case for it.
        require(
            numOffers > 0 && numFills > 0 && numMatches > 0,
            "Invalid trade input"
        );

        require(
            _values.length == 1 + numOffers * 2 + numFills * 2 + numMatches,
            "Invalid _values.length"
        );

        require(
            _hashes.length == (numOffers + numFills) * 2,
            "Invalid _hashes.length"
        );
    }

    /// @dev Validates input lengths based on the expected format
    /// detailed in the `networkTrade` method.
    /// @param _values Values from `networkTrade`
    /// @param _hashes Hashes from `networkTrade`
    function _validateNetworkTradeInputLengths(
        uint256[] memory _values,
        bytes32[] memory _hashes
    )
        private
        pure
    {
        uint256 numOffers = _values[0] & mask8;
        uint256 numFills = (_values[0] & mask16) >> 8;
        uint256 numMatches = (_values[0] & mask24) >> 16;

        // Validate that bits(24..256) are zero
        require(_values[0] >> 24 == 0, "Invalid networkTrade input");

        // Validate that numFills is zero because the offers
        // should be filled against external orders
        require(
            numOffers > 0 && numMatches > 0 && numFills == 0,
            "Invalid networkTrade input"
        );

        require(
            _values.length == 1 + numOffers * 2 + numMatches,
            "Invalid _values.length"
        );

        require(
            _hashes.length == numOffers * 2,
            "Invalid _hashes.length"
        );
    }

    /// @dev See the `BrokerV2.trade` method for an explanation of why offer
    /// uniquness is required.
    /// The set of offers in `_values` must be sorted such that offer nonces'
    /// are arranged in a strictly ascending order.
    /// This allows the validation of offer uniqueness to be done in O(N) time,
    /// with N being the number of offers.
    /// @param _values Values from `trade`
    function _validateUniqueOffers(uint256[] memory _values) private pure {
        uint256 numOffers = _values[0] & mask8;

        uint256 prevNonce;

        for(uint256 i = 0; i < numOffers; i++) {
            uint256 nonce = (_values[i * 2 + 1] & mask120) >> 56;

            if (i == 0) {
                // Set the value of the first nonce
                prevNonce = nonce;
                continue;
            }

            require(nonce > prevNonce, "Invalid offer nonces");
            prevNonce = nonce;
        }
    }

    /// @dev Validate that for every match:
    /// 1. offerIndexes fall within the range of offers
    /// 2. fillIndexes falls within the range of fills
    /// 3. offer.offerAssetId == fill.wantAssetId
    /// 4. offer.wantAssetId == fill.offerAssetId
    /// 5. takeAmount > 0
    /// 6. (offer.wantAmount * takeAmount) % offer.offerAmount == 0
    /// @param _values Values from `trade`
    /// @param _addresses Addresses from `trade`
    function _validateMatches(
        uint256[] memory _values,
        address[] memory _addresses
    )
        private
        pure
    {
        uint256 numOffers = _values[0] & mask8;
        uint256 numFills = (_values[0] & mask16) >> 8;

        uint256 i = 1 + numOffers * 2 + numFills * 2;
        uint256 end = _values.length;

        // loop matches
        for (i; i < end; i++) {
            uint256 offerIndex = _values[i] & mask8;
            uint256 fillIndex = (_values[i] & mask16) >> 8;

            require(offerIndex < numOffers, "Invalid match.offerIndex");

            require(fillIndex >= numOffers && fillIndex < numOffers + numFills, "Invalid match.fillIndex");

            require(
                _addresses[_values[1 + offerIndex * 2] & mask8] !=
                _addresses[_values[1 + fillIndex * 2] & mask8],
                "offer.maker cannot be the same as fill.filler"
            );

            uint256 makerOfferAssetIndex = (_values[1 + offerIndex * 2] & mask16) >> 8;
            uint256 makerWantAssetIndex = (_values[1 + offerIndex * 2] & mask24) >> 16;
            uint256 fillerOfferAssetIndex = (_values[1 + fillIndex * 2] & mask16) >> 8;
            uint256 fillerWantAssetIndex = (_values[1 + fillIndex * 2] & mask24) >> 16;

            require(
                _addresses[makerOfferAssetIndex * 2 + 1] ==
                _addresses[fillerWantAssetIndex * 2 + 1],
                "offer.offerAssetId does not match fill.wantAssetId"
            );

            require(
                _addresses[makerWantAssetIndex * 2 + 1] ==
                _addresses[fillerOfferAssetIndex * 2 + 1],
                "offer.wantAssetId does not match fill.offerAssetId"
            );

            // require that bits(16..128) are all zero for every match
            require((_values[i] & mask128) >> 16 == uint256(0), "Invalid match data");

            uint256 takeAmount = _values[i] >> 128;
            require(takeAmount > 0, "Invalid match.takeAmount");

            uint256 offerDataB = _values[2 + offerIndex * 2];
            // (offer.wantAmount * takeAmount) % offer.offerAmount == 0
            require(
                (offerDataB >> 128).mul(takeAmount).mod(offerDataB & mask128) == 0,
                "Invalid amounts"
            );
        }
    }

    /// @dev Validate that for every match:
    /// 1. offerIndexes fall within the range of offers
    /// 2. _addresses[surplusAssetIndexes * 2] matches the operator address
    /// 3. takeAmount > 0
    /// 4. (offer.wantAmount * takeAmount) % offer.offerAmount == 0
    /// @param _values Values from `trade`
    /// @param _addresses Addresses from `trade`
    /// @param _operator Address of the `BrokerV2.operator`
    function _validateNetworkMatches(
        uint256[] memory _values,
        address[] memory _addresses,
        address _operator
    )
        private
        pure
    {
        uint256 numOffers = _values[0] & mask8;

        // 1 + numOffers * 2
        uint256 i = 1 + (_values[0] & mask8) * 2;
        uint256 end = _values.length;

        // loop matches
        for (i; i < end; i++) {
            uint256 offerIndex = _values[i] & mask8;
            uint256 surplusAssetIndex = (_values[i] & mask24) >> 16;

            require(offerIndex < numOffers, "Invalid match.offerIndex");
            require(_addresses[surplusAssetIndex * 2] == _operator, "Invalid operator address");

            uint256 takeAmount = _values[i] >> 128;
            require(takeAmount > 0, "Invalid match.takeAmount");

            uint256 offerDataB = _values[2 + offerIndex * 2];
            // (offer.wantAmount * takeAmount) % offer.offerAmount == 0
            require(
                (offerDataB >> 128).mul(takeAmount).mod(offerDataB & mask128) == 0,
                "Invalid amounts"
            );
        }
    }

    /// @dev Validate that all fills will be completely filled by the specified
    /// matches. See the `BrokerV2.trade` method for an explanation of why
    /// fills must be completely filled.
    /// @param _values Values from `trade`
    function _validateFillAmounts(uint256[] memory _values) private pure {
        // "filled" is used to store the sum of `takeAmount`s and `giveAmount`s.
        // While a fill's `offerAmount` and `wantAmount` are combined to share
        // a single uint256 value, each sum of `takeAmount`s and `giveAmount`s
        // for a fill is tracked with an individual uint256 value.
        // This is to prevent the verification from being vulnerable to overflow
        // issues.
        uint256[] memory filled = new uint256[](_values.length);

        uint256 i = 1;
        // i += numOffers * 2
        i += (_values[0] & mask8) * 2;
        // i += numFills * 2
        i += ((_values[0] & mask16) >> 8) * 2;

        uint256 end = _values.length;

        // loop matches
        for (i; i < end; i++) {
            uint256 offerIndex = _values[i] & mask8;
            uint256 fillIndex = (_values[i] & mask16) >> 8;
            uint256 takeAmount = _values[i] >> 128;
            uint256 wantAmount = _values[2 + offerIndex * 2] >> 128;
            uint256 offerAmount = _values[2 + offerIndex * 2] & mask128;
            // giveAmount = takeAmount * wantAmount / offerAmount
            uint256 giveAmount = takeAmount.mul(wantAmount).div(offerAmount);

            // (1 + fillIndex * 2) would give the index of the first part
            // of the data for the fill at fillIndex within `_values`,
            // and (2 + fillIndex * 2) would give the index of the second part
            filled[1 + fillIndex * 2] = filled[1 + fillIndex * 2].add(giveAmount);
            filled[2 + fillIndex * 2] = filled[2 + fillIndex * 2].add(takeAmount);
        }

        // numOffers
        i = _values[0] & mask8;
        // i + numFills
        end = i + ((_values[0] & mask16) >> 8);

        // loop fills
        for(i; i < end; i++) {
            require(
                // fill.offerAmount == (sum of given amounts for fill)
                _values[i * 2 + 2] & mask128 == filled[i * 2 + 1] &&
                // fill.wantAmount == (sum of taken amounts for fill)
                _values[i * 2 + 2] >> 128 == filled[i * 2 + 2],
                "Invalid fills"
            );
        }
    }

    /// @dev Validates that for every offer / fill
    /// 1. user address matches address referenced by user.offerAssetIndex
    /// 2. user address matches address referenced by user.wantAssetIndex
    /// 3. user address matches address referenced by user.feeAssetIndex
    /// 4. offerAssetId != wantAssetId
    /// 5. offerAmount > 0 && wantAmount > 0
    /// 6. Specified `operator` address matches the expected `operator` address,
    /// 7. Specified `operator.feeAssetId` matches the offer's feeAssetId
    /// @param _values Values from `trade`
    /// @param _addresses Addresses from `trade`
    function _validateTradeData(
        uint256[] memory _values,
        address[] memory _addresses,
        address _operator
    )
        private
        pure
    {
        // numOffers + numFills
        uint256 end = (_values[0] & mask8) +
                      ((_values[0] & mask16) >> 8);

        for (uint256 i = 0; i < end; i++) {
            uint256 dataA = _values[i * 2 + 1];
            uint256 dataB = _values[i * 2 + 2];
            uint256 feeAssetIndex = ((dataA & mask40) >> 32) * 2;

            require(
                // user address == user in user.offerAssetIndex pair
                _addresses[(dataA & mask8) * 2] ==
                _addresses[((dataA & mask16) >> 8) * 2],
                "Invalid user in user.offerAssetIndex"
            );

            require(
                // user address == user in user.wantAssetIndex pair
                _addresses[(dataA & mask8) * 2] ==
                _addresses[((dataA & mask24) >> 16) * 2],
                "Invalid user in user.wantAssetIndex"
            );

            require(
                // user address == user in user.feeAssetIndex pair
                _addresses[(dataA & mask8) * 2] ==
                _addresses[((dataA & mask32) >> 24) * 2],
                "Invalid user in user.feeAssetIndex"
            );

            require(
                // offerAssetId != wantAssetId
                _addresses[((dataA & mask16) >> 8) * 2 + 1] !=
                _addresses[((dataA & mask24) >> 16) * 2 + 1],
                "Invalid trade assets"
            );

            require(
                // offerAmount > 0 && wantAmount > 0
                (dataB & mask128) > 0 && (dataB >> 128) > 0,
                "Invalid trade amounts"
            );

             require(
                _addresses[feeAssetIndex] == _operator,
                "Invalid operator address"
            );

             require(
                _addresses[feeAssetIndex + 1] ==
                _addresses[((dataA & mask32) >> 24) * 2 + 1],
                "Invalid operator fee asset ID"
            );
        }
    }

    /// @dev Validates signatures for a set of offers or fills
    /// Note that the r value of the offer / fill in _hashes will be
    /// overwritten by the hash of that offer / fill
    /// @param _values Values from `trade`
    /// @param _hashes Hashes from `trade`
    /// @param _addresses Addresses from `trade`
    /// @param _typehash The typehash used to construct the signed hash
    /// @param _i The starting index to verify
    /// @param _end The ending index to verify
    /// @return An array of hash keys if _i started as 0, because only
    /// the hash keys of offers are needed
    function _validateTradeSignatures(
        uint256[] memory _values,
        bytes32[] memory _hashes,
        address[] memory _addresses,
        bytes32 _typehash,
        uint256 _i,
        uint256 _end
    )
        private
        pure
    {
        for (_i; _i < _end; _i++) {
            uint256 dataA = _values[_i * 2 + 1];
            uint256 dataB = _values[_i * 2 + 2];

            bytes32 hashKey = keccak256(abi.encode(
                _typehash,
                _addresses[(dataA & mask8) * 2], // user
                _addresses[((dataA & mask16) >> 8) * 2 + 1], // offerAssetId
                dataB & mask128, // offerAmount
                _addresses[((dataA & mask24) >> 16) * 2 + 1], // wantAssetId
                dataB >> 128, // wantAmount
                _addresses[((dataA & mask32) >> 24) * 2 + 1], // feeAssetId
                dataA >> 128, // feeAmount
                (dataA & mask120) >> 56 // nonce
            ));

            bool prefixedSignature = ((dataA & mask56) >> 48) != 0;

            validateSignature(
                hashKey,
                _addresses[(dataA & mask8) * 2], // user
                uint8((dataA & mask48) >> 40), // The `v` component of the user's signature
                _hashes[_i * 2], // The `r` component of the user's signature
                _hashes[_i * 2 + 1], // The `s` component of the user's signature
                prefixedSignature
            );

            _hashes[_i * 2] = hashKey;
        }
    }

    /// @dev Ensure that the address is a deployed contract
    /// @param _contract The address to check
    function _validateContractAddress(address _contract) private view {
        assembly {
            if iszero(extcodesize(_contract)) { revert(0, 0) }
        }
    }

    /// @dev A thin wrapper around the native `call` function, to
    /// validate that the contract `call` must be successful.
    /// See https://solidity.readthedocs.io/en/v0.5.1/050-breaking-changes.html
    /// for details on constructing the `_payload`
    /// @param _contract Address of the contract to call
    /// @param _payload The data to call the contract with
    /// @return The data returned from the contract call
    function _callContract(
        address _contract,
        bytes memory _payload
    )
        private
        returns (bytes memory)
    {
        bool success;
        bytes memory returnData;

        (success, returnData) = _contract.call(_payload);
        require(success, "Contract call failed");

        return returnData;
    }

    /// @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
    /// @param _data The data returned from a transfer call
    function _validateContractCallResult(bytes memory _data) private pure {
        require(
            _data.length == 0 ||
            (_data.length == 32 && _getUint256FromBytes(_data) != 0),
            "Invalid contract call result"
        );
    }

    /// @dev Converts data of type `bytes` into its corresponding `uint256` value
    /// @param _data The data in bytes
    /// @return The corresponding `uint256` value
    function _getUint256FromBytes(
        bytes memory _data
    )
        private
        pure
        returns (uint256)
    {
        uint256 parsed;
        assembly { parsed := mload(add(_data, 32)) }
        return parsed;
    }
}

// File: contracts/BrokerV2.sol

pragma solidity 0.5.12;





interface IERC1820Registry {
    function setInterfaceImplementer(address account, bytes32 interfaceHash, address implementer) external;
}

interface TokenList {
    function validateToken(address assetId) external view;
}

interface SpenderList {
    function validateSpender(address spender) external view;
    function validateSpenderAuthorization(address user, address spender) external view;
}

/// @title The BrokerV2 contract for Switcheo Exchange
/// @author Switcheo Network
/// @notice This contract faciliates Ethereum and Ethereum token 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.
/// This allows trades to be confirmed immediately by the coordinator,
/// and settled on-chain through this contract at a later time.
///
/// @dev Bit compacting is used in the contract to reduce gas costs, when
/// it is used, params are documented as bits(n..m).
/// This means that the documented value is represented by bits starting
/// from and including `n`, up to and excluding `m`.
/// For example, bits(8..16), indicates that the value is represented by bits:
/// [8, 9, 10, 11, 12, 13, 14, 15].
///
/// Bit manipulation of the form (data & ~(~uint(0) << m)) >> n is frequently
/// used to recover the value at the specified bits.
/// For example, to recover bits(2..7) from a uint8 value, we can use
/// (data & ~(~uint8(0) << 7)) >> 2.
/// Given a `data` value of `1101,0111`, bits(2..7) should give "10101".
/// ~uint8(0): "1111,1111" (8 ones)
/// (~uint8(0) << 7): "1000,0000" (1 followed by 7 zeros)
/// ~(~uint8(0) << 7): "0111,1111" (0 followed by 7 ones)
/// (data & ~(~uint8(0) << 7)): "0101,0111" (bits after the 7th bit is zeroed)
/// (data & ~(~uint8(0) << 7)) >> 2: "0001,0101" (matching the expected "10101")
///
/// Additionally, bit manipulation of the form data >> n is used to recover
/// bits(n..e), where e is equal to the number of bits in the data.
/// For example, to recover bits(4..8) from a uint8 value, we can use data >> 4.
/// Given a data value of "1111,1111", bits(4..8) should give "1111".
/// data >> 4: "0000,1111" (matching the expected "1111")
///
/// There is frequent reference and usage of asset IDs, this is a unique
/// identifier used within the contract to represent individual assets.
/// For all tokens, the asset ID is identical to the contract address
/// of the token, this is so that additional mappings are not needed to
/// identify tokens during deposits and withdrawals.
/// The only exception is the Ethereum token, which does not have a contract
/// address, for this reason, the zero address is used to represent the
/// Ethereum token's ID.
contract BrokerV2 is Ownable, ReentrancyGuard {
    using SafeMath for uint256;

    struct WithdrawalAnnouncement {
        uint256 amount;
        uint256 withdrawableAt;
    }

    // Exchange states
    enum State { Active, Inactive }
    // Exchange admin states
    enum AdminState { Normal, Escalated }

    // The constants for EIP-712 are precompiled to reduce contract size,
    // the original values are left here for reference and verification.
    //
    // bytes32 public constant WITHDRAW_TYPEHASH = keccak256(abi.encodePacked(
    //     "Withdraw(",
    //         "address withdrawer,",
    //         "address receivingAddress,",
    //         "address assetId,",
    //         "uint256 amount,",
    //         "address feeAssetId,",
    //         "uint256 feeAmount,",
    //         "uint256 nonce",
    //     ")"
    // ));
    bytes32 public constant WITHDRAW_TYPEHASH = 0xbe2f4292252fbb88b129dc7717b2f3f74a9afb5b13a2283cac5c056117b002eb;

    // bytes32 public constant OFFER_TYPEHASH = keccak256(abi.encodePacked(
    //     "Offer(",
    //         "address maker,",
    //         "address offerAssetId,",
    //         "uint256 offerAmount,",
    //         "address wantAssetId,",
    //         "uint256 wantAmount,",
    //         "address feeAssetId,",
    //         "uint256 feeAmount,",
    //         "uint256 nonce",
    //     ")"
    // ));
    bytes32 public constant OFFER_TYPEHASH = 0xf845c83a8f7964bc8dd1a092d28b83573b35be97630a5b8a3b8ae2ae79cd9260;

    // bytes32 public constant SWAP_TYPEHASH = keccak256(abi.encodePacked(
    //     "Swap(",
    //         "address maker,",
    //         "address taker,",
    //         "address assetId,",
    //         "uint256 amount,",
    //         "bytes32 hashedSecret,",
    //         "uint256 expiryTime,",
    //         "address feeAssetId,",
    //         "uint256 feeAmount,",
    //         "uint256 nonce",
    //     ")"
    // ));
    bytes32 public constant SWAP_TYPEHASH = 0x6ba9001457a287c210b728198a424a4222098d7fac48f8c5fb5ab10ef907d3ef;

    // The Ether token address is set as the constant 0x00 for backwards
    // compatibility
    address private constant ETHER_ADDR = address(0);

    // The maximum length of swap secret values
    uint256 private constant MAX_SWAP_SECRET_LENGTH = 64;

    // Reason codes are used by the off-chain coordinator to track balance changes
    uint256 private constant REASON_DEPOSIT = 0x01;

    uint256 private constant REASON_WITHDRAW = 0x09;
    uint256 private constant REASON_WITHDRAW_FEE_GIVE = 0x14;
    uint256 private constant REASON_WITHDRAW_FEE_RECEIVE = 0x15;

    uint256 private constant REASON_CANCEL = 0x08;
    uint256 private constant REASON_CANCEL_FEE_GIVE = 0x12;
    uint256 private constant REASON_CANCEL_FEE_RECEIVE = 0x13;

    uint256 private constant REASON_SWAP_GIVE = 0x30;
    uint256 private constant REASON_SWAP_FEE_GIVE = 0x32;
    uint256 private constant REASON_SWAP_RECEIVE = 0x35;
    uint256 private constant REASON_SWAP_FEE_RECEIVE = 0x37;

    uint256 private constant REASON_SWAP_CANCEL_RECEIVE = 0x38;
    uint256 private constant REASON_SWAP_CANCEL_FEE_RECEIVE = 0x3B;
    uint256 private constant REASON_SWAP_CANCEL_FEE_REFUND = 0x3D;

    // 7 days * 24 hours * 60 mins * 60 seconds: 604800
    uint256 private constant MAX_SLOW_WITHDRAW_DELAY = 604800;
    uint256 private constant MAX_SLOW_CANCEL_DELAY = 604800;

    uint256 private constant mask8 = ~(~uint256(0) << 8);
    uint256 private constant mask16 = ~(~uint256(0) << 16);
    uint256 private constant mask24 = ~(~uint256(0) << 24);
    uint256 private constant mask32 = ~(~uint256(0) << 32);
    uint256 private constant mask40 = ~(~uint256(0) << 40);
    uint256 private constant mask120 = ~(~uint256(0) << 120);
    uint256 private constant mask128 = ~(~uint256(0) << 128);
    uint256 private constant mask136 = ~(~uint256(0) << 136);
    uint256 private constant mask144 = ~(~uint256(0) << 144);

    State public state;
    AdminState public adminState;
    // All fees will be transferred to the operator address
    address public operator;
    TokenList public tokenList;
    SpenderList public spenderList;

    // The delay in seconds to complete the respective escape hatch (`slowCancel` / `slowWithdraw`).
    // This gives the off-chain service time to update the off-chain state
    // before the state is separately updated by the user.
    uint256 public slowCancelDelay;
    uint256 public slowWithdrawDelay;

    // A mapping of remaining offer amounts: offerHash => availableAmount
    mapping(bytes32 => uint256) public offers;
    // A mapping of used nonces: nonceIndex => nonceData
    // The storing of nonces is used to ensure that transactions signed by
    // the user can only be used once.
    // For space and gas cost efficiency, one nonceData is used to store the
    // state of 256 nonces.
    // This reduces the average cost of storing a new nonce from 20,000 gas
    // to 5000 + 20,000 / 256 = 5078.125 gas
    // See _markNonce and _nonceTaken for more details.
    mapping(uint256 => uint256) public usedNonces;
    // A mapping of user balances: userAddress => assetId => balance
    mapping(address => mapping(address => uint256)) public balances;
    // A mapping of atomic swap states: swapHash => isSwapActive
    mapping(bytes32 => bool) public atomicSwaps;

    // A record of admin addresses: userAddress => isAdmin
    mapping(address => bool) public adminAddresses;
    // A record of market DApp addresses
    address[] public marketDapps;
    // A mapping of cancellation announcements for the cancel escape hatch: offerHash => cancellableAt
    mapping(bytes32 => uint256) public cancellationAnnouncements;
    // A mapping of withdrawal announcements: userAddress => assetId => { amount, withdrawableAt }
    mapping(address => mapping(address => WithdrawalAnnouncement)) public withdrawalAnnouncements;

    // Emitted on positive balance state transitions
    event BalanceIncrease(
        address indexed user,
        address indexed assetId,
        uint256 amount,
        uint256 reason,
        uint256 nonce
    );

    // Emitted on negative balance state transitions
    event BalanceDecrease(
        address indexed user,
        address indexed assetId,
        uint256 amount,
        uint256 reason,
        uint256 nonce
    );

    // Compacted versions of the `BalanceIncrease` and `BalanceDecrease` events.
    // These are used in the `trade` method, they are compacted to save gas costs.
    event Increment(uint256 data);
    event Decrement(uint256 data);

    event TokenFallback(
        address indexed user,
        address indexed assetId,
        uint256 amount
    );

    event TokensReceived(
        address indexed user,
        address indexed assetId,
        uint256 amount
    );

    event AnnounceCancel(
        bytes32 indexed offerHash,
        uint256 cancellableAt
    );

    event SlowCancel(
        bytes32 indexed offerHash,
        uint256 amount
    );

    event AnnounceWithdraw(
        address indexed withdrawer,
        address indexed assetId,
        uint256 amount,
        uint256 withdrawableAt
    );

    event SlowWithdraw(
        address indexed withdrawer,
        address indexed assetId,
        uint256 amount
    );

    /// @notice Initializes the Broker contract
    /// @dev The coordinator, operator and owner (through Ownable) is initialized
    /// to be the address of the sender.
    /// The Broker is put into an active state, with maximum exit delays set.
    /// The Broker is also registered as an implementer of ERC777TokensRecipient
    /// through the ERC1820 registry.
    constructor(address _tokenListAddress, address _spenderListAddress) public {
        adminAddresses[msg.sender] = true;
        operator = msg.sender;
        tokenList = TokenList(_tokenListAddress);
        spenderList = SpenderList(_spenderListAddress);

        slowWithdrawDelay = MAX_SLOW_WITHDRAW_DELAY;
        slowCancelDelay = MAX_SLOW_CANCEL_DELAY;
        state = State.Active;

        IERC1820Registry erc1820 = IERC1820Registry(
            0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
        );

        erc1820.setInterfaceImplementer(
            address(this),
            keccak256("ERC777TokensRecipient"),
            address(this)
        );
    }

    modifier onlyAdmin() {
        // Error code 1: onlyAdmin, address is not an admin address
        require(adminAddresses[msg.sender], "1");
        _;
    }

    modifier onlyActiveState() {
        // Error code 2: onlyActiveState, state is not 'Active'
        require(state == State.Active, "2");
        _;
    }

    modifier onlyEscalatedAdminState() {
        // Error code 3: onlyEscalatedAdminState, adminState is not 'Escalated'
        require(adminState == AdminState.Escalated, "3");
        _;
    }

    /// @notice Checks whether an address is appointed as an admin user
    /// @param _user The address to check
    /// @return Whether the address is appointed as an admin user
    function isAdmin(address _user) external view returns(bool) {
        return adminAddresses[_user];
    }

    /// @notice Sets tbe Broker's state.
    /// @dev The two available states are `Active` and `Inactive`.
    /// The `Active` state allows for regular exchange activity,
    /// while the `Inactive` state prevents the invocation of deposit
    /// and trading functions.
    /// The `Inactive` state is intended as a means to cease contract operation
    /// in the case of an upgrade or in an emergency.
    /// @param _state The state to transition the contract into
    function setState(State _state) external onlyOwner nonReentrant { state = _state; }

    /// @notice Sets the Broker's admin state.
    /// @dev The two available states are `Normal` and `Escalated`.
    /// In the `Normal` admin state, the admin methods `adminCancel` and `adminWithdraw`
    /// are not invocable.
    /// The admin state must be set to `Escalated` by the contract owner for these
    /// methods to become usable.
    /// In an `Escalated` admin state, admin addresses would be able to cancel offers
    /// and withdraw balances to the respective user's wallet on behalf of users.
    /// The escalated state is intended to be used in the case of a contract upgrade or
    /// in an emergency.
    /// It is set separately from the `Inactive` state so that it is possible
    /// to use admin functions without affecting regular operations.
    /// @param _state The admin state to transition the contract into
    function setAdminState(AdminState _state) external onlyOwner nonReentrant { adminState = _state; }

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

    /// @notice Sets the minimum delay between an `announceCancel` call and
    /// when the cancellation can actually be executed through `slowCancel`.
    /// @dev This gives the off-chain service time to update the off-chain state
    /// before the state is separately updated by the user.
    /// This differs from the regular `cancel` operation, which does not involve a delay.
    /// @param _delay The delay in seconds
    function setSlowCancelDelay(uint256 _delay) external onlyOwner nonReentrant {
        // Error code 4: setSlowCancelDelay, slow cancel delay exceeds max allowable delay
        require(_delay <= MAX_SLOW_CANCEL_DELAY, "4");
        slowCancelDelay = _delay;
    }

    /// @notice Sets the delay between an `announceWithdraw` call and
    /// when the withdrawal can actually be executed through `slowWithdraw`.
    /// @dev This gives the off-chain service time to update the off-chain state
    /// before the state is separately updated by the user.
    /// This differs from the regular `withdraw` operation, which does not involve a delay.
    /// @param _delay The delay in seconds
    function setSlowWithdrawDelay(uint256 _delay) external onlyOwner nonReentrant {
        // Error code 5: setSlowWithdrawDelay, slow withdraw delay exceeds max allowable delay
        require(_delay <= MAX_SLOW_WITHDRAW_DELAY, "5");
        slowWithdrawDelay = _delay;
    }

    /// @notice Gives admin permissons to the specified address.
    /// @dev Admin addresses are intended to coordinate the regular operation
    /// of the Broker contract, and to perform special functions such as
    /// `adminCancel` and `adminWithdraw`.
    /// @param _admin The address to give admin permissions to
    function addAdmin(address _admin) external onlyOwner nonReentrant {
        _validateAddress(_admin);
        // Error code 6: addAdmin, address is already an admin address
        require(!adminAddresses[_admin], "6");
        adminAddresses[_admin] = true;
    }

    /// @notice Removes admin permissons for the specified address.
    /// @param _admin The admin address to remove admin permissions from
    function removeAdmin(address _admin) external onlyOwner nonReentrant {
        _validateAddress(_admin);
        // Error code 7: removeAdmin, address is not an admin address
        require(adminAddresses[_admin], "7");
        delete adminAddresses[_admin];
    }

    /// @notice Adds a market DApp to be used in `networkTrade`
    /// @param _dapp Address of the market DApp
    function addMarketDapp(address _dapp) external onlyOwner nonReentrant {
        _validateAddress(_dapp);
        marketDapps.push(_dapp);
    }

    /// @notice Updates a market DApp to be used in `networkTrade`
    /// @param _index Index of the market DApp to update
    /// @param _dapp The new address of the market DApp
    function updateMarketDapp(uint256 _index, address _dapp) external onlyOwner nonReentrant {
        _validateAddress(_dapp);
        // Error code 8: updateMarketDapp, _index does not refer to an existing non-zero address
        require(marketDapps[_index] != address(0), "8");
        marketDapps[_index] = _dapp;
    }

    /// @notice Removes a market DApp
    /// @param _index Index of the market DApp to remove
    function removeMarketDapp(uint256 _index) external onlyOwner nonReentrant {
        // Error code 9: removeMarketDapp, _index does not refer to a DApp address
        require(marketDapps[_index] != address(0), "9");
        delete marketDapps[_index];
    }

    /// @notice Performs a balance transfer from one address to another
    /// @dev This method is intended to be invoked by spender contracts.
    /// To invoke this method, a spender contract must have been
    /// previously whitelisted and also authorized by the address from which
    /// funds will be deducted.
    /// Balance events are not emitted by this method, they should be separately
    /// emitted by the spender contract.
    /// @param _from The address to deduct from
    /// @param _to The address to credit
    /// @param _assetId The asset to transfer
    /// @param _amount The amount to transfer
    function spendFrom(
        address _from,
        address _to,
        address _assetId,
        uint256 _amount
    )
        external
        nonReentrant
    {
        spenderList.validateSpenderAuthorization(_from, msg.sender);

        _validateAddress(_to);

        balances[_from][_assetId] = balances[_from][_assetId].sub(_amount);
        balances[_to][_assetId] = balances[_to][_assetId].add(_amount);
    }

    /// @notice Allows a whitelisted contract to mark nonces
    /// @dev If the whitelisted contract is malicious or vulnerable then there is
    /// a possibility of a DoS attack. However, since this attack requires cooperation
    /// of the contract owner, the risk is similar to the contract owner withholding
    /// transactions, so there is no violation of the contract's trust model.
    /// In the case that nonces are misused, users will still be able to cancel their offers
    /// and withdraw all their funds using the escape hatch methods.
    /// @param _nonce The nonce to mark
    function markNonce(uint256 _nonce) external nonReentrant {
        spenderList.validateSpender(msg.sender);
        _markNonce(_nonce);
    }

    /// @notice Returns whether a nonce has been taken
    /// @param _nonce The nonce to check
    /// @return Whether the nonce has been taken
    function nonceTaken(uint256 _nonce) external view returns (bool) {
        return _nonceTaken(_nonce);
    }

    /// @notice Deposits ETH into the sender's contract balance
    /// @dev This operation is only usable in an `Active` state
    /// to prevent this contract from receiving ETH in the case that its
    /// operation has been terminated.
    function deposit() external payable onlyActiveState nonReentrant {
        // Error code 10: deposit, msg.value is 0
        require(msg.value > 0, "10");
        _increaseBalance(msg.sender, ETHER_ADDR, msg.value, REASON_DEPOSIT, 0);
    }

    /// @dev This function is needed as market DApps generally send ETH
    /// using the `<address>.transfer` method.
    /// It is left empty to avoid issues with the function call running out
    /// of gas, as some callers set a small limit on how much gas can be
    /// used by the ETH receiver.
    function() payable external {}

    /// @notice Deposits ERC20 tokens under the `_user`'s balance
    /// @dev Transfers token into the Broker contract using the
    /// token's `transferFrom` method.
    /// The user must have previously authorized the token transfer
    /// through the token's `approve` method.
    /// This method has separate `_amount` and `_expectedAmount` values
    /// to support unconventional token transfers, e.g. tokens which have a
    /// proportion burnt on transfer.
    /// @param _user The address of the user depositing the tokens
    /// @param _assetId The address of the token contract
    /// @param _amount The value to invoke the token's `transferFrom` with
    /// @param _expectedAmount The final amount expected to be received by this contract
    /// @param _nonce A nonce for balance tracking, emitted in the BalanceIncrease event
    function depositToken(
        address _user,
        address _assetId,
        uint256 _amount,
        uint256 _expectedAmount,
        uint256 _nonce
    )
        external
        onlyAdmin
        onlyActiveState
        nonReentrant
    {
        _increaseBalance(
            _user,
            _assetId,
            _expectedAmount,
            REASON_DEPOSIT,
            _nonce
        );

        Utils.transferTokensIn(
            _user,
            _assetId,
            _amount,
            _expectedAmount
        );
    }

    /// @notice Deposits ERC223 tokens under the `_user`'s balance
    /// @dev ERC223 tokens should invoke this method when tokens are
    /// sent to the Broker contract.
    /// The invocation will fail unless the token has been previously
    /// whitelisted through the `whitelistToken` method.
    /// @param _user The address of the user sending the tokens
    /// @param _amount The amount of tokens transferred to the Broker
    function tokenFallback(
        address _user,
        uint _amount,
        bytes calldata /* _data */
    )
        external
        onlyActiveState
        nonReentrant
    {
        address assetId = msg.sender;
        tokenList.validateToken(assetId);
        _increaseBalance(_user, assetId, _amount, REASON_DEPOSIT, 0);
        emit TokenFallback(_user, assetId, _amount);
    }

    /// @notice Deposits ERC777 tokens under the `_user`'s balance
    /// @dev ERC777 tokens should invoke this method when tokens are
    /// sent to the Broker contract.
    /// The invocation will fail unless the token has been previously
    /// whitelisted through the `whitelistToken` method.
    /// @param _user The address of the user sending the tokens
    /// @param _to The address receiving the tokens
    /// @param _amount The amount of tokens transferred to the Broker
    function tokensReceived(
        address /* _operator */,
        address _user,
        address _to,
        uint _amount,
        bytes calldata /* _userData */,
        bytes calldata /* _operatorData */
    )
        external
        onlyActiveState
        nonReentrant
    {
        if (_to != address(this)) { return; }
        address assetId = msg.sender;
        tokenList.validateToken(assetId);
        _increaseBalance(_user, assetId, _amount, REASON_DEPOSIT, 0);
        emit TokensReceived(_user, assetId, _amount);
    }

    /// @notice Executes an array of offers and fills
    /// @dev This method accepts an array of "offers" and "fills" together with
    /// an array of "matches" to specify the matching between the "offers" and "fills".
    /// The data is bit compacted for ease of index referencing and to reduce gas costs,
    /// i.e. data representing different types of information is stored within one 256 bit value.
    ///
    /// For efficient balance updates, the `_addresses` array is meant to contain a
    /// unique set of user asset pairs in the form of:
    /// [
    ///     user_1_address,
    ///     asset_1_address,
    ///     user_1_address,
    ///     asset_2_address,
    ///     user_2_address,
    ///     asset_1_address,
    ///     ...
    /// ]
    /// This allows combining multiple balance updates for a user asset pair
    /// into a single update by first calculating the total balance update for
    /// a pair at a specified index, then looping through the sums to perform
    /// the balance update.
    ///
    /// The added benefit is further gas cost reduction because repeated
    /// user asset pairs do not need to be duplicated for the calldata.
    ///
    /// The operator address is enforced to be the contract's current operator
    /// address, and the operator fee asset ID is enforced to be identical to
    /// the maker's / filler's feeAssetId.
    ///
    /// A tradeoff of compacting the bits is that there is a lower maximum value
    /// for offer and fill data, however the limits remain generally practical.
    ///
    /// For `offerAmount`, `wantAmount`, `feeAmount` values, the maximum value
    /// is 2^128. For a token with 18 decimals, this allows support for tokens
    /// with a maximum supply of 1000 million billion billion (33 zeros).
    /// In the case where the maximum value needs to be exceeded, a single
    /// offer / fill can be split into multiple offers / fills by the off-chain
    /// service.
    ///
    /// For nonces the maximum value is 2^64, or more than a billion billion (19 zeros).
    ///
    /// Offers and fills both encompass information about how much (offerAmount)
    /// of a specified token (offerAssetId) the user wants to offer and
    /// how much (wantAmount) of another token (wantAssetId) they want
    /// in return.
    ///
    /// Each match specifies how much of the match's `offer.offerAmount` should
    /// be transferred to the filler, in return, the offer's maker receives:
    /// `offer.wantAmount * match.takeAmount / offer.offerAmount` of the
    /// `offer.wantAssetId` from the filler.
    ///
    /// A few restirctions are enforced to ensure fairness and security of trades:
    /// 1. To prevent unfairness due to rounding issues, it is required that:
    /// `offer.wantAmount * match.takeAmount % offer.offerAmount == 0`.
    ///
    /// 2. Fills can be filled by offers which do not individually match
    /// the `fill.offerAmount` and `fill.wantAmount` ratio. As such, it is
    /// required that:
    /// fill.offerAmount == total amount deducted from filler for the fill's
    /// associated matches (excluding fees)
    /// fill.wantAmount == total amount credited to filler for the fill's
    /// associated matches (excluding fees)
    ///
    /// 3. The offer array must not consist of repeated offers. For efficient
    /// balance updates, a loop through each offer in the offer array is used
    /// to deduct the offer.offerAmount from the respective maker
    /// if the offer has not been recorded by a previos `trade` call.
    /// If an offer is repeated in the offers array, then there would be
    /// duplicate deductions from the maker.
    /// To enforce uniqueness, it is required that offers for a trade transaction
    /// are sorted such that their nonces are in a strictly ascending order.
    ///
    /// 4. The fill array must not consist of repeated fills, for the same
    /// reason why there cannot be repeated offers. Additionally, to prevent
    /// replay attacks, all fill nonces are required to be unused.
    ///
    /// @param _values[0] Number of offers, fills, matches
    /// bits(0..8): number of offers (numOffers)
    /// bits(8..16): number of fills (numFills)
    /// bits(16..24): number of matches (numMatches)
    /// bits(24..256): must be zero
    ///
    /// @param _values[1 + i * 2] First part of offer data for the i'th offer
    /// bits(0..8): Index of the maker's address in _addresses
    /// bits(8..16): Index of the maker offerAssetId pair in _addresses
    /// bits(16..24): Index of the maker wantAssetId pair in _addresses
    /// bits(24..32): Index of the maker feeAssetId pair in _addresses
    /// bits(32..40): Index of the operator feeAssetId pair in _addresses
    /// bits(40..48): The `v` component of the maker's signature for this offer
    /// bits(48..56): Indicates whether the Ethereum signed message
    /// prefix should be prepended during signature verification
    /// bits(56..120): The offer nonce to prevent replay attacks
    /// bits(120..128): Space to indicate whether the offer nonce has been marked before
    /// bits(128..256): The number of tokens to be paid to the operator as fees for this offer
    ///
    /// @param _values[2 + i * 2] Second part of offer data for the i'th offer
    /// bits(0..128): offer.offerAmount, i.e. the number of tokens to offer
    /// bits(128..256): offer.wantAmount, i.e. the number of tokens to ask for in return
    ///
    /// @param _values[1 + numOffers * 2 + i * 2] First part of fill data for the i'th fill
    /// bits(0..8): Index of the filler's address in _addresses
    /// bits(8..16): Index of the filler offerAssetId pair in _addresses
    /// bits(16..24): Index of the filler wantAssetId pair in _addresses
    /// bits(24..32): Index of the filler feeAssetId pair in _addresses
    /// bits(32..40): Index of the operator feeAssetId pair in _addresses
    /// bits(40..48): The `v` component of the filler's signature for this fill
    /// bits(48..56): Indicates whether the Ethereum signed message
    /// prefix should be prepended during signature verification
    /// bits(56..120): The fill nonce to prevent replay attacks
    /// bits(120..128): Left empty to match the offer values format
    /// bits(128..256): The number of tokens to be paid to the operator as fees for this fill
    ///
    /// @param _values[2 + numOffers * 2 + i * 2] Second part of fill data for the i'th fill
    /// bits(0..128): fill.offerAmount, i.e. the number of tokens to offer
    /// bits(128..256): fill.wantAmount, i.e. the number of tokens to ask for in return
    ///
    /// @param _values[1 + numOffers * 2 + numFills * 2 + i] Data for the i'th match
    /// bits(0..8): Index of the offerIndex for this match
    /// bits(8..16): Index of the fillIndex for this match
    /// bits(128..256): The number of tokens to take from the matched offer's offerAmount
    ///
    /// @param _hashes[i * 2] The `r` component of the maker's / filler's signature
    /// for the i'th offer / fill
    ///
    /// @param _hashes[i * 2 + 1] The `s` component of the maker's / filler's signature
    /// for the i'th offer / fill
    ///
    /// @param _addresses An array of user asset pairs in the form of:
    /// [
    ///     user_1_address,
    ///     asset_1_address,
    ///     user_1_address,
    ///     asset_2_address,
    ///     user_2_address,
    ///     asset_1_address,
    ///     ...
    /// ]
    function trade(
        uint256[] memory _values,
        bytes32[] memory _hashes,
        address[] memory _addresses
    )
        public
        onlyAdmin
        onlyActiveState
        nonReentrant
    {
        // Cache the operator address to reduce gas costs from storage reads
        address operatorAddress = operator;
        // An array variable to store balance increments / decrements
        uint256[] memory statements;

        // Cache whether offer nonces are taken in the offer's nonce space
        _cacheOfferNonceStates(_values);

        // `validateTrades` needs to calculate the hash keys of offers and fills
        // to verify the signature of the offer / fill.
        // The calculated hash keys are returned to reduce repeated computation.
        _hashes = Utils.validateTrades(
            _values,
            _hashes,
            _addresses,
            operatorAddress
        );

        statements = Utils.calculateTradeIncrements(_values, _addresses.length / 2);
        _incrementBalances(statements, _addresses, 1);

        statements = Utils.calculateTradeDecrements(_values, _addresses.length / 2);
        _decrementBalances(statements, _addresses);

        // Reduce available offer amounts of offers and store the remaining
        // offer amount in the `offers` mapping.
        // Offer nonces will also be marked as taken.
        _storeOfferData(_values, _hashes);

        // Mark all fill nonces as taken in the `usedNonces` mapping.
        _storeFillNonces(_values);
    }

    /// @notice Executes an array of offers against external orders.
    /// @dev This method accepts an array of "offers" together with
    /// an array of "matches" to specify the matching between the "offers" and
    /// external orders.
    /// The data is bit compacted and formatted in the same way as the `trade` function.
    ///
    /// @param _values[0] Number of offers, fills, matches
    /// bits(0..8): number of offers (numOffers)
    /// bits(8..16): number of fills, must be zero
    /// bits(16..24): number of matches (numMatches)
    /// bits(24..256): must be zero
    ///
    /// @param _values[1 + i * 2] First part of offer data for the i'th offer
    /// bits(0..8): Index of the maker's address in _addresses
    /// bits(8..16): Index of the maker offerAssetId pair in _addresses
    /// bits(16..24): Index of the maker wantAssetId pair in _addresses
    /// bits(24..32): Index of the maker feeAssetId pair in _addresses
    /// bits(32..40): Index of the operator feeAssetId pair in _addresses
    /// bits(40..48): The `v` component of the maker's signature for this offer
    /// bits(48..56): Indicates whether the Ethereum signed message
    /// prefix should be prepended during signature verification
    /// bits(56..120): The offer nonce to prevent replay attacks
    /// bits(120..128): Space to indicate whether the offer nonce has been marked before
    /// bits(128..256): The number of tokens to be paid to the operator as fees for this offer
    ///
    /// @param _values[2 + i * 2] Second part of offer data for the i'th offer
    /// bits(0..128): offer.offerAmount, i.e. the number of tokens to offer
    /// bits(128..256): offer.wantAmount, i.e. the number of tokens to ask for in return
    ///
    /// @param _values[1 + numOffers * 2 + i] Data for the i'th match
    /// bits(0..8): Index of the offerIndex for this match
    /// bits(8..16): Index of the marketDapp for this match
    /// bits(16..24): Index of the surplus receiver and surplus asset ID for this
    /// match, for any excess tokens resulting from the trade
    /// bits(24..128): Additional DApp specific data
    /// bits(128..256): The number of tokens to take from the matched offer's offerAmount
    ///
    /// @param _hashes[i * 2] The `r` component of the maker's / filler's signature
    /// for the i'th offer / fill
    ///
    /// @param _hashes[i * 2 + 1] The `s` component of the maker's / filler's signature
    /// for the i'th offer / fill
    ///
    /// @param _addresses An array of user asset pairs in the form of:
    /// [
    ///     user_1_address,
    ///     asset_1_address,
    ///     user_1_address,
    ///     asset_2_address,
    ///     user_2_address,
    ///     asset_1_address,
    ///     ...
    /// ]
    function networkTrade(
        uint256[] memory _values,
        bytes32[] memory _hashes,
        address[] memory _addresses
    )
        public
        onlyAdmin
        onlyActiveState
        nonReentrant
    {
        // Cache the operator address to reduce gas costs from storage reads
        address operatorAddress = operator;
        // An array variable to store balance increments / decrements
        uint256[] memory statements;

        // Cache whether offer nonces are taken in the offer's nonce space
        _cacheOfferNonceStates(_values);

        // `validateNetworkTrades` needs to calculate the hash keys of offers
        // to verify the signature of the offer.
        // The calculated hash keys for each offer is return to reduce repeated
        // computation.
        _hashes = Utils.validateNetworkTrades(
            _values,
            _hashes,
            _addresses,
            operatorAddress
        );

        statements = Utils.calculateNetworkTradeIncrements(_values, _addresses.length / 2);
        _incrementBalances(statements, _addresses, 1);

        statements = Utils.calculateNetworkTradeDecrements(_values, _addresses.length / 2);
        _decrementBalances(statements, _addresses);

        // Reduce available offer amounts of offers and store the remaining
        // offer amount in the `offers` mapping.
        // Offer nonces will also be marked as taken.
        _storeOfferData(_values, _hashes);

        // There may be excess tokens resulting from a trade
        // Any excess tokens are returned and recorded in `increments`
        statements = Utils.performNetworkTrades(
            _values,
            _addresses,
            marketDapps
        );
        _incrementBalances(statements, _addresses, 0);
    }

    /// @notice Cancels a perviously made offer and refunds the remaining offer
    /// amount to the offer maker.
    /// To reduce gas costs, the original parameters of the offer are not stored
    /// in the contract's storage, only the hash of the parameters is stored for
    /// verification, so the original parameters need to be re-specified here.
    ///
    /// The `_expectedavailableamount` is required to help prevent accidental
    /// cancellation of an offer ahead of time, for example, if there is
    /// a pending fill in the off-chain state.
    ///
    /// @param _values[0] The offerAmount and wantAmount of the offer
    /// bits(0..128): offer.offerAmount
    /// bits(128..256): offer.wantAmount
    ///
    /// @param _values[1] The fee amounts
    /// bits(0..128): offer.feeAmount
    /// bits(128..256): cancelFeeAmount
    ///
    /// @param _values[2] Additional offer and cancellation data
    /// bits(0..128): expectedAvailableAmount
    /// bits(128..136): prefixedSignature
    /// bits(136..144): The `v` component of the maker's signature for the cancellation
    /// bits(144..256): offer.nonce
    ///
    /// @param _hashes[0] The `r` component of the maker's signature for the cancellation
    /// @param _hashes[1] The `s` component of the maker's signature for the cancellation
    ///
    /// @param _addresses[0] offer.maker
    /// @param _addresses[1] offer.offerAssetId
    /// @param _addresses[2] offer.wantAssetId
    /// @param _addresses[3] offer.feeAssetId
    /// @param _addresses[4] offer.cancelFeeAssetId
    function cancel(
        uint256[] calldata _values,
        bytes32[] calldata _hashes,
        address[] calldata _addresses
    )
        external
        onlyAdmin
        nonReentrant
    {
        Utils.validateCancel(_values, _hashes, _addresses);
        bytes32 offerHash = Utils.hashOffer(_values, _addresses);
        _cancel(
            _addresses[0], // maker
            offerHash,
            _values[2] & mask128, // expectedAvailableAmount
            _addresses[1], // offerAssetId
            _values[2] >> 144, // offerNonce
            _addresses[4], // cancelFeeAssetId
            _values[1] >> 128 // cancelFeeAmount
        );
    }

    /// @notice Cancels an offer without requiring the maker's signature
    /// @dev This method is intended to be used in the case of a contract
    /// upgrade or in an emergency. It can only be invoked by an admin and only
    /// after the admin state has been set to `Escalated` by the contract owner.
    ///
    /// To reduce gas costs, the original parameters of the offer are not stored
    /// in the contract's storage, only the hash of the parameters is stored for
    /// verification, so the original parameters need to be re-specified here.
    ///
    /// The `_expectedavailableamount` is required to help prevent accidental
    /// cancellation of an offer ahead of time, for example, if there is
    /// a pending fill in the off-chain state.
    /// @param _maker The address of the offer's maker
    /// @param _offerAssetId The contract address of the offerred asset
    /// @param _offerAmount The number of tokens offerred
    /// @param _wantAssetId The contract address of the asset asked in return
    /// @param _wantAmount The number of tokens asked for in return
    /// @param _feeAssetId The contract address of the fee asset
    /// @param _feeAmount The number of tokens to pay as fees to the operator
    /// @param _offerNonce The nonce of the original offer
    /// @param _expectedAvailableAmount The offer amount remaining
    function adminCancel(
        address _maker,
        address _offerAssetId,
        uint256 _offerAmount,
        address _wantAssetId,
        uint256 _wantAmount,
        address _feeAssetId,
        uint256 _feeAmount,
        uint256 _offerNonce,
        uint256 _expectedAvailableAmount
    )
        external
        onlyAdmin
        onlyEscalatedAdminState
        nonReentrant
    {
        bytes32 offerHash = keccak256(abi.encode(
            OFFER_TYPEHASH,
            _maker,
            _offerAssetId,
            _offerAmount,
            _wantAssetId,
            _wantAmount,
            _feeAssetId,
            _feeAmount,
            _offerNonce
        ));

        _cancel(
            _maker,
            offerHash,
            _expectedAvailableAmount,
            _offerAssetId,
            _offerNonce,
            address(0),
            0
        );
    }

    /// @notice Announces a user's intention to cancel their offer
    /// @dev This method allows a user to cancel their offer without requiring
    /// admin permissions.
    /// An announcement followed by a delay is needed so that the off-chain
    /// service has time to update the off-chain state.
    ///
    /// To reduce gas costs, the original parameters of the offer are not stored
    /// in the contract's storage, only the hash of the parameters is stored for
    /// verification, so the original parameters need to be re-specified here.
    ///
    /// @param _maker The address of the offer's maker
    /// @param _offerAssetId The contract address of the offerred asset
    /// @param _offerAmount The number of tokens offerred
    /// @param _wantAssetId The contract address of the asset asked in return
    /// @param _wantAmount The number of tokens asked for in return
    /// @param _feeAssetId The contract address of the fee asset
    /// @param _feeAmount The number of tokens to pay as fees to the operator
    /// @param _offerNonce The nonce of the original offer
    function announceCancel(
        address _maker,
        address _offerAssetId,
        uint256 _offerAmount,
        address _wantAssetId,
        uint256 _wantAmount,
        address _feeAssetId,
        uint256 _feeAmount,
        uint256 _offerNonce
    )
        external
        nonReentrant
    {
        // Error code 11: announceCancel, invalid msg.sender
        require(_maker == msg.sender, "11");

        bytes32 offerHash = keccak256(abi.encode(
            OFFER_TYPEHASH,
            _maker,
            _offerAssetId,
            _offerAmount,
            _wantAssetId,
            _wantAmount,
            _feeAssetId,
            _feeAmount,
            _offerNonce
        ));

        // Error code 12: announceCancel, nothing left to cancel
        require(offers[offerHash] > 0, "12");

        uint256 cancellableAt = now.add(slowCancelDelay);
        cancellationAnnouncements[offerHash] = cancellableAt;

        emit AnnounceCancel(offerHash, cancellableAt);
    }

    /// @notice Executes an offer cancellation previously announced in `announceCancel`
    /// @dev This method allows a user to cancel their offer without requiring
    /// admin permissions.
    /// An announcement followed by a delay is needed so that the off-chain
    /// service has time to update the off-chain state.
    ///
    /// To reduce gas costs, the original parameters of the offer are not stored
    /// in the contract's storage, only the hash of the parameters is stored for
    /// verification, so the original parameters need to be re-specified here.
    ///
    /// @param _maker The address of the offer's maker
    /// @param _offerAssetId The contract address of the offerred asset
    /// @param _offerAmount The number of tokens offerred
    /// @param _wantAssetId The contract address of the asset asked in return
    /// @param _wantAmount The number of tokens asked for in return
    /// @param _feeAssetId The contract address of the fee asset
    /// @param _feeAmount The number of tokens to pay as fees to the operator
    /// @param _offerNonce The nonce of the original offer
    function slowCancel(
        address _maker,
        address _offerAssetId,
        uint256 _offerAmount,
        address _wantAssetId,
        uint256 _wantAmount,
        address _feeAssetId,
        uint256 _feeAmount,
        uint256 _offerNonce
    )
        external
        nonReentrant
    {
        bytes32 offerHash = keccak256(abi.encode(
            OFFER_TYPEHASH,
            _maker,
            _offerAssetId,
            _offerAmount,
            _wantAssetId,
            _wantAmount,
            _feeAssetId,
            _feeAmount,
            _offerNonce
        ));

        uint256 cancellableAt = cancellationAnnouncements[offerHash];
        // Error code 13: slowCancel, cancellation was not announced
        require(cancellableAt != 0, "13");
        // Error code 14: slowCancel, cancellation delay not yet reached
        require(now >= cancellableAt, "14");

        uint256 availableAmount = offers[offerHash];
        // Error code 15: slowCancel, nothing left to cancel
        require(availableAmount > 0, "15");

        delete cancellationAnnouncements[offerHash];
        _cancel(
            _maker,
            offerHash,
            availableAmount,
            _offerAssetId,
            _offerNonce,
            address(0),
            0
        );

        emit SlowCancel(offerHash, availableAmount);
    }

    /// @notice Withdraws tokens from the Broker contract to a user's wallet balance
    /// @dev The user's internal balance is decreased, and the tokens are transferred
    /// to the `_receivingAddress` signed by the user.
    /// @param _withdrawer The user address whose balance will be reduced
    /// @param _receivingAddress The address to tranfer the tokens to
    /// @param _assetId The contract address of the token to withdraw
    /// @param _amount The number of tokens to withdraw
    /// @param _feeAssetId The contract address of the fee asset
    /// @param _feeAmount The number of tokens to pay as fees to the operator
    /// @param _nonce An unused nonce to prevent replay attacks
    /// @param _v The `v` component of the `_user`'s signature
    /// @param _r The `r` component of the `_user`'s signature
    /// @param _s The `s` component of the `_user`'s signature
    /// @param _prefixedSignature Indicates whether the Ethereum signed message
    /// prefix should be prepended during signature verification
    function withdraw(
        address _withdrawer,
        address payable _receivingAddress,
        address _assetId,
        uint256 _amount,
        address _feeAssetId,
        uint256 _feeAmount,
        uint256 _nonce,
        uint8 _v,
        bytes32 _r,
        bytes32 _s,
        bool _prefixedSignature
    )
        external
        onlyAdmin
        nonReentrant
    {
        _markNonce(_nonce);

        _validateSignature(
            keccak256(abi.encode(
                WITHDRAW_TYPEHASH,
                _withdrawer,
                _receivingAddress,
                _assetId,
                _amount,
                _feeAssetId,
                _feeAmount,
                _nonce
            )),
            _withdrawer,
            _v,
            _r,
            _s,
            _prefixedSignature
        );

        _withdraw(
            _withdrawer,
            _receivingAddress,
            _assetId,
            _amount,
            _feeAssetId,
            _feeAmount,
            _nonce
        );
    }

    /// @notice Withdraws tokens without requiring the withdrawer's signature
    /// @dev This method is intended to be used in the case of a contract
    /// upgrade or in an emergency. It can only be invoked by an admin and only
    /// after the admin state has been set to `Escalated` by the contract owner.
    /// Unlike `withdraw`, tokens can only be withdrawn to the `_withdrawer`'s
    /// address.
    /// @param _withdrawer The user address whose balance will be reduced
    /// @param _assetId The contract address of the token to withdraw
    /// @param _amount The number of tokens to withdraw
    /// @param _nonce An unused nonce for balance tracking
    function adminWithdraw(
        address payable _withdrawer,
        address _assetId,
        uint256 _amount,
        uint256 _nonce
    )
        external
        onlyAdmin
        onlyEscalatedAdminState
        nonReentrant
    {
        _markNonce(_nonce);

        _withdraw(
            _withdrawer,
            _withdrawer,
            _assetId,
            _amount,
            address(0),
            0,
            _nonce
        );
    }

    /// @notice Announces a user's intention to withdraw their funds
    /// @dev This method allows a user to withdraw their funds without requiring
    /// admin permissions.
    /// An announcement followed by a delay before execution is needed so that
    /// the off-chain service has time to update the off-chain state.
    /// @param _assetId The contract address of the token to withdraw
    /// @param _amount The number of tokens to withdraw
    function announceWithdraw(
        address _assetId,
        uint256 _amount
    )
        external
        nonReentrant
    {

        // Error code 16: announceWithdraw, invalid withdrawal amount
        require(_amount > 0 && _amount <= balances[msg.sender][_assetId], "16");

        WithdrawalAnnouncement storage announcement = withdrawalAnnouncements[msg.sender][_assetId];

        announcement.withdrawableAt = now.add(slowWithdrawDelay);
        announcement.amount = _amount;

        emit AnnounceWithdraw(msg.sender, _assetId, _amount, announcement.withdrawableAt);
    }

    /// @notice Executes a withdrawal previously announced in `announceWithdraw`
    /// @dev This method allows a user to withdraw their funds without requiring
    /// admin permissions.
    /// An announcement followed by a delay before execution is needed so that
    /// the off-chain service has time to update the off-chain state.
    /// @param _withdrawer The user address whose balance will be reduced
    /// @param _assetId The contract address of the token to withdraw
    function slowWithdraw(
        address payable _withdrawer,
        address _assetId,
        uint256 _amount
    )
        external
        nonReentrant
    {
        WithdrawalAnnouncement memory announcement = withdrawalAnnouncements[_withdrawer][_assetId];

        // Error code 17: slowWithdraw, withdrawal was not announced
        require(announcement.withdrawableAt != 0, "17");
        // Error code 18: slowWithdraw, withdrawal delay not yet reached
        require(now >= announcement.withdrawableAt, "18");
        // Error code 19: slowWithdraw, withdrawal amount does not match announced amount
        require(announcement.amount == _amount, "19");

        delete withdrawalAnnouncements[_withdrawer][_assetId];
        _withdraw(
            _withdrawer,
            _withdrawer,
            _assetId,
            _amount,
            address(0),
            0,
            0
        );
        emit SlowWithdraw(_withdrawer, _assetId, _amount);
    }

    /// @notice Locks a user's balances for the first part of an atomic swap
    /// @param _addresses[0] maker: the address of the user to deduct the swap tokens from
    /// @param _addresses[1] taker: the address of the swap taker who will receive the swap tokens
    /// if the swap is completed through `executeSwap`
    /// @param _addresses[2] assetId: the contract address of the token to swap
    /// @param _addresses[3] feeAssetId: the contract address of the token to use as fees
    /// @param _values[0] amount: the number of tokens to lock and to transfer if the swap
    ///  is completed through `executeSwap`
    /// @param _values[1] expiryTime: the time in epoch seconds after which the swap will become cancellable
    /// @param _values[2] feeAmount: the number of tokens to be paid to the operator as fees
    /// @param _values[3] nonce: an unused nonce to prevent replay attacks
    /// @param _hashes[0] hashedSecret: the hash of the secret decided by the maker
    /// @param _hashes[1] The `r` component of the user's signature
    /// @param _hashes[2] The `s` component of the user's signature
    /// @param _v The `v` component of the user's signature
    /// @param _prefixedSignature Indicates whether the Ethereum signed message
    /// prefix should be prepended during signature verification
    function createSwap(
        address[4] calldata _addresses,
        uint256[4] calldata _values,
        bytes32[3] calldata _hashes,
        uint8 _v,
        bool _prefixedSignature
    )
        external
        onlyAdmin
        onlyActiveState
        nonReentrant
    {
        // Error code 20: createSwap, invalid swap amount
        require(_values[0] > 0, "20");
        // Error code 21: createSwap, expiry time has already passed
        require(_values[1] > now, "21");
        _validateAddress(_addresses[1]);

        // Error code 39: createSwap, swap maker cannot be the swap taker
        require(_addresses[0] != _addresses[1], "39");

        bytes32 swapHash = _hashSwap(_addresses, _values, _hashes[0]);
        // Error code 22: createSwap, the swap is already active
        require(!atomicSwaps[swapHash], "22");

        _markNonce(_values[3]);

        _validateSignature(
            swapHash,
            _addresses[0], // swap.maker
            _v,
            _hashes[1], // r
            _hashes[2], // s
            _prefixedSignature
        );

        if (_addresses[3] == _addresses[2]) { // feeAssetId == assetId
            // Error code 23: createSwap, swap.feeAmount exceeds swap.amount
            require(_values[2] < _values[0], "23"); // feeAmount < amount
        } else {
            _decreaseBalance(
                _addresses[0], // maker
                _addresses[3], // feeAssetId
                _values[2], // feeAmount
                REASON_SWAP_FEE_GIVE,
                _values[3] // nonce
            );
        }

        _decreaseBalance(
            _addresses[0], // maker
            _addresses[2], // assetId
            _values[0], // amount
            REASON_SWAP_GIVE,
            _values[3] // nonce
        );

        atomicSwaps[swapHash] = true;
    }

    /// @notice Executes a swap by transferring the tokens previously locked through
    /// a `createSwap` call to the swap taker.
    ///
    /// @dev To reduce gas costs, the original parameters of the swap are not stored
    /// in the contract's storage, only the hash of the parameters is stored for
    /// verification, so the original parameters need to be re-specified here.
    ///
    /// @param _addresses[0] maker: the address of the user to deduct the swap tokens from
    /// @param _addresses[1] taker: the address of the swap taker who will receive the swap tokens
    /// @param _addresses[2] assetId: the contract address of the token to swap
    /// @param _addresses[3] feeAssetId: the contract address of the token to use as fees
    /// @param _values[0] amount: the number of tokens previously locked
    /// @param _values[1] expiryTime: the time in epoch seconds after which the swap will become cancellable
    /// @param _values[2] feeAmount: the number of tokens to be paid to the operator as fees
    /// @param _values[3] nonce: an unused nonce to prevent replay attacks
    /// @param _hashedSecret The hash of the secret decided by the maker
    /// @param _preimage The preimage of the `_hashedSecret`
    function executeSwap(
        address[4] calldata _addresses,
        uint256[4] calldata _values,
        bytes32 _hashedSecret,
        bytes calldata _preimage
    )
        external
        nonReentrant
    {
        // Error code 37: swap secret length exceeded
        require(_preimage.length <= MAX_SWAP_SECRET_LENGTH, "37");

        bytes32 swapHash = _hashSwap(_addresses, _values, _hashedSecret);
        // Error code 24: executeSwap, swap is not active
        require(atomicSwaps[swapHash], "24");
        // Error code 25: executeSwap, hash of preimage does not match hashedSecret
        require(sha256(abi.encodePacked(sha256(_preimage))) == _hashedSecret, "25");

        uint256 takeAmount = _values[0];
        if (_addresses[3] == _addresses[2]) { // feeAssetId == assetId
            takeAmount = takeAmount.sub(_values[2]);
        }

        delete atomicSwaps[swapHash];

        _increaseBalance(
            _addresses[1], // taker
            _addresses[2], // assetId
            takeAmount,
            REASON_SWAP_RECEIVE,
            _values[3] // nonce
        );

        _increaseBalance(
            operator,
            _addresses[3], // feeAssetId
            _values[2], // feeAmount
            REASON_SWAP_FEE_RECEIVE,
            _values[3] // nonce
        );
    }

    /// @notice Cancels a swap and refunds the previously locked tokens to
    /// the swap maker.
    ///
    /// @dev To reduce gas costs, the original parameters of the swap are not stored
    /// in the contract's storage, only the hash of the parameters is stored for
    /// verification, so the original parameters need to be re-specified here.
    ///
    /// @param _addresses[0] maker: the address of the user to deduct the swap tokens from
    /// @param _addresses[1] taker: the address of the swap taker who will receive the swap tokens
    /// @param _addresses[2] assetId: the contract address of the token to swap
    /// @param _addresses[3] feeAssetId: the contract address of the token to use as fees
    /// @param _values[0] amount: the number of tokens previously locked
    /// @param _values[1] expiryTime: the time in epoch seconds after which the swap will become cancellable
    /// @param _values[2] feeAmount: the number of tokens to be paid to the operator as fees
    /// @param _values[3] nonce: an unused nonce to prevent replay attacks
    /// @param _hashedSecret The hash of the secret decided by the maker
    /// @param _cancelFeeAmount The number of tokens to be paid to the operator as the cancellation fee
    function cancelSwap(
        address[4] calldata _addresses,
        uint256[4] calldata _values,
        bytes32 _hashedSecret,
        uint256 _cancelFeeAmount
    )
        external
        nonReentrant
    {
        // Error code 26: cancelSwap, expiry time has not been reached
        require(_values[1] <= now, "26");
        bytes32 swapHash = _hashSwap(_addresses, _values, _hashedSecret);
        // Error code 27: cancelSwap, swap is not active
        require(atomicSwaps[swapHash], "27");

        uint256 cancelFeeAmount = _cancelFeeAmount;
        if (!adminAddresses[msg.sender]) { cancelFeeAmount = _values[2]; }

        // cancelFeeAmount <= feeAmount
        // Error code 28: cancelSwap, cancelFeeAmount exceeds swap.feeAmount
        require(cancelFeeAmount <= _values[2], "28");

        uint256 refundAmount = _values[0];
        if (_addresses[3] == _addresses[2]) { // feeAssetId == assetId
            refundAmount = refundAmount.sub(cancelFeeAmount);
        }

        delete atomicSwaps[swapHash];

        _increaseBalance(
            _addresses[0], // maker
            _addresses[2], // assetId
            refundAmount,
            REASON_SWAP_CANCEL_RECEIVE,
            _values[3] // nonce
        );

        _increaseBalance(
            operator,
            _addresses[3], // feeAssetId
            cancelFeeAmount,
            REASON_SWAP_CANCEL_FEE_RECEIVE,
            _values[3] // nonce
        );

        if (_addresses[3] != _addresses[2]) { // feeAssetId != assetId
            uint256 refundFeeAmount = _values[2].sub(cancelFeeAmount);
            _increaseBalance(
                _addresses[0], // maker
                _addresses[3], // feeAssetId
                refundFeeAmount,
                REASON_SWAP_CANCEL_FEE_REFUND,
                _values[3] // nonce
            );
        }
    }

    /// @dev Cache whether offer nonces are taken in the offer's nonce space
    /// @param _values The _values param from the trade / networkTrade method
    function _cacheOfferNonceStates(uint256[] memory _values) private view {
        uint256 i = 1;
        // i + numOffers * 2
        uint256 end = i + (_values[0] & mask8) * 2;

        // loop offers
        for(i; i < end; i += 2) {
            // Error code 38: Invalid nonce space
            require(((_values[i] & mask128) >> 120) == 0, "38");

            uint256 nonce = (_values[i] & mask120) >> 56;
            if (_nonceTaken(nonce)) {
                _values[i] = _values[i] | (uint256(1) << 120);
            }
        }
    }

    /// @dev Reduce available offer amounts of offers and store the remaining
    /// offer amount in the `offers` mapping.
    /// Offer nonces will also be marked as taken.
    /// See the `trade` method for param details.
    /// @param _values Values from `trade`
    /// @param _hashes An array of offer hash keys
    function _storeOfferData(
        uint256[] memory _values,
        bytes32[] memory _hashes
    )
        private
    {
        // takenAmounts with same size as numOffers
        uint256[] memory takenAmounts = new uint256[](_values[0] & mask8);

        uint256 i = 1;
        // i += numOffers * 2
        i += (_values[0] & mask8) * 2;
        // i += numFills * 2
        i += ((_values[0] & mask16) >> 8) * 2;

        uint256 end = _values.length;

        // loop matches
        for (i; i < end; i++) {
            uint256 offerIndex = _values[i] & mask8;
            uint256 takeAmount = _values[i] >> 128;
            takenAmounts[offerIndex] = takenAmounts[offerIndex].add(takeAmount);
        }

        i = 0;
        end = _values[0] & mask8; // numOffers

        // loop offers
        for (i; i < end; i++) {
            // we can use the cached nonce taken value here because offers have been
            // validated to be unique
            bool existingOffer = ((_values[i * 2 + 1] & mask128) >> 120) == 1;
            bytes32 hashKey = _hashes[i * 2];

            uint256 availableAmount = existingOffer ? offers[hashKey] : (_values[i * 2 + 2] & mask128);
            // Error code 31: _storeOfferData, offer's available amount is zero
            require(availableAmount > 0, "31");

            uint256 remainingAmount = availableAmount.sub(takenAmounts[i]);
            if (remainingAmount > 0) { offers[hashKey] = remainingAmount; }
            if (existingOffer && remainingAmount == 0) { delete offers[hashKey]; }

            if (!existingOffer) {
                uint256 nonce = (_values[i * 2 + 1] & mask120) >> 56;
                _markNonce(nonce);
            }
        }
    }

    /// @dev Mark all fill nonces as taken in the `usedNonces` mapping.
    /// This also validates fill uniquness within the set of fills in `_values`,
    /// since fill nonces are marked one at a time with validation that the
    /// nonce to be marked has not been marked before.
    /// See the `trade` method for param details.
    /// @param _values Values from `trade`
    function _storeFillNonces(uint256[] memory _values) private {
        // 1 + numOffers * 2
        uint256 i = 1 + (_values[0] & mask8) * 2;
        // i + numFills * 2
        uint256 end = i + ((_values[0] & mask16) >> 8) * 2;

        // loop fills
        for(i; i < end; i += 2) {
            uint256 nonce = (_values[i] & mask120) >> 56;
            _markNonce(nonce);
        }
    }

    /// @dev The actual cancellation logic shared by `cancel`, `adminCancel`,
    /// `slowCancel`.
    /// The remaining offer amount is refunded back to the offer's maker, and
    /// the specified cancellation fee will be deducted from the maker's balances.
    function _cancel(
        address _maker,
        bytes32 _offerHash,
        uint256 _expectedAvailableAmount,
        address _offerAssetId,
        uint256 _offerNonce,
        address _cancelFeeAssetId,
        uint256 _cancelFeeAmount
    )
        private
    {
        uint256 refundAmount = offers[_offerHash];
        // Error code 32: _cancel, there is no offer amount left to cancel
        require(refundAmount > 0, "32");
        // Error code 33: _cancel, the remaining offer amount does not match
        // the expectedAvailableAmount
        require(refundAmount == _expectedAvailableAmount, "33");

        delete offers[_offerHash];

        if (_cancelFeeAssetId == _offerAssetId) {
            refundAmount = refundAmount.sub(_cancelFeeAmount);
        } else {
            _decreaseBalance(
                _maker,
                _cancelFeeAssetId,
                _cancelFeeAmount,
                REASON_CANCEL_FEE_GIVE,
                _offerNonce
            );
        }

        _increaseBalance(
            _maker,
            _offerAssetId,
            refundAmount,
            REASON_CANCEL,
            _offerNonce
        );

        _increaseBalance(
            operator,
            _cancelFeeAssetId,
            _cancelFeeAmount,
            REASON_CANCEL_FEE_RECEIVE,
            _offerNonce // offer nonce
        );
    }

    /// @dev The actual withdrawal logic shared by `withdraw`, `adminWithdraw`,
    /// `slowWithdraw`. The specified amount is deducted from the `_withdrawer`'s
    /// contract balance and transferred to the external `_receivingAddress`,
    /// and the specified withdrawal fee will be deducted from the `_withdrawer`'s
    /// balance.
    function _withdraw(
        address _withdrawer,
        address payable _receivingAddress,
        address _assetId,
        uint256 _amount,
        address _feeAssetId,
        uint256 _feeAmount,
        uint256 _nonce
    )
        private
    {
        // Error code 34: _withdraw, invalid withdrawal amount
        require(_amount > 0, "34");

        _validateAddress(_receivingAddress);

        _decreaseBalance(
            _withdrawer,
            _assetId,
            _amount,
            REASON_WITHDRAW,
            _nonce
        );

        _increaseBalance(
            operator,
            _feeAssetId,
            _feeAmount,
            REASON_WITHDRAW_FEE_RECEIVE,
            _nonce
        );

        uint256 withdrawAmount;

        if (_feeAssetId == _assetId) {
            withdrawAmount = _amount.sub(_feeAmount);
        } else {
            _decreaseBalance(
                _withdrawer,
                _feeAssetId,
                _feeAmount,
                REASON_WITHDRAW_FEE_GIVE,
                _nonce
            );
            withdrawAmount = _amount;
        }

        if (_assetId == ETHER_ADDR) {
            _receivingAddress.transfer(withdrawAmount);
            return;
        }

        Utils.transferTokensOut(
            _receivingAddress,
            _assetId,
            withdrawAmount
        );
    }

    /// @dev Creates a hash key for a swap using the swap's parameters
    /// @param _addresses[0] Address of the user making the swap
    /// @param _addresses[1] Address of the user taking the swap
    /// @param _addresses[2] Contract address of the asset to swap
    /// @param _addresses[3] Contract address of the fee asset
    /// @param _values[0] The number of tokens to be transferred
    /// @param _values[1] The time in epoch seconds after which the swap will become cancellable
    /// @param _values[2] The number of tokens to pay as fees to the operator
    /// @param _values[3] The swap nonce to prevent replay attacks
    /// @param _hashedSecret The hash of the secret decided by the maker
    /// @return The hash key of the swap
    function _hashSwap(
        address[4] memory _addresses,
        uint256[4] memory _values,
        bytes32 _hashedSecret
    )
        private
        pure
        returns (bytes32)
    {
        return keccak256(abi.encode(
            SWAP_TYPEHASH,
            _addresses[0], // maker
            _addresses[1], // taker
            _addresses[2], // assetId
            _values[0], // amount
            _hashedSecret, // hashedSecret
            _values[1], // expiryTime
            _addresses[3], // feeAssetId
            _values[2], // feeAmount
            _values[3] // nonce
        ));
    }

    /// @dev Checks if the `_nonce` had been previously taken.
    /// To reduce gas costs, a single `usedNonces` value is used to
    /// store the state of 256 nonces, using the formula:
    /// nonceTaken = "usedNonces[_nonce / 256] bit (_nonce % 256)" != 0
    /// For example:
    /// nonce 0 taken: "usedNonces[0] bit 0" != 0 (0 / 256 = 0, 0 % 256 = 0)
    /// nonce 1 taken: "usedNonces[0] bit 1" != 0 (1 / 256 = 0, 1 % 256 = 1)
    /// nonce 2 taken: "usedNonces[0] bit 2" != 0 (2 / 256 = 0, 2 % 256 = 2)
    /// nonce 255 taken: "usedNonces[0] bit 255" != 0 (255 / 256 = 0, 255 % 256 = 255)
    /// nonce 256 taken: "usedNonces[1] bit 0" != 0 (256 / 256 = 1, 256 % 256 = 0)
    /// nonce 257 taken: "usedNonces[1] bit 1" != 0 (257 / 256 = 1, 257 % 256 = 1)
    /// @param _nonce The nonce to check
    /// @return Whether the nonce has been taken
    function _nonceTaken(uint256 _nonce) private view returns (bool) {
        uint256 slotData = _nonce.div(256);
        uint256 shiftedBit = uint256(1) << _nonce.mod(256);
        uint256 bits = usedNonces[slotData];

        // The check is for "!= 0" instead of "== 1" because the shiftedBit is
        // not at the zero'th position, so it would require an additional
        // shift to compare it with "== 1"
        return bits & shiftedBit != 0;
    }

    /// @dev Sets the corresponding `_nonce` bit to 1.
    /// An error will be raised if the corresponding `_nonce` bit was
    /// previously set to 1.
    /// See `_nonceTaken` for details on calculating the corresponding `_nonce` bit.
    /// @param _nonce The nonce to mark
    function _markNonce(uint256 _nonce) private {
        // Error code 35: _markNonce, nonce cannot be zero
        require(_nonce != 0, "35");

        uint256 slotData = _nonce.div(256);
        uint256 shiftedBit = 1 << _nonce.mod(256);
        uint256 bits = usedNonces[slotData];

        // Error code 36: _markNonce, nonce has already been marked
        require(bits & shiftedBit == 0, "36");

        usedNonces[slotData] = bits | shiftedBit;
    }

    /// @dev Validates that the specified `_hash` was signed by the specified `_user`.
    /// This method supports the EIP712 specification, the older Ethereum
    /// signed message specification is also supported for backwards compatibility.
    /// @param _hash The original hash that was signed by the user
    /// @param _user The user who signed the hash
    /// @param _v The `v` component of the `_user`'s signature
    /// @param _r The `r` component of the `_user`'s signature
    /// @param _s The `s` component of the `_user`'s signature
    /// @param _prefixed If true, the signature will be verified
    /// against the Ethereum signed message specification instead of the
    /// EIP712 specification
    function _validateSignature(
        bytes32 _hash,
        address _user,
        uint8 _v,
        bytes32 _r,
        bytes32 _s,
        bool _prefixed
    )
        private
        pure
    {
        Utils.validateSignature(
            _hash,
            _user,
            _v,
            _r,
            _s,
            _prefixed
        );
    }

    /// @dev A utility method to increase the balance of a user.
    /// A corressponding `BalanceIncrease` event will also be emitted.
    /// @param _user The address to increase balance for
    /// @param _assetId The asset's contract address
    /// @param _amount The number of tokens to increase the balance by
    /// @param _reasonCode The reason code for the `BalanceIncrease` event
    /// @param _nonce The nonce for the `BalanceIncrease` event
    function _increaseBalance(
        address _user,
        address _assetId,
        uint256 _amount,
        uint256 _reasonCode,
        uint256 _nonce
    )
        private
    {
        if (_amount == 0) { return; }
        balances[_user][_assetId] = balances[_user][_assetId].add(_amount);

        emit BalanceIncrease(
            _user,
            _assetId,
            _amount,
            _reasonCode,
            _nonce
        );
    }

    /// @dev A utility method to decrease the balance of a user.
    /// A corressponding `BalanceDecrease` event will also be emitted.
    /// @param _user The address to decrease balance for
    /// @param _assetId The asset's contract address
    /// @param _amount The number of tokens to decrease the balance by
    /// @param _reasonCode The reason code for the `BalanceDecrease` event
    /// @param _nonce The nonce for the `BalanceDecrease` event
    function _decreaseBalance(
        address _user,
        address _assetId,
        uint256 _amount,
        uint256 _reasonCode,
        uint256 _nonce
    )
        private
    {
        if (_amount == 0) { return; }
        balances[_user][_assetId] = balances[_user][_assetId].sub(_amount);

        emit BalanceDecrease(
            _user,
            _assetId,
            _amount,
            _reasonCode,
            _nonce
        );
    }

    /// @dev Ensures that `_address` is not the zero address
    /// @param _address The address to check
    function _validateAddress(address _address) private pure {
        Utils.validateAddress(_address);
    }

    /// @dev A utility method to increase balances of multiple addresses.
    /// A corressponding `Increment` event will also be emitted.
    /// @param _increments An array of amounts to increase a user's balance by,
    /// the corresponding user and assetId is referenced by
    /// _addresses[index * 2] and _addresses[index * 2 + 1] respectively
    /// @param _addresses An array of user asset pairs in the form of:
    /// [
    ///     user_1_address,
    ///     asset_1_address,
    ///     user_1_address,
    ///     asset_2_address,
    ///     user_2_address,
    ///     asset_1_address,
    ///     ...
    /// ]
    /// @param _static Indicates if the amount was pre-calculated or only known
    /// at the time the transaction was executed
    function _incrementBalances(
        uint256[] memory _increments,
        address[] memory _addresses,
        uint256 _static
    )
        private
    {
        uint256 end = _increments.length;

        for(uint256 i = 0; i < end; i++) {
            uint256 increment = _increments[i];
            if (increment == 0) { continue; }

            balances[_addresses[i * 2]][_addresses[i * 2 + 1]] =
            balances[_addresses[i * 2]][_addresses[i * 2 + 1]].add(increment);

            emit Increment((i << 248) | (_static << 240) | increment);
        }
    }

    /// @dev A utility method to decrease balances of multiple addresses.
    /// A corressponding `Decrement` event will also be emitted.
    /// @param _decrements An array of amounts to decrease a user's balance by,
    /// the corresponding user and assetId is referenced by
    /// _addresses[index * 2] and _addresses[index * 2 + 1] respectively
    /// @param _addresses An array of user asset pairs in the form of:
    /// [
    ///     user_1_address,
    ///     asset_1_address,
    ///     user_1_address,
    ///     asset_2_address,
    ///     user_2_address,
    ///     asset_1_address,
    ///     ...
    /// ]
    function _decrementBalances(
        uint256[] memory _decrements,
        address[] memory _addresses
    )
        private
    {
        uint256 end = _decrements.length;
        for(uint256 i = 0; i < end; i++) {
            uint256 decrement = _decrements[i];
            if (decrement == 0) { continue; }

            balances[_addresses[i * 2]][_addresses[i * 2 + 1]] =
            balances[_addresses[i * 2]][_addresses[i * 2 + 1]].sub(decrement);

            emit Decrement(i << 248 | decrement);
        }
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_tokenListAddress","type":"address"},{"internalType":"address","name":"_spenderListAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"offerHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"cancellableAt","type":"uint256"}],"name":"AnnounceCancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawableAt","type":"uint256"}],"name":"AnnounceWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reason","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"BalanceDecrease","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reason","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"BalanceIncrease","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"Decrement","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"Increment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"offerHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SlowCancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SlowWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenFallback","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensReceived","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"OFFER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SWAP_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"WITHDRAW_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"addAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_dapp","type":"address"}],"name":"addMarketDapp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"adminAddresses","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_maker","type":"address"},{"internalType":"address","name":"_offerAssetId","type":"address"},{"internalType":"uint256","name":"_offerAmount","type":"uint256"},{"internalType":"address","name":"_wantAssetId","type":"address"},{"internalType":"uint256","name":"_wantAmount","type":"uint256"},{"internalType":"address","name":"_feeAssetId","type":"address"},{"internalType":"uint256","name":"_feeAmount","type":"uint256"},{"internalType":"uint256","name":"_offerNonce","type":"uint256"},{"internalType":"uint256","name":"_expectedAvailableAmount","type":"uint256"}],"name":"adminCancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"adminState","outputs":[{"internalType":"enum BrokerV2.AdminState","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_withdrawer","type":"address"},{"internalType":"address","name":"_assetId","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"adminWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_maker","type":"address"},{"internalType":"address","name":"_offerAssetId","type":"address"},{"internalType":"uint256","name":"_offerAmount","type":"uint256"},{"internalType":"address","name":"_wantAssetId","type":"address"},{"internalType":"uint256","name":"_wantAmount","type":"uint256"},{"internalType":"address","name":"_feeAssetId","type":"address"},{"internalType":"uint256","name":"_feeAmount","type":"uint256"},{"internalType":"uint256","name":"_offerNonce","type":"uint256"}],"name":"announceCancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_assetId","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"announceWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"atomicSwaps","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"_values","type":"uint256[]"},{"internalType":"bytes32[]","name":"_hashes","type":"bytes32[]"},{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"cancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[4]","name":"_addresses","type":"address[4]"},{"internalType":"uint256[4]","name":"_values","type":"uint256[4]"},{"internalType":"bytes32","name":"_hashedSecret","type":"bytes32"},{"internalType":"uint256","name":"_cancelFeeAmount","type":"uint256"}],"name":"cancelSwap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"cancellationAnnouncements","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"claimOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[4]","name":"_addresses","type":"address[4]"},{"internalType":"uint256[4]","name":"_values","type":"uint256[4]"},{"internalType":"bytes32[3]","name":"_hashes","type":"bytes32[3]"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bool","name":"_prefixedSignature","type":"bool"}],"name":"createSwap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_assetId","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_expectedAmount","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"depositToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[4]","name":"_addresses","type":"address[4]"},{"internalType":"uint256[4]","name":"_values","type":"uint256[4]"},{"internalType":"bytes32","name":"_hashedSecret","type":"bytes32"},{"internalType":"bytes","name":"_preimage","type":"bytes"}],"name":"executeSwap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"markNonce","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketDapps","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"_values","type":"uint256[]"},{"internalType":"bytes32[]","name":"_hashes","type":"bytes32[]"},{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"networkTrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"nonceTaken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"offers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"removeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"removeMarketDapp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum BrokerV2.AdminState","name":"_state","type":"uint8"}],"name":"setAdminState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_operator","type":"address"}],"name":"setOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setSlowCancelDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"}],"name":"setSlowWithdrawDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"enum BrokerV2.State","name":"_state","type":"uint8"}],"name":"setState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_maker","type":"address"},{"internalType":"address","name":"_offerAssetId","type":"address"},{"internalType":"uint256","name":"_offerAmount","type":"uint256"},{"internalType":"address","name":"_wantAssetId","type":"address"},{"internalType":"uint256","name":"_wantAmount","type":"uint256"},{"internalType":"address","name":"_feeAssetId","type":"address"},{"internalType":"uint256","name":"_feeAmount","type":"uint256"},{"internalType":"uint256","name":"_offerNonce","type":"uint256"}],"name":"slowCancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"slowCancelDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_withdrawer","type":"address"},{"internalType":"address","name":"_assetId","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"slowWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"slowWithdrawDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"address","name":"_assetId","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"spendFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"spenderList","outputs":[{"internalType":"contract SpenderList","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"internalType":"enum BrokerV2.State","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokenFallback","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenList","outputs":[{"internalType":"contract TokenList","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokensReceived","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"_values","type":"uint256[]"},{"internalType":"bytes32[]","name":"_hashes","type":"bytes32[]"},{"internalType":"address[]","name":"_addresses","type":"address[]"}],"name":"trade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"address","name":"_dapp","type":"address"}],"name":"updateMarketDapp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"usedNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_withdrawer","type":"address"},{"internalType":"address payable","name":"_receivingAddress","type":"address"},{"internalType":"address","name":"_assetId","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_feeAssetId","type":"address"},{"internalType":"uint256","name":"_feeAmount","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"},{"internalType":"bool","name":"_prefixedSignature","type":"bool"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"withdrawalAnnouncements","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"withdrawableAt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405162005cfc38038062005cfc833981810160405260408110156200003757600080fd5b508051602090910151600080546001600160a01b03191633178082556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360016002819055336000818152600c6020526040808220805460ff19908116909517905560038054600480546001600160a01b038a81166001600160a01b031992831617835560058054918b169190921617905562093a8060078190556006556201000090950262010000600160b01b03199091161790941690935582517f455243373737546f6b656e73526563697069656e740000000000000000000000815283519081900360150181207f29965a1d00000000000000000000000000000000000000000000000000000000825230938201849052602482015260448101929092529151731820a4b7618bde71dce8cdc73aab6c95905fad249283926329965a1d926064808301939282900301818387803b158015620001a957600080fd5b505af1158015620001be573d6000803e3d6000fd5b50505050505050615b2780620001d56000396000f3fe6080604052600436106103345760003560e01c806376c5d758116101ab578063c23f001f116100f7578063e34afb0811610095578063f3ba63b81161006f578063f3ba63b8146111f1578063f43948ad14611257578063fc3284de1461126c578063fd29fe7a146112d257610334565b8063e34afb0814611121578063f2fde38b14611175578063f3044550146111a857610334565b8063d0e30db0116100d1578063d0e30db014610e37578063d45c895f14610e3f578063ddf6cbf614610ff1578063e30c39781461110c57610334565b8063c23f001f14610d54578063c904037014610d8f578063c98668db14610db957610334565b8063a0a9085611610164578063b3ab15fb1161013e578063b3ab15fb14610aca578063ba286a5d14610afd578063c0ee0b8a14610caf578063c19d93fb14610d3f57610334565b8063a0a9085614610a18578063a1559cf214610a42578063a42d508314610a7b57610334565b806376c5d7581461098257806387cb697b146109975780638da5cb5b146109ac5780638f32d59b146109c1578063908d9a26146109d65780639e2c58ca14610a0357610334565b806337c09316116102855780634ed38faf11610223578063623a91ee116101fd578063623a91ee146108c75780636717e41c146108dc57806370480275146109065780637073f8c11461093957610334565b80634ed38faf1461085257806356de96db14610885578063570ca735146108b257610334565b8063499199a61161025f578063499199a6146107c55780634b277586146107ef5780634bc30ea7146108285780634e71e0c81461083d57610334565b806337c093161461073e5780634102e54614610768578063474d3ff01461079b57610334565b80631785f53c116102f25780631e90c2d5116102cc5780631e90c2d5146105fa5780632257bdd41461068757806324d7806c146106b15780632bdddd5f146106f857610334565b80631785f53c1461055a57806317c8790f1461058d5780631da72f4a146105b757610334565b806223de291461033657806302939dfe1461042957806302b0038b1461046557806302dfec131461047a57806309291623146104b4578063125b0c6f146104ed575b005b34801561034257600080fd5b50610334600480360360c081101561035957600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561039b57600080fd5b8201836020820111156103ad57600080fd5b803590602001918460018302840111600160201b831117156103ce57600080fd5b919390929091602081019035600160201b8111156103eb57600080fd5b8201836020820111156103fd57600080fd5b803590602001918460018302840111600160201b8311171561041e57600080fd5b509092509050611316565b34801561043557600080fd5b506104536004803603602081101561044c57600080fd5b503561148f565b60408051918252519081900360200190f35b34801561047157600080fd5b506104536114a1565b34801561048657600080fd5b50610334600480360361014081101561049e57600080fd5b50608081016101008201356101208301356114b3565b3480156104c057600080fd5b50610334600480360360408110156104d757600080fd5b506001600160a01b038135169060200135611755565b3480156104f957600080fd5b50610334600480360361012081101561051157600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a08101359091169060c08101359060e081013590610100013561189a565b34801561056657600080fd5b506103346004803603602081101561057d57600080fd5b50356001600160a01b0316611a15565b34801561059957600080fd5b50610334600480360360208110156105b057600080fd5b5035611b29565b3480156105c357600080fd5b50610334600480360360608110156105da57600080fd5b506001600160a01b03813581169160208101359091169060400135611c00565b34801561060657600080fd5b50610334600480360361014081101561061e57600080fd5b6080820190610100830135908301836101408101610120820135600160201b81111561064957600080fd5b82018360208201111561065b57600080fd5b803590602001918460018302840111600160201b8311171561067c57600080fd5b509092509050611dd9565b34801561069357600080fd5b50610334600480360360208110156106aa57600080fd5b50356120fc565b3480156106bd57600080fd5b506106e4600480360360208110156106d457600080fd5b50356001600160a01b03166121b7565b604080519115158252519081900360200190f35b34801561070457600080fd5b506107226004803603602081101561071b57600080fd5b50356121d5565b604080516001600160a01b039092168252519081900360200190f35b34801561074a57600080fd5b506103346004803603602081101561076157600080fd5b50356121fc565b34801561077457600080fd5b506103346004803603602081101561078b57600080fd5b50356001600160a01b03166122d3565b3480156107a757600080fd5b50610453600480360360208110156107be57600080fd5b50356123bd565b3480156107d157600080fd5b50610334600480360360208110156107e857600080fd5b50356123cf565b3480156107fb57600080fd5b506108046124e9565b6040518082600181111561081457fe5b60ff16815260200191505060405180910390f35b34801561083457600080fd5b506104536124f7565b34801561084957600080fd5b5061033461251b565b34801561085e57600080fd5b506106e46004803603602081101561087557600080fd5b50356001600160a01b0316612596565b34801561089157600080fd5b50610334600480360360208110156108a857600080fd5b503560ff166125ab565b3480156108be57600080fd5b50610722612660565b3480156108d357600080fd5b50610453612675565b3480156108e857600080fd5b50610453600480360360208110156108ff57600080fd5b503561267b565b34801561091257600080fd5b506103346004803603602081101561092957600080fd5b50356001600160a01b031661268d565b34801561094557600080fd5b506103346004803603608081101561095c57600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356127a1565b34801561098e57600080fd5b5061045361289f565b3480156109a357600080fd5b506104536128c3565b3480156109b857600080fd5b506107226128c9565b3480156109cd57600080fd5b506106e46128d8565b3480156109e257600080fd5b50610334600480360360208110156109f957600080fd5b503560ff166128e9565b348015610a0f57600080fd5b5061072261295a565b348015610a2457600080fd5b506106e460048036036020811015610a3b57600080fd5b5035612969565b348015610a4e57600080fd5b5061033460048036036040811015610a6557600080fd5b50803590602001356001600160a01b031661297e565b348015610a8757600080fd5b50610334600480360360a0811015610a9e57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135612abd565b348015610ad657600080fd5b5061033460048036036020811015610aed57600080fd5b50356001600160a01b0316612c37565b348015610b0957600080fd5b5061033460048036036060811015610b2057600080fd5b810190602081018135600160201b811115610b3a57600080fd5b820183602082011115610b4c57600080fd5b803590602001918460208302840111600160201b83111715610b6d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610bbc57600080fd5b820183602082011115610bce57600080fd5b803590602001918460208302840111600160201b83111715610bef57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610c3e57600080fd5b820183602082011115610c5057600080fd5b803590602001918460208302840111600160201b83111715610c7157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612d0a945050505050565b348015610cbb57600080fd5b5061033460048036036060811015610cd257600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610d0157600080fd5b820183602082011115610d1357600080fd5b803590602001918460018302840111600160201b83111715610d3457600080fd5b5090925090506134f0565b348015610d4b57600080fd5b50610804613648565b348015610d6057600080fd5b5061045360048036036040811015610d7757600080fd5b506001600160a01b0381358116916020013516613651565b348015610d9b57600080fd5b506106e460048036036020811015610db257600080fd5b503561366e565b348015610dc557600080fd5b506103346004803603610160811015610ddd57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060ff60e0820135169061010081013590610120810135906101400135151561367f565b610334613813565b348015610e4b57600080fd5b5061033460048036036060811015610e6257600080fd5b810190602081018135600160201b811115610e7c57600080fd5b820183602082011115610e8e57600080fd5b803590602001918460208302840111600160201b83111715610eaf57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610efe57600080fd5b820183602082011115610f1057600080fd5b803590602001918460208302840111600160201b83111715610f3157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610f8057600080fd5b820183602082011115610f9257600080fd5b803590602001918460208302840111600160201b83111715610fb357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506138f5945050505050565b348015610ffd57600080fd5b506103346004803603606081101561101457600080fd5b810190602081018135600160201b81111561102e57600080fd5b82018360208201111561104057600080fd5b803590602001918460208302840111600160201b8311171561106157600080fd5b919390929091602081019035600160201b81111561107e57600080fd5b82018360208201111561109057600080fd5b803590602001918460208302840111600160201b831117156110b157600080fd5b919390929091602081019035600160201b8111156110ce57600080fd5b8201836020820111156110e057600080fd5b803590602001918460208302840111600160201b8311171561110157600080fd5b509092509050613ea5565b34801561111857600080fd5b506107226141cd565b34801561112d57600080fd5b5061115c6004803603604081101561114457600080fd5b506001600160a01b03813581169160200135166141dc565b6040805192835260208301919091528051918290030190f35b34801561118157600080fd5b506103346004803603602081101561119857600080fd5b50356001600160a01b0316614200565b3480156111b457600080fd5b50610334600480360360808110156111cb57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135614269565b3480156111fd57600080fd5b50610334600480360361010081101561121557600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a08101359091169060c08101359060e001356143d9565b34801561126357600080fd5b5061072261458e565b34801561127857600080fd5b50610334600480360361010081101561129057600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a08101359091169060c08101359060e0013561459d565b3480156112de57600080fd5b5061033460048036036101a08110156112f657600080fd5b5060808101610100820160ff61016084013516610180840135151561478d565b600060035460ff16600181111561132957fe5b1461135f576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556001600160a01b038716301461137f57611440565b6004805460408051639532b6ab60e01b81523393810184905290516001600160a01b0390921691639532b6ab91602480820192600092909190829003018186803b1580156113cc57600080fd5b505afa1580156113e0573d6000803e3d6000fd5b505050506113f389828960016000614ae0565b806001600160a01b0316896001600160a01b03167f0af1239547617509a79d1ff0ee4be9ca943bc8410cb0b282dda97d27995a0acd896040518082815260200191505060405180910390a3505b6002548114611484576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050505050505050565b600e6020526000908152604090205481565b600080516020615ab383398151915281565b600280546001019081905542602085013511156114fc576040805162461bcd60e51b8152602060048201526002602482015261191b60f11b604482015290519081900360640190fd5b600061155786600480602002604051908101604052809291908260046020028082843760009201919091525050604080516080818101909252915088906004908390839080828437600092019190915250889150614b949050565b6000818152600b602052604090205490915060ff166115a2576040805162461bcd60e51b8152602060048201526002602482015261323760f01b604482015290519081900360640190fd5b336000908152600c6020526040902054839060ff166115c2575060408501355b6040860135811115611600576040805162461bcd60e51b8152602060048201526002602482015261064760f31b604482015290519081900360640190fd5b853560608801356001600160a01b0390811660408a0135909116141561163357611630818363ffffffff614c4d16565b90505b6000838152600b602052604090819020805460ff19169055611671906001600160a01b038a358116918b0135168360388b60035b6020020135614ae0565b6116b5600360029054906101000a90046001600160a01b03168960036004811061169757fe5b60200201356001600160a01b031684603b8b60036004811061166757fe5b60608801356001600160a01b0390811660408a0135909116146117075760006116e2604089013584614c4d565b90506117056001600160a01b038a3581169060608c01351683603d8c6003611667565b505b505050600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b5050505050565b600280546001019081905581158015906117925750336000908152600a602090815260408083206001600160a01b03871684529091529020548211155b6117c8576040805162461bcd60e51b8152602060048201526002602482015261189b60f11b604482015290519081900360640190fd5b336000908152600f602090815260408083206001600160a01b038716845290915290206007546117ff90429063ffffffff614caa16565b6001820181905583825560408051858152602081019290925280516001600160a01b0387169233927fdff70c03c3362d0ad854d2def54b6b9a07001173106116ee768204ccc40d502b92918290030190a3506002548114611895576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050565b336000908152600c602052604090205460ff166118e2576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b6001600354610100900460ff1660018111156118fa57fe5b14611930576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b600280546001019081905560408051600080516020615ab38339815191526020808301919091526001600160a01b03808e1683850152808d166060840152608083018c9052808b1660a084015260c083018a9052881660e083015261010082018790526101208083018790528351808403909101815261014090920190925280519101206119c48b82858d88600080614d0b565b506002548114611a09576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50505050505050505050565b611a1d6128d8565b611a5c576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460010190819055611a7082614e0a565b6001600160a01b0382166000908152600c602052604090205460ff16611ac1576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600c60205260409020805460ff191690556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b5050565b611b316128d8565b611b70576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600280546001019081905562093a80821115611bb7576040805162461bcd60e51b81526020600482015260016024820152600d60fa1b604482015290519081900360640190fd5b60068290556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6002805460010190819055611c13615a78565b506001600160a01b038085166000908152600f6020908152604080832093871683529281529082902082518084019093528054835260010154908201819052611c88576040805162461bcd60e51b8152602060048201526002602482015261313760f01b604482015290519081900360640190fd5b8060200151421015611cc6576040805162461bcd60e51b8152602060048201526002602482015261062760f31b604482015290519081900360640190fd5b80518314611d00576040805162461bcd60e51b8152602060048201526002602482015261313960f01b604482015290519081900360640190fd5b6001600160a01b038086166000908152600f602090815260408083209388168352929052908120818155600101819055611d439086908190879087908080614e78565b836001600160a01b0316856001600160a01b03167fff294538b75f20720425fcd47909c7dec61cc4f29a697ea48b9b86d489f254e3856040518082815260200191505060405180910390a3506002548114611dd3576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50505050565b60028054600101908190556040821115611e1f576040805162461bcd60e51b8152602060048201526002602482015261333760f01b604482015290519081900360640190fd5b6000611e7a87600480602002604051908101604052809291908260046020028082843760009201919091525050604080516080818101909252915089906004908390839080828437600092019190915250899150614b949050565b6000818152600b602052604090205490915060ff16611ec5576040805162461bcd60e51b81526020600482015260026024820152610c8d60f21b604482015290519081900360640190fd5b8460028086866040518083838082843760405192019450602093509091505080830381855afa158015611efc573d6000803e3d6000fd5b5050506040513d6020811015611f1157600080fd5b50516040805160208181019390935281518082038401815290820191829052805190928291908401908083835b60208310611f5d5780518252601f199092019160209182019101611f3e565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015611f9c573d6000803e3d6000fd5b5050506040513d6020811015611fb157600080fd5b505114611fea576040805162461bcd60e51b8152602060048201526002602482015261323560f01b604482015290519081900360640190fd5b853560608801356001600160a01b0390811660408a013590911614156120215761201e81604089013563ffffffff614c4d16565b90505b6000828152600b6020908152604091829020805460ff1916905561205e916001600160a01b03918b0135821691908b0135168360358b6003611667565b6120ae600360029054906101000a90046001600160a01b03168960036004811061208457fe5b60200201356001600160a01b03168960026004811061209f57fe5b602002013560378b6003611667565b505060025481146120f4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050505050565b600280546001019081905560055460408051637f1e83d160e11b815233600482015290516001600160a01b039092169163fe3d07a291602480820192600092909190829003018186803b15801561215257600080fd5b505afa158015612166573d6000803e3d6000fd5b5050505061217382614ff5565b6002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6001600160a01b03166000908152600c602052604090205460ff1690565b600d81815481106121e257fe5b6000918252602090912001546001600160a01b0316905081565b6122046128d8565b612243576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600280546001019081905562093a8082111561228a576040805162461bcd60e51b81526020600482015260016024820152603560f81b604482015290519081900360640190fd5b60078290556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6122db6128d8565b61231a576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600280546001019081905561232e82614e0a565b600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0384161790556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b60086020526000908152604090205481565b6123d76128d8565b612416576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460010190819055600d8054600091908490811061243357fe5b6000918252602090912001546001600160a01b0316141561247f576040805162461bcd60e51b81526020600482015260016024820152603960f81b604482015290519081900360640190fd5b600d828154811061248c57fe5b600091825260209091200180546001600160a01b03191690556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b600354610100900460ff1681565b7f6ba9001457a287c210b728198a424a4222098d7fac48f8c5fb5ab10ef907d3ef81565b6001546001600160a01b0316331461253257600080fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b600c6020526000908152604090205460ff1681565b6125b36128d8565b6125f2576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460019081019182905560038054849260ff1990911690838181111561261757fe5b02179055506002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6003546201000090046001600160a01b031681565b60075481565b60096020526000908152604090205481565b6126956128d8565b6126d4576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b60028054600101908190556126e882614e0a565b6001600160a01b0382166000908152600c602052604090205460ff161561273a576040805162461bcd60e51b81526020600482015260016024820152601b60f91b604482015290519081900360640190fd5b6001600160a01b0382166000908152600c60205260409020805460ff191660011790556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff166127e9576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b6001600354610100900460ff16600181111561280157fe5b14612837576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b600280546001019081905561284b82614ff5565b61285b8586868660008088614e78565b600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b7fbe2f4292252fbb88b129dc7717b2f3f74a9afb5b13a2283cac5c056117b002eb81565b60065481565b6000546001600160a01b031681565b6000546001600160a01b0316331490565b6128f16128d8565b612930576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460019081019182905560038054849261ff00199091169061010090849081111561261757fe5b6004546001600160a01b031681565b600b6020526000908152604090205460ff1681565b6129866128d8565b6129c5576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b60028054600101908190556129d982614e0a565b60006001600160a01b0316600d84815481106129f157fe5b6000918252602090912001546001600160a01b03161415612a3d576040805162461bcd60e51b81526020600482015260016024820152600760fb1b604482015290519081900360640190fd5b81600d8481548110612a4b57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506002548114611895576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff16612b05576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff166001811115612b1857fe5b14612b4e576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600190810191829055612b6b9087908790869086614ae0565b60408051632b07b2ff60e21b81526001600160a01b038089166004830152871660248201526044810186905260648101859052905173d6e266d0221a2e7909fb7f9fd45a84d217e909e79163ac1ecbfc916084808301926000929190829003018186803b158015612bdb57600080fd5b505af4158015612bef573d6000803e3d6000fd5b5050505060025481146120f4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b612c3f6128d8565b612c7e576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460010190819055600354612ca4906201000090046001600160a01b0316614e0a565b6003805462010000600160b01b031916620100006001600160a01b038516021790556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff16612d52576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff166001811115612d6557fe5b14612d9b576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556003546201000090046001600160a01b03166060612dc3866150bc565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e763122a4aa5878787866040518563ffffffff1660e01b815260040180806020018060200180602001856001600160a01b03166001600160a01b03168152602001848103845288818151815260200191508051906020019060200280838360005b83811015612e50578181015183820152602001612e38565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015612e8f578181015183820152602001612e77565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015612ece578181015183820152602001612eb6565b5050505090500197505050505050505060006040518083038186803b158015612ef657600080fd5b505af4158015612f0a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612f3357600080fd5b8101908080516040519392919084600160201b821115612f5257600080fd5b908301906020820185811115612f6757600080fd5b82518660208202830111600160201b82111715612f8357600080fd5b82525081516020918201928201910280838360005b83811015612fb0578181015183820152602001612f98565b50505050905001604052505050945073d6e266d0221a2e7909fb7f9fd45a84d217e909e763fb29e322876002875181612fe557fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561303b578181015183820152602001613023565b50505050905001935050505060006040518083038186803b15801561305f57600080fd5b505af4158015613073573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561309c57600080fd5b8101908080516040519392919084600160201b8211156130bb57600080fd5b9083019060208201858111156130d057600080fd5b82518660208202830111600160201b821117156130ec57600080fd5b82525081516020918201928201910280838360005b83811015613119578181015183820152602001613101565b505050509050016040525050509050613134818560016151bb565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e7635dabb16e87600287518161315a57fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b838110156131b0578181015183820152602001613198565b50505050905001935050505060006040518083038186803b1580156131d457600080fd5b505af41580156131e8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561321157600080fd5b8101908080516040519392919084600160201b82111561323057600080fd5b90830190602082018581111561324557600080fd5b82518660208202830111600160201b8211171561326157600080fd5b82525081516020918201928201910280838360005b8381101561328e578181015183820152602001613276565b5050505090500160405250505090506132a78185615341565b6132b186866154c1565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e76384c2771e8786600d6040518463ffffffff1660e01b815260040180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561332657818101518382015260200161330e565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561336557818101518382015260200161334d565b5050505090500184810382528581815481526020019150805480156133b357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613395575b5050965050505050505060006040518083038186803b1580156133d557600080fd5b505af41580156133e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561341257600080fd5b8101908080516040519392919084600160201b82111561343157600080fd5b90830190602082018581111561344657600080fd5b82518660208202830111600160201b8211171561346257600080fd5b82525081516020918201928201910280838360005b8381101561348f578181015183820152602001613477565b5050505090500160405250505090506134aa818560006151bb565b50506002548114611dd3576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b600060035460ff16600181111561350357fe5b14613539576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556004805460408051639532b6ab60e01b81523393810184905290516001600160a01b0390921691639532b6ab91602480820192600092909190829003018186803b15801561359157600080fd5b505afa1580156135a5573d6000803e3d6000fd5b505050506135b886828760016000614ae0565b806001600160a01b0316866001600160a01b03167f4260c3d560f20eaba927af72aecb4683ed83dfedd6f5984eb4bff1fb1b04dc8f876040518082815260200191505060405180910390a350600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b60035460ff1681565b600a60209081526000928352604080842090915290825290205481565b600061367982615784565b92915050565b336000908152600c602052604090205460ff166136c7576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b60028054600101908190556136db86614ff5565b6137b27fbe2f4292252fbb88b129dc7717b2f3f74a9afb5b13a2283cac5c056117b002eb60001b8d8d8d8d8d8d8d60405160200180898152602001886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001858152602001846001600160a01b03166001600160a01b0316815260200183815260200182815260200198505050505050505050604051602081830303815290604052805190602001208d878787876157d0565b6137c18c8c8c8c8c8c8c614e78565b6002548114613805576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050505050505050505050565b600060035460ff16600181111561382657fe5b1461385c576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190553461389e576040805162461bcd60e51b8152602060048201526002602482015261031360f41b604482015290519081900360640190fd5b6138ae3360003460016000614ae0565b60025481146138f2576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50565b336000908152600c602052604090205460ff1661393d576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff16600181111561395057fe5b14613986576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556003546201000090046001600160a01b031660606139ae866150bc565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e763fba697ae878787866040518563ffffffff1660e01b815260040180806020018060200180602001856001600160a01b03166001600160a01b03168152602001848103845288818151815260200191508051906020019060200280838360005b83811015613a3b578181015183820152602001613a23565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015613a7a578181015183820152602001613a62565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015613ab9578181015183820152602001613aa1565b5050505090500197505050505050505060006040518083038186803b158015613ae157600080fd5b505af4158015613af5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613b1e57600080fd5b8101908080516040519392919084600160201b821115613b3d57600080fd5b908301906020820185811115613b5257600080fd5b82518660208202830111600160201b82111715613b6e57600080fd5b82525081516020918201928201910280838360005b83811015613b9b578181015183820152602001613b83565b50505050905001604052505050945073d6e266d0221a2e7909fb7f9fd45a84d217e909e76351e82b96876002875181613bd057fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015613c26578181015183820152602001613c0e565b50505050905001935050505060006040518083038186803b158015613c4a57600080fd5b505af4158015613c5e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613c8757600080fd5b8101908080516040519392919084600160201b821115613ca657600080fd5b908301906020820185811115613cbb57600080fd5b82518660208202830111600160201b82111715613cd757600080fd5b82525081516020918201928201910280838360005b83811015613d04578181015183820152602001613cec565b505050509050016040525050509050613d1f818560016151bb565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e76303815e7b876002875181613d4557fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015613d9b578181015183820152602001613d83565b50505050905001935050505060006040518083038186803b158015613dbf57600080fd5b505af4158015613dd3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613dfc57600080fd5b8101908080516040519392919084600160201b821115613e1b57600080fd5b908301906020820185811115613e3057600080fd5b82518660208202830111600160201b82111715613e4c57600080fd5b82525081516020918201928201910280838360005b83811015613e79578181015183820152602001613e61565b505050509050016040525050509050613e928185615341565b613e9c86866154c1565b6134aa86615864565b336000908152600c602052604090205460ff16613eed576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b6002805460010190819055604051638369bbaf60e01b81526060600482019081526064820188905273d6e266d0221a2e7909fb7f9fd45a84d217e909e791638369bbaf918a918a918a918a918a918a91908190602481019060448101906084018a60208b0280828437600083820152601f01601f19169091018581038452888152602090810191508990890280828437600083820152601f01601f19169091018581038352868152602090810191508790870280828437600081840152601f19601f820116905080830192505050995050505050505050505060006040518083038186803b158015613fde57600080fd5b505af4158015613ff2573d6000803e3d6000fd5b50505050600073d6e266d0221a2e7909fb7f9fd45a84d217e909e763c931ac21898987876040518563ffffffff1660e01b81526004018080602001806020018381038352878782818152602001925060200280828437600083820152601f01601f19169091018481038352858152602090810191508690860280828437600081840152601f19601f820116905080830192505050965050505050505060206040518083038186803b1580156140a657600080fd5b505af41580156140ba573d6000803e3d6000fd5b505050506040513d60208110156140d057600080fd5b5051905061417f84846000816140e257fe5b905060200201356001600160a01b0316826080600019901b198b8b600281811061410857fe5b90506020020135168787600181811061411d57fe5b905060200201356001600160a01b031660908d8d600281811061413c57fe5b90506020020135901c8989600481811061415257fe5b905060200201356001600160a01b031660808f8f600181811061417157fe5b90506020020135901c614d0b565b5060025481146141c4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50505050505050565b6001546001600160a01b031681565b600f6020908152600092835260408084209091529082529020805460019091015482565b6142086128d8565b614247576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600280546001019081905560055460408051633735486760e11b81526001600160a01b03888116600483015233602483015291519190921691636e6a90ce916044808301926000929190829003018186803b1580156142c757600080fd5b505afa1580156142db573d6000803e3d6000fd5b505050506142e884614e0a565b6001600160a01b038086166000908152600a602090815260408083209387168352929052205461431e908363ffffffff614c4d16565b6001600160a01b038087166000908152600a602081815260408084208986168086529083528185209690965593891683529081528282209382529290925290205461436f908363ffffffff614caa16565b6001600160a01b038086166000908152600a6020908152604080832093881683529290522055600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b60028054600101908190556001600160a01b0389163314614426576040805162461bcd60e51b8152602060048201526002602482015261313160f01b604482015290519081900360640190fd5b60408051600080516020615ab38339815191526020808301919091526001600160a01b03808d1683850152808c166060840152608083018b9052808a1660a084015260c08301899052871660e0830152610100820186905261012080830186905283518084039091018152610140909201835281519181019190912060008181526008909252919020546144e6576040805162461bcd60e51b8152602060048201526002602482015261189960f11b604482015290519081900360640190fd5b60006144fd60065442614caa90919063ffffffff16565b6000838152600e60209081526040918290208390558151838152915192935084927f8f78d3ae5953e6de0b053ccdd0a76139099980dc9e0fb8086f8e1c96edbaa45b9281900390910190a250506002548114611484576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6005546001600160a01b031681565b600280546001019081905560408051600080516020615ab38339815191526020808301919091526001600160a01b03808d1683850152808c166060840152608083018b9052808a1660a084015260c08301899052871660e083015261010082018690526101208083018690528351808403909101815261014090920183528151918101919091206000818152600e9092529190205480614669576040805162461bcd60e51b8152602060048201526002602482015261313360f01b604482015290519081900360640190fd5b804210156146a3576040805162461bcd60e51b81526020600482015260026024820152610c4d60f21b604482015290519081900360640190fd5b600082815260086020526040902054806146e9576040805162461bcd60e51b8152602060048201526002602482015261313560f01b604482015290519081900360640190fd5b600e6000848152602001908152602001600020600090556147108c84838e89600080614d0b565b60408051828152905184917fa9ef9d74f47971616159b4a658e98048b5b7a83a099ba0901f69ce512b47805d919081900360200190a25050506002548114611484576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff166147d5576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff1660018111156147e857fe5b1461481e576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190558435614861576040805162461bcd60e51b8152602060048201526002602482015261032360f41b604482015290519081900360640190fd5b4260208601351161489e576040805162461bcd60e51b8152602060048201526002602482015261323160f01b604482015290519081900360640190fd5b6148b46001600160a01b03602088013516614e0a565b85356001600160a01b0390811660208801359091161415614901576040805162461bcd60e51b8152602060048201526002602482015261333960f01b604482015290519081900360640190fd5b600061495c876004806020026040519081016040528092919082600460200280828437600092019190915250506040805160808181019092529150899060049083908390808284376000920191909152505088359050614b94565b6000818152600b602052604090205490915060ff16156149a8576040805162461bcd60e51b8152602060048201526002602482015261191960f11b604482015290519081900360640190fd5b6149b56060870135614ff5565b6149d58188356001600160a01b031686602089013560408a0135886157d0565b60608701356001600160a01b0390811660408901359091161415614a36578535604087013510614a31576040805162461bcd60e51b8152602060048201526002602482015261323360f01b604482015290519081900360640190fd5b614a61565b614a616001600160a01b03883581169060608a013516604089013560328a60035b60200201356158f5565b614a836001600160a01b03883581169060408a013516883560308a6003614a57565b6000908152600b60205260409020805460ff1916600117905560025481146120f4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b82614aea5761174e565b6001600160a01b038086166000908152600a6020908152604080832093881683529290522054614b20908463ffffffff614caa16565b6001600160a01b038087166000818152600a60209081526040808320948a168084529482529182902094909455805187815293840186905283810185905251919290917f14d4d01c4d5dc621bda40cbf92745f0f6510eb2f5ef6a8f2d026bd4f659e58d49181900360600190a35050505050565b82516020808501516040808701518651878501516060998a015189850151998b015185517f6ba9001457a287c210b728198a424a4222098d7fac48f8c5fb5ab10ef907d3ef818a01526001600160a01b03998a16818801529689169b87019b909b52928716608086015260a085019190915260c084019690965260e08301959095529290931661010084015261012083019390935261014080830194909452805180830390940184526101609091019052815191012090565b600082821115614ca4576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082820183811015614d04576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008681526008602052604090205480614d51576040805162461bcd60e51b8152602060048201526002602482015261199960f11b604482015290519081900360640190fd5b858114614d8a576040805162461bcd60e51b8152602060048201526002602482015261333360f01b604482015290519081900360640190fd5b6000878152600860205260408120556001600160a01b038381169086161415614dc457614dbd818363ffffffff614c4d16565b9050614dd2565b614dd28884846012886158f5565b614de0888683600888614ae0565b600354614e00906201000090046001600160a01b03168484601388614ae0565b5050505050505050565b60408051632f47185360e11b81526001600160a01b0383166004820152905173d6e266d0221a2e7909fb7f9fd45a84d217e909e791635e8e30a6916024808301926000929190829003018186803b158015614e6457600080fd5b505af415801561174e573d6000803e3d6000fd5b60008411614eb2576040805162461bcd60e51b81526020600482015260026024820152610ccd60f21b604482015290519081900360640190fd5b614ebb86614e0a565b614ec98786866009856158f5565b600354614ee9906201000090046001600160a01b03168484601585614ae0565b6000856001600160a01b0316846001600160a01b03161415614f1c57614f15858463ffffffff614c4d16565b9050614f2d565b614f2a8885856014866158f5565b50835b6001600160a01b038616614f78576040516001600160a01b0388169082156108fc029083906000818181858888f19350505050158015614f71573d6000803e3d6000fd5b50506141c4565b6040805163193c114b60e01b81526001600160a01b03808a1660048301528816602482015260448101839052905173d6e266d0221a2e7909fb7f9fd45a84d217e909e79163193c114b916064808301926000929190829003018186803b158015614fe157600080fd5b505af4158015613805573d6000803e3d6000fd5b8061502c576040805162461bcd60e51b8152602060048201526002602482015261333560f01b604482015290519081900360640190fd5b60006150408261010063ffffffff6159a916565b905060006150568361010063ffffffff615a1316565b600083815260096020526040902054600190911b9150808216156150a6576040805162461bcd60e51b8152602060048201526002602482015261199b60f11b604482015290519081900360640190fd5b6000928352600960205260409092209117905550565b805160019060009060ff90849083906150d157fe5b602002602001015116600202820190505b808210156118955782516078906001600160801b039085908590811061510457fe5b602002602001015116901c600014615148576040805162461bcd60e51b8152602060048201526002602482015261066760f31b604482015290519081900360640190fd5b600060386078600019901b1985858151811061516057fe5b602002602001015116901c905061517681615784565b156151af5760786001901b84848151811061518d57fe5b6020026020010151178484815181106151a257fe5b6020026020010181815250505b506002820191506150e2565b825160005b8181101561174e5760008582815181106151d657fe5b6020026020010151905080600014156151ef5750615339565b61527981600a600088866002028151811061520657fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600088866002026001018151811061524257fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054614caa90919063ffffffff16565b600a600087856002028151811061528c57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008785600202600101815181106152c857fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055507f51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a818160f086901b60f885901b17176040518082815260200191505060405180910390a1505b6001016151c0565b815160005b81811015611dd357600084828151811061535c57fe5b60200260200101519050806000141561537557506154b9565b6153ff81600a600087866002028151811061538c57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008786600202600101815181106153c857fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054614c4d90919063ffffffff16565b600a600086856002028151811061541257fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086856002026001018151811061544e57fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055507f32814a5bdfd1b8c3d76c49c54e043d6e8aa93d197a09e16599b567135503f7488160f884901b176040518082815260200191505060405180910390a1505b600101615346565b815160609060ff9084906000906154d457fe5b602002602001015116604051908082528060200260200182016040528015615506578160200160208202803883390190505b50835190915060019060ff90859060009061551d57fe5b6020026020010151166002028101905060086010600019901b198560008151811061554457fe5b602002602001015116901c600202810190506000845190505b808210156155ea57845160009060ff9087908590811061557957fe5b60200260200101511690506000608087858151811061559457fe5b6020026020010151901c90506155c6818684815181106155b057fe5b6020026020010151614caa90919063ffffffff16565b8583815181106155d257fe5b6020908102919091010152505060019091019061555d565b84516000925060ff90869084906155fd57fe5b60200260200101511690505b8082101561174e57600060786080600019901b1987856002026001018151811061562f57fe5b602002602001015116901c6001149050600085846002028151811061565057fe5b6020026020010151905060008261568b5787516001600160801b0390899060028089020190811061567d57fe5b60200260200101511661569b565b6000828152600860205260409020545b9050600081116156d7576040805162461bcd60e51b8152602060048201526002602482015261333160f01b604482015290519081900360640190fd5b60006156ff8787815181106156e857fe5b602002602001015183614c4d90919063ffffffff16565b905080156157195760008381526008602052604090208190555b838015615724575080155b15615739576000838152600860205260408120555b8361577457600060386078600019901b198b896002026001018151811061575c57fe5b602002602001015116901c905061577281614ff5565b505b5050600190930192506156099050565b6000806157998361010063ffffffff6159a916565b905060006157af8461010063ffffffff615a1316565b60009283526009602052604090922054600190921b90911615159392505050565b60408051631056c68960e01b8152600481018890526001600160a01b038716602482015260ff86166044820152606481018590526084810184905282151560a4820152905173d6e266d0221a2e7909fb7f9fd45a84d217e909e791631056c6899160c4808301926000929190829003018186803b15801561585057600080fd5b505af4158015611a09573d6000803e3d6000fd5b805160009060ff908390839061587657fe5b6020026020010151166002026001019050600060086010600019901b19846000815181106158a057fe5b602002602001015116901c600202820190505b8082101561189557600060386078600019901b198585815181106158d357fe5b602002602001015116901c90506158e981614ff5565b506002820191506158b3565b826158ff5761174e565b6001600160a01b038086166000908152600a6020908152604080832093881683529290522054615935908463ffffffff614c4d16565b6001600160a01b038087166000818152600a60209081526040808320948a168084529482529182902094909455805187815293840186905283810185905251919290917f7b0f7fa8d27ccea2b81f143f956fbe50b379ec2593bac595b664f932237d4e869181900360600190a35050505050565b60008082116159ff576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b6000828481615a0a57fe5b04949350505050565b600081615a67576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b818381615a7057fe5b069392505050565b60405180604001604052806000815260200160008152509056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00f845c83a8f7964bc8dd1a092d28b83573b35be97630a5b8a3b8ae2ae79cd92604f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a265627a7a723158208320f1a86db0d7f110c710dd3181db0600eca41d862c7c9460c632f3e17f7ed964736f6c634300050c0032000000000000000000000000c860598a9a38eff76dbbbe67fdc1b7975c0c17bd000000000000000000000000dad636e070baa6d9484eee6a2452557833862c03

Deployed Bytecode

0x6080604052600436106103345760003560e01c806376c5d758116101ab578063c23f001f116100f7578063e34afb0811610095578063f3ba63b81161006f578063f3ba63b8146111f1578063f43948ad14611257578063fc3284de1461126c578063fd29fe7a146112d257610334565b8063e34afb0814611121578063f2fde38b14611175578063f3044550146111a857610334565b8063d0e30db0116100d1578063d0e30db014610e37578063d45c895f14610e3f578063ddf6cbf614610ff1578063e30c39781461110c57610334565b8063c23f001f14610d54578063c904037014610d8f578063c98668db14610db957610334565b8063a0a9085611610164578063b3ab15fb1161013e578063b3ab15fb14610aca578063ba286a5d14610afd578063c0ee0b8a14610caf578063c19d93fb14610d3f57610334565b8063a0a9085614610a18578063a1559cf214610a42578063a42d508314610a7b57610334565b806376c5d7581461098257806387cb697b146109975780638da5cb5b146109ac5780638f32d59b146109c1578063908d9a26146109d65780639e2c58ca14610a0357610334565b806337c09316116102855780634ed38faf11610223578063623a91ee116101fd578063623a91ee146108c75780636717e41c146108dc57806370480275146109065780637073f8c11461093957610334565b80634ed38faf1461085257806356de96db14610885578063570ca735146108b257610334565b8063499199a61161025f578063499199a6146107c55780634b277586146107ef5780634bc30ea7146108285780634e71e0c81461083d57610334565b806337c093161461073e5780634102e54614610768578063474d3ff01461079b57610334565b80631785f53c116102f25780631e90c2d5116102cc5780631e90c2d5146105fa5780632257bdd41461068757806324d7806c146106b15780632bdddd5f146106f857610334565b80631785f53c1461055a57806317c8790f1461058d5780631da72f4a146105b757610334565b806223de291461033657806302939dfe1461042957806302b0038b1461046557806302dfec131461047a57806309291623146104b4578063125b0c6f146104ed575b005b34801561034257600080fd5b50610334600480360360c081101561035957600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561039b57600080fd5b8201836020820111156103ad57600080fd5b803590602001918460018302840111600160201b831117156103ce57600080fd5b919390929091602081019035600160201b8111156103eb57600080fd5b8201836020820111156103fd57600080fd5b803590602001918460018302840111600160201b8311171561041e57600080fd5b509092509050611316565b34801561043557600080fd5b506104536004803603602081101561044c57600080fd5b503561148f565b60408051918252519081900360200190f35b34801561047157600080fd5b506104536114a1565b34801561048657600080fd5b50610334600480360361014081101561049e57600080fd5b50608081016101008201356101208301356114b3565b3480156104c057600080fd5b50610334600480360360408110156104d757600080fd5b506001600160a01b038135169060200135611755565b3480156104f957600080fd5b50610334600480360361012081101561051157600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a08101359091169060c08101359060e081013590610100013561189a565b34801561056657600080fd5b506103346004803603602081101561057d57600080fd5b50356001600160a01b0316611a15565b34801561059957600080fd5b50610334600480360360208110156105b057600080fd5b5035611b29565b3480156105c357600080fd5b50610334600480360360608110156105da57600080fd5b506001600160a01b03813581169160208101359091169060400135611c00565b34801561060657600080fd5b50610334600480360361014081101561061e57600080fd5b6080820190610100830135908301836101408101610120820135600160201b81111561064957600080fd5b82018360208201111561065b57600080fd5b803590602001918460018302840111600160201b8311171561067c57600080fd5b509092509050611dd9565b34801561069357600080fd5b50610334600480360360208110156106aa57600080fd5b50356120fc565b3480156106bd57600080fd5b506106e4600480360360208110156106d457600080fd5b50356001600160a01b03166121b7565b604080519115158252519081900360200190f35b34801561070457600080fd5b506107226004803603602081101561071b57600080fd5b50356121d5565b604080516001600160a01b039092168252519081900360200190f35b34801561074a57600080fd5b506103346004803603602081101561076157600080fd5b50356121fc565b34801561077457600080fd5b506103346004803603602081101561078b57600080fd5b50356001600160a01b03166122d3565b3480156107a757600080fd5b50610453600480360360208110156107be57600080fd5b50356123bd565b3480156107d157600080fd5b50610334600480360360208110156107e857600080fd5b50356123cf565b3480156107fb57600080fd5b506108046124e9565b6040518082600181111561081457fe5b60ff16815260200191505060405180910390f35b34801561083457600080fd5b506104536124f7565b34801561084957600080fd5b5061033461251b565b34801561085e57600080fd5b506106e46004803603602081101561087557600080fd5b50356001600160a01b0316612596565b34801561089157600080fd5b50610334600480360360208110156108a857600080fd5b503560ff166125ab565b3480156108be57600080fd5b50610722612660565b3480156108d357600080fd5b50610453612675565b3480156108e857600080fd5b50610453600480360360208110156108ff57600080fd5b503561267b565b34801561091257600080fd5b506103346004803603602081101561092957600080fd5b50356001600160a01b031661268d565b34801561094557600080fd5b506103346004803603608081101561095c57600080fd5b506001600160a01b038135811691602081013590911690604081013590606001356127a1565b34801561098e57600080fd5b5061045361289f565b3480156109a357600080fd5b506104536128c3565b3480156109b857600080fd5b506107226128c9565b3480156109cd57600080fd5b506106e46128d8565b3480156109e257600080fd5b50610334600480360360208110156109f957600080fd5b503560ff166128e9565b348015610a0f57600080fd5b5061072261295a565b348015610a2457600080fd5b506106e460048036036020811015610a3b57600080fd5b5035612969565b348015610a4e57600080fd5b5061033460048036036040811015610a6557600080fd5b50803590602001356001600160a01b031661297e565b348015610a8757600080fd5b50610334600480360360a0811015610a9e57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135612abd565b348015610ad657600080fd5b5061033460048036036020811015610aed57600080fd5b50356001600160a01b0316612c37565b348015610b0957600080fd5b5061033460048036036060811015610b2057600080fd5b810190602081018135600160201b811115610b3a57600080fd5b820183602082011115610b4c57600080fd5b803590602001918460208302840111600160201b83111715610b6d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610bbc57600080fd5b820183602082011115610bce57600080fd5b803590602001918460208302840111600160201b83111715610bef57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610c3e57600080fd5b820183602082011115610c5057600080fd5b803590602001918460208302840111600160201b83111715610c7157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612d0a945050505050565b348015610cbb57600080fd5b5061033460048036036060811015610cd257600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610d0157600080fd5b820183602082011115610d1357600080fd5b803590602001918460018302840111600160201b83111715610d3457600080fd5b5090925090506134f0565b348015610d4b57600080fd5b50610804613648565b348015610d6057600080fd5b5061045360048036036040811015610d7757600080fd5b506001600160a01b0381358116916020013516613651565b348015610d9b57600080fd5b506106e460048036036020811015610db257600080fd5b503561366e565b348015610dc557600080fd5b506103346004803603610160811015610ddd57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060ff60e0820135169061010081013590610120810135906101400135151561367f565b610334613813565b348015610e4b57600080fd5b5061033460048036036060811015610e6257600080fd5b810190602081018135600160201b811115610e7c57600080fd5b820183602082011115610e8e57600080fd5b803590602001918460208302840111600160201b83111715610eaf57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610efe57600080fd5b820183602082011115610f1057600080fd5b803590602001918460208302840111600160201b83111715610f3157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610f8057600080fd5b820183602082011115610f9257600080fd5b803590602001918460208302840111600160201b83111715610fb357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506138f5945050505050565b348015610ffd57600080fd5b506103346004803603606081101561101457600080fd5b810190602081018135600160201b81111561102e57600080fd5b82018360208201111561104057600080fd5b803590602001918460208302840111600160201b8311171561106157600080fd5b919390929091602081019035600160201b81111561107e57600080fd5b82018360208201111561109057600080fd5b803590602001918460208302840111600160201b831117156110b157600080fd5b919390929091602081019035600160201b8111156110ce57600080fd5b8201836020820111156110e057600080fd5b803590602001918460208302840111600160201b8311171561110157600080fd5b509092509050613ea5565b34801561111857600080fd5b506107226141cd565b34801561112d57600080fd5b5061115c6004803603604081101561114457600080fd5b506001600160a01b03813581169160200135166141dc565b6040805192835260208301919091528051918290030190f35b34801561118157600080fd5b506103346004803603602081101561119857600080fd5b50356001600160a01b0316614200565b3480156111b457600080fd5b50610334600480360360808110156111cb57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135614269565b3480156111fd57600080fd5b50610334600480360361010081101561121557600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a08101359091169060c08101359060e001356143d9565b34801561126357600080fd5b5061072261458e565b34801561127857600080fd5b50610334600480360361010081101561129057600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a08101359091169060c08101359060e0013561459d565b3480156112de57600080fd5b5061033460048036036101a08110156112f657600080fd5b5060808101610100820160ff61016084013516610180840135151561478d565b600060035460ff16600181111561132957fe5b1461135f576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556001600160a01b038716301461137f57611440565b6004805460408051639532b6ab60e01b81523393810184905290516001600160a01b0390921691639532b6ab91602480820192600092909190829003018186803b1580156113cc57600080fd5b505afa1580156113e0573d6000803e3d6000fd5b505050506113f389828960016000614ae0565b806001600160a01b0316896001600160a01b03167f0af1239547617509a79d1ff0ee4be9ca943bc8410cb0b282dda97d27995a0acd896040518082815260200191505060405180910390a3505b6002548114611484576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050505050505050565b600e6020526000908152604090205481565b600080516020615ab383398151915281565b600280546001019081905542602085013511156114fc576040805162461bcd60e51b8152602060048201526002602482015261191b60f11b604482015290519081900360640190fd5b600061155786600480602002604051908101604052809291908260046020028082843760009201919091525050604080516080818101909252915088906004908390839080828437600092019190915250889150614b949050565b6000818152600b602052604090205490915060ff166115a2576040805162461bcd60e51b8152602060048201526002602482015261323760f01b604482015290519081900360640190fd5b336000908152600c6020526040902054839060ff166115c2575060408501355b6040860135811115611600576040805162461bcd60e51b8152602060048201526002602482015261064760f31b604482015290519081900360640190fd5b853560608801356001600160a01b0390811660408a0135909116141561163357611630818363ffffffff614c4d16565b90505b6000838152600b602052604090819020805460ff19169055611671906001600160a01b038a358116918b0135168360388b60035b6020020135614ae0565b6116b5600360029054906101000a90046001600160a01b03168960036004811061169757fe5b60200201356001600160a01b031684603b8b60036004811061166757fe5b60608801356001600160a01b0390811660408a0135909116146117075760006116e2604089013584614c4d565b90506117056001600160a01b038a3581169060608c01351683603d8c6003611667565b505b505050600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b5050505050565b600280546001019081905581158015906117925750336000908152600a602090815260408083206001600160a01b03871684529091529020548211155b6117c8576040805162461bcd60e51b8152602060048201526002602482015261189b60f11b604482015290519081900360640190fd5b336000908152600f602090815260408083206001600160a01b038716845290915290206007546117ff90429063ffffffff614caa16565b6001820181905583825560408051858152602081019290925280516001600160a01b0387169233927fdff70c03c3362d0ad854d2def54b6b9a07001173106116ee768204ccc40d502b92918290030190a3506002548114611895576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050565b336000908152600c602052604090205460ff166118e2576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b6001600354610100900460ff1660018111156118fa57fe5b14611930576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b600280546001019081905560408051600080516020615ab38339815191526020808301919091526001600160a01b03808e1683850152808d166060840152608083018c9052808b1660a084015260c083018a9052881660e083015261010082018790526101208083018790528351808403909101815261014090920190925280519101206119c48b82858d88600080614d0b565b506002548114611a09576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50505050505050505050565b611a1d6128d8565b611a5c576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460010190819055611a7082614e0a565b6001600160a01b0382166000908152600c602052604090205460ff16611ac1576040805162461bcd60e51b81526020600482015260016024820152603760f81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600c60205260409020805460ff191690556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b5050565b611b316128d8565b611b70576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600280546001019081905562093a80821115611bb7576040805162461bcd60e51b81526020600482015260016024820152600d60fa1b604482015290519081900360640190fd5b60068290556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6002805460010190819055611c13615a78565b506001600160a01b038085166000908152600f6020908152604080832093871683529281529082902082518084019093528054835260010154908201819052611c88576040805162461bcd60e51b8152602060048201526002602482015261313760f01b604482015290519081900360640190fd5b8060200151421015611cc6576040805162461bcd60e51b8152602060048201526002602482015261062760f31b604482015290519081900360640190fd5b80518314611d00576040805162461bcd60e51b8152602060048201526002602482015261313960f01b604482015290519081900360640190fd5b6001600160a01b038086166000908152600f602090815260408083209388168352929052908120818155600101819055611d439086908190879087908080614e78565b836001600160a01b0316856001600160a01b03167fff294538b75f20720425fcd47909c7dec61cc4f29a697ea48b9b86d489f254e3856040518082815260200191505060405180910390a3506002548114611dd3576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50505050565b60028054600101908190556040821115611e1f576040805162461bcd60e51b8152602060048201526002602482015261333760f01b604482015290519081900360640190fd5b6000611e7a87600480602002604051908101604052809291908260046020028082843760009201919091525050604080516080818101909252915089906004908390839080828437600092019190915250899150614b949050565b6000818152600b602052604090205490915060ff16611ec5576040805162461bcd60e51b81526020600482015260026024820152610c8d60f21b604482015290519081900360640190fd5b8460028086866040518083838082843760405192019450602093509091505080830381855afa158015611efc573d6000803e3d6000fd5b5050506040513d6020811015611f1157600080fd5b50516040805160208181019390935281518082038401815290820191829052805190928291908401908083835b60208310611f5d5780518252601f199092019160209182019101611f3e565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015611f9c573d6000803e3d6000fd5b5050506040513d6020811015611fb157600080fd5b505114611fea576040805162461bcd60e51b8152602060048201526002602482015261323560f01b604482015290519081900360640190fd5b853560608801356001600160a01b0390811660408a013590911614156120215761201e81604089013563ffffffff614c4d16565b90505b6000828152600b6020908152604091829020805460ff1916905561205e916001600160a01b03918b0135821691908b0135168360358b6003611667565b6120ae600360029054906101000a90046001600160a01b03168960036004811061208457fe5b60200201356001600160a01b03168960026004811061209f57fe5b602002013560378b6003611667565b505060025481146120f4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050505050565b600280546001019081905560055460408051637f1e83d160e11b815233600482015290516001600160a01b039092169163fe3d07a291602480820192600092909190829003018186803b15801561215257600080fd5b505afa158015612166573d6000803e3d6000fd5b5050505061217382614ff5565b6002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6001600160a01b03166000908152600c602052604090205460ff1690565b600d81815481106121e257fe5b6000918252602090912001546001600160a01b0316905081565b6122046128d8565b612243576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600280546001019081905562093a8082111561228a576040805162461bcd60e51b81526020600482015260016024820152603560f81b604482015290519081900360640190fd5b60078290556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6122db6128d8565b61231a576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600280546001019081905561232e82614e0a565b600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0384161790556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b60086020526000908152604090205481565b6123d76128d8565b612416576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460010190819055600d8054600091908490811061243357fe5b6000918252602090912001546001600160a01b0316141561247f576040805162461bcd60e51b81526020600482015260016024820152603960f81b604482015290519081900360640190fd5b600d828154811061248c57fe5b600091825260209091200180546001600160a01b03191690556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b600354610100900460ff1681565b7f6ba9001457a287c210b728198a424a4222098d7fac48f8c5fb5ab10ef907d3ef81565b6001546001600160a01b0316331461253257600080fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b600c6020526000908152604090205460ff1681565b6125b36128d8565b6125f2576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460019081019182905560038054849260ff1990911690838181111561261757fe5b02179055506002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6003546201000090046001600160a01b031681565b60075481565b60096020526000908152604090205481565b6126956128d8565b6126d4576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b60028054600101908190556126e882614e0a565b6001600160a01b0382166000908152600c602052604090205460ff161561273a576040805162461bcd60e51b81526020600482015260016024820152601b60f91b604482015290519081900360640190fd5b6001600160a01b0382166000908152600c60205260409020805460ff191660011790556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff166127e9576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b6001600354610100900460ff16600181111561280157fe5b14612837576040805162461bcd60e51b81526020600482015260016024820152603360f81b604482015290519081900360640190fd5b600280546001019081905561284b82614ff5565b61285b8586868660008088614e78565b600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b7fbe2f4292252fbb88b129dc7717b2f3f74a9afb5b13a2283cac5c056117b002eb81565b60065481565b6000546001600160a01b031681565b6000546001600160a01b0316331490565b6128f16128d8565b612930576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460019081019182905560038054849261ff00199091169061010090849081111561261757fe5b6004546001600160a01b031681565b600b6020526000908152604090205460ff1681565b6129866128d8565b6129c5576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b60028054600101908190556129d982614e0a565b60006001600160a01b0316600d84815481106129f157fe5b6000918252602090912001546001600160a01b03161415612a3d576040805162461bcd60e51b81526020600482015260016024820152600760fb1b604482015290519081900360640190fd5b81600d8481548110612a4b57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506002548114611895576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff16612b05576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff166001811115612b1857fe5b14612b4e576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600190810191829055612b6b9087908790869086614ae0565b60408051632b07b2ff60e21b81526001600160a01b038089166004830152871660248201526044810186905260648101859052905173d6e266d0221a2e7909fb7f9fd45a84d217e909e79163ac1ecbfc916084808301926000929190829003018186803b158015612bdb57600080fd5b505af4158015612bef573d6000803e3d6000fd5b5050505060025481146120f4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b612c3f6128d8565b612c7e576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b6002805460010190819055600354612ca4906201000090046001600160a01b0316614e0a565b6003805462010000600160b01b031916620100006001600160a01b038516021790556002548114611b25576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff16612d52576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff166001811115612d6557fe5b14612d9b576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556003546201000090046001600160a01b03166060612dc3866150bc565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e763122a4aa5878787866040518563ffffffff1660e01b815260040180806020018060200180602001856001600160a01b03166001600160a01b03168152602001848103845288818151815260200191508051906020019060200280838360005b83811015612e50578181015183820152602001612e38565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015612e8f578181015183820152602001612e77565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015612ece578181015183820152602001612eb6565b5050505090500197505050505050505060006040518083038186803b158015612ef657600080fd5b505af4158015612f0a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612f3357600080fd5b8101908080516040519392919084600160201b821115612f5257600080fd5b908301906020820185811115612f6757600080fd5b82518660208202830111600160201b82111715612f8357600080fd5b82525081516020918201928201910280838360005b83811015612fb0578181015183820152602001612f98565b50505050905001604052505050945073d6e266d0221a2e7909fb7f9fd45a84d217e909e763fb29e322876002875181612fe557fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561303b578181015183820152602001613023565b50505050905001935050505060006040518083038186803b15801561305f57600080fd5b505af4158015613073573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561309c57600080fd5b8101908080516040519392919084600160201b8211156130bb57600080fd5b9083019060208201858111156130d057600080fd5b82518660208202830111600160201b821117156130ec57600080fd5b82525081516020918201928201910280838360005b83811015613119578181015183820152602001613101565b505050509050016040525050509050613134818560016151bb565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e7635dabb16e87600287518161315a57fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b838110156131b0578181015183820152602001613198565b50505050905001935050505060006040518083038186803b1580156131d457600080fd5b505af41580156131e8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561321157600080fd5b8101908080516040519392919084600160201b82111561323057600080fd5b90830190602082018581111561324557600080fd5b82518660208202830111600160201b8211171561326157600080fd5b82525081516020918201928201910280838360005b8381101561328e578181015183820152602001613276565b5050505090500160405250505090506132a78185615341565b6132b186866154c1565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e76384c2771e8786600d6040518463ffffffff1660e01b815260040180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561332657818101518382015260200161330e565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561336557818101518382015260200161334d565b5050505090500184810382528581815481526020019150805480156133b357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613395575b5050965050505050505060006040518083038186803b1580156133d557600080fd5b505af41580156133e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561341257600080fd5b8101908080516040519392919084600160201b82111561343157600080fd5b90830190602082018581111561344657600080fd5b82518660208202830111600160201b8211171561346257600080fd5b82525081516020918201928201910280838360005b8381101561348f578181015183820152602001613477565b5050505090500160405250505090506134aa818560006151bb565b50506002548114611dd3576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b600060035460ff16600181111561350357fe5b14613539576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556004805460408051639532b6ab60e01b81523393810184905290516001600160a01b0390921691639532b6ab91602480820192600092909190829003018186803b15801561359157600080fd5b505afa1580156135a5573d6000803e3d6000fd5b505050506135b886828760016000614ae0565b806001600160a01b0316866001600160a01b03167f4260c3d560f20eaba927af72aecb4683ed83dfedd6f5984eb4bff1fb1b04dc8f876040518082815260200191505060405180910390a350600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b60035460ff1681565b600a60209081526000928352604080842090915290825290205481565b600061367982615784565b92915050565b336000908152600c602052604090205460ff166136c7576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b60028054600101908190556136db86614ff5565b6137b27fbe2f4292252fbb88b129dc7717b2f3f74a9afb5b13a2283cac5c056117b002eb60001b8d8d8d8d8d8d8d60405160200180898152602001886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001858152602001846001600160a01b03166001600160a01b0316815260200183815260200182815260200198505050505050505050604051602081830303815290604052805190602001208d878787876157d0565b6137c18c8c8c8c8c8c8c614e78565b6002548114613805576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b505050505050505050505050565b600060035460ff16600181111561382657fe5b1461385c576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190553461389e576040805162461bcd60e51b8152602060048201526002602482015261031360f41b604482015290519081900360640190fd5b6138ae3360003460016000614ae0565b60025481146138f2576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50565b336000908152600c602052604090205460ff1661393d576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff16600181111561395057fe5b14613986576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190556003546201000090046001600160a01b031660606139ae866150bc565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e763fba697ae878787866040518563ffffffff1660e01b815260040180806020018060200180602001856001600160a01b03166001600160a01b03168152602001848103845288818151815260200191508051906020019060200280838360005b83811015613a3b578181015183820152602001613a23565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015613a7a578181015183820152602001613a62565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015613ab9578181015183820152602001613aa1565b5050505090500197505050505050505060006040518083038186803b158015613ae157600080fd5b505af4158015613af5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613b1e57600080fd5b8101908080516040519392919084600160201b821115613b3d57600080fd5b908301906020820185811115613b5257600080fd5b82518660208202830111600160201b82111715613b6e57600080fd5b82525081516020918201928201910280838360005b83811015613b9b578181015183820152602001613b83565b50505050905001604052505050945073d6e266d0221a2e7909fb7f9fd45a84d217e909e76351e82b96876002875181613bd057fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015613c26578181015183820152602001613c0e565b50505050905001935050505060006040518083038186803b158015613c4a57600080fd5b505af4158015613c5e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613c8757600080fd5b8101908080516040519392919084600160201b821115613ca657600080fd5b908301906020820185811115613cbb57600080fd5b82518660208202830111600160201b82111715613cd757600080fd5b82525081516020918201928201910280838360005b83811015613d04578181015183820152602001613cec565b505050509050016040525050509050613d1f818560016151bb565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e76303815e7b876002875181613d4557fe5b046040518363ffffffff1660e01b81526004018080602001838152602001828103825284818151815260200191508051906020019060200280838360005b83811015613d9b578181015183820152602001613d83565b50505050905001935050505060006040518083038186803b158015613dbf57600080fd5b505af4158015613dd3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613dfc57600080fd5b8101908080516040519392919084600160201b821115613e1b57600080fd5b908301906020820185811115613e3057600080fd5b82518660208202830111600160201b82111715613e4c57600080fd5b82525081516020918201928201910280838360005b83811015613e79578181015183820152602001613e61565b505050509050016040525050509050613e928185615341565b613e9c86866154c1565b6134aa86615864565b336000908152600c602052604090205460ff16613eed576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b6002805460010190819055604051638369bbaf60e01b81526060600482019081526064820188905273d6e266d0221a2e7909fb7f9fd45a84d217e909e791638369bbaf918a918a918a918a918a918a91908190602481019060448101906084018a60208b0280828437600083820152601f01601f19169091018581038452888152602090810191508990890280828437600083820152601f01601f19169091018581038352868152602090810191508790870280828437600081840152601f19601f820116905080830192505050995050505050505050505060006040518083038186803b158015613fde57600080fd5b505af4158015613ff2573d6000803e3d6000fd5b50505050600073d6e266d0221a2e7909fb7f9fd45a84d217e909e763c931ac21898987876040518563ffffffff1660e01b81526004018080602001806020018381038352878782818152602001925060200280828437600083820152601f01601f19169091018481038352858152602090810191508690860280828437600081840152601f19601f820116905080830192505050965050505050505060206040518083038186803b1580156140a657600080fd5b505af41580156140ba573d6000803e3d6000fd5b505050506040513d60208110156140d057600080fd5b5051905061417f84846000816140e257fe5b905060200201356001600160a01b0316826080600019901b198b8b600281811061410857fe5b90506020020135168787600181811061411d57fe5b905060200201356001600160a01b031660908d8d600281811061413c57fe5b90506020020135901c8989600481811061415257fe5b905060200201356001600160a01b031660808f8f600181811061417157fe5b90506020020135901c614d0b565b5060025481146141c4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b50505050505050565b6001546001600160a01b031681565b600f6020908152600092835260408084209091529082529020805460019091015482565b6142086128d8565b614247576040805162461bcd60e51b81526020600482018190526024820152600080516020615ad3833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600280546001019081905560055460408051633735486760e11b81526001600160a01b03888116600483015233602483015291519190921691636e6a90ce916044808301926000929190829003018186803b1580156142c757600080fd5b505afa1580156142db573d6000803e3d6000fd5b505050506142e884614e0a565b6001600160a01b038086166000908152600a602090815260408083209387168352929052205461431e908363ffffffff614c4d16565b6001600160a01b038087166000908152600a602081815260408084208986168086529083528185209690965593891683529081528282209382529290925290205461436f908363ffffffff614caa16565b6001600160a01b038086166000908152600a6020908152604080832093881683529290522055600254811461174e576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b60028054600101908190556001600160a01b0389163314614426576040805162461bcd60e51b8152602060048201526002602482015261313160f01b604482015290519081900360640190fd5b60408051600080516020615ab38339815191526020808301919091526001600160a01b03808d1683850152808c166060840152608083018b9052808a1660a084015260c08301899052871660e0830152610100820186905261012080830186905283518084039091018152610140909201835281519181019190912060008181526008909252919020546144e6576040805162461bcd60e51b8152602060048201526002602482015261189960f11b604482015290519081900360640190fd5b60006144fd60065442614caa90919063ffffffff16565b6000838152600e60209081526040918290208390558151838152915192935084927f8f78d3ae5953e6de0b053ccdd0a76139099980dc9e0fb8086f8e1c96edbaa45b9281900390910190a250506002548114611484576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b6005546001600160a01b031681565b600280546001019081905560408051600080516020615ab38339815191526020808301919091526001600160a01b03808d1683850152808c166060840152608083018b9052808a1660a084015260c08301899052871660e083015261010082018690526101208083018690528351808403909101815261014090920183528151918101919091206000818152600e9092529190205480614669576040805162461bcd60e51b8152602060048201526002602482015261313360f01b604482015290519081900360640190fd5b804210156146a3576040805162461bcd60e51b81526020600482015260026024820152610c4d60f21b604482015290519081900360640190fd5b600082815260086020526040902054806146e9576040805162461bcd60e51b8152602060048201526002602482015261313560f01b604482015290519081900360640190fd5b600e6000848152602001908152602001600020600090556147108c84838e89600080614d0b565b60408051828152905184917fa9ef9d74f47971616159b4a658e98048b5b7a83a099ba0901f69ce512b47805d919081900360200190a25050506002548114611484576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b336000908152600c602052604090205460ff166147d5576040805162461bcd60e51b81526020600482015260016024820152603160f81b604482015290519081900360640190fd5b600060035460ff1660018111156147e857fe5b1461481e576040805162461bcd60e51b81526020600482015260016024820152601960f91b604482015290519081900360640190fd5b60028054600101908190558435614861576040805162461bcd60e51b8152602060048201526002602482015261032360f41b604482015290519081900360640190fd5b4260208601351161489e576040805162461bcd60e51b8152602060048201526002602482015261323160f01b604482015290519081900360640190fd5b6148b46001600160a01b03602088013516614e0a565b85356001600160a01b0390811660208801359091161415614901576040805162461bcd60e51b8152602060048201526002602482015261333960f01b604482015290519081900360640190fd5b600061495c876004806020026040519081016040528092919082600460200280828437600092019190915250506040805160808181019092529150899060049083908390808284376000920191909152505088359050614b94565b6000818152600b602052604090205490915060ff16156149a8576040805162461bcd60e51b8152602060048201526002602482015261191960f11b604482015290519081900360640190fd5b6149b56060870135614ff5565b6149d58188356001600160a01b031686602089013560408a0135886157d0565b60608701356001600160a01b0390811660408901359091161415614a36578535604087013510614a31576040805162461bcd60e51b8152602060048201526002602482015261323360f01b604482015290519081900360640190fd5b614a61565b614a616001600160a01b03883581169060608a013516604089013560328a60035b60200201356158f5565b614a836001600160a01b03883581169060408a013516883560308a6003614a57565b6000908152600b60205260409020805460ff1916600117905560025481146120f4576040805162461bcd60e51b815260206004820152601f6024820152600080516020615a93833981519152604482015290519081900360640190fd5b82614aea5761174e565b6001600160a01b038086166000908152600a6020908152604080832093881683529290522054614b20908463ffffffff614caa16565b6001600160a01b038087166000818152600a60209081526040808320948a168084529482529182902094909455805187815293840186905283810185905251919290917f14d4d01c4d5dc621bda40cbf92745f0f6510eb2f5ef6a8f2d026bd4f659e58d49181900360600190a35050505050565b82516020808501516040808701518651878501516060998a015189850151998b015185517f6ba9001457a287c210b728198a424a4222098d7fac48f8c5fb5ab10ef907d3ef818a01526001600160a01b03998a16818801529689169b87019b909b52928716608086015260a085019190915260c084019690965260e08301959095529290931661010084015261012083019390935261014080830194909452805180830390940184526101609091019052815191012090565b600082821115614ca4576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082820183811015614d04576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008681526008602052604090205480614d51576040805162461bcd60e51b8152602060048201526002602482015261199960f11b604482015290519081900360640190fd5b858114614d8a576040805162461bcd60e51b8152602060048201526002602482015261333360f01b604482015290519081900360640190fd5b6000878152600860205260408120556001600160a01b038381169086161415614dc457614dbd818363ffffffff614c4d16565b9050614dd2565b614dd28884846012886158f5565b614de0888683600888614ae0565b600354614e00906201000090046001600160a01b03168484601388614ae0565b5050505050505050565b60408051632f47185360e11b81526001600160a01b0383166004820152905173d6e266d0221a2e7909fb7f9fd45a84d217e909e791635e8e30a6916024808301926000929190829003018186803b158015614e6457600080fd5b505af415801561174e573d6000803e3d6000fd5b60008411614eb2576040805162461bcd60e51b81526020600482015260026024820152610ccd60f21b604482015290519081900360640190fd5b614ebb86614e0a565b614ec98786866009856158f5565b600354614ee9906201000090046001600160a01b03168484601585614ae0565b6000856001600160a01b0316846001600160a01b03161415614f1c57614f15858463ffffffff614c4d16565b9050614f2d565b614f2a8885856014866158f5565b50835b6001600160a01b038616614f78576040516001600160a01b0388169082156108fc029083906000818181858888f19350505050158015614f71573d6000803e3d6000fd5b50506141c4565b6040805163193c114b60e01b81526001600160a01b03808a1660048301528816602482015260448101839052905173d6e266d0221a2e7909fb7f9fd45a84d217e909e79163193c114b916064808301926000929190829003018186803b158015614fe157600080fd5b505af4158015613805573d6000803e3d6000fd5b8061502c576040805162461bcd60e51b8152602060048201526002602482015261333560f01b604482015290519081900360640190fd5b60006150408261010063ffffffff6159a916565b905060006150568361010063ffffffff615a1316565b600083815260096020526040902054600190911b9150808216156150a6576040805162461bcd60e51b8152602060048201526002602482015261199b60f11b604482015290519081900360640190fd5b6000928352600960205260409092209117905550565b805160019060009060ff90849083906150d157fe5b602002602001015116600202820190505b808210156118955782516078906001600160801b039085908590811061510457fe5b602002602001015116901c600014615148576040805162461bcd60e51b8152602060048201526002602482015261066760f31b604482015290519081900360640190fd5b600060386078600019901b1985858151811061516057fe5b602002602001015116901c905061517681615784565b156151af5760786001901b84848151811061518d57fe5b6020026020010151178484815181106151a257fe5b6020026020010181815250505b506002820191506150e2565b825160005b8181101561174e5760008582815181106151d657fe5b6020026020010151905080600014156151ef5750615339565b61527981600a600088866002028151811061520657fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600088866002026001018151811061524257fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054614caa90919063ffffffff16565b600a600087856002028151811061528c57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008785600202600101815181106152c857fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055507f51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a818160f086901b60f885901b17176040518082815260200191505060405180910390a1505b6001016151c0565b815160005b81811015611dd357600084828151811061535c57fe5b60200260200101519050806000141561537557506154b9565b6153ff81600a600087866002028151811061538c57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008786600202600101815181106153c857fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054614c4d90919063ffffffff16565b600a600086856002028151811061541257fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600086856002026001018151811061544e57fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055507f32814a5bdfd1b8c3d76c49c54e043d6e8aa93d197a09e16599b567135503f7488160f884901b176040518082815260200191505060405180910390a1505b600101615346565b815160609060ff9084906000906154d457fe5b602002602001015116604051908082528060200260200182016040528015615506578160200160208202803883390190505b50835190915060019060ff90859060009061551d57fe5b6020026020010151166002028101905060086010600019901b198560008151811061554457fe5b602002602001015116901c600202810190506000845190505b808210156155ea57845160009060ff9087908590811061557957fe5b60200260200101511690506000608087858151811061559457fe5b6020026020010151901c90506155c6818684815181106155b057fe5b6020026020010151614caa90919063ffffffff16565b8583815181106155d257fe5b6020908102919091010152505060019091019061555d565b84516000925060ff90869084906155fd57fe5b60200260200101511690505b8082101561174e57600060786080600019901b1987856002026001018151811061562f57fe5b602002602001015116901c6001149050600085846002028151811061565057fe5b6020026020010151905060008261568b5787516001600160801b0390899060028089020190811061567d57fe5b60200260200101511661569b565b6000828152600860205260409020545b9050600081116156d7576040805162461bcd60e51b8152602060048201526002602482015261333160f01b604482015290519081900360640190fd5b60006156ff8787815181106156e857fe5b602002602001015183614c4d90919063ffffffff16565b905080156157195760008381526008602052604090208190555b838015615724575080155b15615739576000838152600860205260408120555b8361577457600060386078600019901b198b896002026001018151811061575c57fe5b602002602001015116901c905061577281614ff5565b505b5050600190930192506156099050565b6000806157998361010063ffffffff6159a916565b905060006157af8461010063ffffffff615a1316565b60009283526009602052604090922054600190921b90911615159392505050565b60408051631056c68960e01b8152600481018890526001600160a01b038716602482015260ff86166044820152606481018590526084810184905282151560a4820152905173d6e266d0221a2e7909fb7f9fd45a84d217e909e791631056c6899160c4808301926000929190829003018186803b15801561585057600080fd5b505af4158015611a09573d6000803e3d6000fd5b805160009060ff908390839061587657fe5b6020026020010151166002026001019050600060086010600019901b19846000815181106158a057fe5b602002602001015116901c600202820190505b8082101561189557600060386078600019901b198585815181106158d357fe5b602002602001015116901c90506158e981614ff5565b506002820191506158b3565b826158ff5761174e565b6001600160a01b038086166000908152600a6020908152604080832093881683529290522054615935908463ffffffff614c4d16565b6001600160a01b038087166000818152600a60209081526040808320948a168084529482529182902094909455805187815293840186905283810185905251919290917f7b0f7fa8d27ccea2b81f143f956fbe50b379ec2593bac595b664f932237d4e869181900360600190a35050505050565b60008082116159ff576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b6000828481615a0a57fe5b04949350505050565b600081615a67576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b818381615a7057fe5b069392505050565b60405180604001604052806000815260200160008152509056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00f845c83a8f7964bc8dd1a092d28b83573b35be97630a5b8a3b8ae2ae79cd92604f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a265627a7a723158208320f1a86db0d7f110c710dd3181db0600eca41d862c7c9460c632f3e17f7ed964736f6c634300050c0032

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

000000000000000000000000c860598a9a38eff76dbbbe67fdc1b7975c0c17bd000000000000000000000000dad636e070baa6d9484eee6a2452557833862c03

-----Decoded View---------------
Arg [0] : _tokenListAddress (address): 0xc860598A9A38eFf76dbBbE67FDC1b7975c0c17BD
Arg [1] : _spenderListAddress (address): 0xDaD636E070BaA6D9484eEE6A2452557833862C03

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c860598a9a38eff76dbbbe67fdc1b7975c0c17bd
Arg [1] : 000000000000000000000000dad636e070baa6d9484eee6a2452557833862c03


Deployed Bytecode Sourcemap

61282:75486:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81868:553;;8:9:-1;5:2;;;30:1;27;20:12;5:2;81868:553:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;81868:553:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;81868:553:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;81868:553:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;81868:553:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;81868:553:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;81868:553:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;81868:553:0;;-1:-1:-1;81868:553:0;-1:-1:-1;81868:553:0;:::i;67075:60::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;67075:60:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;67075:60:0;;:::i;:::-;;;;;;;;;;;;;;;;62715:107;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62715:107:0;;;:::i;118532:1903::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;118532:1903:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;118532:1903:0;;;;;;;;;;;;:::i;109314:601::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;109314:601:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;109314:601:0;;;;;;;;:::i;99938:922::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99938:922:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;99938:922:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;74729:270::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;74729:270:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;74729:270:0;-1:-1:-1;;;;;74729:270:0;;:::i;72993:267::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;72993:267:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72993:267:0;;:::i;110412:997::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;110412:997:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;110412:997:0;;;;;;;;;;;;;;;;;:::i;115910:1350::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;115910:1350:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;115910:1350:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;115910:1350:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;115910:1350:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;115910:1350:0;;-1:-1:-1;115910:1350:0;-1:-1:-1;115910:1350:0;:::i;77835:144::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;77835:144:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;77835:144:0;;:::i;70580:107::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;70580:107:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;70580:107:0;-1:-1:-1;;;;;70580:107:0;;:::i;:::-;;;;;;;;;;;;;;;;;;66936:28;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66936:28:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66936:28:0;;:::i;:::-;;;;-1:-1:-1;;;;;66936:28:0;;;;;;;;;;;;;;73697:277;;8:9:-1;5:2;;;30:1;27;20:12;5:2;73697:277:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;73697:277:0;;:::i;75121:146::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75121:146:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;75121:146:0;-1:-1:-1;;;;;75121:146:0;;:::i;65962:41::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65962:41:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65962:41:0;;:::i;75888:261::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75888:261:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;75888:261:0;;:::i;65373:28::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65373:28:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63285:106;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63285:106:0;;;:::i;5453:182::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5453:182:0;;;:::i;66841:46::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66841:46:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66841:46:0;-1:-1:-1;;;;;66841:46:0;;:::i;71175:83::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;71175:83:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71175:83:0;;;;:::i;65469:23::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65469:23:0;;;:::i;65846:32::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65846:32:0;;;:::i;66471:45::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66471:45:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66471:45:0;;:::i;74309:269::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;74309:269:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;74309:269:0;-1:-1:-1;;;;;74309:269:0;;:::i;108375:472::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;108375:472:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;108375:472:0;;;;;;;;;;;;;;;;;;;;;;:::i;62165:110::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62165:110:0;;;:::i;65809:30::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65809:30:0;;;:::i;4149:20::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4149:20:0;;;:::i;5007:91::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5007:91:0;;;:::i;72125:98::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;72125:98:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72125:98:0;;;;:::i;65499:26::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65499:26:0;;;:::i;66729:43::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66729:43:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66729:43:0;;:::i;75458:325::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75458:325:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;75458:325:0;;;;;;-1:-1:-1;;;;;75458:325:0;;:::i;79954:564::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;79954:564:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;79954:564:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;72404:148::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;72404:148:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72404:148:0;-1:-1:-1;;;;;72404:148:0;;:::i;94432:1832::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;94432:1832:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;94432:1832:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;94432:1832:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;94432:1832:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;94432:1832:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;94432:1832:0;;;;;;;;-1:-1:-1;94432:1832:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;94432:1832:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;94432:1832:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;94432:1832:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;94432:1832:0;;;;;;;;-1:-1:-1;94432:1832:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;94432:1832:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;94432:1832:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;94432:1832:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;94432:1832:0;;-1:-1:-1;94432:1832:0;;-1:-1:-1;;;;;94432:1832:0:i;80967:399::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;80967:399:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;80967:399:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;80967:399:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;80967:399:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;80967:399:0;;-1:-1:-1;80967:399:0;-1:-1:-1;80967:399:0;:::i;65348:18::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65348:18:0;;;:::i;66593:63::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66593:63:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;66593:63:0;;;;;;;;;;:::i;78135:110::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;78135:110:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;78135:110:0;;:::i;106607:1082::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;106607:1082:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;106607:1082:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;78497:244::-;;;:::i;90034:1573::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;90034:1573:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;90034:1573:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;90034:1573:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;90034:1573:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;90034:1573:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;90034:1573:0;;;;;;;;-1:-1:-1;90034:1573:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;90034:1573:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;90034:1573:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;90034:1573:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;90034:1573:0;;;;;;;;-1:-1:-1;90034:1573:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;90034:1573:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;90034:1573:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;90034:1573:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;90034:1573:0;;-1:-1:-1;90034:1573:0;;-1:-1:-1;;;;;90034:1573:0:i;97868:678::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;97868:678:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;97868:678:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;97868:678:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;97868:678:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;97868:678:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;97868:678:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;97868:678:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;97868:678:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;97868:678:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;97868:678:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;97868:678:0;;-1:-1:-1;97868:678:0;-1:-1:-1;97868:678:0;:::i;4176:27::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4176:27:0;;;:::i;67242:93::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;67242:93:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;67242:93:0;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;5254:104;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5254:104:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5254:104:0;-1:-1:-1;;;;;5254:104:0;;:::i;76790:434::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;76790:434:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;76790:434:0;;;;;;;;;;;;;;;;;;;;;;:::i;101981:1027::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;101981:1027:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;101981:1027:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;65532:30::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65532:30:0;;;:::i;104150:1397::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;104150:1397:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;104150:1397:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;112763:1885::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;112763:1885:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;112763:1885:0;;;;;;;;;;;;;;;;;;;:::i;81868:553::-;70148:12;70139:5;;;;;:21;;;;;;;;70131:35;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;-1:-1:-1;;;;;82173:20:0;;82188:4;82173:20;82169:37;;82197:7;;82169:37;82255:9;;;:32;;;-1:-1:-1;;;82255:32:0;;82234:10;82255:32;;;;;;;;-1:-1:-1;;;;;82255:9:0;;;;:23;;:32;;;;;82216:15;;82255:32;;;;;;;;:9;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;82255:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82255:32:0;;;;82298:60;82315:5;82322:7;82331;63789:4;82356:1;82298:16;:60::i;:::-;82396:7;-1:-1:-1;;;;;82374:39:0;82389:5;-1:-1:-1;;;;;82374:39:0;;82405:7;82374:39;;;;;;;;;;;;;;;;;;7103:1;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;70177:1;81868:553;;;;;;;;:::o;67075:60::-;;;;;;;;;;;;;:::o;62715:107::-;-1:-1:-1;;;;;;;;;;;62715:107:0;:::o;118532:1903::-;7027:13;:18;;7044:1;7027:18;;;;;118855:3;118841:10;;;;:17;;118833:32;;;;;-1:-1:-1;;;118833:32:0;;;;;;;;;;;;-1:-1:-1;;;118833:32:0;;;;;;;;;;;;;;;118876:16;118895:45;118905:10;118895:45;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;118895:45:0;;;;;;;;;;;-1:-1:-1;118917:7:0;;118895:45;;;;118917:7;;118895:45;118917:7;118895:45;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;118926:13:0;;-1:-1:-1;118895:9:0;;-1:-1:-1;118895:45:0:i;:::-;119017:21;;;;:11;:21;;;;;;118876:64;;-1:-1:-1;119017:21:0;;119009:36;;;;;-1:-1:-1;;;119009:36:0;;;;;;;;;;;;-1:-1:-1;;;119009:36:0;;;;;;;;;;;;;;;119131:10;119058:23;119116:26;;;:14;:26;;;;;;119084:16;;119116:26;;119111:66;;-1:-1:-1;119164:10:0;;;;119111:66;119335:10;;;;119316:29;;;119308:44;;;;;-1:-1:-1;;;119308:44:0;;;;;;;;;;;;-1:-1:-1;;;119308:44:0;;;;;;;;;;;;;;;119388:10;;119413:13;;;;-1:-1:-1;;;;;119413:13:0;;;119430;;;;;;;119413:30;119409:136;;;119500:33;:12;119517:15;119500:33;:16;:33;:::i;:::-;119485:48;;119409:136;119564:21;;;;:11;:21;;;;;;;119557:28;;-1:-1:-1;;119557:28:0;;;119598:205;;-1:-1:-1;;;;;119629:13:0;;;;;119666;;;;119705:12;64456:4;119773:7;119781:1;119773:10;;;;;119598:16;:205::i;:::-;119816:201;119847:8;;;;;;;;;-1:-1:-1;;;;;119847:8:0;119870:10;119881:1;119870:13;;;;;;;;;;;-1:-1:-1;;;;;119870:13:0;119912:15;64525:4;119987:7;119995:1;119987:10;;;;;;119816:201;120034:13;;;;-1:-1:-1;;;;;120034:13:0;;;120051;;;;;;;120034:30;120030:398;;120106:23;120132:31;:10;;;;120147:15;120132:14;:31::i;:::-;120106:57;-1:-1:-1;120178:238:0;-1:-1:-1;;;;;120213:13:0;;;;;120254;;;;;120106:57;64593:4;120382:7;120265:1;120382:10;;120178:238;120030:398;;7103:1;;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;118532:1903;;;;;:::o;109314:601::-;7027:13;:18;;7044:1;7027:18;;;;;109537:11;;;;;:56;;-1:-1:-1;109572:10:0;109563:20;;;;:8;:20;;;;;;;;-1:-1:-1;;;;;109563:30:0;;;;;;;;;;109552:41;;;109537:56;109529:71;;;;;-1:-1:-1;;;109529:71:0;;;;;;;;;;;;-1:-1:-1;;;109529:71:0;;;;;;;;;;;;;;;109683:10;109613:43;109659:35;;;:23;:35;;;;;;;;-1:-1:-1;;;;;109659:45:0;;;;;;;;;109755:17;;109747:26;;:3;;:26;:7;:26;:::i;:::-;109717:27;;;:56;;;109784:29;;;109831:76;;;;;;;;;;;;;;;-1:-1:-1;;;;;109831:76:0;;;109848:10;;109831:76;;;;;;;;;7103:1;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;109314:601;;;:::o;99938:922::-;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;70343:20;70329:10;;;;;;;;:34;;;;;;;;70321:48;;;;;-1:-1:-1;;;70321:48:0;;;;;;;;;;;;-1:-1:-1;;;70321:48:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;100385:256;;;-1:-1:-1;;;;;;;;;;;100385:256:0;;;;;;;;-1:-1:-1;;;;;100385:256:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;100385:256:0;;;;;;;100375:267;;;;;100655:197;100439:6;100375:267;100722:24;100460:13;100619:11;7027:13;;100655:7;:197::i;:::-;7103:1;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;70380:1;99938:922;;;;;;;;;:::o;74729:270::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;74809:24;74826:6;74809:16;:24::i;:::-;-1:-1:-1;;;;;74923:22:0;;;;;;:14;:22;;;;;;;;74915:36;;;;;-1:-1:-1;;;74915:36:0;;;;;;;;;;;;-1:-1:-1;;;74915:36:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;74969:22:0;;;;;;:14;:22;;;;;74962:29;;-1:-1:-1;;74962:29:0;;;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;4910:1;74729:270;:::o;72993:267::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;64776:6;73180:31;;;73172:45;;;;;-1:-1:-1;;;73172:45:0;;;;;;;;;;;;-1:-1:-1;;;73172:45:0;;;;;;;;;;;;;;;73228:15;:24;;;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;110412:997;7027:13;:18;;7044:1;7027:18;;;;;110588:42;;:::i;:::-;-1:-1:-1;;;;;;110633:36:0;;;;;;;:23;:36;;;;;;;;:46;;;;;;;;;;;;110588:91;;;;;;;;;;;;;;;;;;;;;110762:47;;;;;-1:-1:-1;;;110762:47:0;;;;;;;;;;;;-1:-1:-1;;;110762:47:0;;;;;;;;;;;;;;;110909:12;:27;;;110902:3;:34;;110894:49;;;;;-1:-1:-1;;;110894:49:0;;;;;;;;;;;;-1:-1:-1;;;110894:49:0;;;;;;;;;;;;;;;111053:19;;:30;;111045:45;;;;;-1:-1:-1;;;111045:45:0;;;;;;;;;;;;-1:-1:-1;;;111045:45:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;111110:36:0;;;;;;;:23;:36;;;;;;;;:46;;;;;;;;;;;111103:53;;;;;;;;111167:174;;111134:11;;;;111147:8;;111266:7;;111110:36;;111167:9;:174::i;:::-;111383:8;-1:-1:-1;;;;;111357:44:0;111370:11;-1:-1:-1;;;;;111357:44:0;;111393:7;111357:44;;;;;;;;;;;;;;;;;;7103:1;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;110412:997;;;;:::o;115910:1350::-;7027:13;:18;;7044:1;7027:18;;;;;63652:2;116203:42;;;116195:57;;;;;-1:-1:-1;;;116195:57:0;;;;;;;;;;;;-1:-1:-1;;;116195:57:0;;;;;;;;;;;;;;;116265:16;116284:45;116294:10;116284:45;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;116284:45:0;;;;;;;;;;;-1:-1:-1;116306:7:0;;116284:45;;;;116306:7;;116284:45;116306:7;116284:45;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;116315:13:0;;-1:-1:-1;116284:9:0;;-1:-1:-1;116284:45:0:i;:::-;116407:21;;;;:11;:21;;;;;;116265:64;;-1:-1:-1;116407:21:0;;116399:36;;;;;-1:-1:-1;;;116399:36:0;;;;;;;;;;;;-1:-1:-1;;;116399:36:0;;;;;;;;;;;;;;;116586:13;116539:43;116563:17;116570:9;;116563:17;;;;;30:3:-1;22:6;14;1:33;116563:17:0;;45:16:-1;;;-1:-1;116563:17:0;;-1:-1:-1;116563:17:0;;-1:-1:-1;;116563:17:0;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;116563:17:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;116563:17:0;116546:35;;;116563:17;116546:35;;;;;;;;;26:21:-1;;;22:32;;6:49;;116546:35:0;;;;;;;116539:43;;116546:35;;;;116539:43;;;;;116546:35;116539:43;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;116539:43:0;;;;;;;-1:-1:-1;263:2;;-1:-1;;116539:43:0;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;116539:43:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;116539:43:0;:60;116531:75;;;;;-1:-1:-1;;;116531:75:0;;;;;;;;;;;;-1:-1:-1;;;116531:75:0;;;;;;;;;;;;;;;116640:10;;116665:13;;;;-1:-1:-1;;;;;116665:13:0;;;116682;;;;;;;116665:30;116661:127;;;116750:26;:10;116765;;;;116750:26;:14;:26;:::i;:::-;116737:39;;116661:127;116807:21;;;;:11;:21;;;;;;;;;116800:28;;-1:-1:-1;;116800:28:0;;;116841:196;;-1:-1:-1;;;;;116872:13:0;;;;;;;116909;;;;;116948:10;64327:4;117007:7;117015:1;117007:10;;116841:196;117050:202;117081:8;;;;;;;;;-1:-1:-1;;;;;117081:8:0;117104:10;117115:1;117104:13;;;;;;;;;;;-1:-1:-1;;;;;117104:13:0;117146:7;117154:1;117146:10;;;;;;;;;;;64389:4;117222:7;117230:1;117222:10;;117050:202;7103:1;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;115910:1350;;;;;;:::o;77835:144::-;7027:13;:18;;7044:1;7027:18;;;;;77903:11;;:39;;;-1:-1:-1;;;77903:39:0;;77931:10;77903:39;;;;;;-1:-1:-1;;;;;77903:11:0;;;;:27;;:39;;;;;7027:13;;77903:39;;;;;;;;:11;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;77903:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77903:39:0;;;;77953:18;77964:6;77953:10;:18::i;:::-;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;70580:107;-1:-1:-1;;;;;70658:21:0;70634:4;70658:21;;;:14;:21;;;;;;;;;70580:107::o;66936:28::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66936:28:0;;-1:-1:-1;66936:28:0;:::o;73697:277::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;64714:6;73890:33;;;73882:47;;;;;-1:-1:-1;;;73882:47:0;;;;;;;;;;;;-1:-1:-1;;;73882:47:0;;;;;;;;;;;;;;;73940:17;:26;;;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;75121:146;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;75202:23;75219:5;75202:16;:23::i;:::-;75236:11;27:10:-1;;39:1;23:18;;45:23;;-1:-1;75236:23:0;;;;;;;;-1:-1:-1;;;;;;75236:23:0;-1:-1:-1;;;;;75236:23:0;;;;;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;65962:41;;;;;;;;;;;;;:::o;75888:261::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;76065:11;:19;;7027:13;;76065:11;76077:6;;76065:19;;;;;;;;;;;;;;;;-1:-1:-1;;;;;76065:19:0;:33;;76057:47;;;;;-1:-1:-1;;;76057:47:0;;;;;;;;;;;;-1:-1:-1;;;76057:47:0;;;;;;;;;;;;;;;76122:11;76134:6;76122:19;;;;;;;;;;;;;;;;;76115:26;;-1:-1:-1;;;;;;76115:26:0;;;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;65373:28;;;;;;;;;:::o;63285:106::-;63325:66;63285:106;:::o;5453:182::-;4687:12;;-1:-1:-1;;;;;4687:12:0;4673:10;:26;4665:35;;;;;;5547:12;;;5540:5;;5519:41;;-1:-1:-1;;;;;5547:12:0;;;;5540:5;;;;5519:41;;;5579:12;;;;5571:20;;-1:-1:-1;;;;;;5571:20:0;;;-1:-1:-1;;;;;5579:12:0;;5571:20;;;;5602:25;;;5453:182::o;66841:46::-;;;;;;;;;;;;;;;:::o;71175:83::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;;;71241:5;:14;;71249:6;;-1:-1:-1;;71241:14:0;;;;71249:6;71241:14;;;;;;;;;;;;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;65469:23;;;;;;-1:-1:-1;;;;;65469:23:0;;:::o;65846:32::-;;;;:::o;66471:45::-;;;;;;;;;;;;;:::o;74309:269::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;74386:24;74403:6;74386:16;:24::i;:::-;-1:-1:-1;;;;;74502:22:0;;;;;;:14;:22;;;;;;;;74501:23;74493:37;;;;;-1:-1:-1;;;74493:37:0;;;;;;;;;;;;-1:-1:-1;;;74493:37:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;74541:22:0;;;;;;:14;:22;;;;;:29;;-1:-1:-1;;74541:29:0;74566:4;74541:29;;;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;108375:472;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;70343:20;70329:10;;;;;;;;:34;;;;;;;;70321:48;;;;;-1:-1:-1;;;70321:48:0;;;;;;;;;;;;-1:-1:-1;;;70321:48:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;108629;108640:6;108629:10;:18::i;:::-;108660:179;108684:11;108710;108736:8;108759:7;108789:1;108806;108822:6;108660:9;:179::i;:::-;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;62165:110;62209:66;62165:110;:::o;65809:30::-;;;;:::o;4149:20::-;;;-1:-1:-1;;;;;4149:20:0;;:::o;5007:91::-;5047:4;5085:5;-1:-1:-1;;;;;5085:5:0;5071:10;:19;;5007:91::o;72125:98::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;;;72201:10;:19;;72214:6;;-1:-1:-1;;72201:19:0;;;;;;72214:6;;72201:19;;;;;;65499:26;;;-1:-1:-1;;;;;65499:26:0;;:::o;66729:43::-;;;;;;;;;;;;;;;:::o;75458:325::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;75558:23;75575:5;75558:16;:23::i;:::-;75729:1;-1:-1:-1;;;;;75698:33:0;:11;75710:6;75698:19;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;75698:19:0;:33;;75690:47;;;;;-1:-1:-1;;;75690:47:0;;;;;;;;;;;;-1:-1:-1;;;75690:47:0;;;;;;;;;;;;;;;75770:5;75748:11;75760:6;75748:19;;;;;;;;;;;;;;;;:27;;;;;-1:-1:-1;;;;;75748:27:0;;;;;-1:-1:-1;;;;;75748:27:0;;;;;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;79954:564;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;70148:12;70139:5;;;;;:21;;;;;;;;70131:35;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;;;80219:150;;80250:5;;80270:8;;80293:15;;80352:6;80219:16;:150::i;:::-;80382:128;;;-1:-1:-1;;;80382:128:0;;-1:-1:-1;;;;;80382:128:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;;:22;;:128;;;;;-1:-1:-1;;80382:128:0;;;;;;;:5;:128;;;5:2:-1;;;;30:1;27;20:12;5:2;80382:128:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;80382:128:0;;;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;72404:148;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;72504:8;;72487:26;;72504:8;;;-1:-1:-1;;;;;72504:8:0;72487:16;:26::i;:::-;72524:8;:20;;-1:-1:-1;;;;;;72524:20:0;;-1:-1:-1;;;;;72524:20:0;;;;;;:8;7139:13;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;94432:1832;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;70148:12;70139:5;;;;;:21;;;;;;;;70131:35;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;94771:8;;;;;-1:-1:-1;;;;;94771:8:0;94861:27;94977:31;95000:7;94977:22;:31::i;:::-;95266:5;:27;95308:7;95330;95352:10;95377:15;95266:137;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;95266:137:0;-1:-1:-1;;;;;95266:137:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95266:137:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95266:137:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95266:137:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;95266:137:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;95266:137:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;95266:137:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;95266:137:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;95266:137:0;;421:4:-1;412:14;;;;95266:137:0;;;;;412:14:-1;95266:137:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95266:137:0;;;;;;;;;;;95256:147;;95429:5;:37;95467:7;95496:1;95476:10;:17;:21;;;;;;95429:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95429:69:0;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;95429:69:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;95429:69:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;95429:69:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;95429:69:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;95429:69:0;;421:4:-1;412:14;;;;95429:69:0;;;;;412:14:-1;95429:69:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95429:69:0;;;;;;;;;;;95416:82;;95509:45;95528:10;95540;95552:1;95509:18;:45::i;:::-;95580:5;:37;95618:7;95647:1;95627:10;:17;:21;;;;;;95580:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95580:69:0;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;95580:69:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;95580:69:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;95580:69:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;95580:69:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;95580:69:0;;421:4:-1;412:14;;;;95580:69:0;;;;;412:14:-1;95580:69:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;95580:69:0;;;;;;;;;;;95567:82;;95660:42;95679:10;95691;95660:18;:42::i;:::-;95897:33;95913:7;95922;95897:15;:33::i;:::-;96090:5;:26;96131:7;96153:10;96178:11;96090:110;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;96090:110:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;96090:110:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;96090:110:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;96090:110:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;96090:110:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;96090:110:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;96090:110:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;96090:110:0;;421:4:-1;412:14;;;;96090:110:0;;;;;412:14:-1;96090:110:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;96090:110:0;;;;;;;;;;;96077:123;;96211:45;96230:10;96242;96254:1;96211:18;:45::i;:::-;7103:1;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;80967:399;70148:12;70139:5;;;;;:21;;;;;;;;70131:35;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;81201:9;;;:32;;;-1:-1:-1;;;81201:32:0;;81180:10;81201:32;;;;;;;;-1:-1:-1;;;;;81201:9:0;;;;:23;;:32;;;;;7027:13;;81201:32;;;;;;;;:9;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;81201:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;81201:32:0;;;;81244:60;81261:5;81268:7;81277;63789:4;81302:1;81244:16;:60::i;:::-;81341:7;-1:-1:-1;;;;;81320:38:0;81334:5;-1:-1:-1;;;;;81320:38:0;;81350:7;81320:38;;;;;;;;;;;;;;;;;;7103:1;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;65348:18;;;;;;:::o;66593:63::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;78135:110::-;78194:4;78218:19;78230:6;78218:11;:19::i;:::-;78211:26;78135:110;-1:-1:-1;;78135:110:0:o;106607:1082::-;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;107013;107024:6;107013:10;:18::i;:::-;107044:429;62209:66;107116:17;;107152:11;107182:17;107218:8;107245:7;107271:11;107301:10;107330:6;107087:264;;;;;;;;;;;-1:-1:-1;;;;;107087:264:0;-1:-1:-1;;;;;107087:264:0;;;;;;-1:-1:-1;;;;;107087:264:0;-1:-1:-1;;;;;107087:264:0;;;;;;-1:-1:-1;;;;;107087:264:0;-1:-1:-1;;;;;107087:264:0;;;;;;;;;;;-1:-1:-1;;;;;107087:264:0;-1:-1:-1;;;;;107087:264:0;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;107087:264:0;;;107077:275;;;;;;107367:11;107393:2;107410;107427;107444:18;107044;:429::i;:::-;107486:195;107510:11;107536:17;107568:8;107591:7;107613:11;107639:10;107664:6;107486:9;:195::i;:::-;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;70011:1;106607:1082;;;;;;;;;;;:::o;78497:244::-;70148:12;70139:5;;;;;:21;;;;;;;;70131:35;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;78632:9;78624:28;;;;;-1:-1:-1;;;78624:28:0;;;;;;;;;;;;-1:-1:-1;;;78624:28:0;;;;;;;;;;;;;;;78663:70;78680:10;63542:1;78704:9;63789:4;78731:1;78663:16;:70::i;:::-;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;70177:1;78497:244::o;90034:1573::-;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;70148:12;70139:5;;;;;:21;;;;;;;;70131:35;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;90366:8;;;;;-1:-1:-1;;;;;90366:8:0;90456:27;90572:31;90595:7;90572:22;:31::i;:::-;90847:5;:20;90882:7;90904;90926:10;90951:15;90847:130;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90847:130:0;-1:-1:-1;;;;;90847:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;90847:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;90847:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;90847:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;90847:130:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;90847:130:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;90847:130:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;90847:130:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;90847:130:0;;421:4:-1;412:14;;;;90847:130:0;;;;;412:14:-1;90847:130:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;90847:130:0;;;;;;;;;;;90837:140;;91003:5;:30;91034:7;91063:1;91043:10;:17;:21;;;;;;91003:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;91003:62:0;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;91003:62:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;91003:62:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;91003:62:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;91003:62:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;91003:62:0;;421:4:-1;412:14;;;;91003:62:0;;;;;412:14:-1;91003:62:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;91003:62:0;;;;;;;;;;;90990:75;;91076:45;91095:10;91107;91119:1;91076:18;:45::i;:::-;91147:5;:30;91178:7;91207:1;91187:10;:17;:21;;;;;;91147:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;91147:62:0;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;91147:62:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;91147:62:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;91147:62:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;91147:62:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;91147:62:0;;421:4:-1;412:14;;;;91147:62:0;;;;;412:14:-1;91147:62:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;91147:62:0;;;;;;;;;;;91134:75;;91220:42;91239:10;91251;91220:18;:42::i;:::-;91457:33;91473:7;91482;91457:15;:33::i;:::-;91574:25;91591:7;91574:16;:25::i;97868:678::-;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;98080:50;;-1:-1:-1;;;98080:50:0;;;;;;;;;;;;;;;:5;;:20;;98101:7;;;;98110;;;;98119:10;;;;98080:50;;;;;;;;;;;;;98101:7;98080:50;;;;98101:7;98080:50;1:33:-1;99:1;81:16;;;74:27;137:4;117:14;-1:-1;;113:30;157:16;;;98080:50:0;;;;;;;;;;;;;-1:-1:-1;98080:50:0;;;;;;;1:33:-1;99:1;81:16;;;74:27;137:4;117:14;-1:-1;;113:30;157:16;;;98080:50:0;;;;;;;;;;;;;-1:-1:-1;98080:50:0;;;;;;;1:33:-1;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;98080:50:0;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;98080:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;98080:50:0;;;;98141:17;98161:5;:15;98177:7;;98186:10;;98161:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;137:4;117:14;-1:-1;;113:30;157:16;;;98161:36:0;;;;;;;;;;;;;-1:-1:-1;98161:36:0;;;;;;;1:33:-1;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;98161:36:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;98161:36:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;98161:36:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;98161:36:0;;-1:-1:-1;98208:330:0;98230:10;;98241:1;98230:13;;;;;;;;;;;-1:-1:-1;;;;;98230:13:0;98267:9;65209:3;65203:1;65194:11;:18;;65192:21;98291:7;;98299:1;98291:10;;;;;;;;;;;;;:20;98353:10;;98364:1;98353:13;;;;;;;;;;;;;-1:-1:-1;;;;;98353:13:0;98411:3;98397:7;;98405:1;98397:10;;;;;;;;;;;;;:17;;98443:10;;98454:1;98443:13;;;;;;;;;;;;;-1:-1:-1;;;;;98443:13:0;98505:3;98491:7;;98499:1;98491:10;;;;;;;;;;;;;:17;;98208:7;:330::i;:::-;7103:1;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;;70011:1;97868:678;;;;;;:::o;4176:27::-;;;-1:-1:-1;;;;;4176:27:0;;:::o;67242:93::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5254:104::-;4853:9;:7;:9::i;:::-;4845:54;;;;;-1:-1:-1;;;4845:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4845:54:0;;;;;;;;;;;;;;;5327:12;:23;;-1:-1:-1;;;;;;5327:23:0;-1:-1:-1;;;;;5327:23:0;;;;;;;;;;5254:104::o;76790:434::-;7027:13;:18;;7044:1;7027:18;;;;;76971:11;;:59;;;-1:-1:-1;;;76971:59:0;;-1:-1:-1;;;;;76971:59:0;;;;;;;77019:10;76971:59;;;;;;:11;;;;;:40;;:59;;;;;7027:13;;76971:59;;;;;;;:11;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;76971:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;76971:59:0;;;;77043:21;77060:3;77043:16;:21::i;:::-;-1:-1:-1;;;;;77105:15:0;;;;;;;:8;:15;;;;;;;;:25;;;;;;;;;;:38;;77135:7;77105:38;:29;:38;:::i;:::-;-1:-1:-1;;;;;77077:15:0;;;;;;;:8;:15;;;;;;;;:25;;;;;;;;;;;;:66;;;;77180:13;;;;;;;;;;;:23;;;;;;;;;;:36;;77208:7;77180:36;:27;:36;:::i;:::-;-1:-1:-1;;;;;77154:13:0;;;;;;;:8;:13;;;;;;;;:23;;;;;;;;;:62;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;101981:1027;7027:13;:18;;7044:1;7027:18;;;;;-1:-1:-1;;;;;102376:20:0;;102386:10;102376:20;102368:35;;;;;-1:-1:-1;;;102368:35:0;;;;;;;;;;;;-1:-1:-1;;;102368:35:0;;;;;;;;;;;;;;;102446:256;;;-1:-1:-1;;;;;;;;;;;102446:256:0;;;;;;;;-1:-1:-1;;;;;102446:256:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;102446:256:0;;;;;;102436:267;;;;;;;;;102416:17;102790;;;:6;:17;;;;;;;102782:36;;;;;-1:-1:-1;;;102782:36:0;;;;;;;;;;;;-1:-1:-1;;;102782:36:0;;;;;;;;;;;;;;;102831:21;102855:24;102863:15;;102855:3;:7;;:24;;;;:::i;:::-;102890:36;;;;:25;:36;;;;;;;;;:52;;;102960:40;;;;;;;102831:48;;-1:-1:-1;102916:9:0;;102960:40;;;;;;;;;;7103:1;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;65532:30;;;-1:-1:-1;;;;;65532:30:0;;:::o;104150:1397::-;7027:13;:18;;7044:1;7027:18;;;;;104501:256;;;-1:-1:-1;;;;;;;;;;;104501:256:0;;;;;;;;-1:-1:-1;;;;;104501:256:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;104501:256:0;;;;;;104491:267;;;;;;;;;7027:13;104795:36;;;:25;:36;;;;;;;104920:18;104912:33;;;;;-1:-1:-1;;;104912:33:0;;;;;;;;;;;;-1:-1:-1;;;104912:33:0;;;;;;;;;;;;;;;105045:13;105038:3;:20;;105030:35;;;;;-1:-1:-1;;;105030:35:0;;;;;;;;;;;;-1:-1:-1;;;105030:35:0;;;;;;;;;;;;;;;105078:23;105104:17;;;:6;:17;;;;;;105202:19;105194:34;;;;;-1:-1:-1;;;105194:34:0;;;;;;;;;;;;-1:-1:-1;;;105194:34:0;;;;;;;;;;;;;;;105248:25;:36;105274:9;105248:36;;;;;;;;;;;105241:43;;;105295:188;105317:6;105338:9;105362:15;105392:13;105420:11;105454:1;105471;105295:7;:188::i;:::-;105501:38;;;;;;;;105512:9;;105501:38;;;;;;;;;;7103:1;;;7139:13;;7123:12;:29;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;112763:1885;69983:10;69968:26;;;;:14;:26;;;;;;;;69960:40;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;-1:-1:-1;;;69960:40:0;;;;;;;;;;;;;;;70148:12;70139:5;;;;;:21;;;;;;;;70131:35;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;-1:-1:-1;;;70131:35:0;;;;;;;;;;;;;;;7027:13;:18;;7044:1;7027:18;;;;;113127:10;;113119:29;;;;;-1:-1:-1;;;113119:29:0;;;;;;;;;;;;-1:-1:-1;;;113119:29:0;;;;;;;;;;;;;;;113250:3;113237:10;;;;:16;113229:31;;;;;-1:-1:-1;;;113229:31:0;;;;;;;;;;;;-1:-1:-1;;;113229:31:0;;;;;;;;;;;;;;;113271;-1:-1:-1;;;;;113288:13:0;;;;;113271:16;:31::i;:::-;113398:13;;-1:-1:-1;;;;;113398:13:0;;;113415;;;;;;;113398:30;;113390:45;;;;;-1:-1:-1;;;113390:45:0;;;;;;;;;;;;-1:-1:-1;;;113390:45:0;;;;;;;;;;;;;;;113448:16;113467:42;113477:10;113467:42;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;113467:42:0;;;;;;;;;;;-1:-1:-1;113489:7:0;;113467:42;;;;113489:7;;113467:42;113489:7;113467:42;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;113498:10:0;;;-1:-1:-1;113467:9:0;:42::i;:::-;113595:21;;;;:11;:21;;;;;;113448:61;;-1:-1:-1;113595:21:0;;113594:22;113586:37;;;;;-1:-1:-1;;;113586:37:0;;;;;;;;;;;;-1:-1:-1;;;113586:37:0;;;;;;;;;;;;;;;113636:22;113647:10;;;;113636;:22::i;:::-;113671:204;113704:8;113727:13;;-1:-1:-1;;;;;113727:13:0;113769:2;113786:10;;;;113816;;;;113846:18;113671;:204::i;:::-;113892:13;;;;-1:-1:-1;;;;;113892:13:0;;;113909;;;;;;;113892:30;113888:496;;;114063:10;;114050;;;;:23;114042:38;;;;;-1:-1:-1;;;114042:38:0;;;;;;;;;;;;-1:-1:-1;;;114042:38:0;;;;;;;;;;;;;;;113888:496;;;114135:237;-1:-1:-1;;;;;114170:13:0;;;;;114211;;;;;114257:10;;;;64269:4;114257:10;114346:1;114338:10;;;;;114135:16;:237::i;:::-;114396:203;-1:-1:-1;;;;;114427:13:0;;;;;114464;;;;;114503:10;;64210:4;114503:10;114577:1;114569:10;;114396:203;114612:21;;;;:11;:21;;;;;:28;;-1:-1:-1;;114612:28:0;114636:4;114612:28;;;7139:13;;7123:29;;7115:73;;;;;-1:-1:-1;;;7115:73:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;7115:73:0;;;;;;;;;;;;;;132577:467;132779:12;132775:29;;132795:7;;132775:29;-1:-1:-1;;;;;132842:15:0;;;;;;;:8;:15;;;;;;;;:25;;;;;;;;;;:38;;132872:7;132842:38;:29;:38;:::i;:::-;-1:-1:-1;;;;;132814:15:0;;;;;;;:8;:15;;;;;;;;:25;;;;;;;;;;;;;:66;;;;132898:138;;;;;;;;;;;;;;;;;;132814:25;;:15;;132898:138;;;;;;;;;132577:467;;;;;:::o;128268:627::-;128545:13;;;128582;;;;128619;;;;;128658:10;;128737;;;;128776:13;;;;;128818:10;;;;128856;;;;128492:394;;63325:66;128492:394;;;;-1:-1:-1;;;;;128492:394:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;128492:394:0;;;;;;128482:405;;;;;;128268:627::o;1359:184::-;1417:7;1450:1;1445;:6;;1437:49;;;;;-1:-1:-1;;;1437:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1509:5:0;;;1359:184::o;903:181::-;961:7;993:5;;;1017:6;;;;1009:46;;;;;-1:-1:-1;;;1009:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;1075:1;903:181;-1:-1:-1;;;903:181:0:o;124313:1412::-;124600:20;124623:18;;;:6;:18;;;;;;124736:16;124728:31;;;;;-1:-1:-1;;;124728:31:0;;;;;;;;;;;;-1:-1:-1;;;124728:31:0;;;;;;;;;;;;;;;124912:24;124896:12;:40;124888:55;;;;;-1:-1:-1;;;124888:55:0;;;;;;;;;;;;-1:-1:-1;;;124888:55:0;;;;;;;;;;;;;;;124963:18;;;;:6;:18;;;;;124956:25;-1:-1:-1;;;;;124998:34:0;;;;;;;124994:347;;;125064:34;:12;125081:16;125064:34;:16;:34;:::i;:::-;125049:49;;124994:347;;;125131:198;125166:6;125191:17;125227:16;64089:4;125303:11;125131:16;:198::i;:::-;125353:157;125384:6;125405:13;125433:12;64028:4;125488:11;125353:16;:157::i;:::-;125554:8;;125523:194;;125554:8;;;-1:-1:-1;;;;;125554:8:0;125577:17;125609:16;64153:4;125680:11;125523:16;:194::i;:::-;124313:1412;;;;;;;;:::o;134098:107::-;134166:31;;;-1:-1:-1;;;134166:31:0;;-1:-1:-1;;;;;134166:31:0;;;;;;;;:5;;:21;;:31;;;;;-1:-1:-1;;134166:31:0;;;;;;;:5;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;134166:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;126078:1419:0;126430:1;126420:7;:11;126412:26;;;;;-1:-1:-1;;;126412:26:0;;;;;;;;;;;;-1:-1:-1;;;126412:26:0;;;;;;;;;;;;;;;126451:35;126468:17;126451:16;:35::i;:::-;126499:149;126530:11;126556:8;126579:7;63845:4;126631:6;126499:16;:149::i;:::-;126692:8;;126661:164;;126692:8;;;-1:-1:-1;;;;;126692:8:0;126715:11;126741:10;63974:4;126808:6;126661:16;:164::i;:::-;126838:22;126892:8;-1:-1:-1;;;;;126877:23:0;:11;-1:-1:-1;;;;;126877:23:0;;126873:356;;;126934:23;:7;126946:10;126934:23;:11;:23;:::i;:::-;126917:40;;126873:356;;;126990:188;127025:11;127055;127085:10;63908:4;127157:6;126990:16;:188::i;:::-;-1:-1:-1;127210:7:0;126873:356;-1:-1:-1;;;;;127245:22:0;;127241:118;;127284:42;;-1:-1:-1;;;;;127284:26:0;;;:42;;;;;127311:14;;127284:42;;;;127311:14;127284:26;:42;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;127284:42:0;127341:7;;;127241:118;127371;;;-1:-1:-1;;;127371:118:0;;-1:-1:-1;;;;;127371:118:0;;;;;;;;;;;;;;;;;;;;;:5;;:23;;:118;;;;;-1:-1:-1;;127371:118:0;;;;;;;:5;:118;;;5:2:-1;;;;30:1;27;20:12;5:2;127371:118:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;130530:466:0;130653:11;130645:26;;;;;-1:-1:-1;;;130645:26:0;;;;;;;;;;;;-1:-1:-1;;;130645:26:0;;;;;;;;;;;;;;;130684:16;130703:15;:6;130714:3;130703:15;:10;:15;:::i;:::-;130684:34;-1:-1:-1;130729:18:0;130755:15;:6;130766:3;130755:15;:10;:15;:::i;:::-;130781:12;130796:20;;;:10;:20;;;;;;130750:1;:20;;;;-1:-1:-1;130906:17:0;;;:22;130898:37;;;;;-1:-1:-1;;;130898:37:0;;;;;;;;;;;;-1:-1:-1;;;130898:37:0;;;;;;;;;;;;;;;130948:20;;;;:10;:20;;;;;;130971:17;;130948:40;;-1:-1:-1;130530:466:0:o;120600:554::-;120755:10;;120694:1;;120682:9;;64824:19;;120755:7;;120682:9;;120755:10;;;;;;;;;;:18;120777:1;120754:24;120750:1;:28;120736:42;;120815:332;120826:3;120822:1;:7;120815:332;;;120915:10;;120940:3;;-1:-1:-1;;;;;65192:21:0;120915:7;;120923:1;;120915:10;;;;;;;;;;;;:20;120914:29;;120948:1;120913:36;120905:51;;;;;-1:-1:-1;;;120905:51:0;;;;;;;;;;;;-1:-1:-1;;;120905:51:0;;;;;;;;;;;;;;;120973:13;121015:2;65146:3;65140:1;65131:11;:18;;65129:21;120990:7;120998:1;120990:10;;;;;;;;;;;;;;:20;120989:28;;120973:44;;121036:18;121048:5;121036:11;:18::i;:::-;121032:104;;;121116:3;121110:1;121102:17;;121088:7;121096:1;121088:10;;;;;;;;;;;;;;:32;121075:7;121083:1;121075:10;;;;;;;;;;;;;:45;;;;;121032:104;120815:332;120836:1;120831:6;;;;120815:332;;134989:586;135174:18;;135160:11;135205:363;135228:3;135224:1;:7;135205:363;;;135253:17;135273:11;135285:1;135273:14;;;;;;;;;;;;;;135253:34;;135306:9;135319:1;135306:14;135302:33;;;135324:8;;;135302:33;135417:65;135472:9;135417:8;:27;135426:10;135437:1;135441;135437:5;135426:17;;;;;;;;;;;;;;-1:-1:-1;;;;;135417:27:0;-1:-1:-1;;;;;135417:27:0;;;;;;;;;;;;:50;135445:10;135456:1;135460;135456:5;135464:1;135456:9;135445:21;;;;;;;;;;;;;;-1:-1:-1;;;;;135417:50:0;-1:-1:-1;;;;;135417:50:0;;;;;;;;;;;;;:54;;:65;;;;:::i;:::-;135351:8;:27;135360:10;135371:1;135375;135371:5;135360:17;;;;;;;;;;;;;;-1:-1:-1;;;;;135351:27:0;-1:-1:-1;;;;;135351:27:0;;;;;;;;;;;;:50;135379:10;135390:1;135394;135390:5;135398:1;135390:9;135379:21;;;;;;;;;;;;;;-1:-1:-1;;;;;135351:50:0;-1:-1:-1;;;;;135351:50:0;;;;;;;;;;;;:131;;;;135504:52;135546:9;135539:3;135528:7;:14;;135520:3;135515:1;:8;;135514:29;:41;135504:52;;;;;;;;;;;;;;;;;;135205:363;;135233:3;;135205:363;;136228:537;136387:18;;136373:11;136416:342;136439:3;136435:1;:7;136416:342;;;136464:17;136484:11;136496:1;136484:14;;;;;;;;;;;;;;136464:34;;136517:9;136530:1;136517:14;136513:33;;;136535:8;;;136513:33;136628:65;136683:9;136628:8;:27;136637:10;136648:1;136652;136648:5;136637:17;;;;;;;;;;;;;;-1:-1:-1;;;;;136628:27:0;-1:-1:-1;;;;;136628:27:0;;;;;;;;;;;;:50;136656:10;136667:1;136671;136667:5;136675:1;136667:9;136656:21;;;;;;;;;;;;;;-1:-1:-1;;;;;136628:50:0;-1:-1:-1;;;;;136628:50:0;;;;;;;;;;;;;:54;;:65;;;;:::i;:::-;136562:8;:27;136571:10;136582:1;136586;136582:5;136571:17;;;;;;;;;;;;;;-1:-1:-1;;;;;136562:27:0;-1:-1:-1;;;;;136562:27:0;;;;;;;;;;;;:50;136590:10;136601:1;136605;136601:5;136609:1;136601:9;136590:21;;;;;;;;;;;;;;-1:-1:-1;;;;;136562:50:0;-1:-1:-1;;;;;136562:50:0;;;;;;;;;;;;:131;;;;136715:31;136736:9;136730:3;136725:1;:8;;:20;136715:31;;;;;;;;;;;;;;;;;;136416:342;;136444:3;;136416:342;;121487:1761;121721:10;;121675:29;;64824:19;;121721:7;;64835:1;;121721:10;;;;;;;;;;:18;121707:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;121707:33:0;-1:-1:-1;121814:10:0;;121675:65;;-1:-1:-1;121765:1:0;;64824:19;;121814:7;;121753:9;;121814:10;;;;;;;;;;:18;121836:1;121813:24;121808:29;;;;121909:1;64901:2;64895:1;64886:11;:17;;64884:20;121885:7;121893:1;121885:10;;;;;;;;;;;;;;:19;121884:26;;121914:1;121883:32;121878:37;;;;121928:11;121942:7;:14;121928:28;;121994:223;122006:3;122002:1;:7;121994:223;;;122052:10;;122031:18;;64824:19;;122052:7;;122060:1;;122052:10;;;;;;;;;;;;:18;122031:39;;122085:18;122120:3;122106:7;122114:1;122106:10;;;;;;;;;;;;;;:17;;122085:38;;122165:40;122194:10;122165:12;122178:10;122165:24;;;;;;;;;;;;;;:28;;:40;;;;:::i;:::-;122138:12;122151:10;122138:24;;;;;;;;;;;;;;;;;:67;-1:-1:-1;;122011:3:0;;;;;121994:223;;;122251:10;;122233:1;;-1:-1:-1;64824:19:0;;122251:7;;122233:1;;122251:10;;;;;;;;;;:18;122245:24;;122319:922;122331:3;122327:1;:7;122319:922;;;122481:18;122537:3;65209;65203:1;65194:11;:18;;65192:21;122504:7;122512:1;122516;122512:5;122520:1;122512:9;122504:18;;;;;;;;;;;;;;:28;122503:37;;122545:1;122502:44;122481:65;;122561:15;122579:7;122587:1;122591;122587:5;122579:14;;;;;;;;;;;;;;122561:32;;122610:23;122636:13;:64;;122671:18;;-1:-1:-1;;;;;65192:21:0;122671:7;;122683:1;122679:5;;;:9;;122671:18;;;;;;;;;;;;:28;122636:64;;;122652:15;;;;:6;:15;;;;;;122636:64;122610:90;;122822:1;122804:15;:19;122796:34;;;;;-1:-1:-1;;;122796:34:0;;;;;;;;;;;;-1:-1:-1;;;122796:34:0;;;;;;;;;;;;;;;122847:23;122873:36;122893:12;122906:1;122893:15;;;;;;;;;;;;;;122873;:19;;:36;;;;:::i;:::-;122847:62;-1:-1:-1;122928:19:0;;122924:63;;122951:15;;;;:6;:15;;;;;:33;;;122924:63;123005:13;:37;;;;-1:-1:-1;123022:20:0;;123005:37;123001:70;;;123053:15;;;;:6;:15;;;;;123046:22;123001:70;123092:13;123087:143;;123126:13;123176:2;65146:3;65140:1;65131:11;:18;;65129:21;123143:7;123151:1;123155;123151:5;123159:1;123151:9;123143:18;;;;;;;;;;;;;;:28;123142:36;;123126:52;;123197:17;123208:5;123197:10;:17::i;:::-;123087:143;;-1:-1:-1;;122336:3:0;;;;;-1:-1:-1;122319:922:0;;-1:-1:-1;122319:922:0;129772:466;129831:4;;129867:15;:6;129878:3;129867:15;:10;:15;:::i;:::-;129848:34;-1:-1:-1;129893:18:0;129928:15;:6;129939:3;129928:15;:10;:15;:::i;:::-;129954:12;129969:20;;;:10;:20;;;;;;;129922:1;129914:29;;;130208:17;;;:22;;;129772:466;-1:-1:-1;;;129772:466:0:o;131733:373::-;131949:149;;;-1:-1:-1;;;131949:149:0;;;;;;;;-1:-1:-1;;;;;131949:149:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:5;;:23;;:149;;;;;-1:-1:-1;;131949:149:0;;;;;;;:5;:149;;;5:2:-1;;;;30:1;27;20:12;5:2;131949:149:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;123639:401:0;123757:10;;123740:9;;64824:19;;123757:7;;123740:9;;123757:10;;;;;;;;;;:18;123779:1;123756:24;123752:1;:28;123740:40;;123820:11;123864:1;64901:2;64895:1;64886:11;:17;;64884:20;123840:7;123848:1;123840:10;;;;;;;;;;;;;;:19;123839:26;;123869:1;123838:32;123834:1;:36;123820:50;;123906:127;123917:3;123913:1;:7;123906:127;;;123945:13;123987:2;65146:3;65140:1;65131:11;:18;;65129:21;123962:7;123970:1;123962:10;;;;;;;;;;;;;;:20;123961:28;;123945:44;;124004:17;124015:5;124004:10;:17::i;:::-;123906:127;123927:1;123922:6;;;;123906:127;;133515:467;133717:12;133713:29;;133733:7;;133713:29;-1:-1:-1;;;;;133780:15:0;;;;;;;:8;:15;;;;;;;;:25;;;;;;;;;;:38;;133810:7;133780:38;:29;:38;:::i;:::-;-1:-1:-1;;;;;133752:15:0;;;;;;;:8;:15;;;;;;;;:25;;;;;;;;;;;;;:66;;;;133836:138;;;;;;;;;;;;;;;;;;133752:25;;:15;;133836:138;;;;;;;;;133515:467;;;;;:::o;2732:333::-;2790:7;2889:1;2885;:5;2877:44;;;;;-1:-1:-1;;;2877:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;2932:9;2948:1;2944;:5;;;;;;;2732:333;-1:-1:-1;;;;2732:333:0:o;3522:152::-;3580:7;3608:6;3600:43;;;;;-1:-1:-1;;;3600:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;3665:1;3661;:5;;;;;;;3522:152;-1:-1:-1;;;3522:152:0:o;61282:75486::-;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

bzzr://8320f1a86db0d7f110c710dd3181db0600eca41d862c7c9460c632f3e17f7ed9

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Chain Token Portfolio % Price Amount Value
ETH
Ether (ETH)
85.13%$2,666.6719.7347$1,919,245.74
ETH11.01%$9.7825,389.4115$248,308.44
ETH0.70%$95,9500.1645$15,779.15
ETH0.61%$95.71143.8577$13,768.62
ETH0.53%$0.99987111,953.4406$11,951.9
ETH0.51%$0.091176125,153.9506$11,411.04
ETH0.50%$111,281.3932$11,281.39
ETH0.31%$0.13321353,161.2982$7,081.78
ETH0.22%$18.69264.8087$4,949.27
ETH0.07%$0.9999891,529.1714$1,529.15
ETH0.06%$5,9270.2422$1,435.37
ETH0.04%$0.002894315,973.743$914.39
ETH0.04%$0.261223,346$874.04
ETH0.03%$1,003.030.7771$779.43
ETH0.02%$0.4414831,231.4968$543.68
ETH0.02%$0.0996485,385.7434$536.68
ETH0.02%$0.992725522.187$518.39
ETH0.02%$56.988.8353$503.44
ETH0.02%$253.61.876$475.76
ETH0.02%$14.0932.83$462.57
ETH0.02%$0.1857532,284.6842$424.39
ETH0.02%$0.1320813,210.9723$424.11
ETH0.01%$0.0479115,725.119$274.29
ETH0.01%$1.97121.5587$239.47
ETH<0.01%$0.1218831,288.6569$157.07
ETH<0.01%$669.940.1545$103.49
ETH<0.01%$54.931.2471$68.5
ETH<0.01%$0.00162141,326.7317$67
ETH<0.01%$0.00164523,985.774$39.46
ETH<0.01%$0.065412594.8861$38.91
ETH<0.01%$0.0206561,402.9519$28.98
ETH<0.01%$126.854$26.85
ETH<0.01%$18.081.2545$22.68
ETH<0.01%$0.023224832.3782$19.33
ETH<0.01%$0.63682222.0806$14.06
ETH<0.01%$0.2671349.9988$13.36
ETH<0.01%$0.030692140.7215$4.32
ETH<0.01%$0.0029091,063.5675$3.09
ETH<0.01%$0.000004176,516.3745$0.7864
ETH<0.01%$0.01842720$0.3685
BSC<0.01%$670.950.11$73.8
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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