Latest 25 from a total of 176,383 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Slow Withdraw | 24334276 | 42 days ago | IN | 0 ETH | 0.00011162 | ||||
| Announce Withdra... | 24334221 | 42 days ago | IN | 0 ETH | 0.00017979 | ||||
| Slow Withdraw | 24334168 | 42 days ago | IN | 0 ETH | 0.00011997 | ||||
| Announce Withdra... | 24333925 | 42 days ago | IN | 0 ETH | 0.00017234 | ||||
| Slow Withdraw | 24197151 | 61 days ago | IN | 0 ETH | 0.00000275 | ||||
| Announce Withdra... | 24193640 | 62 days ago | IN | 0 ETH | 0.00000513 | ||||
| Slow Withdraw | 23402489 | 172 days ago | IN | 0 ETH | 0.00020422 | ||||
| Announce Withdra... | 23402487 | 172 days ago | IN | 0 ETH | 0.00009207 | ||||
| Slow Withdraw | 23037774 | 223 days ago | IN | 0 ETH | 0.00013852 | ||||
| Announce Withdra... | 23037769 | 223 days ago | IN | 0 ETH | 0.00023593 | ||||
| Transfer Tokens ... | 22863679 | 248 days ago | IN | 0 ETH | 0.00000661 | ||||
| Transfer Tokens ... | 22860969 | 248 days ago | IN | 0 ETH | 0.00001403 | ||||
| Transfer Tokens ... | 22831974 | 252 days ago | IN | 0 ETH | 0.00004122 | ||||
| Transfer Tokens ... | 22803797 | 256 days ago | IN | 0 ETH | 0.0007041 | ||||
| Transfer Tokens ... | 22803796 | 256 days ago | IN | 0 ETH | 0.0007086 | ||||
| Transfer Tokens ... | 22803795 | 256 days ago | IN | 0 ETH | 0.0007077 | ||||
| Transfer Tokens ... | 22803794 | 256 days ago | IN | 0 ETH | 0.0007023 | ||||
| Transfer Tokens ... | 22803793 | 256 days ago | IN | 0 ETH | 0.0007086 | ||||
| Transfer Tokens ... | 22803750 | 256 days ago | IN | 0 ETH | 0.00001319 | ||||
| Transfer Tokens ... | 22803731 | 256 days ago | IN | 0 ETH | 0.0004724 | ||||
| Transfer Tokens ... | 22803714 | 256 days ago | IN | 0 ETH | 0.00001851 | ||||
| 0x9d5d85ce | 22803702 | 256 days ago | IN | 0 ETH | 0.0000166 | ||||
| Transfer Tokens ... | 22803670 | 256 days ago | IN | 0 ETH | 0.0000187 | ||||
| Slow Withdraw | 22688092 | 272 days ago | IN | 0 ETH | 0.00010574 | ||||
| Announce Withdra... | 22688090 | 272 days ago | IN | 0 ETH | 0.00016827 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 24334276 | 42 days ago | 245.15754034 ETH | ||||
| Transfer | 24334168 | 42 days ago | 0.24540294 ETH | ||||
| Transfer | 24197151 | 61 days ago | 0.0235 ETH | ||||
| Transfer | 23037774 | 223 days ago | 0.11548581 ETH | ||||
| Transfer | 22688092 | 272 days ago | 0.00643979 ETH | ||||
| Transfer | 22071457 | 358 days ago | 0.16470457 ETH | ||||
| Transfer | 22071449 | 358 days ago | 0.29720025 ETH | ||||
| Transfer | 20741927 | 544 days ago | 0.01090001 ETH | ||||
| Transfer | 20741800 | 544 days ago | 0.1005 ETH | ||||
| Transfer | 20164401 | 625 days ago | 0.54032237 ETH | ||||
| Transfer | 19053649 | 780 days ago | 0.75 ETH | ||||
| Transfer | 18620235 | 841 days ago | 0.03898908 ETH | ||||
| Transfer | 18444248 | 866 days ago | 0.05687141 ETH | ||||
| Transfer | 17732850 | 965 days ago | 0.32196164 ETH | ||||
| Transfer | 17519891 | 995 days ago | 0.11570074 ETH | ||||
| Transfer | 17209830 | 1039 days ago | 0.84791373 ETH | ||||
| Transfer | 17032086 | 1064 days ago | 104.49172662 ETH | ||||
| Transfer | 16061727 | 1200 days ago | 0.02730392 ETH | ||||
| Transfer | 15488309 | 1281 days ago | 0.03296651 ETH | ||||
| Transfer | 15306883 | 1310 days ago | 0.206411 ETH | ||||
| Transfer | 15232416 | 1322 days ago | 1.00324846 ETH | ||||
| Transfer | 15232294 | 1322 days ago | 0.005538 ETH | ||||
| Transfer | 15017762 | 1356 days ago | 0.09884383 ETH | ||||
| - | 14970161 | 1365 days ago | 0.076291 ETH | ||||
| - | 14660414 | 1415 days ago | 0.06088224 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
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
Contract ABI
API[{"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
Net Worth in USD
$1,204,080.14
Net Worth in ETH
591.42703
Token Allocations
ETH
80.14%
LEO
15.10%
DAI
0.99%
Others
3.76%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 80.14% | $2,037.03 | 473.7245 | $964,990.46 | |
| ETH | 15.10% | $9.15 | 19,873.7875 | $181,845.16 | |
| ETH | 0.99% | $0.999913 | 11,929.5615 | $11,928.52 | |
| ETH | 0.95% | $69,691.4 | 0.1645 | $11,460.88 | |
| ETH | 0.94% | $0.99998 | 11,281.3932 | $11,281.17 | |
| ETH | 0.75% | $62.96 | 143.8577 | $9,057.28 | |
| ETH | 0.22% | $0.021368 | 125,153.9506 | $2,674.28 | |
| ETH | 0.20% | $8.95 | 264.8087 | $2,370.04 | |
| ETH | 0.12% | $0.999949 | 1,467.2661 | $1,467.19 | |
| ETH | 0.12% | $1,867.25 | 0.7771 | $1,450.99 | |
| ETH | 0.10% | $0.022519 | 53,161.2982 | $1,197.15 | |
| ETH | 0.06% | $0.205916 | 3,346 | $688.99 | |
| ETH | 0.05% | $2,521.56 | 0.2422 | $610.66 | |
| ETH | 0.04% | $54.56 | 8.8353 | $482.06 | |
| ETH | 0.03% | $0.001224 | 315,973.743 | $386.84 | |
| ETH | 0.03% | $0.068185 | 5,385.7434 | $367.23 | |
| ETH | 0.03% | $10.76 | 32.83 | $353.25 | |
| ETH | 0.02% | $0.088655 | 3,210.9723 | $284.67 | |
| ETH | 0.02% | $0.097276 | 2,284.6842 | $222.24 | |
| ETH | 0.02% | $109.15 | 1.876 | $204.77 | |
| ETH | 0.01% | $0.317253 | 522.187 | $165.67 | |
| ETH | 0.01% | $0.131467 | 1,201.0898 | $157.9 | |
| ETH | <0.01% | $647.37 | 0.1545 | $100 | |
| ETH | <0.01% | $0.001352 | 41,326.7317 | $55.87 | |
| ETH | <0.01% | $0.004737 | 5,725.119 | $27.12 | |
| ETH | <0.01% | $0.999577 | 26.854 | $26.84 | |
| ETH | <0.01% | $0.018521 | 1,288.6569 | $23.87 | |
| ETH | <0.01% | $18.08 | 1.2545 | $22.68 | |
| ETH | <0.01% | $17.88 | 1.2471 | $22.3 | |
| ETH | <0.01% | $0.996409 | 22.0806 | $22 | |
| ETH | <0.01% | $0.148782 | 121.5587 | $18.09 | |
| ETH | <0.01% | $0.010015 | 1,402.9519 | $14.05 | |
| ETH | <0.01% | $0.000406 | 23,985.774 | $9.75 | |
| ETH | <0.01% | $0.031569 | 140.7215 | $4.44 | |
| ETH | <0.01% | $0.004059 | 832.3782 | $3.38 | |
| ETH | <0.01% | $0.005553 | 594.8861 | $3.3 | |
| ETH | <0.01% | $0.057805 | 49.9988 | $2.89 | |
| ETH | <0.01% | $0.00084 | 1,063.5675 | $0.8936 | |
| ETH | <0.01% | $0.000003 | 176,516.3745 | $0.4681 | |
| ETH | <0.01% | $0.017691 | 20 | $0.3538 | |
| ETH | <0.01% | $0.000209 | 1,065 | $0.2222 | |
| ETH | <0.01% | $0.00 | 0.01 | $0.00 | |
| BSC | <0.01% | $644.78 | 0.11 | $70.93 | |
| BASE | <0.01% | $0.019895 | 160 | $3.18 |
Loading...
Loading
Loading...
Loading
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.