More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 176,328 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Slow Withdraw | 21674968 | 26 days ago | IN | 0 ETH | 0.0006659 | ||||
Transfer Tokens ... | 21674928 | 26 days ago | IN | 0 ETH | 0.00051248 | ||||
Slow Withdraw | 20741927 | 156 days ago | IN | 0 ETH | 0.00011979 | ||||
Announce Withdra... | 20741917 | 156 days ago | IN | 0 ETH | 0.0002148 | ||||
Slow Withdraw | 20741800 | 156 days ago | IN | 0 ETH | 0.000129 | ||||
Announce Withdra... | 20741761 | 156 days ago | IN | 0 ETH | 0.00021494 | ||||
Slow Withdraw | 20164401 | 237 days ago | IN | 0 ETH | 0.00037923 | ||||
Announce Withdra... | 20164395 | 237 days ago | IN | 0 ETH | 0.00057372 | ||||
Slow Withdraw | 19053649 | 392 days ago | IN | 0 ETH | 0.00047574 | ||||
Announce Withdra... | 19053647 | 392 days ago | IN | 0 ETH | 0.00076263 | ||||
Slow Withdraw | 18620235 | 453 days ago | IN | 0 ETH | 0.00118342 | ||||
Announce Withdra... | 18620167 | 453 days ago | IN | 0 ETH | 0.00192926 | ||||
Slow Withdraw | 18444248 | 478 days ago | IN | 0 ETH | 0.00085753 | ||||
Announce Withdra... | 18444246 | 478 days ago | IN | 0 ETH | 0.00143131 | ||||
Announce Withdra... | 17888675 | 556 days ago | IN | 0 ETH | 0.00100375 | ||||
Slow Withdraw | 17732850 | 577 days ago | IN | 0 ETH | 0.00099588 | ||||
Announce Withdra... | 17732845 | 577 days ago | IN | 0 ETH | 0.00161818 | ||||
Slow Withdraw | 17519903 | 607 days ago | IN | 0 ETH | 0.00109338 | ||||
Announce Withdra... | 17519899 | 607 days ago | IN | 0 ETH | 0.00125298 | ||||
Slow Withdraw | 17519891 | 607 days ago | IN | 0 ETH | 0.00072785 | ||||
Announce Withdra... | 17519885 | 607 days ago | IN | 0 ETH | 0.00130771 | ||||
Slow Withdraw | 17209830 | 651 days ago | IN | 0 ETH | 0.00599302 | ||||
Announce Withdra... | 17209829 | 651 days ago | IN | 0 ETH | 0.00514437 | ||||
Announce Withdra... | 17209818 | 651 days ago | IN | 0 ETH | 0.01011012 | ||||
Slow Withdraw | 17037430 | 675 days ago | IN | 0 ETH | 0.00205021 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
20741927 | 156 days ago | 0.01090001 ETH | ||||
20741800 | 156 days ago | 0.1005 ETH | ||||
20164401 | 237 days ago | 0.54032237 ETH | ||||
19053649 | 392 days ago | 0.75 ETH | ||||
18620235 | 453 days ago | 0.03898908 ETH | ||||
18444248 | 478 days ago | 0.05687141 ETH | ||||
17732850 | 577 days ago | 0.32196164 ETH | ||||
17519891 | 607 days ago | 0.11570074 ETH | ||||
17209830 | 651 days ago | 0.84791373 ETH | ||||
17032086 | 676 days ago | 104.49172662 ETH | ||||
16061727 | 812 days ago | 0.02730392 ETH | ||||
15488309 | 894 days ago | 0.03296651 ETH | ||||
15306883 | 922 days ago | 0.206411 ETH | ||||
15232416 | 934 days ago | 1.00324846 ETH | ||||
15232294 | 934 days ago | 0.005538 ETH | ||||
15017762 | 968 days ago | 0.09884383 ETH | ||||
14970161 | 977 days ago | 0.076291 ETH | ||||
14660414 | 1027 days ago | 0.06088224 ETH | ||||
14615702 | 1034 days ago | 0.06189102 ETH | ||||
14585994 | 1039 days ago | 0.03741502 ETH | ||||
14514591 | 1050 days ago | 0.0402766 ETH | ||||
14495991 | 1053 days ago | 1.07970234 ETH | ||||
14453915 | 1059 days ago | 0.01241694 ETH | ||||
14348279 | 1076 days ago | 0.03384339 ETH | ||||
14340563 | 1077 days ago | 0.00635323 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
BrokerV2
Compiler Version
v0.5.12+commit.7709ece9
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 85.13% | $2,666.6 | 719.7347 | $1,919,245.74 | |
ETH | 11.01% | $9.78 | 25,389.4115 | $248,308.44 | |
ETH | 0.70% | $95,950 | 0.1645 | $15,779.15 | |
ETH | 0.61% | $95.71 | 143.8577 | $13,768.62 | |
ETH | 0.53% | $0.999871 | 11,953.4406 | $11,951.9 | |
ETH | 0.51% | $0.091176 | 125,153.9506 | $11,411.04 | |
ETH | 0.50% | $1 | 11,281.3932 | $11,281.39 | |
ETH | 0.31% | $0.133213 | 53,161.2982 | $7,081.78 | |
ETH | 0.22% | $18.69 | 264.8087 | $4,949.27 | |
ETH | 0.07% | $0.999989 | 1,529.1714 | $1,529.15 | |
ETH | 0.06% | $5,927 | 0.2422 | $1,435.37 | |
ETH | 0.04% | $0.002894 | 315,973.743 | $914.39 | |
ETH | 0.04% | $0.26122 | 3,346 | $874.04 | |
ETH | 0.03% | $1,003.03 | 0.7771 | $779.43 | |
ETH | 0.02% | $0.441483 | 1,231.4968 | $543.68 | |
ETH | 0.02% | $0.099648 | 5,385.7434 | $536.68 | |
ETH | 0.02% | $0.992725 | 522.187 | $518.39 | |
ETH | 0.02% | $56.98 | 8.8353 | $503.44 | |
ETH | 0.02% | $253.6 | 1.876 | $475.76 | |
ETH | 0.02% | $14.09 | 32.83 | $462.57 | |
ETH | 0.02% | $0.185753 | 2,284.6842 | $424.39 | |
ETH | 0.02% | $0.132081 | 3,210.9723 | $424.11 | |
ETH | 0.01% | $0.047911 | 5,725.119 | $274.29 | |
ETH | 0.01% | $1.97 | 121.5587 | $239.47 | |
ETH | <0.01% | $0.121883 | 1,288.6569 | $157.07 | |
ETH | <0.01% | $669.94 | 0.1545 | $103.49 | |
ETH | <0.01% | $54.93 | 1.2471 | $68.5 | |
ETH | <0.01% | $0.001621 | 41,326.7317 | $67 | |
ETH | <0.01% | $0.001645 | 23,985.774 | $39.46 | |
ETH | <0.01% | $0.065412 | 594.8861 | $38.91 | |
ETH | <0.01% | $0.020656 | 1,402.9519 | $28.98 | |
ETH | <0.01% | $1 | 26.854 | $26.85 | |
ETH | <0.01% | $18.08 | 1.2545 | $22.68 | |
ETH | <0.01% | $0.023224 | 832.3782 | $19.33 | |
ETH | <0.01% | $0.636822 | 22.0806 | $14.06 | |
ETH | <0.01% | $0.26713 | 49.9988 | $13.36 | |
ETH | <0.01% | $0.030692 | 140.7215 | $4.32 | |
ETH | <0.01% | $0.002909 | 1,063.5675 | $3.09 | |
ETH | <0.01% | $0.000004 | 176,516.3745 | $0.7864 | |
ETH | <0.01% | $0.018427 | 20 | $0.3685 | |
BSC | <0.01% | $670.95 | 0.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.