Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0.000003602392113149 ETH
Eth Value
$0.01 (@ $3,343.14/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 60,584 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw Exit | 21400317 | 13 days ago | IN | 0 ETH | 0.0004053 | ||||
Withdraw Exit | 21386563 | 15 days ago | IN | 0 ETH | 0.00096523 | ||||
Exit Wallet | 21386559 | 15 days ago | IN | 0 ETH | 0.00143368 | ||||
Withdraw Exit | 21349945 | 21 days ago | IN | 0 ETH | 0.00074495 | ||||
Exit Wallet | 21349938 | 21 days ago | IN | 0 ETH | 0.00078738 | ||||
Withdraw Exit | 21340274 | 22 days ago | IN | 0 ETH | 0.0015678 | ||||
Exit Wallet | 21340268 | 22 days ago | IN | 0 ETH | 0.00158999 | ||||
Deposit Ether | 21323904 | 24 days ago | IN | 0.00000001 ETH | 0.00220825 | ||||
Exit Wallet | 21273348 | 31 days ago | IN | 0 ETH | 0.00102466 | ||||
Withdraw Exit | 21269045 | 32 days ago | IN | 0 ETH | 0.00041497 | ||||
Exit Wallet | 21269032 | 32 days ago | IN | 0 ETH | 0.00059191 | ||||
Withdraw Exit | 21250163 | 34 days ago | IN | 0 ETH | 0.00070051 | ||||
Withdraw Exit | 21250161 | 34 days ago | IN | 0 ETH | 0.00039162 | ||||
Exit Wallet | 21250159 | 34 days ago | IN | 0 ETH | 0.0006245 | ||||
Withdraw Exit | 21244031 | 35 days ago | IN | 0 ETH | 0.00087857 | ||||
Exit Wallet | 21244014 | 35 days ago | IN | 0 ETH | 0.0013075 | ||||
Withdraw Exit | 21199625 | 42 days ago | IN | 0 ETH | 0.00093058 | ||||
Withdraw Exit | 21199598 | 42 days ago | IN | 0 ETH | 0.00052455 | ||||
Exit Wallet | 21199576 | 42 days ago | IN | 0 ETH | 0.00079935 | ||||
Withdraw Exit | 21020877 | 66 days ago | IN | 0 ETH | 0.00067398 | ||||
Exit Wallet | 21020873 | 66 days ago | IN | 0 ETH | 0.00042405 | ||||
Withdraw Exit | 20953089 | 76 days ago | IN | 0 ETH | 0.00104337 | ||||
Withdraw Exit | 20953055 | 76 days ago | IN | 0 ETH | 0.00082263 | ||||
Withdraw Exit | 20953043 | 76 days ago | IN | 0 ETH | 0.00101427 | ||||
Withdraw Exit | 20953035 | 76 days ago | IN | 0 ETH | 0.00110969 |
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
||||
---|---|---|---|---|---|---|---|
21400317 | 13 days ago | 0 ETH | |||||
21386563 | 15 days ago | 0 ETH | |||||
21349945 | 21 days ago | 0 ETH | |||||
21340274 | 22 days ago | 0 ETH | |||||
21323904 | 24 days ago | 0.00000001 ETH | |||||
21269045 | 32 days ago | 0 ETH | |||||
21250163 | 34 days ago | 0 ETH | |||||
21250161 | 34 days ago | 0 ETH | |||||
21244031 | 35 days ago | 0 ETH | |||||
21199625 | 42 days ago | 0 ETH | |||||
21199598 | 42 days ago | 0 ETH | |||||
21020877 | 66 days ago | 0 ETH | |||||
20953089 | 76 days ago | 0 ETH | |||||
20953055 | 76 days ago | 0 ETH | |||||
20953043 | 76 days ago | 0 ETH | |||||
20953035 | 76 days ago | 0 ETH | |||||
20953024 | 76 days ago | 0 ETH | |||||
20857272 | 89 days ago | 0 ETH | |||||
20659543 | 117 days ago | 0 ETH | |||||
20659543 | 117 days ago | 0 ETH | |||||
20659543 | 117 days ago | 0 ETH | |||||
20659543 | 117 days ago | 0 ETH | |||||
20597142 | 126 days ago | 0 ETH | |||||
20479204 | 142 days ago | 0 ETH | |||||
20469540 | 143 days ago | 0 ETH |
Loading...
Loading
Contract Name:
Exchange
Compiler Version
v0.6.8+commit.0bbfe453
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import { Address } from './Address.sol'; import { ECDSA } from './ECDSA.sol'; import { SafeMath as SafeMath256 } from './SafeMath.sol'; import { AssetRegistry } from './AssetRegistry.sol'; import { AssetTransfers } from './AssetTransfers.sol'; import { AssetUnitConversions } from './AssetUnitConversions.sol'; import { Owned } from './Owned.sol'; import { SafeMath64 } from './SafeMath64.sol'; import { Signatures } from './Signatures.sol'; import { Enums, ICustodian, IERC20, IExchange, Structs } from './Interfaces.sol'; import { UUID } from './UUID.sol'; /** * @notice The Exchange contract. Implements all deposit, trade, and withdrawal logic and associated balance tracking * * @dev The term `asset` refers collectively to ETH and ERC-20 tokens, the term `token` refers only to the latter * @dev Events with indexed string parameters (Deposited and TradeExecuted) only log the hash values for those * parameters, from which the original raw string values cannot be retrieved. For convenience these events contain * the un-indexed string parameter values in addition to the indexed values */ contract Exchange is IExchange, Owned { using SafeMath64 for uint64; using SafeMath256 for uint256; using AssetRegistry for AssetRegistry.Storage; // Events // /** * @notice Emitted when an admin changes the Chain Propagation Period tunable parameter with `setChainPropagationPeriod` */ event ChainPropagationPeriodChanged(uint256 previousValue, uint256 newValue); /** * @notice Emitted when a user deposits ETH with `depositEther` or a token with `depositAsset` or `depositAssetBySymbol` */ event Deposited( uint64 index, address indexed wallet, address indexed assetAddress, string indexed assetSymbolIndex, string assetSymbol, uint64 quantityInPips, uint64 newExchangeBalanceInPips, uint256 newExchangeBalanceInAssetUnits ); /** * @notice Emitted when an admin changes the Dispatch Wallet tunable parameter with `setDispatcher` */ event DispatcherChanged(address previousValue, address newValue); /** * @notice Emitted when an admin changes the Fee Wallet tunable parameter with `setFeeWallet` */ event FeeWalletChanged(address previousValue, address newValue); /** * @notice Emitted when a user invalidates an order nonce with `invalidateOrderNonce` */ event OrderNonceInvalidated( address indexed wallet, uint128 nonce, uint128 timestampInMs, uint256 effectiveBlockNumber ); /** * @notice Emitted when an admin initiates the token registration process with `registerToken` */ event TokenRegistered( IERC20 indexed assetAddress, string assetSymbol, uint8 decimals ); /** * @notice Emitted when an admin finalizes the token registration process with `confirmAssetRegistration`, after * which it can be deposited, traded, or withdrawn */ event TokenRegistrationConfirmed( IERC20 indexed assetAddress, string assetSymbol, uint8 decimals ); /** * @notice Emitted when an admin adds a symbol to a previously registered and confirmed token * via `addTokenSymbol` */ event TokenSymbolAdded(IERC20 indexed assetAddress, string assetSymbol); /** * @notice Emitted when the Dispatcher Wallet submits a trade for execution with `executeTrade` */ event TradeExecuted( address buyWallet, address sellWallet, string indexed baseAssetSymbolIndex, string indexed quoteAssetSymbolIndex, string baseAssetSymbol, string quoteAssetSymbol, uint64 baseQuantityInPips, uint64 quoteQuantityInPips, uint64 tradePriceInPips, bytes32 buyOrderHash, bytes32 sellOrderHash ); /** * @notice Emitted when a user invokes the Exit Wallet mechanism with `exitWallet` */ event WalletExited(address indexed wallet, uint256 effectiveBlockNumber); /** * @notice Emitted when a user withdraws an asset balance through the Exit Wallet mechanism with `withdrawExit` */ event WalletExitWithdrawn( address indexed wallet, address indexed assetAddress, string assetSymbol, uint64 quantityInPips, uint64 newExchangeBalanceInPips, uint256 newExchangeBalanceInAssetUnits ); /** * @notice Emitted when a user clears the exited status of a wallet previously exited with `exitWallet` */ event WalletExitCleared(address indexed wallet); /** * @notice Emitted when the Dispatcher Wallet submits a withdrawal with `withdraw` */ event Withdrawn( address indexed wallet, address indexed assetAddress, string assetSymbol, uint64 quantityInPips, uint64 newExchangeBalanceInPips, uint256 newExchangeBalanceInAssetUnits ); // Internally used structs // struct NonceInvalidation { bool exists; uint64 timestampInMs; uint256 effectiveBlockNumber; } struct WalletExit { bool exists; uint256 effectiveBlockNumber; } // Storage // // Asset registry data AssetRegistry.Storage _assetRegistry; // Mapping of order wallet hash => isComplete mapping(bytes32 => bool) _completedOrderHashes; // Mapping of withdrawal wallet hash => isComplete mapping(bytes32 => bool) _completedWithdrawalHashes; address payable _custodian; uint64 _depositIndex; // Mapping of wallet => asset => balance mapping(address => mapping(address => uint64)) _balancesInPips; // Mapping of wallet => last invalidated timestampInMs mapping(address => NonceInvalidation) _nonceInvalidations; // Mapping of order hash => filled quantity in pips mapping(bytes32 => uint64) _partiallyFilledOrderQuantitiesInPips; mapping(address => WalletExit) _walletExits; // Tunable parameters uint256 _chainPropagationPeriod; address _dispatcherWallet; address _feeWallet; // Constant values // uint256 constant _maxChainPropagationPeriod = (7 * 24 * 60 * 60) / 15; // 1 week at 15s/block uint64 constant _maxTradeFeeBasisPoints = 20 * 100; // 20%; uint64 constant _maxWithdrawalFeeBasisPoints = 20 * 100; // 20%; /** * @notice Instantiate a new `Exchange` contract * * @dev Sets `_owner` and `_admin` to `msg.sender` */ constructor() public Owned() {} /** * @notice Sets the address of the `Custodian` contract * * @dev The `Custodian` accepts `Exchange` and `Governance` addresses in its constructor, after * which they can only be changed by the `Governance` contract itself. Therefore the `Custodian` * must be deployed last and its address set here on an existing `Exchange` contract. This value * is immutable once set and cannot be changed again * * @param newCustodian The address of the `Custodian` contract deployed against this `Exchange` * contract's address */ function setCustodian(address payable newCustodian) external onlyAdmin { require(_custodian == address(0x0), 'Custodian can only be set once'); require(Address.isContract(newCustodian), 'Invalid address'); _custodian = newCustodian; } /*** Tunable parameters ***/ /** * @notice Sets a new Chain Propagation Period - the block delay after which order nonce invalidations * are respected by `executeTrade` and wallet exits are respected by `executeTrade` and `withdraw` * * @param newChainPropagationPeriod The new Chain Propagation Period expressed as a number of blocks. Must * be less than `_maxChainPropagationPeriod` */ function setChainPropagationPeriod(uint256 newChainPropagationPeriod) external onlyAdmin { require( newChainPropagationPeriod < _maxChainPropagationPeriod, 'Must be less than 1 week' ); uint256 oldChainPropagationPeriod = _chainPropagationPeriod; _chainPropagationPeriod = newChainPropagationPeriod; emit ChainPropagationPeriodChanged( oldChainPropagationPeriod, newChainPropagationPeriod ); } /** * @notice Sets the address of the Fee wallet * * @dev Trade and Withdraw fees will accrue in the `_balancesInPips` mappings for this wallet * * @param newFeeWallet The new Fee wallet. Must be different from the current one */ function setFeeWallet(address newFeeWallet) external onlyAdmin { require(newFeeWallet != address(0x0), 'Invalid wallet address'); require( newFeeWallet != _feeWallet, 'Must be different from current fee wallet' ); address oldFeeWallet = _feeWallet; _feeWallet = newFeeWallet; emit FeeWalletChanged(oldFeeWallet, newFeeWallet); } // Accessors // /** * @notice Load a wallet's balance by asset address, in asset units * * @param wallet The wallet address to load the balance for. Can be different from `msg.sender` * @param assetAddress The asset address to load the wallet's balance for * * @return The quantity denominated in asset units of asset at `assetAddress` currently * deposited by `wallet` */ function loadBalanceInAssetUnitsByAddress( address wallet, address assetAddress ) external view returns (uint256) { require(wallet != address(0x0), 'Invalid wallet address'); Structs.Asset memory asset = _assetRegistry.loadAssetByAddress( assetAddress ); return AssetUnitConversions.pipsToAssetUnits( _balancesInPips[wallet][assetAddress], asset.decimals ); } /** * @notice Load a wallet's balance by asset address, in asset units * * @param wallet The wallet address to load the balance for. Can be different from `msg.sender` * @param assetSymbol The asset symbol to load the wallet's balance for * * @return The quantity denominated in asset units of asset `assetSymbol` currently deposited * by `wallet` */ function loadBalanceInAssetUnitsBySymbol( address wallet, string calldata assetSymbol ) external view returns (uint256) { require(wallet != address(0x0), 'Invalid wallet address'); Structs.Asset memory asset = _assetRegistry.loadAssetBySymbol( assetSymbol, getCurrentTimestampInMs() ); return AssetUnitConversions.pipsToAssetUnits( _balancesInPips[wallet][asset.assetAddress], asset.decimals ); } /** * @notice Load a wallet's balance by asset address, in pips * * @param wallet The wallet address to load the balance for. Can be different from `msg.sender` * @param assetAddress The asset address to load the wallet's balance for * * @return The quantity denominated in pips of asset at `assetAddress` currently deposited by `wallet` */ function loadBalanceInPipsByAddress(address wallet, address assetAddress) external view returns (uint64) { require(wallet != address(0x0), 'Invalid wallet address'); return _balancesInPips[wallet][assetAddress]; } /** * @notice Load a wallet's balance by asset symbol, in pips * * @param wallet The wallet address to load the balance for. Can be different from `msg.sender` * @param assetSymbol The asset symbol to load the wallet's balance for * * @return The quantity denominated in pips of asset with `assetSymbol` currently deposited by `wallet` */ function loadBalanceInPipsBySymbol( address wallet, string calldata assetSymbol ) external view returns (uint64) { require(wallet != address(0x0), 'Invalid wallet address'); address assetAddress = _assetRegistry .loadAssetBySymbol(assetSymbol, getCurrentTimestampInMs()) .assetAddress; return _balancesInPips[wallet][assetAddress]; } /** * @notice Load the address of the Fee wallet * * @return The address of the Fee wallet */ function loadFeeWallet() external view returns (address) { return _feeWallet; } /** * @notice Load the quantity filled so far for a partially filled orders * @dev Invalidating an order nonce will not clear partial fill quantities for earlier orders because * the gas cost would potentially be unbound * * @param orderHash The order hash as originally signed by placing wallet that uniquely identifies an order * * @return For partially filled orders, the amount filled so far in pips. For orders in all other states, 0 */ function loadPartiallyFilledOrderQuantityInPips(bytes32 orderHash) external view returns (uint64) { return _partiallyFilledOrderQuantitiesInPips[orderHash]; } // Depositing // /** * @notice Deposit ETH */ function depositEther() external payable { deposit(msg.sender, address(0x0), msg.value); } /** * @notice Deposit `IERC20` compliant tokens * * @param tokenAddress The token contract address * @param quantityInAssetUnits The quantity to deposit. The sending wallet must first call the `approve` method on * the token contract for at least this quantity first */ function depositTokenByAddress( IERC20 tokenAddress, uint256 quantityInAssetUnits ) external { require( address(tokenAddress) != address(0x0), 'Use depositEther to deposit Ether' ); deposit(msg.sender, address(tokenAddress), quantityInAssetUnits); } /** * @notice Deposit `IERC20` compliant tokens * * @param assetSymbol The case-sensitive symbol string for the token * @param quantityInAssetUnits The quantity to deposit. The sending wallet must first call the `approve` method on * the token contract for at least this quantity first */ function depositTokenBySymbol( string calldata assetSymbol, uint256 quantityInAssetUnits ) external { IERC20 tokenAddress = IERC20( _assetRegistry .loadAssetBySymbol(assetSymbol, getCurrentTimestampInMs()) .assetAddress ); require( address(tokenAddress) != address(0x0), 'Use depositEther to deposit ETH' ); deposit(msg.sender, address(tokenAddress), quantityInAssetUnits); } function deposit( address payable wallet, address assetAddress, uint256 quantityInAssetUnits ) private { // Calling exitWallet disables deposits immediately on mining, in contrast to withdrawals and // trades which respect the Chain Propagation Period given by `effectiveBlockNumber` via // `isWalletExitFinalized` require(!_walletExits[wallet].exists, 'Wallet exited'); Structs.Asset memory asset = _assetRegistry.loadAssetByAddress( assetAddress ); uint64 quantityInPips = AssetUnitConversions.assetUnitsToPips( quantityInAssetUnits, asset.decimals ); require(quantityInPips > 0, 'Quantity is too low'); // Convert from pips back into asset units to remove any fractional amount that is too small // to express in pips. If the asset is ETH, this leftover fractional amount accumulates as dust // in the `Exchange` contract. If the asset is a token the `Exchange` will call `transferFrom` // without this fractional amount and there will be no dust uint256 quantityInAssetUnitsWithoutFractionalPips = AssetUnitConversions .pipsToAssetUnits(quantityInPips, asset.decimals); // If the asset is ETH then the funds were already assigned to this contract via msg.value. If // the asset is a token, additionally call the transferFrom function on the token contract for // the pre-approved asset quantity if (assetAddress != address(0x0)) { AssetTransfers.transferFrom( wallet, IERC20(assetAddress), quantityInAssetUnitsWithoutFractionalPips ); } // Forward the funds to the `Custodian` AssetTransfers.transferTo( _custodian, assetAddress, quantityInAssetUnitsWithoutFractionalPips ); uint64 newExchangeBalanceInPips = _balancesInPips[wallet][assetAddress].add( quantityInPips ); uint256 newExchangeBalanceInAssetUnits = AssetUnitConversions .pipsToAssetUnits(newExchangeBalanceInPips, asset.decimals); // Update balance with actual transferred quantity _balancesInPips[wallet][assetAddress] = newExchangeBalanceInPips; _depositIndex++; emit Deposited( _depositIndex, wallet, assetAddress, asset.symbol, asset.symbol, quantityInPips, newExchangeBalanceInPips, newExchangeBalanceInAssetUnits ); } // Invalidation // /** * @notice Invalidate all order nonces with a timestampInMs lower than the one provided * * @param nonce A Version 1 UUID. After calling and once the Chain Propagation Period has elapsed, * `executeTrade` will reject order nonces from this wallet with a timestampInMs component lower than * the one provided */ function invalidateOrderNonce(uint128 nonce) external { uint64 timestampInMs = UUID.getTimestampInMsFromUuidV1(nonce); // Enforce a maximum skew for invalidating nonce timestamps in the future so the user doesn't // lock their wallet from trades indefinitely require( timestampInMs < getOneDayFromNowInMs(), 'Nonce timestamp too far in future' ); if (_nonceInvalidations[msg.sender].exists) { require( _nonceInvalidations[msg.sender].timestampInMs < timestampInMs, 'Nonce timestamp already invalidated' ); require( _nonceInvalidations[msg.sender].effectiveBlockNumber <= block.number, 'Previous invalidation awaiting chain propagation' ); } // Changing the Chain Propagation Period will not affect the effectiveBlockNumber for this invalidation uint256 effectiveBlockNumber = block.number + _chainPropagationPeriod; _nonceInvalidations[msg.sender] = NonceInvalidation( true, timestampInMs, effectiveBlockNumber ); emit OrderNonceInvalidated( msg.sender, nonce, timestampInMs, effectiveBlockNumber ); } // Withdrawing // /** * @notice Settles a user withdrawal submitted off-chain. Calls restricted to currently whitelisted Dispatcher wallet * * @param withdrawal A `Structs.Withdrawal` struct encoding the parameters of the withdrawal */ function withdraw(Structs.Withdrawal memory withdrawal) public override onlyDispatcher { // Validations require(!isWalletExitFinalized(withdrawal.walletAddress), 'Wallet exited'); require( getFeeBasisPoints(withdrawal.gasFeeInPips, withdrawal.quantityInPips) <= _maxWithdrawalFeeBasisPoints, 'Excessive withdrawal fee' ); bytes32 withdrawalHash = validateWithdrawalSignature(withdrawal); require( !_completedWithdrawalHashes[withdrawalHash], 'Hash already withdrawn' ); // If withdrawal is by asset symbol (most common) then resolve to asset address Structs.Asset memory asset = withdrawal.withdrawalType == Enums.WithdrawalType.BySymbol ? _assetRegistry.loadAssetBySymbol( withdrawal.assetSymbol, UUID.getTimestampInMsFromUuidV1(withdrawal.nonce) ) : _assetRegistry.loadAssetByAddress(withdrawal.assetAddress); // SafeMath reverts if balance is overdrawn uint64 netAssetQuantityInPips = withdrawal.quantityInPips.sub( withdrawal.gasFeeInPips ); uint256 netAssetQuantityInAssetUnits = AssetUnitConversions .pipsToAssetUnits(netAssetQuantityInPips, asset.decimals); uint64 newExchangeBalanceInPips = _balancesInPips[withdrawal .walletAddress][asset.assetAddress] .sub(withdrawal.quantityInPips); uint256 newExchangeBalanceInAssetUnits = AssetUnitConversions .pipsToAssetUnits(newExchangeBalanceInPips, asset.decimals); _balancesInPips[withdrawal.walletAddress][asset .assetAddress] = newExchangeBalanceInPips; _balancesInPips[_feeWallet][asset .assetAddress] = _balancesInPips[_feeWallet][asset.assetAddress].add( withdrawal.gasFeeInPips ); ICustodian(_custodian).withdraw( withdrawal.walletAddress, asset.assetAddress, netAssetQuantityInAssetUnits ); _completedWithdrawalHashes[withdrawalHash] = true; emit Withdrawn( withdrawal.walletAddress, asset.assetAddress, asset.symbol, withdrawal.quantityInPips, newExchangeBalanceInPips, newExchangeBalanceInAssetUnits ); } // Wallet exits // /** * @notice Flags the sending wallet as exited, immediately disabling deposits upon mining. * After the Chain Propagation Period passes trades and withdrawals are also disabled for the wallet, * and assets may then be withdrawn one at a time via `withdrawExit` */ function exitWallet() external { require(!_walletExits[msg.sender].exists, 'Wallet already exited'); _walletExits[msg.sender] = WalletExit( true, block.number + _chainPropagationPeriod ); emit WalletExited(msg.sender, block.number + _chainPropagationPeriod); } /** * @notice Withdraw the entire balance of an asset for an exited wallet. The Chain Propagation Period must * have already passed since calling `exitWallet` on `assetAddress` * * @param assetAddress The address of the asset to withdraw */ function withdrawExit(address assetAddress) external { require(isWalletExitFinalized(msg.sender), 'Wallet exit not finalized'); Structs.Asset memory asset = _assetRegistry.loadAssetByAddress( assetAddress ); uint64 balanceInPips = _balancesInPips[msg.sender][assetAddress]; uint256 balanceInAssetUnits = AssetUnitConversions.pipsToAssetUnits( balanceInPips, asset.decimals ); require(balanceInAssetUnits > 0, 'No balance for asset'); _balancesInPips[msg.sender][assetAddress] = 0; ICustodian(_custodian).withdraw( msg.sender, assetAddress, balanceInAssetUnits ); emit WalletExitWithdrawn( msg.sender, assetAddress, asset.symbol, balanceInPips, 0, 0 ); } /** * @notice Clears exited status of sending wallet. Upon mining immediately enables * deposits, trades, and withdrawals by sending wallet */ function clearWalletExit() external { require(_walletExits[msg.sender].exists, 'Wallet not exited'); delete _walletExits[msg.sender]; emit WalletExitCleared(msg.sender); } function isWalletExitFinalized(address wallet) internal view returns (bool) { WalletExit storage exit = _walletExits[wallet]; return exit.exists && exit.effectiveBlockNumber <= block.number; } // Trades // /** * @notice Settles a trade between two orders submitted and matched off-chain * * @dev As a gas optimization, base and quote symbols are passed in separately and combined to verify * the wallet hash, since this is cheaper than splitting the market symbol into its two constituent asset symbols * @dev Stack level too deep if declared external * * @param buy A `Structs.Order` struct encoding the parameters of the buy-side order (receiving base, giving quote) * @param sell A `Structs.Order` struct encoding the parameters of the sell-side order (giving base, receiving quote) * @param trade A `Structs.Trade` struct encoding the parameters of this trade execution of the counterparty orders */ function executeTrade( Structs.Order memory buy, Structs.Order memory sell, Structs.Trade memory trade ) public override onlyDispatcher { require( !isWalletExitFinalized(buy.walletAddress), 'Buy wallet exit finalized' ); require( !isWalletExitFinalized(sell.walletAddress), 'Sell wallet exit finalized' ); require( buy.walletAddress != sell.walletAddress, 'Self-trading not allowed' ); validateAssetPair(buy, sell, trade); validateLimitPrices(buy, sell, trade); validateOrderNonces(buy, sell); (bytes32 buyHash, bytes32 sellHash) = validateOrderSignatures( buy, sell, trade ); validateTradeFees(trade); updateOrderFilledQuantities(buy, buyHash, sell, sellHash, trade); updateBalancesForTrade(buy, sell, trade); emit TradeExecuted( buy.walletAddress, sell.walletAddress, trade.baseAssetSymbol, trade.quoteAssetSymbol, trade.baseAssetSymbol, trade.quoteAssetSymbol, trade.grossBaseQuantityInPips, trade.grossQuoteQuantityInPips, trade.priceInPips, buyHash, sellHash ); } // Updates buyer, seller, and fee wallet balances for both assets in trade pair according to trade parameters function updateBalancesForTrade( Structs.Order memory buy, Structs.Order memory sell, Structs.Trade memory trade ) private { // Seller gives base asset including fees _balancesInPips[sell.walletAddress][trade .baseAssetAddress] = _balancesInPips[sell.walletAddress][trade .baseAssetAddress] .sub(trade.grossBaseQuantityInPips); // Buyer receives base asset minus fees _balancesInPips[buy.walletAddress][trade .baseAssetAddress] = _balancesInPips[buy.walletAddress][trade .baseAssetAddress] .add(trade.netBaseQuantityInPips); // Buyer gives quote asset including fees _balancesInPips[buy.walletAddress][trade .quoteAssetAddress] = _balancesInPips[buy.walletAddress][trade .quoteAssetAddress] .sub(trade.grossQuoteQuantityInPips); // Seller receives quote asset minus fees _balancesInPips[sell.walletAddress][trade .quoteAssetAddress] = _balancesInPips[sell.walletAddress][trade .quoteAssetAddress] .add(trade.netQuoteQuantityInPips); // Maker and taker fees to fee wallet _balancesInPips[_feeWallet][trade .makerFeeAssetAddress] = _balancesInPips[_feeWallet][trade .makerFeeAssetAddress] .add(trade.makerFeeQuantityInPips); _balancesInPips[_feeWallet][trade .takerFeeAssetAddress] = _balancesInPips[_feeWallet][trade .takerFeeAssetAddress] .add(trade.takerFeeQuantityInPips); } function updateOrderFilledQuantities( Structs.Order memory buyOrder, bytes32 buyOrderHash, Structs.Order memory sellOrder, bytes32 sellOrderHash, Structs.Trade memory trade ) private { updateOrderFilledQuantity(buyOrder, buyOrderHash, trade); updateOrderFilledQuantity(sellOrder, sellOrderHash, trade); } // Update filled quantities tracking for order to prevent over- or double-filling orders function updateOrderFilledQuantity( Structs.Order memory order, bytes32 orderHash, Structs.Trade memory trade ) private { require(!_completedOrderHashes[orderHash], 'Order double filled'); // Total quantity of above filled as a result of all trade executions, including this one uint64 newFilledQuantityInPips; // Market orders can express quantity in quote terms, and can be partially filled by multiple // limit maker orders necessitating tracking partially filled amounts in quote terms to // determine completion if (order.isQuantityInQuote) { require( isMarketOrderType(order.orderType), 'Order quote quantity only valid for market orders' ); newFilledQuantityInPips = trade.grossQuoteQuantityInPips.add( _partiallyFilledOrderQuantitiesInPips[orderHash] ); } else { // All other orders track partially filled quantities in base terms newFilledQuantityInPips = trade.grossBaseQuantityInPips.add( _partiallyFilledOrderQuantitiesInPips[orderHash] ); } require( newFilledQuantityInPips <= order.quantityInPips, 'Order overfilled' ); if (newFilledQuantityInPips < order.quantityInPips) { // If the order was partially filled, track the new filled quantity _partiallyFilledOrderQuantitiesInPips[orderHash] = newFilledQuantityInPips; } else { // If the order was completed, delete any partial fill tracking and instead track its completion // to prevent future double fills delete _partiallyFilledOrderQuantitiesInPips[orderHash]; _completedOrderHashes[orderHash] = true; } } // Validations // function validateAssetPair( Structs.Order memory buy, Structs.Order memory sell, Structs.Trade memory trade ) private view { require( trade.baseAssetAddress != trade.quoteAssetAddress, 'Base and quote assets must be different' ); // Buy order market pair Structs.Asset memory buyBaseAsset = _assetRegistry.loadAssetBySymbol( trade.baseAssetSymbol, UUID.getTimestampInMsFromUuidV1(buy.nonce) ); Structs.Asset memory buyQuoteAsset = _assetRegistry.loadAssetBySymbol( trade.quoteAssetSymbol, UUID.getTimestampInMsFromUuidV1(buy.nonce) ); require( buyBaseAsset.assetAddress == trade.baseAssetAddress && buyQuoteAsset.assetAddress == trade.quoteAssetAddress, 'Buy order market symbol address resolution mismatch' ); // Sell order market pair Structs.Asset memory sellBaseAsset = _assetRegistry.loadAssetBySymbol( trade.baseAssetSymbol, UUID.getTimestampInMsFromUuidV1(sell.nonce) ); Structs.Asset memory sellQuoteAsset = _assetRegistry.loadAssetBySymbol( trade.quoteAssetSymbol, UUID.getTimestampInMsFromUuidV1(sell.nonce) ); require( sellBaseAsset.assetAddress == trade.baseAssetAddress && sellQuoteAsset.assetAddress == trade.quoteAssetAddress, 'Sell order market symbol address resolution mismatch' ); // Fee asset validation require( trade.makerFeeAssetAddress == trade.baseAssetAddress || trade.makerFeeAssetAddress == trade.quoteAssetAddress, 'Maker fee asset is not in trade pair' ); require( trade.takerFeeAssetAddress == trade.baseAssetAddress || trade.takerFeeAssetAddress == trade.quoteAssetAddress, 'Taker fee asset is not in trade pair' ); require( trade.makerFeeAssetAddress != trade.takerFeeAssetAddress, 'Maker and taker fee assets must be different' ); } function validateLimitPrices( Structs.Order memory buy, Structs.Order memory sell, Structs.Trade memory trade ) private pure { require( trade.grossBaseQuantityInPips > 0, 'Base quantity must be greater than zero' ); require( trade.grossQuoteQuantityInPips > 0, 'Quote quantity must be greater than zero' ); if (isLimitOrderType(buy.orderType)) { require( getImpliedQuoteQuantityInPips( trade.grossBaseQuantityInPips, buy.limitPriceInPips ) >= trade.grossQuoteQuantityInPips, 'Buy order limit price exceeded' ); } if (isLimitOrderType(sell.orderType)) { require( getImpliedQuoteQuantityInPips( trade.grossBaseQuantityInPips, sell.limitPriceInPips ) <= trade.grossQuoteQuantityInPips, 'Sell order limit price exceeded' ); } } function validateTradeFees(Structs.Trade memory trade) private pure { uint64 makerTotalQuantityInPips = trade.makerFeeAssetAddress == trade.baseAssetAddress ? trade.grossBaseQuantityInPips : trade.grossQuoteQuantityInPips; require( getFeeBasisPoints( trade.makerFeeQuantityInPips, makerTotalQuantityInPips ) <= _maxTradeFeeBasisPoints, 'Excessive maker fee' ); uint64 takerTotalQuantityInPips = trade.takerFeeAssetAddress == trade.baseAssetAddress ? trade.grossBaseQuantityInPips : trade.grossQuoteQuantityInPips; require( getFeeBasisPoints( trade.takerFeeQuantityInPips, takerTotalQuantityInPips ) <= _maxTradeFeeBasisPoints, 'Excessive taker fee' ); require( trade.netBaseQuantityInPips.add( trade.makerFeeAssetAddress == trade.baseAssetAddress ? trade.makerFeeQuantityInPips : trade.takerFeeQuantityInPips ) == trade.grossBaseQuantityInPips, 'Net base plus fee is not equal to gross' ); require( trade.netQuoteQuantityInPips.add( trade.makerFeeAssetAddress == trade.quoteAssetAddress ? trade.makerFeeQuantityInPips : trade.takerFeeQuantityInPips ) == trade.grossQuoteQuantityInPips, 'Net quote plus fee is not equal to gross' ); } function validateOrderSignatures( Structs.Order memory buy, Structs.Order memory sell, Structs.Trade memory trade ) private pure returns (bytes32, bytes32) { bytes32 buyOrderHash = validateOrderSignature(buy, trade); bytes32 sellOrderHash = validateOrderSignature(sell, trade); return (buyOrderHash, sellOrderHash); } function validateOrderSignature( Structs.Order memory order, Structs.Trade memory trade ) private pure returns (bytes32) { bytes32 orderHash = Signatures.getOrderWalletHash( order, trade.baseAssetSymbol, trade.quoteAssetSymbol ); require( Signatures.isSignatureValid( orderHash, order.walletSignature, order.walletAddress ), order.side == Enums.OrderSide.Buy ? 'Invalid wallet signature for buy order' : 'Invalid wallet signature for sell order' ); return orderHash; } function validateOrderNonces( Structs.Order memory buy, Structs.Order memory sell ) private view { require( UUID.getTimestampInMsFromUuidV1(buy.nonce) > getLastInvalidatedTimestamp(buy.walletAddress), 'Buy order nonce timestamp too low' ); require( UUID.getTimestampInMsFromUuidV1(sell.nonce) > getLastInvalidatedTimestamp(sell.walletAddress), 'Sell order nonce timestamp too low' ); } function validateWithdrawalSignature(Structs.Withdrawal memory withdrawal) private pure returns (bytes32) { bytes32 withdrawalHash = Signatures.getWithdrawalWalletHash(withdrawal); require( Signatures.isSignatureValid( withdrawalHash, withdrawal.walletSignature, withdrawal.walletAddress ), 'Invalid wallet signature' ); return withdrawalHash; } // Asset registry // /** * @notice Initiate registration process for a token asset. Only `IERC20` compliant tokens can be * added - ETH is hardcoded in the registry * * @param tokenAddress The address of the `IERC20` compliant token contract to add * @param symbol The symbol identifying the token asset * @param decimals The decimal precision of the token */ function registerToken( IERC20 tokenAddress, string calldata symbol, uint8 decimals ) external onlyAdmin { _assetRegistry.registerToken(tokenAddress, symbol, decimals); emit TokenRegistered(tokenAddress, symbol, decimals); } /** * @notice Finalize registration process for a token asset. All parameters must exactly match a previous * call to `registerToken` * * @param tokenAddress The address of the `IERC20` compliant token contract to add * @param symbol The symbol identifying the token asset * @param decimals The decimal precision of the token */ function confirmTokenRegistration( IERC20 tokenAddress, string calldata symbol, uint8 decimals ) external onlyAdmin { _assetRegistry.confirmTokenRegistration(tokenAddress, symbol, decimals); emit TokenRegistrationConfirmed(tokenAddress, symbol, decimals); } /** * @notice Add a symbol to a token that has already been registered and confirmed * * @param tokenAddress The address of the `IERC20` compliant token contract the symbol will identify * @param symbol The symbol identifying the token asset */ function addTokenSymbol(IERC20 tokenAddress, string calldata symbol) external onlyAdmin { _assetRegistry.addTokenSymbol(tokenAddress, symbol); emit TokenSymbolAdded(tokenAddress, symbol); } /** * @notice Loads an asset descriptor struct by its symbol and timestamp * * @dev Since multiple token addresses can potentially share the same symbol (in case of a token * swap/contract upgrade) the provided `timestampInMs` is compared against each asset's * `confirmedTimestampInMs` to uniquely determine the newest asset for the symbol at that point in time * * @param assetSymbol The asset's symbol * @param timestampInMs Point in time used to disambiguate multiple tokens with same symbol * * @return A `Structs.Asset` record describing the asset */ function loadAssetBySymbol(string calldata assetSymbol, uint64 timestampInMs) external view returns (Structs.Asset memory) { return _assetRegistry.loadAssetBySymbol(assetSymbol, timestampInMs); } // Dispatcher whitelisting // /** * @notice Sets the wallet whitelisted to dispatch transactions calling the `executeTrade` and `withdraw` functions * * @param newDispatcherWallet The new whitelisted dispatcher wallet. Must be different from the current one */ function setDispatcher(address newDispatcherWallet) external onlyAdmin { require(newDispatcherWallet != address(0x0), 'Invalid wallet address'); require( newDispatcherWallet != _dispatcherWallet, 'Must be different from current dispatcher' ); address oldDispatcherWallet = _dispatcherWallet; _dispatcherWallet = newDispatcherWallet; emit DispatcherChanged(oldDispatcherWallet, newDispatcherWallet); } /** * @notice Clears the currently set whitelisted dispatcher wallet, effectively disabling calling the * `executeTrade` and `withdraw` functions until a new wallet is set with `setDispatcher` */ function removeDispatcher() external onlyAdmin { emit DispatcherChanged(_dispatcherWallet, address(0x0)); _dispatcherWallet = address(0x0); } modifier onlyDispatcher() { require(msg.sender == _dispatcherWallet, 'Caller is not dispatcher'); _; } // Utils // function isLimitOrderType(Enums.OrderType orderType) private pure returns (bool) { return orderType == Enums.OrderType.Limit || orderType == Enums.OrderType.LimitMaker || orderType == Enums.OrderType.StopLossLimit || orderType == Enums.OrderType.TakeProfitLimit; } function isMarketOrderType(Enums.OrderType orderType) private pure returns (bool) { return orderType == Enums.OrderType.Market || orderType == Enums.OrderType.StopLoss || orderType == Enums.OrderType.TakeProfit; } function getCurrentTimestampInMs() private view returns (uint64) { uint64 msInOneSecond = 1000; return uint64(block.timestamp) * msInOneSecond; } function getFeeBasisPoints(uint64 fee, uint64 total) private pure returns (uint64) { uint64 basisPointsInTotal = 100 * 100; // 100 basis points/percent * 100 percent/total return fee.mul(basisPointsInTotal).div(total); } function getImpliedQuoteQuantityInPips( uint64 baseQuantityInPips, uint64 limitPriceInPips ) private pure returns (uint64) { // To convert a fractional price to integer pips, shift right by the pip precision of 8 decimals uint256 pipsMultiplier = 10**8; uint256 impliedQuoteQuantityInPips = uint256(baseQuantityInPips) .mul(uint256(limitPriceInPips)) .div(pipsMultiplier); require( impliedQuoteQuantityInPips < 2**64, 'Implied quote pip quantity overflows uint64' ); return uint64(impliedQuoteQuantityInPips); } function getLastInvalidatedTimestamp(address walletAddress) private view returns (uint64) { if ( _nonceInvalidations[walletAddress].exists && _nonceInvalidations[walletAddress].effectiveBlockNumber <= block.number ) { return _nonceInvalidations[walletAddress].timestampInMs; } return 0; } function getOneDayFromNowInMs() private view returns (uint64) { uint64 secondsInOneDay = 24 * 60 * 60; // 24 hours/day * 60 min/hour * 60 seconds/min uint64 msInOneSecond = 1000; return (uint64(block.timestamp) + secondsInOneDay) * msInOneSecond; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.8; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import { Address } from './Address.sol'; import { IERC20, Structs } from './Interfaces.sol'; /** * @notice Library helper functions for managing a registry of asset descriptors indexed by address and symbol */ library AssetRegistry { struct Storage { mapping(address => Structs.Asset) assetsByAddress; // Mapping value is array since the same symbol can be re-used for a different address // (usually as a result of a token swap or upgrade) mapping(string => Structs.Asset[]) assetsBySymbol; } function registerToken( Storage storage self, IERC20 tokenAddress, string memory symbol, uint8 decimals ) internal { require(decimals <= 32, 'Token cannot have more than 32 decimals'); require( tokenAddress != IERC20(0x0) && Address.isContract(address(tokenAddress)), 'Invalid token address' ); // The string type does not have a length property so cast to bytes to check for empty string require(bytes(symbol).length > 0, 'Invalid token symbol'); require( !self.assetsByAddress[address(tokenAddress)].isConfirmed, 'Token already finalized' ); self.assetsByAddress[address(tokenAddress)] = Structs.Asset({ exists: true, assetAddress: address(tokenAddress), symbol: symbol, decimals: decimals, isConfirmed: false, confirmedTimestampInMs: 0 }); } function confirmTokenRegistration( Storage storage self, IERC20 tokenAddress, string memory symbol, uint8 decimals ) internal { Structs.Asset memory asset = self.assetsByAddress[address(tokenAddress)]; require(asset.exists, 'Unknown token'); require(!asset.isConfirmed, 'Token already finalized'); require(isStringEqual(asset.symbol, symbol), 'Symbols do not match'); require(asset.decimals == decimals, 'Decimals do not match'); asset.isConfirmed = true; asset.confirmedTimestampInMs = uint64(block.timestamp * 1000); // Block timestamp is in seconds, store ms self.assetsByAddress[address(tokenAddress)] = asset; self.assetsBySymbol[symbol].push(asset); } function addTokenSymbol( Storage storage self, IERC20 tokenAddress, string memory symbol ) internal { Structs.Asset memory asset = self.assetsByAddress[address(tokenAddress)]; require( asset.exists && asset.isConfirmed, 'Registration of token not finalized' ); require(!isStringEqual(symbol, 'ETH'), 'ETH symbol reserved for Ether'); // This will prevent swapping assets for previously existing orders uint64 msInOneSecond = 1000; asset.confirmedTimestampInMs = uint64(block.timestamp * msInOneSecond); self.assetsBySymbol[symbol].push(asset); } /** * @dev Resolves an asset address into corresponding Asset struct * * @param assetAddress Ethereum address of asset */ function loadAssetByAddress(Storage storage self, address assetAddress) internal view returns (Structs.Asset memory) { if (assetAddress == address(0x0)) { return getEthAsset(); } Structs.Asset memory asset = self.assetsByAddress[assetAddress]; require( asset.exists && asset.isConfirmed, 'No confirmed asset found for address' ); return asset; } /** * @dev Resolves a asset symbol into corresponding Asset struct * * @param symbol Asset symbol, e.g. 'IDEX' * @param timestampInMs Milliseconds since Unix epoch, usually parsed from a UUID v1 order nonce. * Constrains symbol resolution to the asset most recently confirmed prior to timestampInMs. Reverts * if no such asset exists */ function loadAssetBySymbol( Storage storage self, string memory symbol, uint64 timestampInMs ) internal view returns (Structs.Asset memory) { if (isStringEqual('ETH', symbol)) { return getEthAsset(); } Structs.Asset memory asset; if (self.assetsBySymbol[symbol].length > 0) { for (uint8 i = 0; i < self.assetsBySymbol[symbol].length; i++) { if ( self.assetsBySymbol[symbol][i].confirmedTimestampInMs <= timestampInMs ) { asset = self.assetsBySymbol[symbol][i]; } } } require( asset.exists && asset.isConfirmed, 'No confirmed asset found for symbol' ); return asset; } /** * @dev ETH is modeled as an always-confirmed Asset struct for programmatic consistency */ function getEthAsset() private pure returns (Structs.Asset memory) { return Structs.Asset(true, address(0x0), 'ETH', 18, true, 0); } // See https://solidity.readthedocs.io/en/latest/types.html#bytes-and-strings-as-arrays function isStringEqual(string memory a, string memory b) private pure returns (bool) { return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b)); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import { SafeMath as SafeMath256 } from './SafeMath.sol'; import { IERC20 } from './Interfaces.sol'; /** * @notice This library provides helper utilities for transfering assets in and out of contracts. * It further validates ERC-20 compliant balance updates in the case of token assets */ library AssetTransfers { using SafeMath256 for uint256; /** * @dev Transfers tokens from a wallet into a contract during deposits. `wallet` must already * have called `approve` on the token contract for at least `tokenQuantity`. Note this only * applies to tokens since ETH is sent in the deposit transaction via `msg.value` */ function transferFrom( address wallet, IERC20 tokenAddress, uint256 quantityInAssetUnits ) internal { uint256 balanceBefore = tokenAddress.balanceOf(address(this)); // Because we check for the expected balance change we can safely ignore the return value of transferFrom tokenAddress.transferFrom(wallet, address(this), quantityInAssetUnits); uint256 balanceAfter = tokenAddress.balanceOf(address(this)); require( balanceAfter.sub(balanceBefore) == quantityInAssetUnits, 'Token contract returned transferFrom success without expected balance change' ); } /** * @dev Transfers ETH or token assets from a contract to 1) another contract, when `Exchange` * forwards funds to `Custodian` during deposit or 2) a wallet, when withdrawing */ function transferTo( address payable walletOrContract, address asset, uint256 quantityInAssetUnits ) internal { if (asset == address(0x0)) { require( walletOrContract.send(quantityInAssetUnits), 'ETH transfer failed' ); } else { uint256 balanceBefore = IERC20(asset).balanceOf(walletOrContract); // Because we check for the expected balance change we can safely ignore the return value of transfer IERC20(asset).transfer(walletOrContract, quantityInAssetUnits); uint256 balanceAfter = IERC20(asset).balanceOf(walletOrContract); require( balanceAfter.sub(balanceBefore) == quantityInAssetUnits, 'Token contract returned transfer success without expected balance change' ); } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import { SafeMath as SafeMath256 } from './SafeMath.sol'; /** * @notice Library helpers for converting asset quantities between asset units and pips */ library AssetUnitConversions { using SafeMath256 for uint256; function pipsToAssetUnits(uint64 quantityInPips, uint8 assetDecimals) internal pure returns (uint256) { require(assetDecimals <= 32, 'Asset cannot have more than 32 decimals'); // Exponents cannot be negative, so divide or multiply based on exponent signedness if (assetDecimals > 8) { return uint256(quantityInPips).mul(uint256(10)**(assetDecimals - 8)); } return uint256(quantityInPips).div(uint256(10)**(8 - assetDecimals)); } function assetUnitsToPips(uint256 quantityInAssetUnits, uint8 assetDecimals) internal pure returns (uint64) { require(assetDecimals <= 32, 'Asset cannot have more than 32 decimals'); uint256 quantityInPips; // Exponents cannot be negative, so divide or multiply based on exponent signedness if (assetDecimals > 8) { quantityInPips = quantityInAssetUnits.div( uint256(10)**(assetDecimals - 8) ); } else { quantityInPips = quantityInAssetUnits.mul( uint256(10)**(8 - assetDecimals) ); } require(quantityInPips < 2**64, 'Pip quantity overflows uint64'); return uint64(quantityInPips); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.8; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { revert("ECDSA: invalid signature length"); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { revert("ECDSA: invalid signature 's' value"); } if (v != 27 && v != 28) { revert("ECDSA: invalid signature 'v' value"); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * replicates the behavior of the * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] * JSON-RPC method. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; pragma experimental ABIEncoderV2; /** * @notice Enums used in `Order` and `Withdrawal` structs */ contract Enums { enum OrderSelfTradePrevention { // Decrement and cancel dc, // Cancel oldest co, // Cancel newest cn, // Cancel both cb } enum OrderSide { Buy, Sell } enum OrderTimeInForce { // Good until cancelled gtc, // Good until time gtt, // Immediate or cancel ioc, // Fill or kill fok } enum OrderType { Market, Limit, LimitMaker, StopLoss, StopLossLimit, TakeProfit, TakeProfitLimit } enum WithdrawalType { BySymbol, ByAddress } } /** * @notice Struct definitions */ contract Structs { /** * @notice Argument type for `Exchange.executeTrade` and `Signatures.getOrderWalletHash` */ struct Order { // Not currently used but reserved for future use. Must be 1 uint8 signatureHashVersion; // UUIDv1 unique to wallet uint128 nonce; // Wallet address that placed order and signed hash address walletAddress; // Type of order Enums.OrderType orderType; // Order side wallet is on Enums.OrderSide side; // Order quantity in base or quote asset terms depending on isQuantityInQuote flag uint64 quantityInPips; // Is quantityInPips in quote terms bool isQuantityInQuote; // For limit orders, price in decimal pips * 10^8 in quote terms uint64 limitPriceInPips; // For stop orders, stop loss or take profit price in decimal pips * 10^8 in quote terms uint64 stopPriceInPips; // Optional custom client order ID string clientOrderId; // TIF option specified by wallet for order Enums.OrderTimeInForce timeInForce; // STP behavior specified by wallet for order Enums.OrderSelfTradePrevention selfTradePrevention; // Cancellation time specified by wallet for GTT TIF order uint64 cancelAfter; // The ECDSA signature of the order hash as produced by Signatures.getOrderWalletHash bytes walletSignature; } /** * @notice Return type for `Exchange.loadAssetBySymbol`, and `Exchange.loadAssetByAddress`; also * used internally by `AssetRegistry` */ struct Asset { // Flag to distinguish from empty struct bool exists; // The asset's address address assetAddress; // The asset's symbol string symbol; // The asset's decimal precision uint8 decimals; // Flag set when asset registration confirmed. Asset deposits, trades, or withdrawals only allowed if true bool isConfirmed; // Timestamp as ms since Unix epoch when isConfirmed was asserted uint64 confirmedTimestampInMs; } /** * @notice Argument type for `Exchange.executeTrade` specifying execution parameters for matching orders */ struct Trade { // Base asset symbol string baseAssetSymbol; // Quote asset symbol string quoteAssetSymbol; // Base asset address address baseAssetAddress; // Quote asset address address quoteAssetAddress; // Gross amount including fees of base asset executed uint64 grossBaseQuantityInPips; // Gross amount including fees of quote asset executed uint64 grossQuoteQuantityInPips; // Net amount of base asset received by buy side wallet after fees uint64 netBaseQuantityInPips; // Net amount of quote asset received by sell side wallet after fees uint64 netQuoteQuantityInPips; // Asset address for liquidity maker's fee address makerFeeAssetAddress; // Asset address for liquidity taker's fee address takerFeeAssetAddress; // Fee paid by liquidity maker uint64 makerFeeQuantityInPips; // Fee paid by liquidity taker uint64 takerFeeQuantityInPips; // Execution price of trade in decimal pips * 10^8 in quote terms uint64 priceInPips; // Which side of the order (buy or sell) the liquidity maker was on Enums.OrderSide makerSide; } /** * @notice Argument type for `Exchange.withdraw` and `Signatures.getWithdrawalWalletHash` */ struct Withdrawal { // Distinguishes between withdrawals by asset symbol or address Enums.WithdrawalType withdrawalType; // UUIDv1 unique to wallet uint128 nonce; // Address of wallet to which funds will be returned address payable walletAddress; // Asset symbol string assetSymbol; // Asset address address assetAddress; // Used when assetSymbol not specified // Withdrawal quantity uint64 quantityInPips; // Gas fee deducted from withdrawn quantity to cover dispatcher tx costs uint64 gasFeeInPips; // Not currently used but reserved for future use. Must be true bool autoDispatchEnabled; // The ECDSA signature of the withdrawal hash as produced by Signatures.getWithdrawalWalletHash bytes walletSignature; } } /** * @notice Interface of the ERC20 standard as defined in the EIP, but with no return values for * transfer and transferFrom. By asserting expected balance changes when calling these two methods * we can safely ignore their return values. This allows support of non-compliant tokens that do not * return a boolean. See https://github.com/ethereum/solidity/issues/4116 */ interface IERC20 { /** * @notice Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @notice Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @notice Moves `amount` tokens from the caller's account to `recipient`. * * Most implementing contracts return a boolean value indicating whether the operation succeeded, but * we ignore this and rely on asserting balance changes instead * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external; /** * @notice Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @notice Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @notice Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Most implementing contracts return a boolean value indicating whether the operation succeeded, but * we ignore this and rely on asserting balance changes instead * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external; /** * @notice Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @notice Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } /** * @notice Interface to Custodian contract. Used by Exchange and Governance contracts for internal * delegate calls */ interface ICustodian { /** * @notice ETH can only be sent by the Exchange */ receive() external payable; /** * @notice Withdraw any asset and amount to a target wallet * * @dev No balance checking performed * * @param wallet The wallet to which assets will be returned * @param asset The address of the asset to withdraw (ETH or ERC-20 contract) * @param quantityInAssetUnits The quantity in asset units to withdraw */ function withdraw( address payable wallet, address asset, uint256 quantityInAssetUnits ) external; /** * @notice Load address of the currently whitelisted Exchange contract * * @return The address of the currently whitelisted Exchange contract */ function loadExchange() external view returns (address); /** * @notice Sets a new Exchange contract address * * @param newExchange The address of the new whitelisted Exchange contract */ function setExchange(address newExchange) external; /** * @notice Load address of the currently whitelisted Governance contract * * @return The address of the currently whitelisted Governance contract */ function loadGovernance() external view returns (address); /** * @notice Sets a new Governance contract address * * @param newGovernance The address of the new whitelisted Governance contract */ function setGovernance(address newGovernance) external; } /** * @notice Interface to Exchange contract. Provided only to document struct usage */ interface IExchange { /** * @notice Settles a trade between two orders submitted and matched off-chain * * @param buy A `Structs.Order` struct encoding the parameters of the buy-side order (receiving base, giving quote) * @param sell A `Structs.Order` struct encoding the parameters of the sell-side order (giving base, receiving quote) * @param trade A `Structs.Trade` struct encoding the parameters of this trade execution of the counterparty orders */ function executeTrade( Structs.Order calldata buy, Structs.Order calldata sell, Structs.Trade calldata trade ) external; /** * @notice Settles a user withdrawal submitted off-chain. Calls restricted to currently whitelisted Dispatcher wallet * * @param withdrawal A `Structs.Withdrawal` struct encoding the parameters of the withdrawal */ function withdraw(Structs.Withdrawal calldata withdrawal) external; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; /** * @notice Mixin that provide separate owner and admin roles for RBAC */ abstract contract Owned { address immutable _owner; address _admin; modifier onlyOwner { require(msg.sender == _owner, 'Caller must be owner'); _; } modifier onlyAdmin { require(msg.sender == _admin, 'Caller must be admin'); _; } /** * @notice Sets both the owner and admin roles to the contract creator */ constructor() public { _owner = msg.sender; _admin = msg.sender; } /** * @notice Sets a new whitelisted admin wallet * * @param newAdmin The new whitelisted admin wallet. Must be different from the current one */ function setAdmin(address newAdmin) external onlyOwner { require(newAdmin != address(0x0), 'Invalid wallet address'); require(newAdmin != _admin, 'Must be different from current admin'); _admin = newAdmin; } /** * @notice Clears the currently whitelisted admin wallet, effectively disabling any functions requiring * the admin role */ function removeAdmin() external onlyOwner { _admin = address(0x0); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.8; /** * @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) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); 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-contracts/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) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); 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) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; /** * @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 SafeMath64 { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint64 a, uint64 b) internal pure returns (uint64) { uint64 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(uint64 a, uint64 b) internal pure returns (uint64) { return sub(a, b, 'SafeMath: subtraction overflow'); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub( uint64 a, uint64 b, string memory errorMessage ) internal pure returns (uint64) { require(b <= a, errorMessage); uint64 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(uint64 a, uint64 b) internal pure returns (uint64) { // 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-contracts/pull/522 if (a == 0) { return 0; } uint64 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(uint64 a, uint64 b) internal pure returns (uint64) { return div(a, b, 'SafeMath: division by zero'); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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. * * _Available since v2.4.0._ */ function div( uint64 a, uint64 b, string memory errorMessage ) internal pure returns (uint64) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint64 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import { ECDSA } from './ECDSA.sol'; import { Enums, Structs } from './Interfaces.sol'; /** * Library helpers for building hashes and verifying wallet signatures on `Order` and `Withdrawal` structs */ library Signatures { function isSignatureValid( bytes32 hash, bytes memory signature, address signer ) internal pure returns (bool) { return ECDSA.recover(ECDSA.toEthSignedMessageHash(hash), signature) == signer; } function getOrderWalletHash( Structs.Order memory order, string memory baseSymbol, string memory quoteSymbol ) internal pure returns (bytes32) { require( order.signatureHashVersion == 1, 'Signature hash version must be 1' ); return keccak256( // Placing all the fields in a single `abi.encodePacked` call causes a `stack too deep` error abi.encodePacked( abi.encodePacked( order.signatureHashVersion, order.nonce, order.walletAddress, getMarketSymbol(baseSymbol, quoteSymbol), uint8(order.orderType), uint8(order.side), // Ledger qtys and prices are in pip, but order was signed by wallet owner with decimal values pipToDecimal(order.quantityInPips) ), abi.encodePacked( order.isQuantityInQuote, order.limitPriceInPips > 0 ? pipToDecimal(order.limitPriceInPips) : '', order.stopPriceInPips > 0 ? pipToDecimal(order.stopPriceInPips) : '', order.clientOrderId, uint8(order.timeInForce), uint8(order.selfTradePrevention), order.cancelAfter ) ) ); } function getWithdrawalWalletHash(Structs.Withdrawal memory withdrawal) internal pure returns (bytes32) { return keccak256( abi.encodePacked( withdrawal.nonce, withdrawal.walletAddress, // Ternary branches must resolve to the same type, so wrap in idempotent encodePacked withdrawal.withdrawalType == Enums.WithdrawalType.BySymbol ? abi.encodePacked(withdrawal.assetSymbol) : abi.encodePacked(withdrawal.assetAddress), pipToDecimal(withdrawal.quantityInPips), withdrawal.autoDispatchEnabled ) ); } /** * @dev Combines base and quote asset symbols into the market symbol originally signed by the * wallet. For example if base is 'IDEX' and quote is 'ETH', the resulting market symbol is * 'IDEX-ETH'. This approach is used rather than passing in the market symbol and splitting it * since the latter incurs a higher gas cost */ function getMarketSymbol(string memory baseSymbol, string memory quoteSymbol) private pure returns (string memory) { bytes memory baseSymbolBytes = bytes(baseSymbol); bytes memory hyphenBytes = bytes('-'); bytes memory quoteSymbolBytes = bytes(quoteSymbol); bytes memory marketSymbolBytes = bytes( new string( baseSymbolBytes.length + quoteSymbolBytes.length + hyphenBytes.length ) ); uint256 i; uint256 j; for (i = 0; i < baseSymbolBytes.length; i++) { marketSymbolBytes[j++] = baseSymbolBytes[i]; } // Hyphen is one byte marketSymbolBytes[j++] = hyphenBytes[0]; for (i = 0; i < quoteSymbolBytes.length; i++) { marketSymbolBytes[j++] = quoteSymbolBytes[i]; } return string(marketSymbolBytes); } /** * @dev Converts an integer pip quantity back into the fixed-precision decimal pip string * originally signed by the wallet. For example, 1234567890 becomes '12.34567890' */ function pipToDecimal(uint256 pips) private pure returns (string memory) { // Inspired by https://github.com/provable-things/ethereum-api/blob/831f4123816f7a3e57ebea171a3cdcf3b528e475/oraclizeAPI_0.5.sol#L1045-L1062 uint256 copy = pips; uint256 length; while (copy != 0) { length++; copy /= 10; } if (length < 9) { length = 9; // a zero before the decimal point plus 8 decimals } length++; // for the decimal point bytes memory decimal = new bytes(length); for (uint256 i = length; i > 0; i--) { if (length - i == 8) { decimal[i - 1] = bytes1(uint8(46)); // period } else { decimal[i - 1] = bytes1(uint8(48 + (pips % 10))); pips /= 10; } } return string(decimal); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.6.8; import { SafeMath64 } from './SafeMath64.sol'; /** * Library helper for extracting timestamp component of Version 1 UUIDs */ library UUID { using SafeMath64 for uint64; /** * Extracts the timestamp component of a Version 1 UUID. Used to make time-based assertions * against a wallet-privided nonce */ function getTimestampInMsFromUuidV1(uint128 uuid) internal pure returns (uint64 msSinceUnixEpoch) { // https://tools.ietf.org/html/rfc4122#section-4.1.2 uint128 version = (uuid >> 76) & 0x0000000000000000000000000000000F; require(version == 1, 'Must be v1 UUID'); // Time components are in reverse order so shift+mask each to reassemble uint128 timeHigh = (uuid >> 16) & 0x00000000000000000FFF000000000000; uint128 timeMid = (uuid >> 48) & 0x00000000000000000000FFFF00000000; uint128 timeLow = (uuid >> 96) & 0x000000000000000000000000FFFFFFFF; uint128 nsSinceGregorianEpoch = (timeHigh | timeMid | timeLow); // Gregorian offset given in seconds by https://www.wolframalpha.com/input/?i=convert+1582-10-15+UTC+to+unix+time msSinceUnixEpoch = uint64(nsSinceGregorianEpoch / 10000).sub( 12219292800000 ); return msSinceUnixEpoch; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"ChainPropagationPeriodChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"index","type":"uint64"},{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"string","name":"assetSymbolIndex","type":"string"},{"indexed":false,"internalType":"string","name":"assetSymbol","type":"string"},{"indexed":false,"internalType":"uint64","name":"quantityInPips","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newExchangeBalanceInPips","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"newExchangeBalanceInAssetUnits","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"DispatcherChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousValue","type":"address"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"FeeWalletChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint128","name":"nonce","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"timestampInMs","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"effectiveBlockNumber","type":"uint256"}],"name":"OrderNonceInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"string","name":"assetSymbol","type":"string"},{"indexed":false,"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"TokenRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"string","name":"assetSymbol","type":"string"},{"indexed":false,"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"TokenRegistrationConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"string","name":"assetSymbol","type":"string"}],"name":"TokenSymbolAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"buyWallet","type":"address"},{"indexed":false,"internalType":"address","name":"sellWallet","type":"address"},{"indexed":true,"internalType":"string","name":"baseAssetSymbolIndex","type":"string"},{"indexed":true,"internalType":"string","name":"quoteAssetSymbolIndex","type":"string"},{"indexed":false,"internalType":"string","name":"baseAssetSymbol","type":"string"},{"indexed":false,"internalType":"string","name":"quoteAssetSymbol","type":"string"},{"indexed":false,"internalType":"uint64","name":"baseQuantityInPips","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"quoteQuantityInPips","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"tradePriceInPips","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"buyOrderHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"sellOrderHash","type":"bytes32"}],"name":"TradeExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"WalletExitCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"string","name":"assetSymbol","type":"string"},{"indexed":false,"internalType":"uint64","name":"quantityInPips","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newExchangeBalanceInPips","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"newExchangeBalanceInAssetUnits","type":"uint256"}],"name":"WalletExitWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"effectiveBlockNumber","type":"uint256"}],"name":"WalletExited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"string","name":"assetSymbol","type":"string"},{"indexed":false,"internalType":"uint64","name":"quantityInPips","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newExchangeBalanceInPips","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"newExchangeBalanceInAssetUnits","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"contract IERC20","name":"tokenAddress","type":"address"},{"internalType":"string","name":"symbol","type":"string"}],"name":"addTokenSymbol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearWalletExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenAddress","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"confirmTokenRegistration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositEther","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"quantityInAssetUnits","type":"uint256"}],"name":"depositTokenByAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"assetSymbol","type":"string"},{"internalType":"uint256","name":"quantityInAssetUnits","type":"uint256"}],"name":"depositTokenBySymbol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"signatureHashVersion","type":"uint8"},{"internalType":"uint128","name":"nonce","type":"uint128"},{"internalType":"address","name":"walletAddress","type":"address"},{"internalType":"enum Enums.OrderType","name":"orderType","type":"uint8"},{"internalType":"enum Enums.OrderSide","name":"side","type":"uint8"},{"internalType":"uint64","name":"quantityInPips","type":"uint64"},{"internalType":"bool","name":"isQuantityInQuote","type":"bool"},{"internalType":"uint64","name":"limitPriceInPips","type":"uint64"},{"internalType":"uint64","name":"stopPriceInPips","type":"uint64"},{"internalType":"string","name":"clientOrderId","type":"string"},{"internalType":"enum Enums.OrderTimeInForce","name":"timeInForce","type":"uint8"},{"internalType":"enum Enums.OrderSelfTradePrevention","name":"selfTradePrevention","type":"uint8"},{"internalType":"uint64","name":"cancelAfter","type":"uint64"},{"internalType":"bytes","name":"walletSignature","type":"bytes"}],"internalType":"struct Structs.Order","name":"buy","type":"tuple"},{"components":[{"internalType":"uint8","name":"signatureHashVersion","type":"uint8"},{"internalType":"uint128","name":"nonce","type":"uint128"},{"internalType":"address","name":"walletAddress","type":"address"},{"internalType":"enum Enums.OrderType","name":"orderType","type":"uint8"},{"internalType":"enum Enums.OrderSide","name":"side","type":"uint8"},{"internalType":"uint64","name":"quantityInPips","type":"uint64"},{"internalType":"bool","name":"isQuantityInQuote","type":"bool"},{"internalType":"uint64","name":"limitPriceInPips","type":"uint64"},{"internalType":"uint64","name":"stopPriceInPips","type":"uint64"},{"internalType":"string","name":"clientOrderId","type":"string"},{"internalType":"enum Enums.OrderTimeInForce","name":"timeInForce","type":"uint8"},{"internalType":"enum Enums.OrderSelfTradePrevention","name":"selfTradePrevention","type":"uint8"},{"internalType":"uint64","name":"cancelAfter","type":"uint64"},{"internalType":"bytes","name":"walletSignature","type":"bytes"}],"internalType":"struct Structs.Order","name":"sell","type":"tuple"},{"components":[{"internalType":"string","name":"baseAssetSymbol","type":"string"},{"internalType":"string","name":"quoteAssetSymbol","type":"string"},{"internalType":"address","name":"baseAssetAddress","type":"address"},{"internalType":"address","name":"quoteAssetAddress","type":"address"},{"internalType":"uint64","name":"grossBaseQuantityInPips","type":"uint64"},{"internalType":"uint64","name":"grossQuoteQuantityInPips","type":"uint64"},{"internalType":"uint64","name":"netBaseQuantityInPips","type":"uint64"},{"internalType":"uint64","name":"netQuoteQuantityInPips","type":"uint64"},{"internalType":"address","name":"makerFeeAssetAddress","type":"address"},{"internalType":"address","name":"takerFeeAssetAddress","type":"address"},{"internalType":"uint64","name":"makerFeeQuantityInPips","type":"uint64"},{"internalType":"uint64","name":"takerFeeQuantityInPips","type":"uint64"},{"internalType":"uint64","name":"priceInPips","type":"uint64"},{"internalType":"enum Enums.OrderSide","name":"makerSide","type":"uint8"}],"internalType":"struct Structs.Trade","name":"trade","type":"tuple"}],"name":"executeTrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exitWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"nonce","type":"uint128"}],"name":"invalidateOrderNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"assetSymbol","type":"string"},{"internalType":"uint64","name":"timestampInMs","type":"uint64"}],"name":"loadAssetBySymbol","outputs":[{"components":[{"internalType":"bool","name":"exists","type":"bool"},{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"bool","name":"isConfirmed","type":"bool"},{"internalType":"uint64","name":"confirmedTimestampInMs","type":"uint64"}],"internalType":"struct Structs.Asset","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"address","name":"assetAddress","type":"address"}],"name":"loadBalanceInAssetUnitsByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"string","name":"assetSymbol","type":"string"}],"name":"loadBalanceInAssetUnitsBySymbol","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"address","name":"assetAddress","type":"address"}],"name":"loadBalanceInPipsByAddress","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"string","name":"assetSymbol","type":"string"}],"name":"loadBalanceInPipsBySymbol","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"loadFeeWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"loadPartiallyFilledOrderQuantityInPips","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenAddress","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"registerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeDispatcher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newChainPropagationPeriod","type":"uint256"}],"name":"setChainPropagationPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newCustodian","type":"address"}],"name":"setCustodian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDispatcherWallet","type":"address"}],"name":"setDispatcher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeWallet","type":"address"}],"name":"setFeeWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum Enums.WithdrawalType","name":"withdrawalType","type":"uint8"},{"internalType":"uint128","name":"nonce","type":"uint128"},{"internalType":"address payable","name":"walletAddress","type":"address"},{"internalType":"string","name":"assetSymbol","type":"string"},{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint64","name":"quantityInPips","type":"uint64"},{"internalType":"uint64","name":"gasFeeInPips","type":"uint64"},{"internalType":"bool","name":"autoDispatchEnabled","type":"bool"},{"internalType":"bytes","name":"walletSignature","type":"bytes"}],"internalType":"struct Structs.Withdrawal","name":"withdrawal","type":"tuple"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetAddress","type":"address"}],"name":"withdrawExit","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b5033606081901b608052600080546001600160a01b03191682178155615ff99062000049903980610f2952806113685250615ff96000f3fe6080604052600436106101415760003560e01c806372e8f08d116100b157806372e8f08d146102ea578063869af2121461030a57806390d49b9d14610337578063985c4af51461035757806398ea5fca146103775780639a202d471461037f578063ae0e969e14610394578063ba22bd76146103c1578063d7a6aec7146103e1578063dbb3653514610401578063dcc6349014610421578063eb5068f214610441578063ef3b9d4a1461045657610141565b80630226b70e1461014657806302ca6002146101685780630c187a721461019357806313cfda2c146101a85780631abb5832146101d557806320e6a8e3146101f5578063403f3731146102155780634196818214610235578063457aa3c6146102555780634a284ef91461027557806365fce5b71461028a5780636bb509f2146102aa578063704b6c02146102ca575b600080fd5b34801561015257600080fd5b50610166610161366004614559565b610476565b005b34801561017457600080fd5b5061017d610540565b60405161018a9190614c10565b60405180910390f35b34801561019f57600080fd5b50610166610550565b3480156101b457600080fd5b506101c86101c33660046144b7565b6105d4565b60405161018a9190615ea2565b3480156101e157600080fd5b506101c86101f03660046144ef565b610662565b34801561020157600080fd5b50610166610210366004614541565b610736565b34801561022157600080fd5b5061016661023036600461449b565b6107c7565b34801561024157600080fd5b506101666102503660046145e9565b610861565b34801561026157600080fd5b50610166610270366004614559565b6108e3565b34801561028157600080fd5b50610166610996565b34801561029657600080fd5b506101666102a536600461468d565b610a0a565b3480156102b657600080fd5b506101666102c5366004614850565b610bb1565b3480156102d657600080fd5b506101666102e536600461449b565b610f1e565b3480156102f657600080fd5b506101666103053660046144ef565b610fdc565b34801561031657600080fd5b5061032a610325366004614632565b611099565b60405161018a9190615e07565b34801561034357600080fd5b5061016661035236600461449b565b6110f3565b34801561036357600080fd5b5061016661037236600461449b565b6111c4565b61016661134f565b34801561038b57600080fd5b5061016661135d565b3480156103a057600080fd5b506103b46103af366004614541565b6113b7565b60405161018a9190615eb9565b3480156103cd57600080fd5b506101666103dc36600461449b565b6113d5565b3480156103ed57600080fd5b506101666103fc366004614962565b6114a6565b34801561040d57600080fd5b506103b461041c3660046144b7565b61161e565b34801561042d57600080fd5b5061016661043c3660046145be565b61167b565b34801561044d57600080fd5b506101666116b0565b34801561046257600080fd5b506103b46104713660046144ef565b611762565b6000546001600160a01b031633146104a95760405162461bcd60e51b81526004016104a0906159ba565b60405180910390fd5b6104f58484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001949392508691505063ffffffff61180c16565b836001600160a01b03167fa8968236dc4afb2c189afeb69c91b02445e6bd09f0ffe27256b62838edc99edb84848460405161053293929190614d25565b60405180910390a250505050565b600c546001600160a01b03165b90565b6000546001600160a01b0316331461057a5760405162461bcd60e51b81526004016104a0906159ba565b600b546040517fddb86df2d5262dd7b44067db5962cc7875e9db409cb21c88adfe3c5760315e39916105ba916001600160a01b0390911690600090614c61565b60405180910390a1600b80546001600160a01b0319169055565b60006001600160a01b0383166105fc5760405162461bcd60e51b81526004016104a090615c07565b610604614140565b61061560018463ffffffff611b6216565b6001600160a01b038086166000908152600660209081526040808320938816835292905220546060820151919250610658916001600160401b0390911690611cbb565b9150505b92915050565b60006001600160a01b03841661068a5760405162461bcd60e51b81526004016104a090615c07565b610692614140565b6106e484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106d59250611d33915050565b6001919063ffffffff611d3b16565b6001600160a01b0380871660009081526006602090815260408083208286015190941683529290522054606082015191925061072b916001600160401b0390911690611cbb565b9150505b9392505050565b6000546001600160a01b031633146107605760405162461bcd60e51b81526004016104a0906159ba565b619d8081106107815760405162461bcd60e51b81526004016104a0906155ab565b600a8054908290556040517f9a22227d6c0251a79ef8b846202ddcbe9d682ee5482e84abeec6dda096398a6f906107bb9083908590615eab565b60405180910390a15050565b6000546001600160a01b031633146107f15760405162461bcd60e51b81526004016104a0906159ba565b6005546001600160a01b03161561081a5760405162461bcd60e51b81526004016104a0906157f0565b61082381611fa5565b61083f5760405162461bcd60e51b81526004016104a090614ee0565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60006108a684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106d59250611d33915050565b6020015190506001600160a01b0381166108d25760405162461bcd60e51b81526004016104a090615574565b6108dd338284611fab565b50505050565b6000546001600160a01b0316331461090d5760405162461bcd60e51b81526004016104a0906159ba565b6109598484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001949392508691505063ffffffff6121d016565b836001600160a01b03167fcf66acda7673c71cd9458c59067eb30a473eeaf2fa05d008acf47616cbbbe01c84848460405161053293929190614d25565b3360009081526009602052604090205460ff166109c55760405162461bcd60e51b81526004016104a090615bdc565b33600081815260096020526040808220805460ff19168155600101829055517fb771d4b2a83beca38f442c8903629e0e8ab1a07cf76e94eb2977153167e209369190a2565b600b546001600160a01b03163314610a345760405162461bcd60e51b81526004016104a090614df9565b610a41836040015161237a565b15610a5e5760405162461bcd60e51b81526004016104a090615cf0565b610a6b826040015161237a565b15610a885760405162461bcd60e51b81526004016104a0906150fd565b81604001516001600160a01b031683604001516001600160a01b03161415610ac25760405162461bcd60e51b81526004016104a090615455565b610acd8383836123ab565b610ad8838383612620565b610ae28383612731565b600080610af08585856127c3565b91509150610afd836127ee565b610b0a85838684876129e8565b610b15858585612a05565b8260200151604051610b279190614ac2565b60405190819003812084519091610b3e9190614ac2565b60405180910390207fbd75b2e24c3d43ec9f10f3583265606c0a7d8b67d147f9dc48376b81456823a1876040015187604001518760000151886020015189608001518a60a001518b61018001518b8b604051610ba299989796959493929190614c7b565b60405180910390a35050505050565b600b546001600160a01b03163314610bdb5760405162461bcd60e51b81526004016104a090614df9565b610be8816040015161237a565b15610c055760405162461bcd60e51b81526004016104a090615d6b565b6107d06001600160401b0316610c238260c001518360a00151612cff565b6001600160401b03161115610c4a5760405162461bcd60e51b81526004016104a0906156cf565b6000610c5582612d36565b60008181526004602052604090205490915060ff1615610c875760405162461bcd60e51b81526004016104a090615827565b610c8f614140565b600083516001811115610c9e57fe5b14610cbf576080830151610cba9060019063ffffffff611b6216565b610cd4565b610cd483606001516106d58560200151612d74565b90506000610cfc8460c001518560a001516001600160401b0316612e0190919063ffffffff16565b90506000610d0e828460600151611cbb565b60a08601516040808801516001600160a01b03908116600090815260066020908152838220898201519093168252919091529081205492935091610d63916001600160401b039091169063ffffffff612e0116565b90506000610d75828660600151611cbb565b6040888101516001600160a01b039081166000908152600660208181528483208b820180518616855290825285842080546001600160401b0319166001600160401b038b81169190911790915560c08f0151600c548716865293835286852091519095168452905292902054929350610def921690612e43565b600c546001600160a01b0390811660009081526006602090815260408083208a830180518616855292529182902080546001600160401b0319166001600160401b0395909516949094179093556005548a82015193519151636ce5768960e11b815292169263d9caed1292610e6992908890600401614c24565b600060405180830381600087803b158015610e8357600080fd5b505af1158015610e97573d6000803e3d6000fd5b505050600087815260046020908152604091829020805460ff19166001179055870151898201518883015160a08c015193516001600160a01b03938416955091909216927f6960a1f64ecf9da0d1d1bcbfa3dd27f8c1c60de69b13faa28127dafa36c111e492610f0d9290919088908890614d5f565b60405180910390a350505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f665760405162461bcd60e51b81526004016104a090615779565b6001600160a01b038116610f8c5760405162461bcd60e51b81526004016104a090615c07565b6000546001600160a01b0382811691161415610fba5760405162461bcd60e51b81526004016104a09061502e565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146110065760405162461bcd60e51b81526004016104a0906159ba565b6110518383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001949392505063ffffffff612e74169050565b826001600160a01b03167f7f63a63f4a2ea318da0b031794d0b5a3183a1b2de54e053ceb17cabdba031735838360405161108c929190614d11565b60405180910390a2505050565b6110a1614140565b6110eb84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019392508691505063ffffffff611d3b16565b949350505050565b6000546001600160a01b0316331461111d5760405162461bcd60e51b81526004016104a0906159ba565b6001600160a01b0381166111435760405162461bcd60e51b81526004016104a090615c07565b600c546001600160a01b03828116911614156111715760405162461bcd60e51b81526004016104a0906157a7565b600c80546001600160a01b038381166001600160a01b03198316179092556040519116907f9f4f5dce3c4d197b5d7496cb96e25f0a89809167195964b0daa3ef5fed63c00a906107bb9083908590614c61565b6111cd3361237a565b6111e95760405162461bcd60e51b81526004016104a0906153f3565b6111f1614140565b61120260018363ffffffff611b6216565b3360009081526006602090815260408083206001600160a01b038716845290915281205460608301519293506001600160401b031691611243908390611cbb565b9050600081116112655760405162461bcd60e51b81526004016104a090615d92565b3360008181526006602090815260408083206001600160a01b03898116855292529182902080546001600160401b03191690556005549151636ce5768960e11b815291169163d9caed12916112c1919088908690600401614c24565b600060405180830381600087803b1580156112db57600080fd5b505af11580156112ef573d6000803e3d6000fd5b50505050836001600160a01b0316336001600160a01b03167f02e03f232c88c87047c5a9cfbad1213b842503fee6a002ec2eec9f5a64725bf48560400151856000806040516113419493929190614d5f565b60405180910390a350505050565b61135b33600034611fab565b565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113a55760405162461bcd60e51b81526004016104a090615779565b600080546001600160a01b0319169055565b6000818152600860205260409020546001600160401b03165b919050565b6000546001600160a01b031633146113ff5760405162461bcd60e51b81526004016104a0906159ba565b6001600160a01b0381166114255760405162461bcd60e51b81526004016104a090615c07565b600b546001600160a01b03828116911614156114535760405162461bcd60e51b81526004016104a090615888565b600b80546001600160a01b038381166001600160a01b03198316179092556040519116907fddb86df2d5262dd7b44067db5962cc7875e9db409cb21c88adfe3c5760315e39906107bb9083908590614c61565b60006114b182612d74565b90506114bb613089565b6001600160401b0316816001600160401b0316106114eb5760405162461bcd60e51b81526004016104a0906153b2565b3360009081526007602052604090205460ff161561157457336000908152600760205260409020546001600160401b0380831661010090920416106115425760405162461bcd60e51b81526004016104a090614e9d565b336000908152600760205260409020600101544310156115745760405162461bcd60e51b81526004016104a090615adf565b600a546040805160608101825260018082526001600160401b0385811660208085019182524390960184860181815233600081815260079099529787902095518654935160ff199094169015151768ffffffffffffffff001916610100939094169290920292909217845551929091019190915590519091907f10cf19671b43c88b1f02d4e94932d7ffaa89c7278bc5b8868fa7b7676210809b9061108c90869086908690615e78565b60006001600160a01b0383166116465760405162461bcd60e51b81526004016104a090615c07565b506001600160a01b0391821660009081526006602090815260408083209390941682529190915220546001600160401b031690565b6001600160a01b0382166116a15760405162461bcd60e51b81526004016104a090615738565b6116ac338383611fab565b5050565b3360009081526009602052604090205460ff16156116e05760405162461bcd60e51b81526004016104a090615503565b6040805180820182526001808252600a80544390810160208086019182523360008181526009909252908790209551865460ff19169015151786559051949093019390935554925190927fd60f9f7b2f1a208268475a927bd727c4e198fc8b40aab3004ebcc2bc78ca84809261175892910190615ea2565b60405180910390a2565b60006001600160a01b03841661178a5760405162461bcd60e51b81526004016104a090615c07565b60006117cf84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106d59250611d33915050565b6020908101516001600160a01b03808816600090815260068452604080822092909316815292529020546001600160401b03169150509392505050565b611814614140565b6001600160a01b0384811660009081526020878152604091829020825160c081018452815460ff8116151582526101009081900490951681840152600180830180548651600293821615909802600019011691909104601f81018590048502870185018652808752919592948601939091908301828280156118d75780601f106118ac576101008083540402835291602001916118d7565b820191906000526020600020905b8154815290600101906020018083116118ba57829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091506119335760405162461bcd60e51b81526004016104a09061522b565b8060800151156119555760405162461bcd60e51b81526004016104a090615857565b611963816040015184613096565b61197f5760405162461bcd60e51b81526004016104a090614f09565b8160ff16816060015160ff16146119a85760405162461bcd60e51b81526004016104a090615426565b6001608082018190526001600160401b036103e842021660a08301526001600160a01b0380861660009081526020888152604091829020855181548388015190951661010002610100600160a81b031991151560ff1990961695909517169390931783559084015180518594611a2393908501920190614176565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ff001960ff90951660ff19909316929092179390931617929092161790556040516001860190611a8d908590614ac2565b9081526040805191829003602090810190922080546001818101835560009283529184902085516003909202018054868601516001600160a01b031661010002610100600160a81b031993151560ff1990921691909117929092169190911781559184015180518594611b04938501920190614176565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ff001960ff90951660ff19909316929092179390931617929092161790555050505050565b611b6a614140565b6001600160a01b038216611b8757611b806130ef565b905061065c565b611b8f614140565b6001600160a01b0383811660009081526020868152604091829020825160c081018452815460ff8116151582526101009081900490951681840152600180830180548651600293821615909802600019011691909104601f8101859004850287018501865280875291959294860193909190830182828015611c525780601f10611c2757610100808354040283529160200191611c52565b820191906000526020600020905b815481529060010190602001808311611c3557829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091508015611c9f575080608001515b61072f5760405162461bcd60e51b81526004016104a090615976565b600060208260ff161115611ce15760405162461bcd60e51b81526004016104a090615a15565b60088260ff161115611d1057611b806001600160401b03841660ff600719850116600a0a63ffffffff61314816565b61072f6001600160401b03841660ff600885900316600a0a63ffffffff61318216565b426103e80290565b611d43614140565b611d686040518060400160405280600381526020016208aa8960eb1b81525084613096565b15611d7c57611d756130ef565b905061072f565b611d84614140565b60008560010185604051611d989190614ac2565b908152604051908190036020019020541115611f7a5760005b8560010185604051611dc39190614ac2565b9081526040519081900360200190205460ff82161015611f7857836001600160401b03168660010186604051611df99190614ac2565b90815260200160405180910390208260ff1681548110611e1557fe5b60009182526020909120600390910201600201546201000090046001600160401b031611611f70578560010185604051611e4f9190614ac2565b90815260200160405180910390208160ff1681548110611e6b57fe5b60009182526020918290206040805160c081018252600393909302909101805460ff811615158452610100908190046001600160a01b031684860152600180830180548551600293821615909402600019011691909104601f8101879004870283018701855280835294959294938601939192909190830182828015611f325780601f10611f0757610100808354040283529160200191611f32565b820191906000526020600020905b815481529060010190602001808311611f1557829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015291505b600101611db1565b505b80518015611f89575080608001515b6110eb5760405162461bcd60e51b81526004016104a090615621565b3b151590565b6001600160a01b03831660009081526009602052604090205460ff1615611fe45760405162461bcd60e51b81526004016104a090615d6b565b611fec614140565b611ffd60018463ffffffff611b6216565b9050600061200f8383606001516131c1565b90506000816001600160401b03161161203a5760405162461bcd60e51b81526004016104a090615168565b600061204a828460600151611cbb565b90506001600160a01b0385161561206657612066868683613256565b60055461207d906001600160a01b031686836133e9565b6001600160a01b0380871660009081526006602090815260408083209389168352929052908120546120be906001600160401b03168463ffffffff612e4316565b905060006120d0828660600151611cbb565b6001600160a01b038981166000908152600660209081526040808320938c16835292905281902080546001600160401b0319166001600160401b03868116919091179091556005805467ffffffffffffffff60a01b198116600160a01b9182900484166001019093160291909117905586810151905191925061215291614ac2565b6040518091039020876001600160a01b0316896001600160a01b03167fc2813a84168de59cf710030ba2acb13031b567b8ba76f70e8ab0782aa9469a7a600560149054906101000a90046001600160401b031689604001518988886040516121be959493929190615ecd565b60405180910390a45050505050505050565b60208160ff1611156121f45760405162461bcd60e51b81526004016104a09061536b565b6001600160a01b03831615801590612210575061221083611fa5565b61222c5760405162461bcd60e51b81526004016104a090615ab0565b600082511161224d5760405162461bcd60e51b81526004016104a090615bae565b6001600160a01b038316600090815260208590526040902060020154610100900460ff161561228e5760405162461bcd60e51b81526004016104a090615857565b6040805160c08101825260018082526001600160a01b03868116602080850182815285870189815260ff8916606088015260006080880181905260a088018190529384528b83529690922085518154935160ff1990941690151517610100600160a81b03191661010093909416929092029290921781559351805193949361231d938501929190910190614176565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ff001960ff90951660ff199093169290921793909316179290921617905550505050565b6001600160a01b0381166000908152600960205260408120805460ff16801561072f57506001015443101592915050565b80606001516001600160a01b031681604001516001600160a01b031614156123e55760405162461bcd60e51b81526004016104a090615487565b6123ed614140565b61240282600001516106d58660200151612d74565b905061240c614140565b61242183602001516106d58760200151612d74565b905082604001516001600160a01b031682602001516001600160a01b0316148015612465575082606001516001600160a01b031681602001516001600160a01b0316145b6124815760405162461bcd60e51b81526004016104a090615195565b612489614140565b61249e84600001516106d58760200151612d74565b90506124a8614140565b6124bd85602001516106d58860200151612d74565b905084604001516001600160a01b031682602001516001600160a01b0316148015612501575084606001516001600160a01b031681602001516001600160a01b0316145b61251d5760405162461bcd60e51b81526004016104a090615a5c565b84604001516001600160a01b03168561010001516001600160a01b03161480612560575084606001516001600160a01b03168561010001516001600160a01b0316145b61257c5760405162461bcd60e51b81526004016104a090615327565b84604001516001600160a01b03168561012001516001600160a01b031614806125bf575084606001516001600160a01b03168561012001516001600160a01b0316145b6125db5760405162461bcd60e51b81526004016104a0906155dd565b8461012001516001600160a01b03168561010001516001600160a01b031614156126175760405162461bcd60e51b81526004016104a090614fe2565b50505050505050565b600081608001516001600160401b03161161264d5760405162461bcd60e51b81526004016104a090615dc0565b60008160a001516001600160401b03161161267a5760405162461bcd60e51b81526004016104a090615d23565b61268783606001516135ce565b156126d3578060a001516001600160401b03166126ac82608001518560e00151613627565b6001600160401b031610156126d35760405162461bcd60e51b81526004016104a0906158d1565b6126e082606001516135ce565b1561272c578060a001516001600160401b031661270582608001518460e00151613627565b6001600160401b0316111561272c5760405162461bcd60e51b81526004016104a090615b77565b505050565b61273e8260400151613680565b6001600160401b03166127548360200151612d74565b6001600160401b03161161277a5760405162461bcd60e51b81526004016104a090615935565b6127878160400151613680565b6001600160401b031661279d8260200151612d74565b6001600160401b0316116116ac5760405162461bcd60e51b81526004016104a090615252565b60008060006127d286856136fd565b905060006127e086866136fd565b919791965090945050505050565b600081604001516001600160a01b03168261010001516001600160a01b03161461281c578160a00151612822565b81608001515b90506107d06001600160401b031661283f83610140015183612cff565b6001600160401b031611156128665760405162461bcd60e51b81526004016104a09061509b565b600082604001516001600160a01b03168361012001516001600160a01b031614612894578260a0015161289a565b82608001515b90506107d06001600160401b03166128b784610160015183612cff565b6001600160401b031611156128de5760405162461bcd60e51b81526004016104a090614f6e565b82608001516001600160401b031661293d84604001516001600160a01b03168561010001516001600160a01b03161461291c57846101600151612923565b8461014001515b60c08601516001600160401b03169063ffffffff612e4316565b6001600160401b0316146129635760405162461bcd60e51b81526004016104a090614f9b565b8260a001516001600160401b03166129c284606001516001600160a01b03168561010001516001600160a01b0316146129a1578461016001516129a8565b8461014001515b60e08601516001600160401b03169063ffffffff612e4316565b6001600160401b03161461272c5760405162461bcd60e51b81526004016104a090615b2f565b6129f385858361379e565b6129fe83838361379e565b5050505050565b60808101516040808401516001600160a01b03908116600090815260066020908152838220848701519093168252919091522054612a54916001600160401b039091169063ffffffff612e0116565b6040838101516001600160a01b0390811660009081526006602081815284832087860180518616855290825285842080546001600160401b0319166001600160401b0398891617905560c08801518a8701518616855292825285842090519094168352929092529190912054612acb921690612e43565b604084810180516001600160a01b039081166000908152600660208181528583208887015185168452815285832080546001600160401b0319166001600160401b0398891617905560a088015194518416835290815284822060608801519093168252919091529190912054612b42921690612e01565b6040848101516001600160a01b039081166000908152600660208181528483206060880180518616855290825285842080546001600160401b0319166001600160401b0398891617905560e0880151898701518616855292825285842090519094168352929092529190912054612bba921690612e43565b6040838101516001600160a01b03908116600090815260066020818152848320606088015185168452815284832080546001600160401b0319166001600160401b03978816179055610140870151600c54851684529181528483206101008801519094168352929092529190912054612c34921690612e43565b600c80546001600160a01b03908116600090815260066020818152604080842061010089015186168552825280842080546001600160401b0319166001600160401b039889161790556101608801519554851684529181528183206101208801519094168352929092522054612cab921690612e43565b600c546001600160a01b039081166000908152600660209081526040808320610120969096015190931682529390935290912080546001600160401b0319166001600160401b039092169190911790555050565b600061271061065883612d216001600160401b0387168463ffffffff61392216565b6001600160401b03169063ffffffff61397d16565b600080612d42836139bc565b9050612d58818461010001518560400151613a77565b61065c5760405162461bcd60e51b81526004016104a090614dc7565b6000600f604c83901c1660018114612d9e5760405162461bcd60e51b81526004016104a090615072565b610fff60301b601084901c1665ffff00000000603085901c1663ffffffff606086901c168183178117612df6650b1d069b54006127106001600160801b038416046001600160401b0316612e0190919063ffffffff16565b979650505050505050565b600061072f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613aa7565b60008282016001600160401b03808516908216101561072f5760405162461bcd60e51b81526004016104a0906150c8565b612e7c614140565b6001600160a01b0383811660009081526020868152604091829020825160c081018452815460ff8116151582526101009081900490951681840152600180830180548651600293821615909802600019011691909104601f8101859004850287018501865280875291959294860193909190830182828015612f3f5780601f10612f1457610100808354040283529160200191612f3f565b820191906000526020600020905b815481529060010190602001808311612f2257829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091508015612f8c575080608001515b612fa85760405162461bcd60e51b81526004016104a0906151e8565b612fcd826040518060400160405280600381526020016208aa8960eb1b815250613096565b15612fea5760405162461bcd60e51b81526004016104a090615131565b426103e89081026001600160401b031660a08301526040516001860190613012908590614ac2565b9081526040805191829003602090810190922080546001818101835560009283529184902086516003909202018054878601516001600160a01b031661010002610100600160a81b031993151560ff1990921691909117929092169190911781559185015180518694611b04938501920190614176565b4262015180016103e80290565b6000816040516020016130a99190614ac2565b60405160208183030381529060405280519060200120836040516020016130d09190614ac2565b6040516020818303038152906040528051906020012014905092915050565b6130f7614140565b506040805160c08101825260018082526000602080840182905284518086018652600381526208aa8960eb1b918101919091529383019390935260126060830152608082015260a081019190915290565b6000826131575750600061065c565b8282028284828161316457fe5b041461072f5760405162461bcd60e51b81526004016104a09061568e565b600061072f83836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b815250613ae6565b600060208260ff1611156131e75760405162461bcd60e51b81526004016104a090615a15565b600060088360ff1611156132165761320f8460ff600719860116600a0a63ffffffff61318216565b9050613233565b6132308460ff600886900316600a0a63ffffffff61314816565b90505b600160401b811061072f5760405162461bcd60e51b81526004016104a090615701565b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190613285903090600401614c10565b60206040518083038186803b15801561329d57600080fd5b505afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d5919061497d565b6040516323b872dd60e01b81529091506001600160a01b038416906323b872dd9061330890879030908790600401614c24565b600060405180830381600087803b15801561332257600080fd5b505af1158015613336573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b03861691506370a0823190613369903090600401614c10565b60206040518083038186803b15801561338157600080fd5b505afa158015613395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b9919061497d565b9050826133cc828463ffffffff613b1d16565b146129fe5760405162461bcd60e51b81526004016104a090614e2b565b6001600160a01b03821661343d576040516001600160a01b0384169082156108fc029083906000818181858888f193505050506134385760405162461bcd60e51b81526004016104a0906159e8565b61272c565b6040516370a0823160e01b81526000906001600160a01b038416906370a082319061346c908790600401614c10565b60206040518083038186803b15801561348457600080fd5b505afa158015613498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134bc919061497d565b60405163a9059cbb60e01b81529091506001600160a01b0384169063a9059cbb906134ed9087908690600401614c48565b600060405180830381600087803b15801561350757600080fd5b505af115801561351b573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b03861691506370a082319061354e908890600401614c10565b60206040518083038186803b15801561356657600080fd5b505afa15801561357a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359e919061497d565b9050826135b1828463ffffffff613b1d16565b146129fe5760405162461bcd60e51b81526004016104a090615c82565b600060018260068111156135de57fe5b14806135f5575060028260068111156135f357fe5b145b8061360b5750600482600681111561360957fe5b145b8061065c575060065b82600681111561362057fe5b1492915050565b60006305f5e1008161365b8261364f6001600160401b0388811690881663ffffffff61314816565b9063ffffffff61318216565b9050600160401b81106106585760405162461bcd60e51b81526004016104a090615c37565b6001600160a01b03811660009081526007602052604081205460ff1680156136c357506001600160a01b0382166000908152600760205260409020600101544310155b156136f557506001600160a01b03811660009081526007602052604090205461010090046001600160401b03166113d0565b506000919050565b6000806137138484600001518560200151613b5f565b905061372981856101a001518660400151613a77565b60008560800151600181111561373b57fe5b1461375e57604051806060016040528060278152602001615f9d60279139613778565b604051806060016040528060268152602001615f77602691395b906137965760405162461bcd60e51b81526004016104a09190614d4c565b509392505050565b60008281526003602052604090205460ff16156137cd5760405162461bcd60e51b81526004016104a090615908565b60008360c0015115613839576137e68460600151613d01565b6138025760405162461bcd60e51b81526004016104a090615294565b60008381526008602052604090205460a0830151613832916001600160401b03918216911663ffffffff612e4316565b905061386c565b6000838152600860205260409020546080830151613869916001600160401b03918216911663ffffffff612e4316565b90505b8360a001516001600160401b0316816001600160401b031611156138a25760405162461bcd60e51b81526004016104a090615664565b8360a001516001600160401b0316816001600160401b031610156138ec57600083815260086020526040902080546001600160401b0319166001600160401b0383161790556108dd565b5050600090815260086020908152604080832080546001600160401b031916905560039091529020805460ff1916600117905550565b60006001600160401b03831661393a5750600061065c565b8282026001600160401b03808416908086169083168161395657fe5b046001600160401b03161461072f5760405162461bcd60e51b81526004016104a09061568e565b600061072f83836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b815250613d34565b602081015160408201516000919082845160018111156139d857fe5b14613a065783608001516040516020016139f291906149eb565b604051602081830303815290604052613a2b565b8360600151604051602001613a1b9190614ac2565b6040516020818303038152906040525b613a418560a001516001600160401b0316613d7c565b8560e00151604051602001613a5a959493929190614b0f565b604051602081830303815290604052805190602001209050919050565b6000816001600160a01b0316613a95613a8f86613e78565b85613e8b565b6001600160a01b031614949350505050565b6000836001600160401b0316836001600160401b031611158290613ade5760405162461bcd60e51b81526004016104a09190614d4c565b505050900390565b60008183613b075760405162461bcd60e51b81526004016104a09190614d4c565b506000838581613b1357fe5b0495945050505050565b600061072f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613faf565b6000836000015160ff16600114613b885760405162461bcd60e51b81526004016104a0906154ce565b835160208501516040860151613b9e8686613fd3565b87606001516006811115613bae57fe5b88608001516001811115613bbe57fe5b613bd48a60a001516001600160401b0316613d7c565b604051602001613bea9796959493929190614b7d565b6040516020818303038152906040528460c0015160008660e001516001600160401b031611613c285760405180602001604052806000815250613c3e565b613c3e8660e001516001600160401b0316613d7c565b60008761010001516001600160401b031611613c695760405180602001604052806000815250613c80565b613c808761010001516001600160401b0316613d7c565b8761012001518861014001516003811115613c9757fe5b8961016001516003811115613ca857fe5b8a6101800151604051602001613cc49796959493929190614a03565b60408051601f1981840301815290829052613ce29291602001614a94565b6040516020818303038152906040528051906020012090509392505050565b600080826006811115613d1057fe5b1480613d2757506003826006811115613d2557fe5b145b8061065c57506005613614565b6000816001600160401b038416613d5e5760405162461bcd60e51b81526004016104a09190614d4c565b506000836001600160401b0316856001600160401b031681613b1357fe5b60608160005b8115613d9657600101600a82049150613d82565b6009811015613da3575060095b6001016060816001600160401b0381118015613dbe57600080fd5b506040519080825280601f01601f191660200182016040528015613de9576020820181803683370190505b509050815b8015613e6f5780830360081415613e2f57602e60f81b826001830381518110613e1357fe5b60200101906001600160f81b031916908160001a905350613e66565b600a860660300160f81b826001830381518110613e4857fe5b60200101906001600160f81b031916908160001a905350600a860495505b60001901613dee565b50949350505050565b600081604051602001613a5a9190614ade565b60008151604114613eae5760405162461bcd60e51b81526004016104a090614f37565b60208201516040830151606084015160001a6fa2a8918ca85bafe22016d0b997e4df60600160ff1b03821115613ef65760405162461bcd60e51b81526004016104a0906152e5565b8060ff16601b14158015613f0e57508060ff16601c14155b15613f2b5760405162461bcd60e51b81526004016104a090615532565b600060018783868660405160008152602001604052604051613f509493929190614cf3565b6020604051602081039080840390855afa158015613f72573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613fa55760405162461bcd60e51b81526004016104a090614d95565b9695505050505050565b60008184841115613ade5760405162461bcd60e51b81526004016104a09190614d4c565b604080518082019091526001808252602d60f81b60208301528251845160609386939092869286929101016001600160401b038111801561401357600080fd5b506040519080825280601f01601f19166020018201604052801561403e576020820181803683370190505b5090506000805b85518210156140995785828151811061405a57fe5b602001015160f81c60f81b83828060010193508151811061407757fe5b60200101906001600160f81b031916908160001a905350600190910190614045565b846000815181106140a657fe5b602001015160f81c60f81b8382806001019350815181106140c357fe5b60200101906001600160f81b031916908160001a905350600091505b8351821015614133578382815181106140f457fe5b602001015160f81c60f81b83828060010193508151811061411157fe5b60200101906001600160f81b031916908160001a9053506001909101906140df565b5090979650505050505050565b6040805160c08101825260008082526020820181905260609282018390529181018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106141b757805160ff19168380011785556141e4565b828001600101855582156141e4579182015b828111156141e45782518255916020019190600101906141c9565b506141f09291506141f4565b5090565b61054d91905b808211156141f057600081556001016141fa565b803561065c81615f5e565b8035801515811461065c57600080fd5b600082601f830112614239578081fd5b81356001600160401b0381111561424e578182fd5b614261601f8201601f1916602001615f0c565b915080825283602082850101111561427857600080fd5b8060208401602084013760009082016020015292915050565b80356004811061065c57600080fd5b80356002811061065c57600080fd5b80356007811061065c57600080fd5b60008083601f8401126142cf578182fd5b5081356001600160401b038111156142e5578182fd5b6020830191508360208285010111156142fd57600080fd5b9250929050565b60006101c0808385031215614317578182fd5b61432081615f0c565b91505061432d838361448a565b815261433c836020840161445c565b602082015261434e836040840161420e565b604082015261436083606084016142af565b606082015261437283608084016142a0565b60808201526143848360a08401614473565b60a08201526143968360c08401614219565b60c08201526143a88360e08401614473565b60e08201526101006143bc84828501614473565b90820152610120828101356001600160401b03808211156143dc57600080fd5b6143e886838701614229565b8385015261014092506143fd86848701614291565b83850152610160925061441286848701614291565b83850152610180925061442786848701614473565b838501526101a092508285013591508082111561444357600080fd5b5061445085828601614229565b82840152505092915050565b80356001600160801b038116811461065c57600080fd5b80356001600160401b038116811461065c57600080fd5b803560ff8116811461065c57600080fd5b6000602082840312156144ac578081fd5b813561072f81615f5e565b600080604083850312156144c9578081fd5b82356144d481615f5e565b915060208301356144e481615f5e565b809150509250929050565b600080600060408486031215614503578081fd5b833561450e81615f5e565b925060208401356001600160401b03811115614528578182fd5b614534868287016142be565b9497909650939450505050565b600060208284031215614552578081fd5b5035919050565b6000806000806060858703121561456e578182fd5b843561457981615f5e565b935060208501356001600160401b03811115614593578283fd5b61459f878288016142be565b90945092506145b39050866040870161448a565b905092959194509250565b600080604083850312156145d0578182fd5b82356145db81615f5e565b946020939093013593505050565b6000806000604084860312156145fd578081fd5b83356001600160401b03811115614612578182fd5b61461e868287016142be565b909790965060209590950135949350505050565b600080600060408486031215614646578081fd5b83356001600160401b038082111561465c578283fd5b614668878388016142be565b9095509350602086013591508082168214614681578283fd5b50809150509250925092565b6000806000606084860312156146a1578081fd5b83356001600160401b03808211156146b7578283fd5b6146c387838801614304565b945060208601359150808211156146d8578283fd5b6146e487838801614304565b935060408601359150808211156146f9578283fd5b6101c091860180880383131561470d578384fd5b61471683615f0c565b8135935082841115614726578485fd5b61473289858401614229565b81526020820135935082841115614747578485fd5b61475389858401614229565b6020820152614765896040840161420e565b6040820152614777896060840161420e565b60608201526147898960808401614473565b608082015261479b8960a08401614473565b60a08201526147ad8960c08401614473565b60c08201526147bf8960e08401614473565b60e082015261010093506147d58985840161420e565b8482015261012093506147ea8985840161420e565b8482015261014093506147ff89858401614473565b84820152610160935061481489858401614473565b84820152610180935061482989858401614473565b848201526101a0935061483e898584016142a0565b84820152809450505050509250925092565b600060208284031215614861578081fd5b81356001600160401b0380821115614877578283fd5b61012091840180860383131561488b578384fd5b61489483615f0c565b61489e87836142a0565b81526148ad876020840161445c565b60208201526148bf876040840161420e565b604082015260608201359350828411156148d7578485fd5b6148e387858401614229565b60608201526148f5876080840161420e565b60808201526149078760a08401614473565b60a08201526149198760c08401614473565b60c082015261492b8760e08401614219565b60e082015261010093508382013583811115614945578586fd5b61495188828501614229565b948201949094529695505050505050565b600060208284031215614973578081fd5b61072f838361445c565b60006020828403121561498e578081fd5b5051919050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526149d7816020860160208601615f32565b601f01601f19169290920160200192915050565b60609190911b6001600160601b031916815260140190565b600088151560f81b82528751614a20816001850160208c01615f32565b8751908301614a36826001830160208c01615f32565b8751918101614a4c836001830160208c01615f32565b60f897881b6001600160f81b0319908116600192909401918201939093529590961b166002850152505060c01b6001600160c01b0319166003820152600b0195945050505050565b60008351614aa6818460208801615f32565b8351908301614ab9828260208801615f32565b01949350505050565b60008251614ad4818460208701615f32565b9190910192915050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b608086901b6001600160801b0319168152606085901b6001600160601b03191660108201528351600090614b4a816024850160208901615f32565b8451908301614b60826024830160208901615f32565b93151560f81b602494909101938401525050602501949350505050565b6001600160f81b031960f889901b811682526001600160801b0319608089901b1660018301526001600160601b0319606088901b166011830152855160009190614bce816025860160208b01615f32565b808401828860f81b166025820152828760f81b16602682015285519250614bfc836027830160208901615f32565b9091016027019a9950505050505050505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038a811682528916602082015261012060408201819052600090614ca88382018b6149bf565b8381036060850152614cba818b6149bf565b6001600160401b03998a16608086015297891660a08501525050509290941660c083015260e08201526101000191909152949350505050565b93845260ff9290921660208401526040830152606082015260800190565b6000602082526110eb602083018486614995565b600060408252614d39604083018587614995565b905060ff83166020830152949350505050565b60006020825261072f60208301846149bf565b600060808252614d7260808301876149bf565b6001600160401b0395861660208401529390941660408201526060015292915050565b60208082526018908201527745434453413a20696e76616c6964207369676e617475726560401b604082015260600190565b602080825260189082015277496e76616c69642077616c6c6574207369676e617475726560401b604082015260600190565b60208082526018908201527721b0b63632b91034b9903737ba103234b9b830ba31b432b960411b604082015260600190565b6020808252604c908201527f546f6b656e20636f6e74726163742072657475726e6564207472616e7366657260408201527f46726f6d207375636365737320776974686f757420657870656374656420626160608201526b6c616e6365206368616e676560a01b608082015260a00190565b60208082526023908201527f4e6f6e63652074696d657374616d7020616c726561647920696e76616c6964616040820152621d195960ea1b606082015260800190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b6020808252601490820152730a6f2dac4ded8e640c8de40dcdee840dac2e8c6d60631b604082015260600190565b6020808252601f908201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604082015260600190565b6020808252601390820152724578636573736976652074616b65722066656560681b604082015260600190565b60208082526027908201527f4e6574206261736520706c757320666565206973206e6f7420657175616c20746040820152666f2067726f737360c81b606082015260800190565b6020808252602c908201527f4d616b657220616e642074616b65722066656520617373657473206d7573742060408201526b189948191a5999995c995b9d60a21b606082015260800190565b60208082526024908201527f4d75737420626520646966666572656e742066726f6d2063757272656e7420616040820152633236b4b760e11b606082015260800190565b6020808252600f908201526e135d5cdd081899481d8c4815555251608a1b604082015260600190565b602080825260139082015272457863657373697665206d616b65722066656560681b604082015260600190565b6020808252601b908201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604082015260600190565b6020808252601a908201527914d95b1b081dd85b1b195d08195e1a5d08199a5b985b1a5e995960321b604082015260600190565b6020808252601d908201527f4554482073796d626f6c20726573657276656420666f72204574686572000000604082015260600190565b6020808252601390820152725175616e7469747920697320746f6f206c6f7760681b604082015260600190565b60208082526033908201527f427579206f72646572206d61726b65742073796d626f6c2061646472657373206040820152720e4cae6ded8eae8d2dedc40dad2e6dac2e8c6d606b1b606082015260800190565b60208082526023908201527f526567697374726174696f6e206f6620746f6b656e206e6f742066696e616c696040820152621e995960ea1b606082015260800190565b6020808252600d908201526c2ab735b737bbb7103a37b5b2b760991b604082015260600190565b60208082526022908201527f53656c6c206f72646572206e6f6e63652074696d657374616d7020746f6f206c6040820152616f7760f01b606082015260800190565b60208082526031908201527f4f726465722071756f7465207175616e74697479206f6e6c792076616c696420604082015270666f72206d61726b6574206f726465727360781b606082015260800190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604082015261756560f01b606082015260800190565b60208082526024908201527f4d616b657220666565206173736574206973206e6f7420696e207472616465206040820152633830b4b960e11b606082015260800190565b60208082526027908201527f546f6b656e2063616e6e6f742068617665206d6f7265207468616e20333220646040820152666563696d616c7360c81b606082015260800190565b60208082526021908201527f4e6f6e63652074696d657374616d7020746f6f2066617220696e2066757475726040820152606560f81b606082015260800190565b60208082526019908201527815d85b1b195d08195e1a5d081b9bdd08199a5b985b1a5e9959603a1b604082015260600190565b602080825260159082015274088cac6d2dac2d8e640c8de40dcdee840dac2e8c6d605b1b604082015260600190565b60208082526018908201527714d95b198b5d1c98591a5b99c81b9bdd08185b1b1bddd95960421b604082015260600190565b60208082526027908201527f4261736520616e642071756f746520617373657473206d7573742062652064696040820152661999995c995b9d60ca1b606082015260800190565b6020808252818101527f5369676e617475726520686173682076657273696f6e206d7573742062652031604082015260600190565b60208082526015908201527415d85b1b195d08185b1c9958591e48195e1a5d1959605a1b604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604082015261756560f01b606082015260800190565b6020808252601f908201527f557365206465706f736974457468657220746f206465706f7369742045544800604082015260600190565b6020808252601890820152774d757374206265206c657373207468616e2031207765656b60401b604082015260600190565b60208082526024908201527f54616b657220666565206173736574206973206e6f7420696e207472616465206040820152633830b4b960e11b606082015260800190565b60208082526023908201527f4e6f20636f6e6669726d656420617373657420666f756e6420666f722073796d604082015262189bdb60ea1b606082015260800190565b60208082526010908201526f13dc99195c881bdd995c999a5b1b195960821b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260189082015277457863657373697665207769746864726177616c2066656560401b604082015260600190565b6020808252601d908201527f506970207175616e74697479206f766572666c6f77732075696e743634000000604082015260600190565b60208082526021908201527f557365206465706f736974457468657220746f206465706f73697420457468656040820152603960f91b606082015260800190565b60208082526014908201527321b0b63632b91036bab9ba1031329037bbb732b960611b604082015260600190565b60208082526029908201527f4d75737420626520646966666572656e742066726f6d2063757272656e7420666040820152681959481dd85b1b195d60ba1b606082015260800190565b6020808252601e908201527f437573746f6469616e2063616e206f6e6c7920626520736574206f6e63650000604082015260600190565b6020808252601690820152752430b9b41030b63932b0b23c903bb4ba34323930bbb760511b604082015260600190565b602080825260179082015276151bdad95b88185b1c9958591e48199a5b985b1a5e9959604a1b604082015260600190565b60208082526029908201527f4d75737420626520646966666572656e742066726f6d2063757272656e74206460408201526834b9b830ba31b432b960b91b606082015260800190565b6020808252601e908201527f427579206f72646572206c696d69742070726963652065786365656465640000604082015260600190565b60208082526013908201527213dc99195c88191bdd589b1948199a5b1b1959606a1b604082015260600190565b60208082526021908201527f427579206f72646572206e6f6e63652074696d657374616d7020746f6f206c6f6040820152607760f81b606082015260800190565b60208082526024908201527f4e6f20636f6e6669726d656420617373657420666f756e6420666f72206164646040820152637265737360e01b606082015260800190565b60208082526014908201527321b0b63632b91036bab9ba1031329030b236b4b760611b604082015260600190565b602080825260139082015272115512081d1c985b9cd9995c8819985a5b1959606a1b604082015260600190565b60208082526027908201527f41737365742063616e6e6f742068617665206d6f7265207468616e20333220646040820152666563696d616c7360c81b606082015260800190565b60208082526034908201527f53656c6c206f72646572206d61726b65742073796d626f6c2061646472657373604082015273040e4cae6ded8eae8d2dedc40dad2e6dac2e8c6d60631b606082015260800190565b602080825260159082015274496e76616c696420746f6b656e206164647265737360581b604082015260600190565b60208082526030908201527f50726576696f757320696e76616c69646174696f6e206177616974696e67206360408201526f3430b4b710383937b830b3b0ba34b7b760811b606082015260800190565b60208082526028908201527f4e65742071756f746520706c757320666565206973206e6f7420657175616c20604082015267746f2067726f737360c01b606082015260800190565b6020808252601f908201527f53656c6c206f72646572206c696d697420707269636520657863656564656400604082015260600190565b602080825260149082015273125b9d985b1a59081d1bdad95b881cde5b589bdb60621b604082015260600190565b60208082526011908201527015d85b1b195d081b9bdd08195e1a5d1959607a1b604082015260600190565b602080825260169082015275496e76616c69642077616c6c6574206164647265737360501b604082015260600190565b6020808252602b908201527f496d706c6965642071756f746520706970207175616e74697479206f7665726660408201526a1b1bdddcc81d5a5b9d0d8d60aa1b606082015260800190565b60208082526048908201527f546f6b656e20636f6e74726163742072657475726e6564207472616e7366657260408201527f207375636365737320776974686f75742065787065637465642062616c616e6360608201526765206368616e676560c01b608082015260a00190565b602080825260199082015278109d5e481dd85b1b195d08195e1a5d08199a5b985b1a5e9959603a1b604082015260600190565b60208082526028908201527f51756f7465207175616e74697479206d7573742062652067726561746572207460408201526768616e207a65726f60c01b606082015260800190565b6020808252600d908201526c15d85b1b195d08195e1a5d1959609a1b604082015260600190565b602080825260149082015273139bc818985b185b98d948199bdc88185cdcd95d60621b604082015260600190565b60208082526027908201527f42617365207175616e74697479206d7573742062652067726561746572207468604082015266616e207a65726f60c81b606082015260800190565b60006020825282511515602083015260018060a01b036020840151166040830152604083015160c06060840152615e4160e08401826149bf565b60ff60608601511660808501526080850151151560a08501526001600160401b0360a08601511660c0850152809250505092915050565b6001600160801b039390931683526001600160401b03919091166020830152604082015260600190565b90815260200190565b918252602082015260400190565b6001600160401b0391909116815260200190565b60006001600160401b03808816835260a06020840152615ef060a08401886149bf565b9581166040840152939093166060820152608001525092915050565b6040518181016001600160401b0381118282101715615f2a57600080fd5b604052919050565b60005b83811015615f4d578181015183820152602001615f35565b838111156108dd5750506000910152565b6001600160a01b0381168114615f7357600080fd5b5056fe496e76616c69642077616c6c6574207369676e617475726520666f7220627579206f72646572496e76616c69642077616c6c6574207369676e617475726520666f722073656c6c206f72646572a26469706673582212205dd7ac35c5f7c6f5ec79f4ba79633e7c75138d994328bbe33fa2efc0d21be22d64736f6c63430006080033
Deployed Bytecode
0x6080604052600436106101415760003560e01c806372e8f08d116100b157806372e8f08d146102ea578063869af2121461030a57806390d49b9d14610337578063985c4af51461035757806398ea5fca146103775780639a202d471461037f578063ae0e969e14610394578063ba22bd76146103c1578063d7a6aec7146103e1578063dbb3653514610401578063dcc6349014610421578063eb5068f214610441578063ef3b9d4a1461045657610141565b80630226b70e1461014657806302ca6002146101685780630c187a721461019357806313cfda2c146101a85780631abb5832146101d557806320e6a8e3146101f5578063403f3731146102155780634196818214610235578063457aa3c6146102555780634a284ef91461027557806365fce5b71461028a5780636bb509f2146102aa578063704b6c02146102ca575b600080fd5b34801561015257600080fd5b50610166610161366004614559565b610476565b005b34801561017457600080fd5b5061017d610540565b60405161018a9190614c10565b60405180910390f35b34801561019f57600080fd5b50610166610550565b3480156101b457600080fd5b506101c86101c33660046144b7565b6105d4565b60405161018a9190615ea2565b3480156101e157600080fd5b506101c86101f03660046144ef565b610662565b34801561020157600080fd5b50610166610210366004614541565b610736565b34801561022157600080fd5b5061016661023036600461449b565b6107c7565b34801561024157600080fd5b506101666102503660046145e9565b610861565b34801561026157600080fd5b50610166610270366004614559565b6108e3565b34801561028157600080fd5b50610166610996565b34801561029657600080fd5b506101666102a536600461468d565b610a0a565b3480156102b657600080fd5b506101666102c5366004614850565b610bb1565b3480156102d657600080fd5b506101666102e536600461449b565b610f1e565b3480156102f657600080fd5b506101666103053660046144ef565b610fdc565b34801561031657600080fd5b5061032a610325366004614632565b611099565b60405161018a9190615e07565b34801561034357600080fd5b5061016661035236600461449b565b6110f3565b34801561036357600080fd5b5061016661037236600461449b565b6111c4565b61016661134f565b34801561038b57600080fd5b5061016661135d565b3480156103a057600080fd5b506103b46103af366004614541565b6113b7565b60405161018a9190615eb9565b3480156103cd57600080fd5b506101666103dc36600461449b565b6113d5565b3480156103ed57600080fd5b506101666103fc366004614962565b6114a6565b34801561040d57600080fd5b506103b461041c3660046144b7565b61161e565b34801561042d57600080fd5b5061016661043c3660046145be565b61167b565b34801561044d57600080fd5b506101666116b0565b34801561046257600080fd5b506103b46104713660046144ef565b611762565b6000546001600160a01b031633146104a95760405162461bcd60e51b81526004016104a0906159ba565b60405180910390fd5b6104f58484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001949392508691505063ffffffff61180c16565b836001600160a01b03167fa8968236dc4afb2c189afeb69c91b02445e6bd09f0ffe27256b62838edc99edb84848460405161053293929190614d25565b60405180910390a250505050565b600c546001600160a01b03165b90565b6000546001600160a01b0316331461057a5760405162461bcd60e51b81526004016104a0906159ba565b600b546040517fddb86df2d5262dd7b44067db5962cc7875e9db409cb21c88adfe3c5760315e39916105ba916001600160a01b0390911690600090614c61565b60405180910390a1600b80546001600160a01b0319169055565b60006001600160a01b0383166105fc5760405162461bcd60e51b81526004016104a090615c07565b610604614140565b61061560018463ffffffff611b6216565b6001600160a01b038086166000908152600660209081526040808320938816835292905220546060820151919250610658916001600160401b0390911690611cbb565b9150505b92915050565b60006001600160a01b03841661068a5760405162461bcd60e51b81526004016104a090615c07565b610692614140565b6106e484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106d59250611d33915050565b6001919063ffffffff611d3b16565b6001600160a01b0380871660009081526006602090815260408083208286015190941683529290522054606082015191925061072b916001600160401b0390911690611cbb565b9150505b9392505050565b6000546001600160a01b031633146107605760405162461bcd60e51b81526004016104a0906159ba565b619d8081106107815760405162461bcd60e51b81526004016104a0906155ab565b600a8054908290556040517f9a22227d6c0251a79ef8b846202ddcbe9d682ee5482e84abeec6dda096398a6f906107bb9083908590615eab565b60405180910390a15050565b6000546001600160a01b031633146107f15760405162461bcd60e51b81526004016104a0906159ba565b6005546001600160a01b03161561081a5760405162461bcd60e51b81526004016104a0906157f0565b61082381611fa5565b61083f5760405162461bcd60e51b81526004016104a090614ee0565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b60006108a684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106d59250611d33915050565b6020015190506001600160a01b0381166108d25760405162461bcd60e51b81526004016104a090615574565b6108dd338284611fab565b50505050565b6000546001600160a01b0316331461090d5760405162461bcd60e51b81526004016104a0906159ba565b6109598484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001949392508691505063ffffffff6121d016565b836001600160a01b03167fcf66acda7673c71cd9458c59067eb30a473eeaf2fa05d008acf47616cbbbe01c84848460405161053293929190614d25565b3360009081526009602052604090205460ff166109c55760405162461bcd60e51b81526004016104a090615bdc565b33600081815260096020526040808220805460ff19168155600101829055517fb771d4b2a83beca38f442c8903629e0e8ab1a07cf76e94eb2977153167e209369190a2565b600b546001600160a01b03163314610a345760405162461bcd60e51b81526004016104a090614df9565b610a41836040015161237a565b15610a5e5760405162461bcd60e51b81526004016104a090615cf0565b610a6b826040015161237a565b15610a885760405162461bcd60e51b81526004016104a0906150fd565b81604001516001600160a01b031683604001516001600160a01b03161415610ac25760405162461bcd60e51b81526004016104a090615455565b610acd8383836123ab565b610ad8838383612620565b610ae28383612731565b600080610af08585856127c3565b91509150610afd836127ee565b610b0a85838684876129e8565b610b15858585612a05565b8260200151604051610b279190614ac2565b60405190819003812084519091610b3e9190614ac2565b60405180910390207fbd75b2e24c3d43ec9f10f3583265606c0a7d8b67d147f9dc48376b81456823a1876040015187604001518760000151886020015189608001518a60a001518b61018001518b8b604051610ba299989796959493929190614c7b565b60405180910390a35050505050565b600b546001600160a01b03163314610bdb5760405162461bcd60e51b81526004016104a090614df9565b610be8816040015161237a565b15610c055760405162461bcd60e51b81526004016104a090615d6b565b6107d06001600160401b0316610c238260c001518360a00151612cff565b6001600160401b03161115610c4a5760405162461bcd60e51b81526004016104a0906156cf565b6000610c5582612d36565b60008181526004602052604090205490915060ff1615610c875760405162461bcd60e51b81526004016104a090615827565b610c8f614140565b600083516001811115610c9e57fe5b14610cbf576080830151610cba9060019063ffffffff611b6216565b610cd4565b610cd483606001516106d58560200151612d74565b90506000610cfc8460c001518560a001516001600160401b0316612e0190919063ffffffff16565b90506000610d0e828460600151611cbb565b60a08601516040808801516001600160a01b03908116600090815260066020908152838220898201519093168252919091529081205492935091610d63916001600160401b039091169063ffffffff612e0116565b90506000610d75828660600151611cbb565b6040888101516001600160a01b039081166000908152600660208181528483208b820180518616855290825285842080546001600160401b0319166001600160401b038b81169190911790915560c08f0151600c548716865293835286852091519095168452905292902054929350610def921690612e43565b600c546001600160a01b0390811660009081526006602090815260408083208a830180518616855292529182902080546001600160401b0319166001600160401b0395909516949094179093556005548a82015193519151636ce5768960e11b815292169263d9caed1292610e6992908890600401614c24565b600060405180830381600087803b158015610e8357600080fd5b505af1158015610e97573d6000803e3d6000fd5b505050600087815260046020908152604091829020805460ff19166001179055870151898201518883015160a08c015193516001600160a01b03938416955091909216927f6960a1f64ecf9da0d1d1bcbfa3dd27f8c1c60de69b13faa28127dafa36c111e492610f0d9290919088908890614d5f565b60405180910390a350505050505050565b336001600160a01b037f000000000000000000000000b2d3731fd28309c399774fb26f993697c174f4511614610f665760405162461bcd60e51b81526004016104a090615779565b6001600160a01b038116610f8c5760405162461bcd60e51b81526004016104a090615c07565b6000546001600160a01b0382811691161415610fba5760405162461bcd60e51b81526004016104a09061502e565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146110065760405162461bcd60e51b81526004016104a0906159ba565b6110518383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001949392505063ffffffff612e74169050565b826001600160a01b03167f7f63a63f4a2ea318da0b031794d0b5a3183a1b2de54e053ceb17cabdba031735838360405161108c929190614d11565b60405180910390a2505050565b6110a1614140565b6110eb84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019392508691505063ffffffff611d3b16565b949350505050565b6000546001600160a01b0316331461111d5760405162461bcd60e51b81526004016104a0906159ba565b6001600160a01b0381166111435760405162461bcd60e51b81526004016104a090615c07565b600c546001600160a01b03828116911614156111715760405162461bcd60e51b81526004016104a0906157a7565b600c80546001600160a01b038381166001600160a01b03198316179092556040519116907f9f4f5dce3c4d197b5d7496cb96e25f0a89809167195964b0daa3ef5fed63c00a906107bb9083908590614c61565b6111cd3361237a565b6111e95760405162461bcd60e51b81526004016104a0906153f3565b6111f1614140565b61120260018363ffffffff611b6216565b3360009081526006602090815260408083206001600160a01b038716845290915281205460608301519293506001600160401b031691611243908390611cbb565b9050600081116112655760405162461bcd60e51b81526004016104a090615d92565b3360008181526006602090815260408083206001600160a01b03898116855292529182902080546001600160401b03191690556005549151636ce5768960e11b815291169163d9caed12916112c1919088908690600401614c24565b600060405180830381600087803b1580156112db57600080fd5b505af11580156112ef573d6000803e3d6000fd5b50505050836001600160a01b0316336001600160a01b03167f02e03f232c88c87047c5a9cfbad1213b842503fee6a002ec2eec9f5a64725bf48560400151856000806040516113419493929190614d5f565b60405180910390a350505050565b61135b33600034611fab565b565b336001600160a01b037f000000000000000000000000b2d3731fd28309c399774fb26f993697c174f45116146113a55760405162461bcd60e51b81526004016104a090615779565b600080546001600160a01b0319169055565b6000818152600860205260409020546001600160401b03165b919050565b6000546001600160a01b031633146113ff5760405162461bcd60e51b81526004016104a0906159ba565b6001600160a01b0381166114255760405162461bcd60e51b81526004016104a090615c07565b600b546001600160a01b03828116911614156114535760405162461bcd60e51b81526004016104a090615888565b600b80546001600160a01b038381166001600160a01b03198316179092556040519116907fddb86df2d5262dd7b44067db5962cc7875e9db409cb21c88adfe3c5760315e39906107bb9083908590614c61565b60006114b182612d74565b90506114bb613089565b6001600160401b0316816001600160401b0316106114eb5760405162461bcd60e51b81526004016104a0906153b2565b3360009081526007602052604090205460ff161561157457336000908152600760205260409020546001600160401b0380831661010090920416106115425760405162461bcd60e51b81526004016104a090614e9d565b336000908152600760205260409020600101544310156115745760405162461bcd60e51b81526004016104a090615adf565b600a546040805160608101825260018082526001600160401b0385811660208085019182524390960184860181815233600081815260079099529787902095518654935160ff199094169015151768ffffffffffffffff001916610100939094169290920292909217845551929091019190915590519091907f10cf19671b43c88b1f02d4e94932d7ffaa89c7278bc5b8868fa7b7676210809b9061108c90869086908690615e78565b60006001600160a01b0383166116465760405162461bcd60e51b81526004016104a090615c07565b506001600160a01b0391821660009081526006602090815260408083209390941682529190915220546001600160401b031690565b6001600160a01b0382166116a15760405162461bcd60e51b81526004016104a090615738565b6116ac338383611fab565b5050565b3360009081526009602052604090205460ff16156116e05760405162461bcd60e51b81526004016104a090615503565b6040805180820182526001808252600a80544390810160208086019182523360008181526009909252908790209551865460ff19169015151786559051949093019390935554925190927fd60f9f7b2f1a208268475a927bd727c4e198fc8b40aab3004ebcc2bc78ca84809261175892910190615ea2565b60405180910390a2565b60006001600160a01b03841661178a5760405162461bcd60e51b81526004016104a090615c07565b60006117cf84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106d59250611d33915050565b6020908101516001600160a01b03808816600090815260068452604080822092909316815292529020546001600160401b03169150509392505050565b611814614140565b6001600160a01b0384811660009081526020878152604091829020825160c081018452815460ff8116151582526101009081900490951681840152600180830180548651600293821615909802600019011691909104601f81018590048502870185018652808752919592948601939091908301828280156118d75780601f106118ac576101008083540402835291602001916118d7565b820191906000526020600020905b8154815290600101906020018083116118ba57829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091506119335760405162461bcd60e51b81526004016104a09061522b565b8060800151156119555760405162461bcd60e51b81526004016104a090615857565b611963816040015184613096565b61197f5760405162461bcd60e51b81526004016104a090614f09565b8160ff16816060015160ff16146119a85760405162461bcd60e51b81526004016104a090615426565b6001608082018190526001600160401b036103e842021660a08301526001600160a01b0380861660009081526020888152604091829020855181548388015190951661010002610100600160a81b031991151560ff1990961695909517169390931783559084015180518594611a2393908501920190614176565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ff001960ff90951660ff19909316929092179390931617929092161790556040516001860190611a8d908590614ac2565b9081526040805191829003602090810190922080546001818101835560009283529184902085516003909202018054868601516001600160a01b031661010002610100600160a81b031993151560ff1990921691909117929092169190911781559184015180518594611b04938501920190614176565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ff001960ff90951660ff19909316929092179390931617929092161790555050505050565b611b6a614140565b6001600160a01b038216611b8757611b806130ef565b905061065c565b611b8f614140565b6001600160a01b0383811660009081526020868152604091829020825160c081018452815460ff8116151582526101009081900490951681840152600180830180548651600293821615909802600019011691909104601f8101859004850287018501865280875291959294860193909190830182828015611c525780601f10611c2757610100808354040283529160200191611c52565b820191906000526020600020905b815481529060010190602001808311611c3557829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091508015611c9f575080608001515b61072f5760405162461bcd60e51b81526004016104a090615976565b600060208260ff161115611ce15760405162461bcd60e51b81526004016104a090615a15565b60088260ff161115611d1057611b806001600160401b03841660ff600719850116600a0a63ffffffff61314816565b61072f6001600160401b03841660ff600885900316600a0a63ffffffff61318216565b426103e80290565b611d43614140565b611d686040518060400160405280600381526020016208aa8960eb1b81525084613096565b15611d7c57611d756130ef565b905061072f565b611d84614140565b60008560010185604051611d989190614ac2565b908152604051908190036020019020541115611f7a5760005b8560010185604051611dc39190614ac2565b9081526040519081900360200190205460ff82161015611f7857836001600160401b03168660010186604051611df99190614ac2565b90815260200160405180910390208260ff1681548110611e1557fe5b60009182526020909120600390910201600201546201000090046001600160401b031611611f70578560010185604051611e4f9190614ac2565b90815260200160405180910390208160ff1681548110611e6b57fe5b60009182526020918290206040805160c081018252600393909302909101805460ff811615158452610100908190046001600160a01b031684860152600180830180548551600293821615909402600019011691909104601f8101879004870283018701855280835294959294938601939192909190830182828015611f325780601f10611f0757610100808354040283529160200191611f32565b820191906000526020600020905b815481529060010190602001808311611f1557829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015291505b600101611db1565b505b80518015611f89575080608001515b6110eb5760405162461bcd60e51b81526004016104a090615621565b3b151590565b6001600160a01b03831660009081526009602052604090205460ff1615611fe45760405162461bcd60e51b81526004016104a090615d6b565b611fec614140565b611ffd60018463ffffffff611b6216565b9050600061200f8383606001516131c1565b90506000816001600160401b03161161203a5760405162461bcd60e51b81526004016104a090615168565b600061204a828460600151611cbb565b90506001600160a01b0385161561206657612066868683613256565b60055461207d906001600160a01b031686836133e9565b6001600160a01b0380871660009081526006602090815260408083209389168352929052908120546120be906001600160401b03168463ffffffff612e4316565b905060006120d0828660600151611cbb565b6001600160a01b038981166000908152600660209081526040808320938c16835292905281902080546001600160401b0319166001600160401b03868116919091179091556005805467ffffffffffffffff60a01b198116600160a01b9182900484166001019093160291909117905586810151905191925061215291614ac2565b6040518091039020876001600160a01b0316896001600160a01b03167fc2813a84168de59cf710030ba2acb13031b567b8ba76f70e8ab0782aa9469a7a600560149054906101000a90046001600160401b031689604001518988886040516121be959493929190615ecd565b60405180910390a45050505050505050565b60208160ff1611156121f45760405162461bcd60e51b81526004016104a09061536b565b6001600160a01b03831615801590612210575061221083611fa5565b61222c5760405162461bcd60e51b81526004016104a090615ab0565b600082511161224d5760405162461bcd60e51b81526004016104a090615bae565b6001600160a01b038316600090815260208590526040902060020154610100900460ff161561228e5760405162461bcd60e51b81526004016104a090615857565b6040805160c08101825260018082526001600160a01b03868116602080850182815285870189815260ff8916606088015260006080880181905260a088018190529384528b83529690922085518154935160ff1990941690151517610100600160a81b03191661010093909416929092029290921781559351805193949361231d938501929190910190614176565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ff001960ff90951660ff199093169290921793909316179290921617905550505050565b6001600160a01b0381166000908152600960205260408120805460ff16801561072f57506001015443101592915050565b80606001516001600160a01b031681604001516001600160a01b031614156123e55760405162461bcd60e51b81526004016104a090615487565b6123ed614140565b61240282600001516106d58660200151612d74565b905061240c614140565b61242183602001516106d58760200151612d74565b905082604001516001600160a01b031682602001516001600160a01b0316148015612465575082606001516001600160a01b031681602001516001600160a01b0316145b6124815760405162461bcd60e51b81526004016104a090615195565b612489614140565b61249e84600001516106d58760200151612d74565b90506124a8614140565b6124bd85602001516106d58860200151612d74565b905084604001516001600160a01b031682602001516001600160a01b0316148015612501575084606001516001600160a01b031681602001516001600160a01b0316145b61251d5760405162461bcd60e51b81526004016104a090615a5c565b84604001516001600160a01b03168561010001516001600160a01b03161480612560575084606001516001600160a01b03168561010001516001600160a01b0316145b61257c5760405162461bcd60e51b81526004016104a090615327565b84604001516001600160a01b03168561012001516001600160a01b031614806125bf575084606001516001600160a01b03168561012001516001600160a01b0316145b6125db5760405162461bcd60e51b81526004016104a0906155dd565b8461012001516001600160a01b03168561010001516001600160a01b031614156126175760405162461bcd60e51b81526004016104a090614fe2565b50505050505050565b600081608001516001600160401b03161161264d5760405162461bcd60e51b81526004016104a090615dc0565b60008160a001516001600160401b03161161267a5760405162461bcd60e51b81526004016104a090615d23565b61268783606001516135ce565b156126d3578060a001516001600160401b03166126ac82608001518560e00151613627565b6001600160401b031610156126d35760405162461bcd60e51b81526004016104a0906158d1565b6126e082606001516135ce565b1561272c578060a001516001600160401b031661270582608001518460e00151613627565b6001600160401b0316111561272c5760405162461bcd60e51b81526004016104a090615b77565b505050565b61273e8260400151613680565b6001600160401b03166127548360200151612d74565b6001600160401b03161161277a5760405162461bcd60e51b81526004016104a090615935565b6127878160400151613680565b6001600160401b031661279d8260200151612d74565b6001600160401b0316116116ac5760405162461bcd60e51b81526004016104a090615252565b60008060006127d286856136fd565b905060006127e086866136fd565b919791965090945050505050565b600081604001516001600160a01b03168261010001516001600160a01b03161461281c578160a00151612822565b81608001515b90506107d06001600160401b031661283f83610140015183612cff565b6001600160401b031611156128665760405162461bcd60e51b81526004016104a09061509b565b600082604001516001600160a01b03168361012001516001600160a01b031614612894578260a0015161289a565b82608001515b90506107d06001600160401b03166128b784610160015183612cff565b6001600160401b031611156128de5760405162461bcd60e51b81526004016104a090614f6e565b82608001516001600160401b031661293d84604001516001600160a01b03168561010001516001600160a01b03161461291c57846101600151612923565b8461014001515b60c08601516001600160401b03169063ffffffff612e4316565b6001600160401b0316146129635760405162461bcd60e51b81526004016104a090614f9b565b8260a001516001600160401b03166129c284606001516001600160a01b03168561010001516001600160a01b0316146129a1578461016001516129a8565b8461014001515b60e08601516001600160401b03169063ffffffff612e4316565b6001600160401b03161461272c5760405162461bcd60e51b81526004016104a090615b2f565b6129f385858361379e565b6129fe83838361379e565b5050505050565b60808101516040808401516001600160a01b03908116600090815260066020908152838220848701519093168252919091522054612a54916001600160401b039091169063ffffffff612e0116565b6040838101516001600160a01b0390811660009081526006602081815284832087860180518616855290825285842080546001600160401b0319166001600160401b0398891617905560c08801518a8701518616855292825285842090519094168352929092529190912054612acb921690612e43565b604084810180516001600160a01b039081166000908152600660208181528583208887015185168452815285832080546001600160401b0319166001600160401b0398891617905560a088015194518416835290815284822060608801519093168252919091529190912054612b42921690612e01565b6040848101516001600160a01b039081166000908152600660208181528483206060880180518616855290825285842080546001600160401b0319166001600160401b0398891617905560e0880151898701518616855292825285842090519094168352929092529190912054612bba921690612e43565b6040838101516001600160a01b03908116600090815260066020818152848320606088015185168452815284832080546001600160401b0319166001600160401b03978816179055610140870151600c54851684529181528483206101008801519094168352929092529190912054612c34921690612e43565b600c80546001600160a01b03908116600090815260066020818152604080842061010089015186168552825280842080546001600160401b0319166001600160401b039889161790556101608801519554851684529181528183206101208801519094168352929092522054612cab921690612e43565b600c546001600160a01b039081166000908152600660209081526040808320610120969096015190931682529390935290912080546001600160401b0319166001600160401b039092169190911790555050565b600061271061065883612d216001600160401b0387168463ffffffff61392216565b6001600160401b03169063ffffffff61397d16565b600080612d42836139bc565b9050612d58818461010001518560400151613a77565b61065c5760405162461bcd60e51b81526004016104a090614dc7565b6000600f604c83901c1660018114612d9e5760405162461bcd60e51b81526004016104a090615072565b610fff60301b601084901c1665ffff00000000603085901c1663ffffffff606086901c168183178117612df6650b1d069b54006127106001600160801b038416046001600160401b0316612e0190919063ffffffff16565b979650505050505050565b600061072f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613aa7565b60008282016001600160401b03808516908216101561072f5760405162461bcd60e51b81526004016104a0906150c8565b612e7c614140565b6001600160a01b0383811660009081526020868152604091829020825160c081018452815460ff8116151582526101009081900490951681840152600180830180548651600293821615909802600019011691909104601f8101859004850287018501865280875291959294860193909190830182828015612f3f5780601f10612f1457610100808354040283529160200191612f3f565b820191906000526020600020905b815481529060010190602001808311612f2257829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091508015612f8c575080608001515b612fa85760405162461bcd60e51b81526004016104a0906151e8565b612fcd826040518060400160405280600381526020016208aa8960eb1b815250613096565b15612fea5760405162461bcd60e51b81526004016104a090615131565b426103e89081026001600160401b031660a08301526040516001860190613012908590614ac2565b9081526040805191829003602090810190922080546001818101835560009283529184902086516003909202018054878601516001600160a01b031661010002610100600160a81b031993151560ff1990921691909117929092169190911781559185015180518694611b04938501920190614176565b4262015180016103e80290565b6000816040516020016130a99190614ac2565b60405160208183030381529060405280519060200120836040516020016130d09190614ac2565b6040516020818303038152906040528051906020012014905092915050565b6130f7614140565b506040805160c08101825260018082526000602080840182905284518086018652600381526208aa8960eb1b918101919091529383019390935260126060830152608082015260a081019190915290565b6000826131575750600061065c565b8282028284828161316457fe5b041461072f5760405162461bcd60e51b81526004016104a09061568e565b600061072f83836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b815250613ae6565b600060208260ff1611156131e75760405162461bcd60e51b81526004016104a090615a15565b600060088360ff1611156132165761320f8460ff600719860116600a0a63ffffffff61318216565b9050613233565b6132308460ff600886900316600a0a63ffffffff61314816565b90505b600160401b811061072f5760405162461bcd60e51b81526004016104a090615701565b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190613285903090600401614c10565b60206040518083038186803b15801561329d57600080fd5b505afa1580156132b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d5919061497d565b6040516323b872dd60e01b81529091506001600160a01b038416906323b872dd9061330890879030908790600401614c24565b600060405180830381600087803b15801561332257600080fd5b505af1158015613336573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b03861691506370a0823190613369903090600401614c10565b60206040518083038186803b15801561338157600080fd5b505afa158015613395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133b9919061497d565b9050826133cc828463ffffffff613b1d16565b146129fe5760405162461bcd60e51b81526004016104a090614e2b565b6001600160a01b03821661343d576040516001600160a01b0384169082156108fc029083906000818181858888f193505050506134385760405162461bcd60e51b81526004016104a0906159e8565b61272c565b6040516370a0823160e01b81526000906001600160a01b038416906370a082319061346c908790600401614c10565b60206040518083038186803b15801561348457600080fd5b505afa158015613498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134bc919061497d565b60405163a9059cbb60e01b81529091506001600160a01b0384169063a9059cbb906134ed9087908690600401614c48565b600060405180830381600087803b15801561350757600080fd5b505af115801561351b573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b03861691506370a082319061354e908890600401614c10565b60206040518083038186803b15801561356657600080fd5b505afa15801561357a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359e919061497d565b9050826135b1828463ffffffff613b1d16565b146129fe5760405162461bcd60e51b81526004016104a090615c82565b600060018260068111156135de57fe5b14806135f5575060028260068111156135f357fe5b145b8061360b5750600482600681111561360957fe5b145b8061065c575060065b82600681111561362057fe5b1492915050565b60006305f5e1008161365b8261364f6001600160401b0388811690881663ffffffff61314816565b9063ffffffff61318216565b9050600160401b81106106585760405162461bcd60e51b81526004016104a090615c37565b6001600160a01b03811660009081526007602052604081205460ff1680156136c357506001600160a01b0382166000908152600760205260409020600101544310155b156136f557506001600160a01b03811660009081526007602052604090205461010090046001600160401b03166113d0565b506000919050565b6000806137138484600001518560200151613b5f565b905061372981856101a001518660400151613a77565b60008560800151600181111561373b57fe5b1461375e57604051806060016040528060278152602001615f9d60279139613778565b604051806060016040528060268152602001615f77602691395b906137965760405162461bcd60e51b81526004016104a09190614d4c565b509392505050565b60008281526003602052604090205460ff16156137cd5760405162461bcd60e51b81526004016104a090615908565b60008360c0015115613839576137e68460600151613d01565b6138025760405162461bcd60e51b81526004016104a090615294565b60008381526008602052604090205460a0830151613832916001600160401b03918216911663ffffffff612e4316565b905061386c565b6000838152600860205260409020546080830151613869916001600160401b03918216911663ffffffff612e4316565b90505b8360a001516001600160401b0316816001600160401b031611156138a25760405162461bcd60e51b81526004016104a090615664565b8360a001516001600160401b0316816001600160401b031610156138ec57600083815260086020526040902080546001600160401b0319166001600160401b0383161790556108dd565b5050600090815260086020908152604080832080546001600160401b031916905560039091529020805460ff1916600117905550565b60006001600160401b03831661393a5750600061065c565b8282026001600160401b03808416908086169083168161395657fe5b046001600160401b03161461072f5760405162461bcd60e51b81526004016104a09061568e565b600061072f83836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b815250613d34565b602081015160408201516000919082845160018111156139d857fe5b14613a065783608001516040516020016139f291906149eb565b604051602081830303815290604052613a2b565b8360600151604051602001613a1b9190614ac2565b6040516020818303038152906040525b613a418560a001516001600160401b0316613d7c565b8560e00151604051602001613a5a959493929190614b0f565b604051602081830303815290604052805190602001209050919050565b6000816001600160a01b0316613a95613a8f86613e78565b85613e8b565b6001600160a01b031614949350505050565b6000836001600160401b0316836001600160401b031611158290613ade5760405162461bcd60e51b81526004016104a09190614d4c565b505050900390565b60008183613b075760405162461bcd60e51b81526004016104a09190614d4c565b506000838581613b1357fe5b0495945050505050565b600061072f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613faf565b6000836000015160ff16600114613b885760405162461bcd60e51b81526004016104a0906154ce565b835160208501516040860151613b9e8686613fd3565b87606001516006811115613bae57fe5b88608001516001811115613bbe57fe5b613bd48a60a001516001600160401b0316613d7c565b604051602001613bea9796959493929190614b7d565b6040516020818303038152906040528460c0015160008660e001516001600160401b031611613c285760405180602001604052806000815250613c3e565b613c3e8660e001516001600160401b0316613d7c565b60008761010001516001600160401b031611613c695760405180602001604052806000815250613c80565b613c808761010001516001600160401b0316613d7c565b8761012001518861014001516003811115613c9757fe5b8961016001516003811115613ca857fe5b8a6101800151604051602001613cc49796959493929190614a03565b60408051601f1981840301815290829052613ce29291602001614a94565b6040516020818303038152906040528051906020012090509392505050565b600080826006811115613d1057fe5b1480613d2757506003826006811115613d2557fe5b145b8061065c57506005613614565b6000816001600160401b038416613d5e5760405162461bcd60e51b81526004016104a09190614d4c565b506000836001600160401b0316856001600160401b031681613b1357fe5b60608160005b8115613d9657600101600a82049150613d82565b6009811015613da3575060095b6001016060816001600160401b0381118015613dbe57600080fd5b506040519080825280601f01601f191660200182016040528015613de9576020820181803683370190505b509050815b8015613e6f5780830360081415613e2f57602e60f81b826001830381518110613e1357fe5b60200101906001600160f81b031916908160001a905350613e66565b600a860660300160f81b826001830381518110613e4857fe5b60200101906001600160f81b031916908160001a905350600a860495505b60001901613dee565b50949350505050565b600081604051602001613a5a9190614ade565b60008151604114613eae5760405162461bcd60e51b81526004016104a090614f37565b60208201516040830151606084015160001a6fa2a8918ca85bafe22016d0b997e4df60600160ff1b03821115613ef65760405162461bcd60e51b81526004016104a0906152e5565b8060ff16601b14158015613f0e57508060ff16601c14155b15613f2b5760405162461bcd60e51b81526004016104a090615532565b600060018783868660405160008152602001604052604051613f509493929190614cf3565b6020604051602081039080840390855afa158015613f72573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613fa55760405162461bcd60e51b81526004016104a090614d95565b9695505050505050565b60008184841115613ade5760405162461bcd60e51b81526004016104a09190614d4c565b604080518082019091526001808252602d60f81b60208301528251845160609386939092869286929101016001600160401b038111801561401357600080fd5b506040519080825280601f01601f19166020018201604052801561403e576020820181803683370190505b5090506000805b85518210156140995785828151811061405a57fe5b602001015160f81c60f81b83828060010193508151811061407757fe5b60200101906001600160f81b031916908160001a905350600190910190614045565b846000815181106140a657fe5b602001015160f81c60f81b8382806001019350815181106140c357fe5b60200101906001600160f81b031916908160001a905350600091505b8351821015614133578382815181106140f457fe5b602001015160f81c60f81b83828060010193508151811061411157fe5b60200101906001600160f81b031916908160001a9053506001909101906140df565b5090979650505050505050565b6040805160c08101825260008082526020820181905260609282018390529181018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106141b757805160ff19168380011785556141e4565b828001600101855582156141e4579182015b828111156141e45782518255916020019190600101906141c9565b506141f09291506141f4565b5090565b61054d91905b808211156141f057600081556001016141fa565b803561065c81615f5e565b8035801515811461065c57600080fd5b600082601f830112614239578081fd5b81356001600160401b0381111561424e578182fd5b614261601f8201601f1916602001615f0c565b915080825283602082850101111561427857600080fd5b8060208401602084013760009082016020015292915050565b80356004811061065c57600080fd5b80356002811061065c57600080fd5b80356007811061065c57600080fd5b60008083601f8401126142cf578182fd5b5081356001600160401b038111156142e5578182fd5b6020830191508360208285010111156142fd57600080fd5b9250929050565b60006101c0808385031215614317578182fd5b61432081615f0c565b91505061432d838361448a565b815261433c836020840161445c565b602082015261434e836040840161420e565b604082015261436083606084016142af565b606082015261437283608084016142a0565b60808201526143848360a08401614473565b60a08201526143968360c08401614219565b60c08201526143a88360e08401614473565b60e08201526101006143bc84828501614473565b90820152610120828101356001600160401b03808211156143dc57600080fd5b6143e886838701614229565b8385015261014092506143fd86848701614291565b83850152610160925061441286848701614291565b83850152610180925061442786848701614473565b838501526101a092508285013591508082111561444357600080fd5b5061445085828601614229565b82840152505092915050565b80356001600160801b038116811461065c57600080fd5b80356001600160401b038116811461065c57600080fd5b803560ff8116811461065c57600080fd5b6000602082840312156144ac578081fd5b813561072f81615f5e565b600080604083850312156144c9578081fd5b82356144d481615f5e565b915060208301356144e481615f5e565b809150509250929050565b600080600060408486031215614503578081fd5b833561450e81615f5e565b925060208401356001600160401b03811115614528578182fd5b614534868287016142be565b9497909650939450505050565b600060208284031215614552578081fd5b5035919050565b6000806000806060858703121561456e578182fd5b843561457981615f5e565b935060208501356001600160401b03811115614593578283fd5b61459f878288016142be565b90945092506145b39050866040870161448a565b905092959194509250565b600080604083850312156145d0578182fd5b82356145db81615f5e565b946020939093013593505050565b6000806000604084860312156145fd578081fd5b83356001600160401b03811115614612578182fd5b61461e868287016142be565b909790965060209590950135949350505050565b600080600060408486031215614646578081fd5b83356001600160401b038082111561465c578283fd5b614668878388016142be565b9095509350602086013591508082168214614681578283fd5b50809150509250925092565b6000806000606084860312156146a1578081fd5b83356001600160401b03808211156146b7578283fd5b6146c387838801614304565b945060208601359150808211156146d8578283fd5b6146e487838801614304565b935060408601359150808211156146f9578283fd5b6101c091860180880383131561470d578384fd5b61471683615f0c565b8135935082841115614726578485fd5b61473289858401614229565b81526020820135935082841115614747578485fd5b61475389858401614229565b6020820152614765896040840161420e565b6040820152614777896060840161420e565b60608201526147898960808401614473565b608082015261479b8960a08401614473565b60a08201526147ad8960c08401614473565b60c08201526147bf8960e08401614473565b60e082015261010093506147d58985840161420e565b8482015261012093506147ea8985840161420e565b8482015261014093506147ff89858401614473565b84820152610160935061481489858401614473565b84820152610180935061482989858401614473565b848201526101a0935061483e898584016142a0565b84820152809450505050509250925092565b600060208284031215614861578081fd5b81356001600160401b0380821115614877578283fd5b61012091840180860383131561488b578384fd5b61489483615f0c565b61489e87836142a0565b81526148ad876020840161445c565b60208201526148bf876040840161420e565b604082015260608201359350828411156148d7578485fd5b6148e387858401614229565b60608201526148f5876080840161420e565b60808201526149078760a08401614473565b60a08201526149198760c08401614473565b60c082015261492b8760e08401614219565b60e082015261010093508382013583811115614945578586fd5b61495188828501614229565b948201949094529695505050505050565b600060208284031215614973578081fd5b61072f838361445c565b60006020828403121561498e578081fd5b5051919050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526149d7816020860160208601615f32565b601f01601f19169290920160200192915050565b60609190911b6001600160601b031916815260140190565b600088151560f81b82528751614a20816001850160208c01615f32565b8751908301614a36826001830160208c01615f32565b8751918101614a4c836001830160208c01615f32565b60f897881b6001600160f81b0319908116600192909401918201939093529590961b166002850152505060c01b6001600160c01b0319166003820152600b0195945050505050565b60008351614aa6818460208801615f32565b8351908301614ab9828260208801615f32565b01949350505050565b60008251614ad4818460208701615f32565b9190910192915050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b608086901b6001600160801b0319168152606085901b6001600160601b03191660108201528351600090614b4a816024850160208901615f32565b8451908301614b60826024830160208901615f32565b93151560f81b602494909101938401525050602501949350505050565b6001600160f81b031960f889901b811682526001600160801b0319608089901b1660018301526001600160601b0319606088901b166011830152855160009190614bce816025860160208b01615f32565b808401828860f81b166025820152828760f81b16602682015285519250614bfc836027830160208901615f32565b9091016027019a9950505050505050505050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b038a811682528916602082015261012060408201819052600090614ca88382018b6149bf565b8381036060850152614cba818b6149bf565b6001600160401b03998a16608086015297891660a08501525050509290941660c083015260e08201526101000191909152949350505050565b93845260ff9290921660208401526040830152606082015260800190565b6000602082526110eb602083018486614995565b600060408252614d39604083018587614995565b905060ff83166020830152949350505050565b60006020825261072f60208301846149bf565b600060808252614d7260808301876149bf565b6001600160401b0395861660208401529390941660408201526060015292915050565b60208082526018908201527745434453413a20696e76616c6964207369676e617475726560401b604082015260600190565b602080825260189082015277496e76616c69642077616c6c6574207369676e617475726560401b604082015260600190565b60208082526018908201527721b0b63632b91034b9903737ba103234b9b830ba31b432b960411b604082015260600190565b6020808252604c908201527f546f6b656e20636f6e74726163742072657475726e6564207472616e7366657260408201527f46726f6d207375636365737320776974686f757420657870656374656420626160608201526b6c616e6365206368616e676560a01b608082015260a00190565b60208082526023908201527f4e6f6e63652074696d657374616d7020616c726561647920696e76616c6964616040820152621d195960ea1b606082015260800190565b6020808252600f908201526e496e76616c6964206164647265737360881b604082015260600190565b6020808252601490820152730a6f2dac4ded8e640c8de40dcdee840dac2e8c6d60631b604082015260600190565b6020808252601f908201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604082015260600190565b6020808252601390820152724578636573736976652074616b65722066656560681b604082015260600190565b60208082526027908201527f4e6574206261736520706c757320666565206973206e6f7420657175616c20746040820152666f2067726f737360c81b606082015260800190565b6020808252602c908201527f4d616b657220616e642074616b65722066656520617373657473206d7573742060408201526b189948191a5999995c995b9d60a21b606082015260800190565b60208082526024908201527f4d75737420626520646966666572656e742066726f6d2063757272656e7420616040820152633236b4b760e11b606082015260800190565b6020808252600f908201526e135d5cdd081899481d8c4815555251608a1b604082015260600190565b602080825260139082015272457863657373697665206d616b65722066656560681b604082015260600190565b6020808252601b908201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604082015260600190565b6020808252601a908201527914d95b1b081dd85b1b195d08195e1a5d08199a5b985b1a5e995960321b604082015260600190565b6020808252601d908201527f4554482073796d626f6c20726573657276656420666f72204574686572000000604082015260600190565b6020808252601390820152725175616e7469747920697320746f6f206c6f7760681b604082015260600190565b60208082526033908201527f427579206f72646572206d61726b65742073796d626f6c2061646472657373206040820152720e4cae6ded8eae8d2dedc40dad2e6dac2e8c6d606b1b606082015260800190565b60208082526023908201527f526567697374726174696f6e206f6620746f6b656e206e6f742066696e616c696040820152621e995960ea1b606082015260800190565b6020808252600d908201526c2ab735b737bbb7103a37b5b2b760991b604082015260600190565b60208082526022908201527f53656c6c206f72646572206e6f6e63652074696d657374616d7020746f6f206c6040820152616f7760f01b606082015260800190565b60208082526031908201527f4f726465722071756f7465207175616e74697479206f6e6c792076616c696420604082015270666f72206d61726b6574206f726465727360781b606082015260800190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604082015261756560f01b606082015260800190565b60208082526024908201527f4d616b657220666565206173736574206973206e6f7420696e207472616465206040820152633830b4b960e11b606082015260800190565b60208082526027908201527f546f6b656e2063616e6e6f742068617665206d6f7265207468616e20333220646040820152666563696d616c7360c81b606082015260800190565b60208082526021908201527f4e6f6e63652074696d657374616d7020746f6f2066617220696e2066757475726040820152606560f81b606082015260800190565b60208082526019908201527815d85b1b195d08195e1a5d081b9bdd08199a5b985b1a5e9959603a1b604082015260600190565b602080825260159082015274088cac6d2dac2d8e640c8de40dcdee840dac2e8c6d605b1b604082015260600190565b60208082526018908201527714d95b198b5d1c98591a5b99c81b9bdd08185b1b1bddd95960421b604082015260600190565b60208082526027908201527f4261736520616e642071756f746520617373657473206d7573742062652064696040820152661999995c995b9d60ca1b606082015260800190565b6020808252818101527f5369676e617475726520686173682076657273696f6e206d7573742062652031604082015260600190565b60208082526015908201527415d85b1b195d08185b1c9958591e48195e1a5d1959605a1b604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604082015261756560f01b606082015260800190565b6020808252601f908201527f557365206465706f736974457468657220746f206465706f7369742045544800604082015260600190565b6020808252601890820152774d757374206265206c657373207468616e2031207765656b60401b604082015260600190565b60208082526024908201527f54616b657220666565206173736574206973206e6f7420696e207472616465206040820152633830b4b960e11b606082015260800190565b60208082526023908201527f4e6f20636f6e6669726d656420617373657420666f756e6420666f722073796d604082015262189bdb60ea1b606082015260800190565b60208082526010908201526f13dc99195c881bdd995c999a5b1b195960821b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260189082015277457863657373697665207769746864726177616c2066656560401b604082015260600190565b6020808252601d908201527f506970207175616e74697479206f766572666c6f77732075696e743634000000604082015260600190565b60208082526021908201527f557365206465706f736974457468657220746f206465706f73697420457468656040820152603960f91b606082015260800190565b60208082526014908201527321b0b63632b91036bab9ba1031329037bbb732b960611b604082015260600190565b60208082526029908201527f4d75737420626520646966666572656e742066726f6d2063757272656e7420666040820152681959481dd85b1b195d60ba1b606082015260800190565b6020808252601e908201527f437573746f6469616e2063616e206f6e6c7920626520736574206f6e63650000604082015260600190565b6020808252601690820152752430b9b41030b63932b0b23c903bb4ba34323930bbb760511b604082015260600190565b602080825260179082015276151bdad95b88185b1c9958591e48199a5b985b1a5e9959604a1b604082015260600190565b60208082526029908201527f4d75737420626520646966666572656e742066726f6d2063757272656e74206460408201526834b9b830ba31b432b960b91b606082015260800190565b6020808252601e908201527f427579206f72646572206c696d69742070726963652065786365656465640000604082015260600190565b60208082526013908201527213dc99195c88191bdd589b1948199a5b1b1959606a1b604082015260600190565b60208082526021908201527f427579206f72646572206e6f6e63652074696d657374616d7020746f6f206c6f6040820152607760f81b606082015260800190565b60208082526024908201527f4e6f20636f6e6669726d656420617373657420666f756e6420666f72206164646040820152637265737360e01b606082015260800190565b60208082526014908201527321b0b63632b91036bab9ba1031329030b236b4b760611b604082015260600190565b602080825260139082015272115512081d1c985b9cd9995c8819985a5b1959606a1b604082015260600190565b60208082526027908201527f41737365742063616e6e6f742068617665206d6f7265207468616e20333220646040820152666563696d616c7360c81b606082015260800190565b60208082526034908201527f53656c6c206f72646572206d61726b65742073796d626f6c2061646472657373604082015273040e4cae6ded8eae8d2dedc40dad2e6dac2e8c6d60631b606082015260800190565b602080825260159082015274496e76616c696420746f6b656e206164647265737360581b604082015260600190565b60208082526030908201527f50726576696f757320696e76616c69646174696f6e206177616974696e67206360408201526f3430b4b710383937b830b3b0ba34b7b760811b606082015260800190565b60208082526028908201527f4e65742071756f746520706c757320666565206973206e6f7420657175616c20604082015267746f2067726f737360c01b606082015260800190565b6020808252601f908201527f53656c6c206f72646572206c696d697420707269636520657863656564656400604082015260600190565b602080825260149082015273125b9d985b1a59081d1bdad95b881cde5b589bdb60621b604082015260600190565b60208082526011908201527015d85b1b195d081b9bdd08195e1a5d1959607a1b604082015260600190565b602080825260169082015275496e76616c69642077616c6c6574206164647265737360501b604082015260600190565b6020808252602b908201527f496d706c6965642071756f746520706970207175616e74697479206f7665726660408201526a1b1bdddcc81d5a5b9d0d8d60aa1b606082015260800190565b60208082526048908201527f546f6b656e20636f6e74726163742072657475726e6564207472616e7366657260408201527f207375636365737320776974686f75742065787065637465642062616c616e6360608201526765206368616e676560c01b608082015260a00190565b602080825260199082015278109d5e481dd85b1b195d08195e1a5d08199a5b985b1a5e9959603a1b604082015260600190565b60208082526028908201527f51756f7465207175616e74697479206d7573742062652067726561746572207460408201526768616e207a65726f60c01b606082015260800190565b6020808252600d908201526c15d85b1b195d08195e1a5d1959609a1b604082015260600190565b602080825260149082015273139bc818985b185b98d948199bdc88185cdcd95d60621b604082015260600190565b60208082526027908201527f42617365207175616e74697479206d7573742062652067726561746572207468604082015266616e207a65726f60c81b606082015260800190565b60006020825282511515602083015260018060a01b036020840151166040830152604083015160c06060840152615e4160e08401826149bf565b60ff60608601511660808501526080850151151560a08501526001600160401b0360a08601511660c0850152809250505092915050565b6001600160801b039390931683526001600160401b03919091166020830152604082015260600190565b90815260200190565b918252602082015260400190565b6001600160401b0391909116815260200190565b60006001600160401b03808816835260a06020840152615ef060a08401886149bf565b9581166040840152939093166060820152608001525092915050565b6040518181016001600160401b0381118282101715615f2a57600080fd5b604052919050565b60005b83811015615f4d578181015183820152602001615f35565b838111156108dd5750506000910152565b6001600160a01b0381168114615f7357600080fd5b5056fe496e76616c69642077616c6c6574207369676e617475726520666f7220627579206f72646572496e76616c69642077616c6c6574207369676e617475726520666f722073656c6c206f72646572a26469706673582212205dd7ac35c5f7c6f5ec79f4ba79633e7c75138d994328bbe33fa2efc0d21be22d64736f6c63430006080033
Deployed Bytecode Sourcemap
1220:38806:5:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;35081:281:5;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;35081:281:5;;;;;;;;:::i;:::-;;11712:85;;5:9:-1;2:2;;;27:1;24;17:12;2:2;11712:85:5;;;:::i;:::-;;;;;;;;;;;;;;;;37580:151;;5:9:-1;2:2;;;27:1;24;17:12;2:2;37580:151:5;;;:::i;8990:422::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;8990:422:5;;;;;;;;:::i;:::-;;;;;;;;9793:465;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;9793:465:5;;;;;;;;:::i;7507:455::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;7507:455:5;;;;;;;;:::i;6843:249::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;6843:249:5;;;;;;;;:::i;13497:442::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;13497:442:5;;;;;;;;:::i;34477:248::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;34477:248:5;;;;;;;;:::i;22047:187::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;22047:187:5;;;:::i;23190:1171::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;23190:1171:5;;;;;;;;:::i;18097:2154::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;18097:2154:5;;;;;;;;:::i;733:222:7:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;733:222:7;;;;;;;;:::i;35628:209:5:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;35628:209:5;;;;;;;;:::i;36433:215::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;36433:215:5;;;;;;;;:::i;:::-;;;;;;;;8216:368;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;8216:368:5;;;;;;;;:::i;21111:778::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;21111:778:5;;;;;;;;:::i;12509:96::-;;;:::i;1097:74:7:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1097:74:7;;;:::i;12270:178:5:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;12270:178:5;;;;;;;;:::i;:::-;;;;;;;;36930:439;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;36930:439:5;;;;;;;;:::i;16672:1168::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;16672:1168:5;;;;;;;;:::i;10626:238::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;10626:238:5;;;;;;;;:::i;12899:285::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;12899:285:5;;;;;;;;:::i;20557:292::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;20557:292:5;;;:::i;11230:370::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;11230:370:5;;;;;;;;:::i;35081:281::-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;;;;;;;;;35217:71:5::1;35257:12;35271:6;;35217:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16:::0;::::1;74:27:::0;;;;-1:-1;35217:14:5::1;::::0;:71;;-1:-1:-1;35279:8:5;;-1:-1:-1;;35217:71:5::1;:39;:71;:::i;:::-;35326:12;-1:-1:-1::0;;;;;35299:58:5::1;;35340:6;;35348:8;35299:58;;;;;;;;;;;;;;;;;35081:281:::0;;;;:::o;11712:85::-;11782:10;;-1:-1:-1;;;;;11782:10:5;11712:85;;:::o;37580:151::-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;37656:17:5::1;::::0;37638:50:::1;::::0;::::1;::::0;::::1;::::0;-1:-1:-1;;;;;37656:17:5;;::::1;::::0;::::1;::::0;37638:50:::1;;;;;;;;;;37694:17;:32:::0;;-1:-1:-1;;;;;;37694:32:5::1;::::0;;37580:151::o;8990:422::-;9105:7;-1:-1:-1;;;;;9128:22:5;;9120:57;;;;-1:-1:-1;;;9120:57:5;;;;;;;;;9184:26;;:::i;:::-;9213:59;:14;9254:12;9213:59;:33;:59;:::i;:::-;-1:-1:-1;;;;;9338:23:5;;;;;;;:15;:23;;;;;;;;:37;;;;;;;;;;9385:14;;;;9184:88;;-1:-1:-1;9291:116:5;;-1:-1:-1;;;;;9338:37:5;;;;9291;:116::i;:::-;9278:129;;;8990:422;;;;;:::o;9793:465::-;9914:7;-1:-1:-1;;;;;9937:22:5;;9929:57;;;;-1:-1:-1;;;9929:57:5;;;;;;;;;9993:26;;:::i;:::-;10022:90;10062:11;;10022:90;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;10081:25:5;;-1:-1:-1;10081:23:5;;-1:-1:-1;;10081:25:5:i;:::-;10022:14;;:90;;:32;:90;:::i;:::-;-1:-1:-1;;;;;10178:23:5;;;;;;;:15;:23;;;;;;;;10202:18;;;;10178:43;;;;;;;;;;10231:14;;;;9993:119;;-1:-1:-1;10131:122:5;;-1:-1:-1;;;;;10178:43:5;;;;10131:37;:122::i;:::-;10118:135;;;9793:465;;;;;;:::o;7507:455::-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;5957:23:5::1;7627:25;:54;7612:109;;;;-1:-1:-1::0;;;7612:109:5::1;;;;;;;;;7764:23;::::0;;7793:51;;;;7856:101:::1;::::0;::::1;::::0;::::1;::::0;7764:23;;7819:25;;7856:101:::1;;;;;;;;;;398:1:7;7507:455:5::0;:::o;6843:249::-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;6928:10:5::1;::::0;-1:-1:-1;;;;;6928:10:5::1;:26:::0;6920:69:::1;;;;-1:-1:-1::0;;;6920:69:5::1;;;;;;;;;7003:32;7022:12;7003:18;:32::i;:::-;6995:60;;;;-1:-1:-1::0;;;6995:60:5::1;;;;;;;;;7062:10;:25:::0;;-1:-1:-1;;;;;;7062:25:5::1;-1:-1:-1::0;;;;;7062:25:5;;;::::1;::::0;;;::::1;::::0;;6843:249::o;13497:442::-;13613:19;13649:81;13691:11;;13649:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;13704:25:5;;-1:-1:-1;13704:23:5;;-1:-1:-1;;13704:25:5:i;13649:81::-;:103;;;;-1:-1:-1;;;;;;13779:37:5;;13764:99;;;;-1:-1:-1;;;13764:99:5;;;;;;;;;13870:64;13878:10;13898:12;13913:20;13870:7;:64::i;:::-;13497:442;;;;:::o;34477:248::-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;34602:60:5::1;34631:12;34645:6;;34602:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16:::0;::::1;74:27:::0;;;;-1:-1;34602:14:5::1;::::0;:60;;-1:-1:-1;34653:8:5;;-1:-1:-1;;34602:60:5::1;:28;:60;:::i;:::-;34689:12;-1:-1:-1::0;;;;;34673:47:5::1;;34703:6;;34711:8;34673:47;;;;;;;;;22047:187:::0;22110:10;22097:24;;;;:12;:24;;;;;:31;;;22089:61;;;;-1:-1:-1;;;22089:61:5;;;;;;;;;22177:10;22164:24;;;;:12;:24;;;;;;22157:31;;-1:-1:-1;;22157:31:5;;;;;;;;22200:29;;;22164:24;22200:29;22047:187::o;23190:1171::-;37789:17;;-1:-1:-1;;;;;37789:17:5;37775:10;:31;37767:68;;;;-1:-1:-1;;;37767:68:5;;;;;;;;;23362:40:::1;23384:3;:17;;;23362:21;:40::i;:::-;23361:41;23346:97;;;;-1:-1:-1::0;;;23346:97:5::1;;;;;;;;;23465:41;23487:4;:18;;;23465:21;:41::i;:::-;23464:42;23449:99;;;;-1:-1:-1::0;;;23449:99:5::1;;;;;;;;;23590:4;:18;;;-1:-1:-1::0;;;;;23569:39:5::1;:3;:17;;;-1:-1:-1::0;;;;;23569:39:5::1;;;23554:94;;;;-1:-1:-1::0;;;23554:94:5::1;;;;;;;;;23655:35;23673:3;23678:4;23684:5;23655:17;:35::i;:::-;23696:37;23716:3;23721:4;23727:5;23696:19;:37::i;:::-;23739:30;23759:3;23764:4;23739:19;:30::i;:::-;23776:15;23793:16:::0;23813:65:::1;23844:3;23855:4;23867:5;23813:23;:65::i;:::-;23775:103;;;;23884:24;23902:5;23884:17;:24::i;:::-;23915:64;23943:3;23948:7;23957:4;23963:8;23973:5;23915:27;:64::i;:::-;23985:40;24008:3;24013:4;24019:5;23985:22;:40::i;:::-;24138:5;:22;;;24037:319;;;;;;;;;::::0;;;;::::1;::::0;;24109:21;;24037:319;;::::1;::::0;24109:21;24037:319:::1;;;;;;;;;;;24058:3;:17;;;24083:4;:18;;;24168:5;:21;;;24197:5;:22;;;24227:5;:29;;;24264:5;:30;;;24302:5;:17;;;24327:7;24342:8;24037:319;;;;;;;;;;;;;;;;;;;;;;;37841:1;;23190:1171:::0;;;:::o;18097:2154::-;37789:17;;-1:-1:-1;;;;;37789:17:5;37775:10;:31;37767:68;;;;-1:-1:-1;;;37767:68:5;;;;;;;;;18232:47:::1;18254:10;:24;;;18232:21;:47::i;:::-;18231:48;18223:74;;;;-1:-1:-1::0;;;18223:74:5::1;;;;;;;;;6116:8;-1:-1:-1::0;;;;;18318:109:5::1;:69;18336:10;:23;;;18361:10;:25;;;18318:17;:69::i;:::-;-1:-1:-1::0;;;;;18318:109:5::1;;;18303:164;;;;-1:-1:-1::0;;;18303:164:5::1;;;;;;;;;18473:22;18498:39;18526:10;18498:27;:39::i;:::-;18559:42;::::0;;;:26:::1;:42;::::0;;;;;18473:64;;-1:-1:-1;18559:42:5::1;;18558:43;18543:96;;;;-1:-1:-1::0;;;18543:96:5::1;;;;;;;;;18730:26;;:::i;:::-;18794:29;18759:25:::0;;:64:::1;::::0;::::1;;;;;;;:271;;19006:23;::::0;::::1;::::0;18972:58:::1;::::0;:14:::1;::::0;:58:::1;:33;:58;:::i;:::-;18759:271;;;18832:131;18874:10;:22;;;18906:49;18938:10;:16;;;18906:31;:49::i;18832:131::-;18730:300;;19085:29;19117:66;19154:10;:23;;;19117:10;:25;;;-1:-1:-1::0;;;;;19117:29:5::1;;;:66;;;;:::i;:::-;19085:98;;19189:36;19228:84;19273:22;19297:5;:14;;;19228:44;:84::i;:::-;19432:25;::::0;::::1;::::0;19368:31:::1;::::0;;::::1;::::0;-1:-1:-1;;;;;19352:48:5;;::::1;19318:31;19352:48:::0;;;:15:::1;:48;::::0;;;;;;19401:18;;::::1;::::0;19352:68;;::::1;::::0;;;;;;;;;;19189:123;;-1:-1:-1;19318:31:5;19352:106:::1;::::0;-1:-1:-1;;;;;19352:68:5;;::::1;::::0;:106:::1;:79;:106;:::i;:::-;19318:140;;19464:38;19505:86;19550:24;19576:5;:14;;;19505:44;:86::i;:::-;19614:24;::::0;;::::1;::::0;-1:-1:-1;;;;;19598:41:5;;::::1;;::::0;;;:15:::1;:41;::::0;;;;;;19640:25;;::::1;::::0;;19598:68;::::1;::::0;;;;;;;;:95;;-1:-1:-1;;;;;;19598:95:5::1;-1:-1:-1::0;;;;;19598:95:5;;::::1;::::0;;;::::1;::::0;;;19815:23:::1;::::0;::::1;::::0;19772:10:::1;::::0;;::::1;19756:27:::0;;;;;;;;19784:18;;19756:47;;::::1;::::0;;;;;;;;19464:127;;-1:-1:-1;19756:88:5::1;::::0;:47:::1;::::0;:51:::1;:88::i;:::-;19715:10;::::0;-1:-1:-1;;;;;19715:10:5;;::::1;19699:27;::::0;;;:15:::1;:27;::::0;;;;;;;19727:25;;::::1;::::0;;19699:54;::::1;::::0;;;;;;;;:145;;-1:-1:-1;;;;;;19699:145:5::1;-1:-1:-1::0;;;;;19699:145:5;;;::::1;::::0;;;::::1;::::0;;;19862:10:::1;::::0;19890:24;;::::1;::::0;19922:18;;19851:131;;-1:-1:-1;;;19851:131:5;;19862:10;::::1;::::0;19851:31:::1;::::0;:131:::1;::::0;19922:18;19948:28;;19851:131:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;19851:131:5;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;-1:-1:::0;;;19989:42:5::1;::::0;;;:26:::1;:42;::::0;;;;;;;;:49;;-1:-1:-1;;19989:49:5::1;20034:4;19989:49;::::0;;20099:18;::::1;::::0;20067:24;;::::1;::::0;20125:12;;::::1;::::0;20145:25:::1;::::0;::::1;::::0;20050:196;;-1:-1:-1;;;;;20050:196:5;;::::1;::::0;-1:-1:-1;20050:196:5;;;::::1;::::0;::::1;::::0;::::1;::::0;20125:12;;20145:25;20178:24;;20210:30;;20050:196:::1;;;;;;;;;;37841:1;;;;;;18097:2154:::0;:::o;733:222:7:-;254:10;-1:-1:-1;;;;;268:6:7;254:20;;246:53;;;;-1:-1:-1;;;246:53:7;;;;;;;;;-1:-1:-1;;;;;802:24:7;::::1;794:59;;;;-1:-1:-1::0;;;794:59:7::1;;;;;;;;;879:6;::::0;-1:-1:-1;;;;;867:18:7;;::::1;879:6:::0;::::1;867:18;;859:67;;;;-1:-1:-1::0;;;859:67:7::1;;;;;;;;;933:6;:17:::0;;-1:-1:-1;;;;;;933:17:7::1;-1:-1:-1::0;;;;;933:17:7;;;::::1;::::0;;;::::1;::::0;;733:222::o;35628:209:5:-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;35732:51:5::1;35762:12;35776:6;;35732:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16:::0;::::1;74:27:::0;;;;-1:-1;35732:14:5::1;::::0;:51;;-1:-1:-1;;35732:51:5::1;:29;:51;::::0;-1:-1:-1;35732:51:5:i:1;:::-;35811:12;-1:-1:-1::0;;;;;35794:38:5::1;;35825:6;;35794:38;;;;;;;;;;;;;;;;35628:209:::0;;;:::o;36433:215::-;36546:20;;:::i;:::-;36583:60;36616:11;;36583:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;36583:14:5;;:60;-1:-1:-1;36629:13:5;;-1:-1:-1;;36583:60:5;:32;:60;:::i;:::-;36576:67;36433:215;-1:-1:-1;;;;36433:215:5:o;8216:368::-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;-1:-1:-1;;;;;8293:28:5;::::1;8285:63;;;;-1:-1:-1::0;;;8285:63:5::1;;;;;;;;;8385:10;::::0;-1:-1:-1;;;;;8369:26:5;;::::1;8385:10:::0;::::1;8369:26;;8354:98;;;;-1:-1:-1::0;;;8354:98:5::1;;;;;;;;;8482:10;::::0;;-1:-1:-1;;;;;8498:25:5;;::::1;-1:-1:-1::0;;;;;;8498:25:5;::::1;;::::0;;;8535:44:::1;::::0;8482:10;::::1;::::0;8535:44:::1;::::0;::::1;::::0;8482:10;;8511:12;;8535:44:::1;;21111:778:::0;21178:33;21200:10;21178:21;:33::i;:::-;21170:71;;;;-1:-1:-1;;;21170:71:5;;;;;;;;;21248:26;;:::i;:::-;21277:59;:14;21318:12;21277:59;:33;:59;:::i;:::-;21381:10;21342:20;21365:27;;;:15;:27;;;;;;;;-1:-1:-1;;;;;21365:41:5;;;;;;;;;;21508:14;;;;21248:88;;-1:-1:-1;;;;;;21365:41:5;;21442:86;;21365:41;;21442:37;:86::i;:::-;21412:116;;21565:1;21543:19;:23;21535:56;;;;-1:-1:-1;;;21535:56:5;;;;;;;;;21613:10;21641:1;21597:27;;;:15;:27;;;;;;;;-1:-1:-1;;;;;21597:41:5;;;;;;;;;;;:45;;-1:-1:-1;;;;;;21597:45:5;;;21659:10;;21648:102;;-1:-1:-1;;;21648:102:5;;21659:10;;;21648:31;;:102;;21613:10;21625:12;;21725:19;;21648:102;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;21648:102:5;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;21648:102:5;;;;21807:12;-1:-1:-1;;;;;21762:122:5;21789:10;-1:-1:-1;;;;;21762:122:5;;21827:5;:12;;;21847:13;21868:1;21877;21762:122;;;;;;;;;;;;;;;;;;21111:778;;;;:::o;12509:96::-;12556:44;12564:10;12584:3;12590:9;12556:7;:44::i;:::-;12509:96::o;1097:74:7:-;254:10;-1:-1:-1;;;;;268:6:7;254:20;;246:53;;;;-1:-1:-1;;;246:53:7;;;;;;;;;1162:3:::1;1145:21:::0;;-1:-1:-1;;;;;;1145:21:7::1;::::0;;1097:74::o;12270:178:5:-;12372:6;12395:48;;;:37;:48;;;;;;-1:-1:-1;;;;;12395:48:5;12270:178;;;;:::o;36930:439::-;361:6:7;;-1:-1:-1;;;;;361:6:7;347:10;:20;339:53;;;;-1:-1:-1;;;339:53:7;;;;;;;;;-1:-1:-1;;;;;37015:35:5;::::1;37007:70;;;;-1:-1:-1::0;;;37007:70:5::1;;;;;;;;;37121:17;::::0;-1:-1:-1;;;;;37098:40:5;;::::1;37121:17:::0;::::1;37098:40;;37083:112;;;;-1:-1:-1::0;;;37083:112:5::1;;;;;;;;;37231:17;::::0;;-1:-1:-1;;;;;37254:39:5;;::::1;-1:-1:-1::0;;;;;;37254:39:5;::::1;;::::0;;;37305:59:::1;::::0;37231:17;::::1;::::0;37305:59:::1;::::0;::::1;::::0;37231:17;;37274:19;;37305:59:::1;;16672:1168:::0;16732:20;16755:38;16787:5;16755:31;:38::i;:::-;16732:61;;16978:22;:20;:22::i;:::-;-1:-1:-1;;;;;16962:38:5;:13;-1:-1:-1;;;;;16962:38:5;;16947:102;;;;-1:-1:-1;;;16947:102:5;;;;;;;;;17080:10;17060:31;;;;:19;:31;;;;;:38;;;17056:353;;;17145:10;17125:31;;;;:19;:31;;;;;:45;-1:-1:-1;;;;;17125:61:5;;;:45;;;;;:61;17108:133;;;;-1:-1:-1;;;17108:133:5;;;;;;;;;17286:10;17266:31;;;;:19;:31;;;;;:52;;;17322:12;-1:-1:-1;17266:68:5;17249:153;;;;-1:-1:-1;;;17249:153:5;;;;;;;;;17569:23;;17632:84;;;;;;;;17657:4;17632:84;;;-1:-1:-1;;;;;17632:84:5;;;;;;;;;;17554:12;:38;;;17632:84;;;;;;17618:10;-1:-1:-1;17598:31:5;;;:19;:31;;;;;;;:118;;;;;;-1:-1:-1;;17598:118:5;;;;;;;-1:-1:-1;;17598:118:5;;;;;;;;;;;;;;;;;;;;;;;;;17728:107;;17554:38;;17618:10;17728:107;;;;17775:5;;17632:84;;17554:38;;17728:107;;10626:238;10735:6;-1:-1:-1;;;;;10759:22:5;;10751:57;;;;-1:-1:-1;;;10751:57:5;;;;;;;;;-1:-1:-1;;;;;;10822:23:5;;;;;;;:15;:23;;;;;;;;:37;;;;;;;;;;;;-1:-1:-1;;;;;10822:37:5;;10626:238::o;12899:285::-;-1:-1:-1;;;;;13023:37:5;;13008:101;;;;-1:-1:-1;;;13008:101:5;;;;;;;;;13115:64;13123:10;13143:12;13158:20;13115:7;:64::i;:::-;12899:285;;:::o;20557:292::-;20616:10;20603:24;;;;:12;:24;;;;;:31;;;20602:32;20594:66;;;;-1:-1:-1;;;20594:66:5;;;;;;;;;20694:74;;;;;;;;20712:4;20694:74;;;20739:23;;;20724:12;:38;;;20694:74;;;;;;;20680:10;-1:-1:-1;20667:24:5;;;:12;:24;;;;;;;:101;;;;-1:-1:-1;;20667:101:5;;;;;;;;;;;;;;;;;20820:23;20780:64;;20680:10;;20780:64;;;;20805:38;;;20780:64;;;;;;;;;;20557:292::o;11230:370::-;11345:6;-1:-1:-1;;;;;11367:22:5;;11359:57;;;;-1:-1:-1;;;11359:57:5;;;;;;;;;11423:20;11446:79;11486:11;;11446:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;11499:25:5;;-1:-1:-1;11499:23:5;;-1:-1:-1;;11499:25:5:i;11446:79::-;:99;;;;;-1:-1:-1;;;;;11558:23:5;;;;;;;:15;:23;;;;;;:37;;;;;;;;;;;-1:-1:-1;;;;;11558:37:5;;-1:-1:-1;;11230:370:5;;;;;:::o;1488:714:1:-;1638:26;;:::i;:::-;-1:-1:-1;;;;;1667:43:1;;;:20;:43;;;;;;;;;;;;1638:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1638:72:1;;;;;;;;;;;;;;;;;;;;;;;;;1667:43;;1638:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1638:72:1;;;-1:-1:-1;;1638:72:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1638:72:1;;;;;;1724:12;;;;-1:-1:-1;1716:38:1;;;;-1:-1:-1;;;1716:38:1;;;;;;;;;1769:5;:17;;;1768:18;1760:54;;;;-1:-1:-1;;;1760:54:1;;;;;;;;;1828:35;1842:5;:12;;;1856:6;1828:13;:35::i;:::-;1820:68;;;;-1:-1:-1;;;1820:68:1;;;;;;;;;1920:8;1902:26;;:5;:14;;;:26;;;1894:60;;;;-1:-1:-1;;;1894:60:1;;;;;;;;;1981:4;1961:17;;;:24;;;-1:-1:-1;;;;;2047:4:1;2029:15;:22;1991:61;:28;;;:61;-1:-1:-1;;;;;2101:43:1;;;1961:24;2101:43;;;;;;;;;;;;:51;;;;;;;;;;;;;-1:-1:-1;;;;;;2101:51:1;;;-1:-1:-1;;2101:51:1;;;;;;;;;;;;;;;;;;;;1961:5;;2101:51;;;;;;;;;:::i;:::-;-1:-1:-1;2101:51:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2101:51:1;;;-1:-1:-1;;;;;;2101:51:1;;;;;-1:-1:-1;;2101:51:1;;;;-1:-1:-1;;2101:51:1;;;;;;;;;;;;;;;;;;;2158:27;;2101:51;2158:19;;;:27;;2178:6;;2158:27;;;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;2158:39:1;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2158:39:1;;;-1:-1:-1;;;;;;2158:39:1;;;-1:-1:-1;;2158:39:1;;;;;;;;;;;;;;;;;;;;;;;2191:5;;2158:39;;;;;;;;:::i;:::-;-1:-1:-1;2158:39:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2158:39:1;;;-1:-1:-1;;;;;;2158:39:1;;;;;-1:-1:-1;;2158:39:1;;;;-1:-1:-1;;2158:39:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1488:714:1:o;2953:405::-;3060:20;;:::i;:::-;-1:-1:-1;;;;;3094:28:1;;3090:69;;3139:13;:11;:13::i;:::-;3132:20;;;;3090:69;3165:26;;:::i;:::-;-1:-1:-1;;;;;3194:34:1;;;:20;:34;;;;;;;;;;;;3165:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3165:63:1;;;;;;;;;;;;;;;;;;;;;;;;;3194:34;;3165:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3165:63:1;;;-1:-1:-1;;3165:63:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3165:63:1;;;;;;3249:12;;;;-1:-1:-1;3249:33:1;;;;;3265:5;:17;;;3249:33;3234:100;;;;-1:-1:-1;;;3234:100:1;;;;;;;;326:472:3;431:7;473:2;456:13;:19;;;;448:71;;;;-1:-1:-1;;;448:71:3;;;;;;;;;634:1;618:13;:17;;;614:106;;;652:61;-1:-1:-1;;;;;652:23:3;;680:32;-1:-1:-1;;694:17:3;;680:32;688:2;680:32;652:61;:27;:61;:::i;614:106::-;732:61;-1:-1:-1;;;;;732:23:3;;760:32;774:1;:17;;;760:32;768:2;760:32;732:61;:27;:61;:::i;38433:156:5:-;38552:15;38527:4;38545:39;38433:156;:::o;3722:691:1:-;3854:20;;:::i;:::-;3886:28;;;;;;;;;;;;;;-1:-1:-1;;;3886:28:1;;;3907:6;3886:13;:28::i;:::-;3882:69;;;3931:13;:11;:13::i;:::-;3924:20;;;;3882:69;3957:26;;:::i;:::-;4030:1;3993:4;:19;;4013:6;3993:27;;;;;;;;;;;;;;;;;;;;;:34;:38;3989:296;;;4046:7;4041:238;4063:4;:19;;4083:6;4063:27;;;;;;;;;;;;;;;;;;;;;:34;4059:38;;;;4041:238;;;4186:13;-1:-1:-1;;;;;4129:70:1;:4;:19;;4149:6;4129:27;;;;;;;;;;;;;;;;;;;;4157:1;4129:30;;;;;;;;;;;;;;;;;;;;;;;:53;;;;;;-1:-1:-1;;;;;4129:53:1;:70;4114:157;;4230:4;:19;;4250:6;4230:27;;;;;;;;;;;;;;;;;;;;4258:1;4230:30;;;;;;;;;;;;;;;;;;;4222:38;;;;;;;;4230:30;;;;;;;;4222:38;;;;;;;;;;;;;;-1:-1:-1;;;;;4222:38:1;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4222:38:1;;;;;;;;;;;;;;;;;;;;;;;;;4230:30;;4222:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4222:38:1;;;-1:-1:-1;;4222:38:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4222:38:1;;;;;;;-1:-1:-1;4114:157:1;4099:3;;4041:238;;;;3989:296;4305:12;;:33;;;;;4321:5;:17;;;4305:33;4290:99;;;;-1:-1:-1;;;4290:99:1;;;;;;;;718:413:0;1078:20;1116:8;;;718:413::o;13943:2369:5:-;-1:-1:-1;;;;;14297:20:5;;;;;;:12;:20;;;;;:27;;;14296:28;14288:54;;;;-1:-1:-1;;;14288:54:5;;;;;;;;;14349:26;;:::i;:::-;14378:59;:14;14419:12;14378:59;:33;:59;:::i;:::-;14349:88;;14443:21;14467:93;14512:20;14540:5;:14;;;14467:37;:93::i;:::-;14443:117;;14591:1;14574:14;-1:-1:-1;;;;;14574:18:5;;14566:50;;;;-1:-1:-1;;;14566:50:5;;;;;;;;;14983:49;15035:76;15080:14;15096:5;:14;;;15035:44;:76::i;:::-;14983:128;-1:-1:-1;;;;;;15359:28:5;;;15355:181;;15397:132;15434:6;15457:12;15480:41;15397:27;:132::i;:::-;15618:10;;15585:118;;-1:-1:-1;;;;;15618:10:5;15636:12;15656:41;15585:25;:118::i;:::-;-1:-1:-1;;;;;15744:23:5;;;15710:31;15744:23;;;:15;:23;;;;;;;;:37;;;;;;;;;;;;:69;;-1:-1:-1;;;;;15744:37:5;15793:14;15744:69;:41;:69;:::i;:::-;15710:103;;15819:38;15860:86;15905:24;15931:5;:14;;;15860:44;:86::i;:::-;-1:-1:-1;;;;;16008:23:5;;;;;;;:15;:23;;;;;;;;:37;;;;;;;;;;;:64;;-1:-1:-1;;;;;;16008:64:5;-1:-1:-1;;;;;16008:64:5;;;;;;;;;;16078:13;:15;;-1:-1:-1;;;;16078:15:5;;-1:-1:-1;;;16078:15:5;;;;;;-1:-1:-1;16078:15:5;;;;;;;;;;;16177:12;;;;16105:202;;15819:127;;-1:-1:-1;16105:202:5;;;;;;;;;;;;16157:12;-1:-1:-1;;;;;16105:202:5;16143:6;-1:-1:-1;;;;;16105:202:5;;16122:13;;;;;;;;;-1:-1:-1;;;;;16122:13:5;16197:5;:12;;;16217:14;16239:24;16271:30;16105:202;;;;;;;;;;;;;;;;;;;13943:2369;;;;;;;;:::o;623:861:1:-;782:2;770:8;:14;;;;762:66;;;;-1:-1:-1;;;762:66:1;;;;;;;;;-1:-1:-1;;;;;849:27:1;;;;;;:72;;;880:41;907:12;880:18;:41::i;:::-;834:124;;;;-1:-1:-1;;;834:124:1;;;;;;;;;1093:1;1076:6;1070:20;:24;1062:57;;;;-1:-1:-1;;;1062:57:1;;;;;;;;;-1:-1:-1;;;;;1141:43:1;;:20;:43;;;;;;;;;;:55;;;;;;;;1140:56;1125:110;;;;-1:-1:-1;;;1125:110:1;;;;;;;;;1288:191;;;;;;;;1318:4;1288:191;;;-1:-1:-1;;;;;1288:191:1;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1288:191:1;;;;;;;;;;;;1242:43;;;;;;;;;;:237;;;;;;-1:-1:-1;;1242:237:1;;;;;;;-1:-1:-1;;;;;;1242:237:1;;;;;;;;;;;;;;;;;;;;1288:191;;1242:43;:237;;;;;;;;;;;:::i;:::-;-1:-1:-1;1242:237:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1242:237:1;;;-1:-1:-1;;;;;;1242:237:1;;;;;-1:-1:-1;;1242:237:1;;;;-1:-1:-1;;1242:237:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;623:861:1:o;22238:202:5:-;-1:-1:-1;;;;;22346:20:5;;22308:4;22346:20;;;:12;:20;;;;;22379:11;;;;:56;;;;-1:-1:-1;22394:25:5;;;22423:12;-1:-1:-1;22394:41:5;;22372:63;-1:-1:-1;;22238:202:5:o;28054:1929::-;28238:5;:23;;;-1:-1:-1;;;;;28212:49:5;:5;:22;;;-1:-1:-1;;;;;28212:49:5;;;28197:119;;;;-1:-1:-1;;;28197:119:5;;;;;;;;;28352:33;;:::i;:::-;28388:117;28428:5;:21;;;28457:42;28489:3;:9;;;28457:31;:42::i;28388:117::-;28352:153;;28511:34;;:::i;:::-;28548:118;28588:5;:22;;;28618:42;28650:3;:9;;;28618:31;:42::i;28548:118::-;28511:155;;28716:5;:22;;;-1:-1:-1;;;;;28687:51:5;:12;:25;;;-1:-1:-1;;;;;28687:51:5;;:116;;;;;28780:5;:23;;;-1:-1:-1;;;;;28750:53:5;:13;:26;;;-1:-1:-1;;;;;28750:53:5;;28687:116;28672:198;;;;-1:-1:-1;;;28672:198:5;;;;;;;;;28907:34;;:::i;:::-;28944:118;28984:5;:21;;;29013:43;29045:4;:10;;;29013:31;:43::i;28944:118::-;28907:155;;29068:35;;:::i;:::-;29106:119;29146:5;:22;;;29176:43;29208:4;:10;;;29176:31;:43::i;29106:119::-;29068:157;;29276:5;:22;;;-1:-1:-1;;;;;29246:52:5;:13;:26;;;-1:-1:-1;;;;;29246:52:5;;:118;;;;;29341:5;:23;;;-1:-1:-1;;;;;29310:54:5;:14;:27;;;-1:-1:-1;;;;;29310:54:5;;29246:118;29231:201;;;;-1:-1:-1;;;29231:201:5;;;;;;;;;29512:5;:22;;;-1:-1:-1;;;;;29482:52:5;:5;:26;;;-1:-1:-1;;;;;29482:52:5;;:117;;;;29576:5;:23;;;-1:-1:-1;;;;;29546:53:5;:5;:26;;;-1:-1:-1;;;;;29546:53:5;;29482:117;29467:184;;;;-1:-1:-1;;;29467:184:5;;;;;;;;;29702:5;:22;;;-1:-1:-1;;;;;29672:52:5;:5;:26;;;-1:-1:-1;;;;;29672:52:5;;:117;;;;29766:5;:23;;;-1:-1:-1;;;;;29736:53:5;:5;:26;;;-1:-1:-1;;;;;29736:53:5;;29672:117;29657:184;;;;-1:-1:-1;;;29657:184:5;;;;;;;;;29892:5;:26;;;-1:-1:-1;;;;;29862:56:5;:5;:26;;;-1:-1:-1;;;;;29862:56:5;;;29847:131;;;;-1:-1:-1;;;29847:131:5;;;;;;;;;28054:1929;;;;;;;:::o;29987:909::-;30179:1;30147:5;:29;;;-1:-1:-1;;;;;30147:33:5;;30132:103;;;;-1:-1:-1;;;30132:103:5;;;;;;;;;30289:1;30256:5;:30;;;-1:-1:-1;;;;;30256:34:5;;30241:105;;;;-1:-1:-1;;;30241:105:5;;;;;;;;;30357:31;30374:3;:13;;;30357:16;:31::i;:::-;30353:265;;;30531:5;:30;;;-1:-1:-1;;;;;30415:146:5;:112;30456:5;:29;;;30497:3;:20;;;30415:29;:112::i;:::-;-1:-1:-1;;;;;30415:146:5;;;30398:213;;;;-1:-1:-1;;;30398:213:5;;;;;;;;;30628:32;30645:4;:14;;;30628:16;:32::i;:::-;30624:268;;;30804:5;:30;;;-1:-1:-1;;;;;30687:147:5;:113;30728:5;:29;;;30769:4;:21;;;30687:29;:113::i;:::-;-1:-1:-1;;;;;30687:147:5;;;30670:215;;;;-1:-1:-1;;;30670:215:5;;;;;;;;;29987:909;;;:::o;33209:453::-;33390:46;33418:3;:17;;;33390:27;:46::i;:::-;-1:-1:-1;;;;;33337:99:5;:42;33369:3;:9;;;33337:31;:42::i;:::-;-1:-1:-1;;;;;33337:99:5;;33322:163;;;;-1:-1:-1;;;33322:163:5;;;;;;;;;33560:47;33588:4;:18;;;33560:27;:47::i;:::-;-1:-1:-1;;;;;33506:101:5;:43;33538:4;:10;;;33506:31;:43::i;:::-;-1:-1:-1;;;;;33506:101:5;;33491:166;;;;-1:-1:-1;;;33491:166:5;;;;;;;;32277:346;32429:7;32438;32453:20;32476:34;32499:3;32504:5;32476:22;:34::i;:::-;32453:57;;32516:21;32540:35;32563:4;32569:5;32540:22;:35::i;:::-;32590:12;;;;-1:-1:-1;32277:346:5;;-1:-1:-1;;;;;32277:346:5:o;30900:1373::-;30974:31;31044:5;:22;;;-1:-1:-1;;;;;31008:58:5;:5;:26;;;-1:-1:-1;;;;;31008:58:5;;:135;;31113:5;:30;;;31008:135;;;31075:5;:29;;;31008:135;30974:169;;6049:8;-1:-1:-1;;;;;31164:124:5;:97;31191:5;:28;;;31229:24;31164:17;:97::i;:::-;-1:-1:-1;;;;;31164:124:5;;;31149:174;;;;-1:-1:-1;;;31149:174:5;;;;;;;;;31330:31;31400:5;:22;;;-1:-1:-1;;;;;31364:58:5;:5;:26;;;-1:-1:-1;;;;;31364:58:5;;:135;;31469:5;:30;;;31364:135;;;31431:5;:29;;;31364:135;31330:169;;6049:8;-1:-1:-1;;;;;31520:124:5;:97;31547:5;:28;;;31585:24;31520:17;:97::i;:::-;-1:-1:-1;;;;;31520:124:5;;;31505:174;;;;-1:-1:-1;;;31505:174:5;;;;;;;;;31888:5;:29;;;-1:-1:-1;;;;;31701:216:5;:183;31772:5;:22;;;-1:-1:-1;;;;;31742:52:5;:5;:26;;;-1:-1:-1;;;;;31742:52:5;;:134;;31848:5;:28;;;31742:134;;;31807:5;:28;;;31742:134;31701:27;;;;-1:-1:-1;;;;;31701:31:5;;:183;:31;:183;:::i;:::-;-1:-1:-1;;;;;31701:216:5;;31686:286;;;;-1:-1:-1;;;31686:286:5;;;;;;;;;32182:5;:30;;;-1:-1:-1;;;;;31993:219:5;:185;32065:5;:23;;;-1:-1:-1;;;;;32035:53:5;:5;:26;;;-1:-1:-1;;;;;32035:53:5;;:135;;32142:5;:28;;;32035:135;;;32101:5;:28;;;32035:135;31993:28;;;;-1:-1:-1;;;;;31993:32:5;;:185;:32;:185;:::i;:::-;-1:-1:-1;;;;;31993:219:5;;31978:290;;;;-1:-1:-1;;;31978:290:5;;;;;;;;25927:336;26138:56;26164:8;26174:12;26188:5;26138:25;:56::i;:::-;26200:58;26226:9;26237:13;26252:5;26200:25;:58::i;:::-;25927:336;;;;;:::o;24477:1446::-;24813:29;;;;24751:18;;;;;-1:-1:-1;;;;;24735:35:5;;;;;;;:15;:35;;;;;;;24771:29;;;;24735:66;;;;;;;;;;;:108;;-1:-1:-1;;;;;24735:66:5;;;;:108;:77;:108;:::i;:::-;24682:18;;;;;-1:-1:-1;;;;;24666:35:5;;;;;;;:15;:35;;;;;;;24702:29;;;;;24666:66;;;;;;;;;;:177;;-1:-1:-1;;;;;;24666:177:5;-1:-1:-1;;;;;24666:177:5;;;;;;25038:27;;;;24977:17;;;;24961:34;;;;;;;;;;24996:29;;24961:65;;;;;;;;;;;;;;:105;;:65;;:76;:105::i;:::-;24909:17;;;;;;-1:-1:-1;;;;;24893:34:5;;;;;;;:15;:34;;;;;;;24928:29;;;;24893:65;;;;;;;;;:173;;-1:-1:-1;;;;;;24893:173:5;-1:-1:-1;;;;;24893:173:5;;;;;;25266:30;;;;25204:17;;25188:34;;;;;;;;;;25223:30;;;;25188:66;;;;;;;;;;;;;;:109;;:66;;:77;:109::i;:::-;25135:17;;;;;-1:-1:-1;;;;;25119:34:5;;;;;;;:15;:34;;;;;;;25154:30;;;;;25119:66;;;;;;;;;;:178;;-1:-1:-1;;;;;;25119:178:5;-1:-1:-1;;;;;25119:178:5;;;;;;25498:28;;;;25435:18;;;;25419:35;;;;;;;;;;25455:30;;25419:67;;;;;;;;;;;;;;:108;;:67;;:78;:108::i;:::-;25365:18;;;;;-1:-1:-1;;;;;25349:35:5;;;;;;;:15;:35;;;;;;;25385:30;;;;25349:67;;;;;;;;;:178;;-1:-1:-1;;;;;;25349:178:5;-1:-1:-1;;;;;25349:178:5;;;;;;25715:28;;;;25657:10;;;;25641:27;;;;;;;;25349:178;25669:33;;;25641:62;;;;;;;;;;;;;;:103;;:62;;:73;:103::i;:::-;25592:10;;;-1:-1:-1;;;;;25592:10:5;;;25576:27;;;;:15;:27;;;;;;;;25592:10;25604:33;;;25576:62;;;;;;;;;:168;;-1:-1:-1;;;;;;25576:168:5;-1:-1:-1;;;;;25576:168:5;;;;;;25889:28;;;;25831:10;;;;25815:27;;;;;;;;25843:33;;;;25815:62;;;;;;;;;;;:103;;:62;;:73;:103::i;:::-;25766:10;;-1:-1:-1;;;;;25766:10:5;;;25750:27;;;;:15;:27;;;;;;;;25778:33;;;;;;25750:62;;;;;;;;;;;;:168;;-1:-1:-1;;;;;;25750:168:5;-1:-1:-1;;;;;25750:168:5;;;;;;;;;-1:-1:-1;;24477:1446:5:o;38593:244::-;38680:6;38724:9;38794:38;38826:5;38794:27;-1:-1:-1;;;;;38794:7:5;;38724:9;38794:27;:7;:27;:::i;:::-;-1:-1:-1;;;;;38794:31:5;;:38;:31;:38;:::i;33666:421::-;33775:7;33792:22;33817:46;33852:10;33817:34;:46::i;:::-;33792:71;;33885:129;33922:14;33946:10;:26;;;33982:10;:24;;;33885:27;:129::i;:::-;33870:184;;;;-1:-1:-1;;;33870:184:5;;;;;;;;388:901:11;473:23;596:34;590:2;582:10;;;581:49;655:1;644:12;;636:40;;;;-1:-1:-1;;;636:40:11;;;;;;;;;-1:-1:-1;;;788:2:11;780:10;;;779:49;867:34;861:2;853:10;;;852:49;926:10;934:2;926:10;;;;1013:18;;;:28;;1185:69;1234:14;1216:5;-1:-1:-1;;;;;1192:29:11;;;-1:-1:-1;;;;;1185:41:11;;;:69;;;;:::i;:::-;1166:88;388:901;-1:-1:-1;;;;;;;388:901:11:o;1261:125:9:-;1317:6;1338:43;1342:1;1345;1338:43;;;;;;;;;;;;;;;;;:3;:43::i;859:158::-;915:6;940:5;;;-1:-1:-1;;;;;959:6:9;;;;;;;;951:46;;;;-1:-1:-1;;;951:46:9;;;;;;;;2206:607:1;2326:26;;:::i;:::-;-1:-1:-1;;;;;2355:43:1;;;:20;:43;;;;;;;;;;;;2326:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2326:72:1;;;;;;;;;;;;;;;;;;;;;;;;;2355:43;;2326:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;2326:72:1;;;-1:-1:-1;;2326:72:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2326:72:1;;;;;;2419:12;;;;-1:-1:-1;2419:33:1;;;;;2435:5;:17;;;2419:33;2404:99;;;;-1:-1:-1;;;2404:99:1;;;;;;;;;2518:28;2532:6;2518:28;;;;;;;;;;;;;-1:-1:-1;;;2518:28:1;;;:13;:28::i;:::-;2517:29;2509:71;;;;-1:-1:-1;;;2509:71:1;;;;;;;;;2730:15;2682:4;2730:31;;;-1:-1:-1;;;;;2692:70:1;:28;;;:70;2769:27;;:19;;;;:27;;2789:6;;2769:27;;;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;2769:39:1;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2769:39:1;;;-1:-1:-1;;;;;;2769:39:1;;;-1:-1:-1;;2769:39:1;;;;;;;;;;;;;;;;;;;;;;;2802:5;;2769:39;;;;;;;;:::i;39761:263:5:-;39968:15;39854:12;39961:41;39942:4;39960:59;39761:263;:::o;4751:181:1:-;4842:4;4924:1;4907:19;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4907:19:1;;;4897:30;;;;;;4890:1;4873:19;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4873:19:1;;;4863:30;;;;;;:64;4856:71;;4751:181;;;;:::o;4519:138::-;4564:20;;:::i;:::-;-1:-1:-1;4599:53:1;;;;;;;;4613:4;4599:53;;;-1:-1:-1;4599:53:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;4599:53:1;;;;;;;;;;;;;;4640:2;4599:53;;;;;;;;;;;;;;;4519:138;:::o;2180:459:8:-;2238:7;2479:6;2475:45;;-1:-1:-1;2508:1:8;2501:8;;2475:45;2542:5;;;2546:1;2542;:5;:1;2565:5;;;;;:10;2557:56;;;;-1:-1:-1;;;2557:56:8;;;;;;;;3101:130;3159:7;3185:39;3189:1;3192;3185:39;;;;;;;;;;;;;-1:-1:-1;;;3185:39:8;;;:3;:39::i;802:673:3:-;914:6;955:2;938:13;:19;;;;930:71;;;;-1:-1:-1;;;930:71:3;;;;;;;;;1008:22;1144:1;1128:13;:17;;;1124:241;;;1172:74;:20;1206:32;-1:-1:-1;;1220:17:3;;1206:32;1214:2;1206:32;1172:74;:24;:74;:::i;:::-;1155:91;;1124:241;;;1284:74;:20;1318:32;1332:1;:17;;;1318:32;1326:2;1318:32;1284:74;:24;:74;:::i;:::-;1267:91;;1124:241;-1:-1:-1;;;1378:14:3;:22;1370:64;;;;-1:-1:-1;;;1370:64:3;;;;;;;;745:608:2;889:37;;-1:-1:-1;;;889:37:2;;865:21;;-1:-1:-1;;;;;889:22:2;;;;;:37;;920:4;;889:37;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;889:37:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;889:37:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;889:37:2;;;;;;;;;1043:70;;-1:-1:-1;;;1043:70:2;;865:61;;-1:-1:-1;;;;;;1043:25:2;;;;;:70;;1069:6;;1085:4;;1092:20;;1043:70;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1043:70:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;1143:37:2;;-1:-1:-1;;;1143:37:2;;1120:20;;-1:-1:-1;;;;;;1143:22:2;;;-1:-1:-1;1143:22:2;;:37;;1174:4;;1143:37;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1143:37:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1143:37:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1143:37:2;;;;;;;;;1120:60;-1:-1:-1;1236:20:2;1201:31;1120:60;1218:13;1201:31;:16;:31;:::i;:::-;:55;1186:162;;;;-1:-1:-1;;;1186:162:2;;;;;;;;1548:785;-1:-1:-1;;;;;1682:21:2;;1678:651;;1730:43;;-1:-1:-1;;;;;1730:21:2;;;:43;;;;;1752:20;;1730:43;;;;1752:20;1730:21;:43;;;;;;;1713:99;;;;-1:-1:-1;;;1713:99:2;;;;;;;;;1678:651;;;1857:41;;-1:-1:-1;;;1857:41:2;;1833:21;;-1:-1:-1;;;;;1857:23:2;;;;;:41;;1881:16;;1857:41;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1857:41:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1857:41:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1857:41:2;;;;;;;;;2015:62;;-1:-1:-1;;;2015:62:2;;1833:65;;-1:-1:-1;;;;;;2015:22:2;;;;;:62;;2038:16;;2056:20;;2015:62;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2015:62:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;2109:41:2;;-1:-1:-1;;;2109:41:2;;2086:20;;-1:-1:-1;;;;;;2109:23:2;;;-1:-1:-1;2109:23:2;;:41;;2133:16;;2109:41;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2109:41:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2109:41:2;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2109:41:2;;;;;;;;;2086:64;-1:-1:-1;2210:20:2;2175:31;2086:64;2192:13;2175:31;:16;:31;:::i;:::-;:55;2158:164;;;;-1:-1:-1;;;2158:164:2;;;;;;;;37866:308:5;37953:4;37993:21;37980:9;:34;;;;;;;;;:83;;;-1:-1:-1;38037:26:5;38024:9;:39;;;;;;;;;37980:83;:135;;;-1:-1:-1;38086:29:5;38073:9;:42;;;;;;;;;37980:135;:189;;;-1:-1:-1;38138:31:5;38125:44;:9;:44;;;;;;;;;37967:202;37866:308;-1:-1:-1;;37866:308:5:o;38841:573::-;38966:6;39106:5;38966:6;39155:92;39106:5;39155:65;-1:-1:-1;;;;;39155:27:5;;;;39194:25;;39155:65;:38;:65;:::i;:::-;:76;:92;:76;:92;:::i;:::-;39118:129;;-1:-1:-1;;;39268:26:5;:34;39253:108;;;;-1:-1:-1;;;39253:108:5;;;;;;;;39418:339;-1:-1:-1;;;;;39539:34:5;;39512:6;39539:34;;;:19;:34;;;;;:41;;;:122;;;;-1:-1:-1;;;;;;39590:34:5;;;;;;:19;:34;;;;;:55;;;39649:12;-1:-1:-1;39590:71:5;39539:122;39528:210;;;-1:-1:-1;;;;;;39683:34:5;;;;;;:19;:34;;;;;:48;;;;-1:-1:-1;;;;;39683:48:5;39676:55;;39528:210;-1:-1:-1;39751:1:5;39418:339;;;:::o;32627:578::-;32749:7;32764:17;32784:107;32821:5;32834;:21;;;32863:5;:22;;;32784:29;:107::i;:::-;32764:127;;32913:114;32950:9;32969:5;:21;;;33000:5;:19;;;32913:27;:114::i;:::-;33049:19;33035:5;:10;;;:33;;;;;;;;;:136;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32898:279;;;;;-1:-1:-1;;;32898:279:5;;;;;;;;;;-1:-1:-1;33191:9:5;32627:578;-1:-1:-1;;;32627:578:5:o;26358:1671::-;26507:32;;;;:21;:32;;;;;;;;26506:33;26498:65;;;;-1:-1:-1;;;26498:65:5;;;;;;;;;26664:30;26923:5;:23;;;26919:518;;;26973:34;26991:5;:15;;;26973:17;:34::i;:::-;26956:120;;;;-1:-1:-1;;;26956:120:5;;;;;;;;;27154:48;;;;:37;:48;;;;;;27110:30;;;;:100;;-1:-1:-1;;;;;27110:34:5;;;;27154:48;27110:100;:34;:100;:::i;:::-;27084:126;;26919:518;;;27374:48;;;;:37;:48;;;;;;27331:29;;;;:99;;-1:-1:-1;;;;;27331:33:5;;;;27374:48;27331:99;:33;:99;:::i;:::-;27305:125;;26919:518;27485:5;:20;;;-1:-1:-1;;;;;27458:47:5;:23;-1:-1:-1;;;;;27458:47:5;;;27443:94;;;;-1:-1:-1;;;27443:94:5;;;;;;;;;27574:5;:20;;;-1:-1:-1;;;;;27548:46:5;:23;-1:-1:-1;;;;;27548:46:5;;27544:481;;;27678:48;;;;:37;:48;;;;;:74;;-1:-1:-1;;;;;;27678:74:5;-1:-1:-1;;;;;27678:74:5;;;;;27544:481;;;-1:-1:-1;;27923:48:5;;;;:37;:48;;;;;;;;27916:55;;-1:-1:-1;;;;;;27916:55:5;;;27979:21;:32;;;;;:39;;-1:-1:-1;;27979:39:5;-1:-1:-1;27979:39:5;;;-1:-1:-1;26358:1671:5:o;2091:415:9:-;2147:6;-1:-1:-1;;;;;2371:6:9;;2367:35;;-1:-1:-1;2394:1:9;2387:8;;2367:35;2419:5;;;-1:-1:-1;;;;;2438:10:9;;;;:5;;;;;;;;;;;;-1:-1:-1;;;;;2438:10:9;;2430:56;;;;-1:-1:-1;;;2430:56:9;;;;;;;;2937:121;2993:6;3014:39;3018:1;3021;3014:39;;;;;;;;;;;;;-1:-1:-1;;;3014:39:9;;;:3;:39::i;1854:628:10:-;2037:16;;;;2065:24;;;;1960:7;;2037:16;1960:7;2197:25;;:58;;;;;;;;;:169;;2342:10;:23;;;2325:41;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2325:41:10;;;2197:169;;;2287:10;:22;;;2270:40;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2270:40:10;;;2197:169;2378:39;2391:10;:25;;;-1:-1:-1;;;;;2378:39:10;:12;:39::i;:::-;2429:10;:30;;;2009:460;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2009:460:10;;;1990:487;;;;;;1977:500;;1854:628;;;:::o;330:219::-;449:4;538:6;-1:-1:-1;;;;;474:70:10;:60;488:34;517:4;488:28;:34::i;:::-;524:9;474:13;:60::i;:::-;-1:-1:-1;;;;;474:70:10;;;330:219;-1:-1:-1;;;;330:219:10:o;1686:185:9:-;1786:6;1813:1;-1:-1:-1;;;;;1808:6:9;:1;-1:-1:-1;;;;;1808:6:9;;;1816:12;1800:29;;;;;-1:-1:-1;;;1800:29:9;;;;;;;;;;-1:-1:-1;;;1846:5:9;;;1686:185::o;3713:272:8:-;3799:7;3833:12;3826:5;3818:28;;;;-1:-1:-1;;;3818:28:8;;;;;;;;;;;3856:9;3872:1;3868;:5;;;;;;;3713:272;-1:-1:-1;;;;;3713:272:8:o;1321:134::-;1379:7;1405:43;1409:1;1412;1405:43;;;;;;;;;;;;;;;;;:3;:43::i;553:1297:10:-;701:7;731:5;:26;;;:31;;761:1;731:31;716:94;;;;-1:-1:-1;;;716:94:10;;;;;;;;;1008:26;;1048:11;;;;1073:19;;;;1106:40;1122:10;1134:11;1106:15;:40::i;:::-;1166:5;:15;;;1160:22;;;;;;;;1202:5;:10;;;1196:17;;;;;;;;1334:34;1347:5;:20;;;-1:-1:-1;;;;;1334:34:10;:12;:34::i;:::-;978:402;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;978:402:10;;;1422:5;:23;;;1484:1;1459:5;:22;;;-1:-1:-1;;;;;1459:26:10;;:98;;;;;;;;;;;;;;;;;1502:36;1515:5;:22;;;-1:-1:-1;;;;;1502:36:10;:12;:36::i;:::-;1595:1;1571:5;:21;;;-1:-1:-1;;;;;1571:25:10;;:96;;;;;;;;;;;;;;;;;1613:35;1626:5;:21;;;-1:-1:-1;;;;;1613:35:10;:12;:35::i;:::-;1681:5;:19;;;1720:5;:17;;;1714:24;;;;;;;;1758:5;:25;;;1752:32;;;;;;;;1798:5;:17;;;1392:435;;;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;1392:435:10;;;;950:887;;;49:4:-1;950:887:10;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;950:887:10;;;829:1016;;;;;;816:1029;;553:1297;;;;;:::o;38178:251:5:-;38266:4;;38293:9;:35;;;;;;;;;:82;;;-1:-1:-1;38351:24:5;38338:9;:37;;;;;;;;;38293:82;:131;;;-1:-1:-1;38398:26:5;38385:39;;3545:328:9;3645:6;3736:12;-1:-1:-1;;;;;3729:5:9;;3721:28;;;;-1:-1:-1;;;3721:28:9;;;;;;;;;;;3755:8;3770:1;-1:-1:-1;;;;;3766:5:9;:1;-1:-1:-1;;;;;3766:5:9;;;;;3829:776:10;3887:13;4068:4;4053:12;4098:59;4105:9;;4098:59;;4124:8;;4148:2;4140:10;;;;4098:59;;;4175:1;4166:6;:10;4162:92;;;-1:-1:-1;4195:1:10;4162:92;4259:8;;4299:20;4259:8;-1:-1:-1;;;;;4322:17:10;;2:2:-1;;;;27:1;24;17:12;2:2;4322:17:10;;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;108:14;4322:17:10;87:42:-1;143:17;;-1:-1;4322:17:10;-1:-1:-1;4299:40:10;-1:-1:-1;4362:6:10;4345:228;4370:5;;4345:228;;4403:1;4394:6;:10;4408:1;4394:15;4390:177;;;4451:2;4438:17;;4421:7;4433:1;4429;:5;4421:14;;;;;;;;;;;:34;-1:-1:-1;;;;;4421:34:10;;;;;;;;;4390:177;;;4533:2;4526:4;:9;4520:2;:16;4507:31;;4490:7;4502:1;4498;:5;4490:14;;;;;;;;;;;:48;-1:-1:-1;;;;;4490:48:10;;;;;;;;-1:-1:-1;4556:2:10;4548:10;;;;4390:177;-1:-1:-1;;4377:3:10;4345:228;;;-1:-1:-1;4592:7:10;3829:776;-1:-1:-1;;;;3829:776:10:o;3396:265:4:-;3465:7;3648:4;3595:58;;;;;;;;;1064:2068;1142:7;1203:9;:16;1223:2;1203:22;1199:94;;1241:41;;-1:-1:-1;;;1241:41:4;;;;;;;;1199:94;1643:4;1628:20;;1622:27;1688:4;1673:20;;1667:27;1741:4;1726:20;;1720:27;1359:9;1712:36;-1:-1:-1;;;;;2646:79:4;;2642:154;;;2741:44;;-1:-1:-1;;;2741:44:4;;;;;;;;2642:154;2810:1;:7;;2815:2;2810:7;;:18;;;;;2821:1;:7;;2826:2;2821:7;;2810:18;2806:93;;;2844:44;;-1:-1:-1;;;2844:44:4;;;;;;;;2806:93;2993:14;3010:24;3020:4;3026:1;3029;3032;3010:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;3010:24:4;;-1:-1:-1;;3010:24:4;;;-1:-1:-1;;;;;;;3052:20:4;;3044:57;;;;-1:-1:-1;;;3044:57:4;;;;;;;;;3119:6;1064:2068;-1:-1:-1;;;;;;1064:2068:4:o;1746:187:8:-;1832:7;1867:12;1859:6;;;;1851:29;;;;-1:-1:-1;;;1851:29:8;;;;;;;;;2832:805:10;3048:10;;;;;;;;;;;;;-1:-1:-1;;;3048:10:10;;;;3212:23;;3187:22;;2944:13;;3004:10;;3048;;3102:11;;2944:13;;3187:48;;:69;-1:-1:-1;;;;;3167:97:10;;2:2:-1;;;;27:1;24;17:12;2:2;3167:97:10;;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;108:14;3167:97:10;87:42:-1;143:17;;-1:-1;3167:97:10;-1:-1:-1;3121:149:10;-1:-1:-1;3277:9:10;;3308:103;3324:15;:22;3320:1;:26;3308:103;;;3386:15;3402:1;3386:18;;;;;;;;;;;;;;;;3361:17;3379:3;;;;;;3361:22;;;;;;;;;;;:43;-1:-1:-1;;;;;3361:43:10;;;;;;;;-1:-1:-1;3348:3:10;;;;;3308:103;;;3468:11;3480:1;3468:14;;;;;;;;;;;;;;;;3443:17;3461:3;;;;;;3443:22;;;;;;;;;;;:39;-1:-1:-1;;;;;3443:39:10;;;;;;;;;3498:1;3494:5;;3489:105;3505:16;:23;3501:1;:27;3489:105;;;3568:16;3585:1;3568:19;;;;;;;;;;;;;;;;3543:17;3561:3;;;;;;3543:22;;;;;;;;;;;:44;-1:-1:-1;;;;;3543:44:10;;;;;;;;-1:-1:-1;3530:3:10;;;;;3489:105;;;-1:-1:-1;3614:17:10;;2832:805;-1:-1:-1;;;;;;;2832:805:10:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;5:130;72:20;;97:33;72:20;97:33;;295:124;359:20;;94476:13;;94469:21;97992:32;;97982:2;;98038:1;;98028:12;564:440;;665:3;658:4;650:6;646:17;642:27;632:2;;-1:-1;;673:12;632:2;720:6;707:20;-1:-1;;;;;92786:6;92783:30;92780:2;;;-1:-1;;92816:12;92780:2;742:64;92889:9;92870:17;;-1:-1;;92866:33;92957:4;92947:15;742:64;;;733:73;;826:6;819:5;812:21;930:3;92957:4;921:6;854;912:16;;909:25;906:2;;;947:1;;937:12;906:2;96030:6;92957:4;854:6;850:17;92957:4;888:5;884:16;96007:30;96086:1;96068:16;;;92957:4;96068:16;96061:27;888:5;625:379;-1:-1;;625:379;1179:188;1275:20;;98430:1;98420:12;;98410:2;;98446:1;;98436:12;1374:158;1455:20;;98545:1;98535:12;;98525:2;;98561:1;;98551:12;1718:158;1799:20;;98782:1;98772:12;;98762:2;;98798:1;;98788:12;2073:337;;;2188:3;2181:4;2173:6;2169:17;2165:27;2155:2;;-1:-1;;2196:12;2155:2;-1:-1;2226:20;;-1:-1;;;;;2255:30;;2252:2;;;-1:-1;;2288:12;2252:2;2332:4;2324:6;2320:17;2308:29;;2383:3;2332:4;2363:17;2324:6;2349:32;;2346:41;2343:2;;;2400:1;;2390:12;2343:2;2148:262;;;;;;2896:2605;;3008:6;;2996:9;2991:3;2987:19;2983:32;2980:2;;;-1:-1;;3018:12;2980:2;3046:22;3008:6;3046:22;;;3037:31;;;3166:47;3209:3;3185:22;3166:47;;;3148:16;3141:73;3309:49;3354:3;3276:2;3334:9;3330:22;3309:49;;;3276:2;3295:5;3291:16;3284:75;3462:49;3507:3;3429:2;3487:9;3483:22;3462:49;;;3429:2;3448:5;3444:16;3437:75;3611:63;3670:3;3578:2;3650:9;3646:22;3611:63;;;3578:2;3597:5;3593:16;3586:89;3770:63;3829:3;3736;3809:9;3805:22;3770:63;;;3736:3;3756:5;3752:16;3745:89;3939:48;3983:3;3905;3963:9;3959:22;3939:48;;;3905:3;3925:5;3921:16;3914:74;4096:46;4138:3;4062;4118:9;4114:22;4096:46;;;4062:3;4082:5;4078:16;4071:72;4250:48;4294:3;4216;4274:9;4270:22;4250:48;;;4216:3;4236:5;4232:16;4225:74;4371:3;4407:48;4451:3;4371;4431:9;4427:22;4407:48;;;4387:18;;;4380:76;4554:3;4539:19;;;4526:33;-1:-1;;;;;4568:30;;;4565:2;;;3134:1;;4601:12;4565:2;4648:59;4703:3;4694:6;4683:9;4679:22;4648:59;;;4554:3;4632:5;4628:18;4621:87;4776:3;;;4812:70;4878:3;4776;4858:9;4854:22;4812:70;;;4776:3;4796:5;4792:18;4785:98;4959:3;;;4995:78;5069:3;4959;5049:9;5045:22;4995:78;;;4959:3;4979:5;4975:18;4968:106;5142:3;;;5178:48;5222:3;5142;5202:9;5198:22;5178:48;;;5142:3;5162:5;5158:18;5151:76;5327:3;;;;5316:9;5312:19;5299:33;5285:47;;4579:18;5344:6;5341:30;5338:2;;;3134:1;;5374:12;5338:2;;5421:58;5475:3;5466:6;5455:9;5451:22;5421:58;;;5327:3;5405:5;5401:18;5394:86;;;2974:2527;;;;;9982:130;10049:20;;-1:-1;;;;;94756:46;;98993:35;;98983:2;;99042:1;;99032:12;10397:128;10463:20;;-1:-1;;;;;95082:30;;99240:34;;99230:2;;99288:1;;99278:12;10532:126;10597:20;;95195:4;95184:16;;99361:33;;99351:2;;99408:1;;99398:12;10665:241;;10769:2;10757:9;10748:7;10744:23;10740:32;10737:2;;;-1:-1;;10775:12;10737:2;85:6;72:20;97:33;124:5;97:33;;11177:366;;;11298:2;11286:9;11277:7;11273:23;11269:32;11266:2;;;-1:-1;;11304:12;11266:2;85:6;72:20;97:33;124:5;97:33;;;11356:63;-1:-1;11456:2;11495:22;;72:20;97:33;72:20;97:33;;;11464:63;;;;11260:283;;;;;;11550:492;;;;11691:2;11679:9;11670:7;11666:23;11662:32;11659:2;;;-1:-1;;11697:12;11659:2;85:6;72:20;97:33;124:5;97:33;;;11749:63;-1:-1;11877:2;11862:18;;11849:32;-1:-1;;;;;11890:30;;11887:2;;;-1:-1;;11923:12;11887:2;11961:65;12018:7;12009:6;11998:9;11994:22;11961:65;;;11653:389;;11951:75;;-1:-1;11951:75;;-1:-1;;;;11653:389;12049:241;;12153:2;12141:9;12132:7;12128:23;12124:32;12121:2;;;-1:-1;;12159:12;12121:2;-1:-1;493:20;;12115:175;-1:-1;12115:175;12826:643;;;;;12997:2;12985:9;12976:7;12972:23;12968:32;12965:2;;;-1:-1;;13003:12;12965:2;1107:6;1094:20;1119:48;1161:5;1119:48;;;13055:78;-1:-1;13198:2;13183:18;;13170:32;-1:-1;;;;;13211:30;;13208:2;;;-1:-1;;13244:12;13208:2;13282:65;13339:7;13330:6;13319:9;13315:22;13282:65;;;13272:75;;-1:-1;13272:75;-1:-1;13402:51;;-1:-1;13445:7;13384:2;13421:22;;13402:51;;;13392:61;;12959:510;;;;;;;;13476:396;;;13612:2;13600:9;13591:7;13587:23;13583:32;13580:2;;;-1:-1;;13618:12;13580:2;1107:6;1094:20;1119:48;1161:5;1119:48;;;13670:78;13785:2;13824:22;;;;10186:20;;-1:-1;;;13574:298;13879:492;;;;14020:2;14008:9;13999:7;13995:23;13991:32;13988:2;;;-1:-1;;14026:12;13988:2;14084:17;14071:31;-1:-1;;;;;14114:6;14111:30;14108:2;;;-1:-1;;14144:12;14108:2;14182:65;14239:7;14230:6;14219:9;14215:22;14182:65;;;14172:75;;;;-1:-1;14284:2;14323:22;;;;10186:20;;13982:389;-1:-1;;;;13982:389;14378:490;;;;14518:2;14506:9;14497:7;14493:23;14489:32;14486:2;;;-1:-1;;14524:12;14486:2;14582:17;14569:31;-1:-1;;;;;14620:18;14612:6;14609:30;14606:2;;;-1:-1;;14642:12;14606:2;14680:65;14737:7;14728:6;14717:9;14713:22;14680:65;;;14670:75;;-1:-1;14670:75;-1:-1;14782:2;14820:22;;10463:20;;-1:-1;95082:30;;;99240:34;;99230:2;;-1:-1;;99278:12;99230:2;;14790:62;;;;14480:388;;;;;;14875:887;;;;15082:2;15070:9;15061:7;15057:23;15053:32;15050:2;;;-1:-1;;15088:12;15050:2;15146:17;15133:31;-1:-1;;;;;15184:18;15176:6;15173:30;15170:2;;;-1:-1;;15206:12;15170:2;15236:76;15304:7;15295:6;15284:9;15280:22;15236:76;;;15226:86;;15377:2;15366:9;15362:18;15349:32;15335:46;;15184:18;15393:6;15390:30;15387:2;;;-1:-1;;15423:12;15387:2;15453:76;15521:7;15512:6;15501:9;15497:22;15453:76;;;15443:86;;15594:2;15583:9;15579:18;15566:32;15552:46;;15184:18;15610:6;15607:30;15604:2;;;-1:-1;;15640:12;15604:2;5647:6;;15714:22;;5626:19;;;5622:32;-1:-1;5619:2;;;-1:-1;;5657:12;5619:2;5685:22;5647:6;5685:22;;;5781:17;5768:31;5754:45;;15184:18;5811:6;5808:30;5805:2;;;-1:-1;;5841:12;5805:2;5886:59;5941:3;5932:6;5921:9;5917:22;5886:59;;;5868:16;5861:85;15377:2;6036:9;6032:18;6019:32;6005:46;;15184:18;6063:6;6060:30;6057:2;;;-1:-1;;6093:12;6057:2;6138:59;6193:3;6184:6;6173:9;6169:22;6138:59;;;15377:2;6124:5;6120:16;6113:85;6304:49;6349:3;15594:2;6329:9;6325:22;6304:49;;;15594:2;6290:5;6286:16;6279:75;6461:49;6506:3;15082:2;6486:9;6482:22;6461:49;;;15082:2;6447:5;6443:16;6436:75;6625:48;6669:3;6591;6649:9;6645:22;6625:48;;;6591:3;6611:5;6607:16;6600:74;6789:48;6833:3;6755;6813:9;6809:22;6789:48;;;6755:3;6775:5;6771:16;6764:74;6950:48;6994:3;6916;6974:9;6970:22;6950:48;;;6916:3;6936:5;6932:16;6925:74;7112:48;7156:3;7078;7136:9;7132:22;7112:48;;;7078:3;7098:5;7094:16;7087:74;7238:3;;;7274:49;7319:3;7238;7299:9;7295:22;7274:49;;;7238:3;7258:5;7254:18;7247:77;7401:3;;;7437:49;7482:3;7401;7462:9;7458:22;7437:49;;;7401:3;7421:5;7417:18;7410:77;7566:3;;;7602:48;7646:3;7566;7626:9;7622:22;7602:48;;;7566:3;7586:5;7582:18;7575:76;7730:3;;;7766:48;7810:3;7730;7790:9;7786:22;7766:48;;;7730:3;7750:5;7746:18;7739:76;7883:3;;;7919:48;7963:3;7883;7943:9;7939:22;7919:48;;;7883:3;7903:5;7899:18;7892:76;8034:3;;;8070:63;8129:3;8034;8109:9;8105:22;8070:63;;;8034:3;8054:5;8050:18;8043:91;15660:86;;;;;;;15044:718;;;;;;15769:383;;15901:2;15889:9;15880:7;15876:23;15872:32;15869:2;;;-1:-1;;15907:12;15869:2;15965:17;15952:31;-1:-1;;;;;16003:18;15995:6;15992:30;15989:2;;;-1:-1;;16025:12;15989:2;8311:6;;16104:22;;8290:19;;;8286:32;-1:-1;8283:2;;;-1:-1;;8321:12;8283:2;8349:22;8311:6;8349:22;;;8463:68;8527:3;8503:22;8463:68;;;8445:16;8438:94;8627:49;8672:3;15901:2;8652:9;8648:22;8627:49;;;15901:2;8613:5;8609:16;8602:75;8780:57;8833:3;8747:2;8813:9;8809:22;8780:57;;;8747:2;8766:5;8762:16;8755:83;8934:2;8923:9;8919:18;8906:32;8892:46;;16003:18;8950:6;8947:30;8944:2;;;-1:-1;;8980:12;8944:2;9025:59;9080:3;9071:6;9060:9;9056:22;9025:59;;;8934:2;9011:5;9007:16;9000:85;9188:49;9233:3;9154;9213:9;9209:22;9188:49;;;9154:3;9174:5;9170:16;9163:75;9343:48;9387:3;9309;9367:9;9363:22;9343:48;;;9309:3;9329:5;9325:16;9318:74;9495:48;9539:3;9461;9519:9;9515:22;9495:48;;;9461:3;9481:5;9477:16;9470:74;9654:46;9696:3;9620;9676:9;9672:22;9654:46;;;9620:3;9640:5;9636:16;9629:72;9801:3;;;;9790:9;9786:19;9773:33;16003:18;9818:6;9815:30;9812:2;;;-1:-1;;9848:12;9812:2;9895:58;9949:3;9940:6;9929:9;9925:22;9895:58;;;9875:18;;;9868:86;;;;9879:5;15863:289;-1:-1;;;;;;15863:289;16159:241;;16263:2;16251:9;16242:7;16238:23;16234:32;16231:2;;;-1:-1;;16269:12;16231:2;16331:53;16376:7;16352:22;16331:53;;16655:263;;16770:2;16758:9;16749:7;16745:23;16741:32;16738:2;;;-1:-1;;16776:12;16738:2;-1:-1;10334:13;;16732:186;-1:-1;16732:186;19009:300;;93824:6;93819:3;93812:19;96030:6;96025:3;93861:4;93856:3;93852:14;96007:30;-1:-1;93861:4;96077:6;93856:3;96068:16;;96061:27;93861:4;92889:9;;97241:2;19295:6;97221:14;97217:28;93856:3;19264:39;;19257:46;;19111:198;;;;;;19317:327;;19452:5;93395:12;93824:6;93819:3;93812:19;19536:52;19581:6;93861:4;93856:3;93852:14;93861:4;19562:5;19558:16;19536:52;;;92889:9;97221:14;-1:-1;;97217:28;19600:39;;;;93861:4;19600:39;;19399:245;-1:-1;;19399:245;48662:253;97640:14;;;;;-1:-1;;;;;;97640:14;17323:74;;48887:2;48878:12;;48778:137;48922:1117;;18026:5;94476:13;94469:21;97541:3;97537:15;17989:3;17982:52;18485:5;93395:12;18596:52;18641:6;49353:1;49348:3;49344:11;18629:4;18622:5;18618:16;18596:52;;;93395:12;;;18660:16;;18596:52;93395:12;49353:1;18660:16;;18629:4;18618:16;;18596:52;;;93395:12;;;18660:16;;18596:52;93395:12;49353:1;18660:16;;18629:4;18618:16;;18596:52;;;97537:15;;;;-1:-1;;;;;;97537:15;;;49353:1;18660:16;;;;;;;48596:54;;;;97537:15;;;;;49789:11;;;48596:54;-1:-1;;97433:15;;-1:-1;;;;;;97433:15;49895:11;;;48225:56;50003:11;;;49250:789;-1:-1;;;;;49250:789;50046:428;;18485:5;93395:12;18596:52;18641:6;18636:3;18629:4;18622:5;18618:16;18596:52;;;93395:12;;;18660:16;;18596:52;93395:12;18660:16;18629:4;18618:16;;18596:52;;;18660:16;;50226:248;-1:-1;;;;50226:248;50481:275;;18485:5;93395:12;18596:52;18641:6;18636:3;18629:4;18622:5;18618:16;18596:52;;;18660:16;;;;;50617:139;-1:-1;;50617:139;50763:520;23501:66;23481:87;;23465:2;23587:12;;18117:37;;;;51246:12;;;50980:303;51290:868;94767:34;97329:15;;;-1:-1;;;;;;97329:15;47593:58;;97640:14;;;;-1:-1;;;;;;97640:14;51675:2;51666:12;;17323:74;93395:12;;51290:868;;18596:52;93395:12;51793;;;18629:4;18618:16;;18596:52;;;93395:12;;;18660:16;;18596:52;93395:12;51793;18660:16;;18629:4;18618:16;;18596:52;;;94476:13;;94469:21;97541:3;97537:15;51793:12;18660:16;;;;;;;17982:52;-1:-1;;52122:11;;;51566:592;-1:-1;;;;51566:592;52165:1104;-1:-1;;;;;;97537:15;;;;;;48596:54;;-1:-1;;;;;;94767:34;97329:15;;;;92794:18;52573:11;;47593:58;-1:-1;;;;;;97640:14;;;;;52683:12;;;17323:74;93395:12;;-1:-1;;97537:15;18596:52;93395:12;52794;;;18629:4;18618:16;;18596:52;;;18669:6;52577:3;18660:16;97537:15;48642:5;97541:3;97537:15;;52794:12;18660:16;;48596:54;97537:15;48642:5;97541:3;97537:15;;53014:11;18660:16;53014:11;48596:54;18485:5;93395:12;18439:52;;18596;18641:6;53120:11;18660:16;53120:11;18629:4;18622:5;18618:16;18596:52;;;18660:16;;;53120:11;18660:16;;52477:792;-1:-1;;;;;;;;;;52477:792;53276:222;-1:-1;;;;;94876:54;;;;17161:45;;53403:2;53388:18;;53374:124;53750:476;-1:-1;;;;;94876:54;;;17161:45;;94876:54;;;;54129:2;54114:18;;17161:45;54212:2;54197:18;;18117:37;;;;53949:2;53934:18;;53920:306;54233:349;-1:-1;;;;;94876:54;;;;17004:58;;54568:2;54553:18;;18117:37;54396:2;54381:18;;54367:215;54589:333;-1:-1;;;;;94876:54;;;17161:45;;94876:54;;54908:2;54893:18;;17161:45;54744:2;54729:18;;54715:207;55285:1280;-1:-1;;;;;94876:54;;;17161:45;;94876:54;;55835:2;55820:18;;17161:45;55670:3;55872:2;55857:18;;55850:48;;;55285:1280;;55912:78;55655:19;;;55976:6;55912:78;;;56038:9;56032:4;56028:20;56023:2;56012:9;56008:18;56001:48;56063:78;56136:4;56127:6;56063:78;;;-1:-1;;;;;95082:30;;;56218:3;56203:19;;47973:36;95082:30;;;56300:3;56285:19;;47973:36;-1:-1;;;95082:30;;;;56382:3;56367:19;;47973:36;56466:3;56451:19;;18117:37;56550:3;56535:19;18117:37;;;;56055:86;55641:924;-1:-1;;;;55641:924;57023:548;18117:37;;;95195:4;95184:16;;;;57391:2;57376:18;;48350:35;57474:2;57459:18;;18117:37;57557:2;57542:18;;18117:37;57230:3;57215:19;;57201:370;57578:330;;57735:2;57756:17;57749:47;57810:88;57735:2;57724:9;57720:18;57884:6;57876;57810:88;;57915:433;;58096:2;58117:17;58110:47;58171:88;58096:2;58085:9;58081:18;58245:6;58237;58171:88;;;58163:96;;95195:4;48378:5;95184:16;58334:2;58323:9;58319:18;48350:35;58067:281;;;;;;;58355:310;;58502:2;58523:17;58516:47;58577:78;58502:2;58491:9;58487:18;58641:6;58577:78;;58672:670;;58916:3;58938:17;58931:47;58992:78;58916:3;58905:9;58901:19;59056:6;58992:78;;;-1:-1;;;;;95082:30;;;59147:2;59132:18;;47973:36;95082:30;;;;59237:2;59222:18;;18915:57;59328:2;59313:18;18767:58;58984:86;58887:455;-1:-1;;58887:455;59992:416;60192:2;60206:47;;;20597:2;60177:18;;;93812:19;-1:-1;;;93852:14;;;20613:47;20679:12;;;60163:245;60415:416;60615:2;60629:47;;;20930:2;60600:18;;;93812:19;-1:-1;;;93852:14;;;20946:47;21012:12;;;60586:245;60838:416;61038:2;61052:47;;;21263:2;61023:18;;;93812:19;-1:-1;;;93852:14;;;21279:47;21345:12;;;61009:245;61261:416;61461:2;61475:47;;;21596:2;61446:18;;;93812:19;21632:34;93852:14;;;21612:55;21701:34;21687:12;;;21680:56;-1:-1;;;21756:12;;;21749:36;21804:12;;;61432:245;61684:416;61884:2;61898:47;;;22055:2;61869:18;;;93812:19;22091:34;93852:14;;;22071:55;-1:-1;;;22146:12;;;22139:27;22185:12;;;61855:245;62107:416;62307:2;62321:47;;;22436:2;62292:18;;;93812:19;-1:-1;;;93852:14;;;22452:38;22509:12;;;62278:245;62530:416;62730:2;62744:47;;;22760:2;62715:18;;;93812:19;-1:-1;;;93852:14;;;22776:43;22838:12;;;62701:245;62953:416;63153:2;63167:47;;;23089:2;63138:18;;;93812:19;23125:33;93852:14;;;23105:54;23178:12;;;63124:245;63376:416;63576:2;63590:47;;;23838:2;63561:18;;;93812:19;-1:-1;;;93852:14;;;23854:42;23915:12;;;63547:245;63799:416;63999:2;64013:47;;;24166:2;63984:18;;;93812:19;24202:34;93852:14;;;24182:55;-1:-1;;;24257:12;;;24250:31;24300:12;;;63970:245;64222:416;64422:2;64436:47;;;24551:2;64407:18;;;93812:19;24587:34;93852:14;;;24567:55;-1:-1;;;24642:12;;;24635:36;24690:12;;;64393:245;64645:416;64845:2;64859:47;;;24941:2;64830:18;;;93812:19;24977:34;93852:14;;;24957:55;-1:-1;;;25032:12;;;25025:28;25072:12;;;64816:245;65068:416;65268:2;65282:47;;;25323:2;65253:18;;;93812:19;-1:-1;;;93852:14;;;25339:38;25396:12;;;65239:245;65491:416;65691:2;65705:47;;;25647:2;65676:18;;;93812:19;-1:-1;;;93852:14;;;25663:42;25724:12;;;65662:245;65914:416;66114:2;66128:47;;;25975:2;66099:18;;;93812:19;-1:-1;;;93852:14;;;25991:50;26060:12;;;66085:245;66337:416;66537:2;66551:47;;;26311:2;66522:18;;;93812:19;-1:-1;;;93852:14;;;26327:49;26395:12;;;66508:245;66760:416;66960:2;66974:47;;;26646:2;66945:18;;;93812:19;26682:31;93852:14;;;26662:52;26733:12;;;66931:245;67183:416;67383:2;67397:47;;;26984:2;67368:18;;;93812:19;-1:-1;;;93852:14;;;27000:42;27061:12;;;67354:245;67606:416;67806:2;67820:47;;;27312:2;67791:18;;;93812:19;27348:34;93852:14;;;27328:55;-1:-1;;;27403:12;;;27396:43;27458:12;;;67777:245;68029:416;68229:2;68243:47;;;27709:2;68214:18;;;93812:19;27745:34;93852:14;;;27725:55;-1:-1;;;27800:12;;;27793:27;27839:12;;;68200:245;68452:416;68652:2;68666:47;;;28090:2;68637:18;;;93812:19;-1:-1;;;93852:14;;;28106:36;28161:12;;;68623:245;68875:416;69075:2;69089:47;;;28412:2;69060:18;;;93812:19;28448:34;93852:14;;;28428:55;-1:-1;;;28503:12;;;28496:26;28541:12;;;69046:245;69298:416;69498:2;69512:47;;;28792:2;69483:18;;;93812:19;28828:34;93852:14;;;28808:55;-1:-1;;;28883:12;;;28876:41;28936:12;;;69469:245;69721:416;69921:2;69935:47;;;29187:2;69906:18;;;93812:19;29223:34;93852:14;;;29203:55;-1:-1;;;29278:12;;;29271:26;29316:12;;;69892:245;70144:416;70344:2;70358:47;;;29567:2;70329:18;;;93812:19;29603:34;93852:14;;;29583:55;-1:-1;;;29658:12;;;29651:28;29698:12;;;70315:245;70567:416;70767:2;70781:47;;;29949:2;70752:18;;;93812:19;29985:34;93852:14;;;29965:55;-1:-1;;;30040:12;;;30033:31;30083:12;;;70738:245;70990:416;71190:2;71204:47;;;30334:2;71175:18;;;93812:19;30370:34;93852:14;;;30350:55;-1:-1;;;30425:12;;;30418:25;30462:12;;;71161:245;71413:416;71613:2;71627:47;;;30713:2;71598:18;;;93812:19;-1:-1;;;93852:14;;;30729:48;30796:12;;;71584:245;71836:416;72036:2;72050:47;;;31047:2;72021:18;;;93812:19;-1:-1;;;93852:14;;;31063:44;31126:12;;;72007:245;72259:416;72459:2;72473:47;;;31377:2;72444:18;;;93812:19;-1:-1;;;93852:14;;;31393:47;31459:12;;;72430:245;72682:416;72882:2;72896:47;;;31710:2;72867:18;;;93812:19;31746:34;93852:14;;;31726:55;-1:-1;;;31801:12;;;31794:31;31844:12;;;72853:245;73105:416;73305:2;73319:47;;;73290:18;;;93812:19;32131:34;93852:14;;;32111:55;32185:12;;;73276:245;73528:416;73728:2;73742:47;;;32436:2;73713:18;;;93812:19;-1:-1;;;93852:14;;;32452:44;32515:12;;;73699:245;73951:416;74151:2;74165:47;;;32766:2;74136:18;;;93812:19;32802:34;93852:14;;;32782:55;-1:-1;;;32857:12;;;32850:26;32895:12;;;74122:245;74374:416;74574:2;74588:47;;;33146:2;74559:18;;;93812:19;33182:33;93852:14;;;33162:54;33235:12;;;74545:245;74797:416;74997:2;75011:47;;;33486:2;74982:18;;;93812:19;-1:-1;;;93852:14;;;33502:47;33568:12;;;74968:245;75220:416;75420:2;75434:47;;;33819:2;75405:18;;;93812:19;33855:34;93852:14;;;33835:55;-1:-1;;;33910:12;;;33903:28;33950:12;;;75391:245;75643:416;75843:2;75857:47;;;34201:2;75828:18;;;93812:19;34237:34;93852:14;;;34217:55;-1:-1;;;34292:12;;;34285:27;34331:12;;;75814:245;76066:416;76266:2;76280:47;;;34582:2;76251:18;;;93812:19;-1:-1;;;93852:14;;;34598:39;34656:12;;;76237:245;76489:416;76689:2;76703:47;;;34907:2;76674:18;;;93812:19;34943:34;93852:14;;;34923:55;-1:-1;;;34998:12;;;34991:25;35035:12;;;76660:245;76912:416;77112:2;77126:47;;;35286:2;77097:18;;;93812:19;-1:-1;;;93852:14;;;35302:47;35368:12;;;77083:245;77335:416;77535:2;77549:47;;;35619:2;77520:18;;;93812:19;35655:31;93852:14;;;35635:52;35706:12;;;77506:245;77758:416;77958:2;77972:47;;;35957:2;77943:18;;;93812:19;35993:34;93852:14;;;35973:55;-1:-1;;;36048:12;;;36041:25;36085:12;;;77929:245;78181:416;78381:2;78395:47;;;36336:2;78366:18;;;93812:19;-1:-1;;;93852:14;;;36352:43;36414:12;;;78352:245;78604:416;78804:2;78818:47;;;36665:2;78789:18;;;93812:19;36701:34;93852:14;;;36681:55;-1:-1;;;36756:12;;;36749:33;36801:12;;;78775:245;79027:416;79227:2;79241:47;;;37052:2;79212:18;;;93812:19;37088:32;93852:14;;;37068:53;37140:12;;;79198:245;79450:416;79650:2;79664:47;;;37391:2;79635:18;;;93812:19;-1:-1;;;93852:14;;;37407:45;37471:12;;;79621:245;79873:416;80073:2;80087:47;;;37722:2;80058:18;;;93812:19;-1:-1;;;93852:14;;;37738:46;37803:12;;;80044:245;80296:416;80496:2;80510:47;;;38054:2;80481:18;;;93812:19;38090:34;93852:14;;;38070:55;-1:-1;;;38145:12;;;38138:33;38190:12;;;80467:245;80719:416;80919:2;80933:47;;;38441:2;80904:18;;;93812:19;38477:32;93852:14;;;38457:53;38529:12;;;80890:245;81142:416;81342:2;81356:47;;;38780:2;81327:18;;;93812:19;-1:-1;;;93852:14;;;38796:42;38857:12;;;81313:245;81565:416;81765:2;81779:47;;;39108:2;81750:18;;;93812:19;39144:34;93852:14;;;39124:55;-1:-1;;;39199:12;;;39192:25;39236:12;;;81736:245;81988:416;82188:2;82202:47;;;39487:2;82173:18;;;93812:19;39523:34;93852:14;;;39503:55;-1:-1;;;39578:12;;;39571:28;39618:12;;;82159:245;82411:416;82611:2;82625:47;;;39869:2;82596:18;;;93812:19;-1:-1;;;93852:14;;;39885:43;39947:12;;;82582:245;82834:416;83034:2;83048:47;;;40198:2;83019:18;;;93812:19;-1:-1;;;93852:14;;;40214:42;40275:12;;;83005:245;83257:416;83457:2;83471:47;;;40526:2;83442:18;;;93812:19;40562:34;93852:14;;;40542:55;-1:-1;;;40617:12;;;40610:31;40660:12;;;83428:245;83680:416;83880:2;83894:47;;;40911:2;83865:18;;;93812:19;40947:34;93852:14;;;40927:55;-1:-1;;;41002:12;;;40995:44;41058:12;;;83851:245;84103:416;84303:2;84317:47;;;41309:2;84288:18;;;93812:19;-1:-1;;;93852:14;;;41325:44;41388:12;;;84274:245;84526:416;84726:2;84740:47;;;41639:2;84711:18;;;93812:19;41675:34;93852:14;;;41655:55;-1:-1;;;41730:12;;;41723:40;41782:12;;;84697:245;84949:416;85149:2;85163:47;;;42033:2;85134:18;;;93812:19;42069:34;93852:14;;;42049:55;-1:-1;;;42124:12;;;42117:32;42168:12;;;85120:245;85372:416;85572:2;85586:47;;;42419:2;85557:18;;;93812:19;42455:33;93852:14;;;42435:54;42508:12;;;85543:245;85795:416;85995:2;86009:47;;;42759:2;85980:18;;;93812:19;-1:-1;;;93852:14;;;42775:43;42837:12;;;85966:245;86218:416;86418:2;86432:47;;;43088:2;86403:18;;;93812:19;-1:-1;;;93852:14;;;43104:40;43163:12;;;86389:245;86641:416;86841:2;86855:47;;;43414:2;86826:18;;;93812:19;-1:-1;;;93852:14;;;43430:45;43494:12;;;86812:245;87064:416;87264:2;87278:47;;;43745:2;87249:18;;;93812:19;43781:34;93852:14;;;43761:55;-1:-1;;;43836:12;;;43829:35;43883:12;;;87235:245;87487:416;87687:2;87701:47;;;44134:2;87672:18;;;93812:19;44170:34;93852:14;;;44150:55;44239:34;44225:12;;;44218:56;-1:-1;;;44294:12;;;44287:32;44338:12;;;87658:245;87910:416;88110:2;88124:47;;;44589:2;88095:18;;;93812:19;-1:-1;;;93852:14;;;44605:48;44672:12;;;88081:245;88333:416;88533:2;88547:47;;;44923:2;88518:18;;;93812:19;44959:34;93852:14;;;44939:55;-1:-1;;;45014:12;;;45007:32;45058:12;;;88504:245;88756:416;88956:2;88970:47;;;45309:2;88941:18;;;93812:19;-1:-1;;;93852:14;;;45325:36;45380:12;;;88927:245;89179:416;89379:2;89393:47;;;45631:2;89364:18;;;93812:19;-1:-1;;;93852:14;;;45647:43;45709:12;;;89350:245;89602:416;89802:2;89816:47;;;45960:2;89787:18;;;93812:19;45996:34;93852:14;;;45976:55;-1:-1;;;46051:12;;;46044:31;46094:12;;;89773:245;90025:362;;90198:2;90219:17;90212:47;46392:16;46386:23;94476:13;94469:21;90198:2;90187:9;90183:18;17853:34;92794:18;;97640:14;;;90198:2;46552:5;46548:16;46542:23;94876:54;46619:14;90187:9;46619:14;17161:45;46619:14;46708:5;46704:16;46698:23;46318:4;46741:14;90187:9;46741:14;46734:38;46787:73;46309:14;90187:9;46309:14;46841:12;46787:73;;;95195:4;46741:14;46942:5;46938:16;46932:23;95184:16;47005:14;90187:9;47005:14;48350:35;47005:14;47099:5;47095:16;47089:23;94476:13;94469:21;47160:14;90187:9;47160:14;17853:34;-1:-1;;;;;47160:14;47265:5;47261:16;47255:23;95082:30;46318:4;90187:9;47330:14;47973:36;90265:112;;;;;90169:218;;;;;90394:442;-1:-1;;;;;94756:46;;;;47455:37;;-1:-1;;;;;95082:30;;;;90739:2;90724:18;;18915:57;90822:2;90807:18;;18117:37;90576:2;90561:18;;90547:289;90843:222;18117:37;;;90970:2;90955:18;;90941:124;91072:333;18117:37;;;91391:2;91376:18;;18117:37;91227:2;91212:18;;91198:207;91412:218;-1:-1;;;;;95082:30;;;;47973:36;;91537:2;91522:18;;91508:122;91637:744;;-1:-1;;;;;95093:18;48002:5;95082:30;47980:3;47973:36;91890:3;92007:2;91996:9;91992:18;91985:48;92047:78;91890:3;91879:9;91875:19;92111:6;92047:78;;;95082:30;;;92202:2;92187:18;;47973:36;95082:30;;;;92283:2;92268:18;;47973:36;92366:3;92351:19;18117:37;-1:-1;92039:86;91861:520;-1:-1;;91861:520;92388:256;92450:2;92444:9;92476:17;;;-1:-1;;;;;92536:34;;92572:22;;;92533:62;92530:2;;;92608:1;;92598:12;92530:2;92450;92617:22;92428:216;;-1:-1;92428:216;96103:268;96168:1;96175:101;96189:6;96186:1;96183:13;96175:101;;;96256:11;;;96250:18;96237:11;;;96230:39;96211:2;96204:10;96175:101;;;96291:6;96288:1;96285:13;96282:2;;;-1:-1;;96168:1;96338:16;;96331:27;96152:219;97672:117;-1:-1;;;;;94876:54;;97731:35;;97721:2;;97780:1;;97770:12;97721:2;97715:74;
Swarm Source
ipfs://5dd7ac35c5f7c6f5ec79f4ba79633e7c75138d994328bbe33fa2efc0d21be22d
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.