Contract Overview
Balance:
0.00000006 MATIC
MATIC Value:
Less Than $0.01 (@ $0.66/MATIC)
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xbba1ea1b63342b901f7941d9872a0bf609a888f9e52fc1b25faea20c15ae1e12 | 0x611e4e61 | 21255597 | 194 days 6 hrs ago | 0x543c55c95fc8a3fc4a5fc47663a11eae2d2f3404 | IN | Create: AssetRegistry | 0.00000006 MATIC | 0.05185923 |
[ Download CSV Export ]
Contract Name:
AssetRegistry
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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 on 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"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { 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.8.4; import { Address } from './Address.sol'; import { Asset } from './Structs.sol'; import { AssetTransfers } from './AssetTransfers.sol'; import { AssetUnitConversions } from './AssetUnitConversions.sol'; import { BalanceTracking } from './BalanceTracking.sol'; import { IERC20 } from './Interfaces.sol'; /** * @notice Library helper functions for reading from a registry of asset descriptors indexed by address and symbol */ library AssetRegistry { struct Storage { mapping(address => 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 => Asset[]) assetsBySymbol; // Blockchain-specific native asset symbol string nativeAssetSymbol; } // Admin // function registerToken( AssetRegistry.Storage storage self, IERC20 tokenAddress, string calldata symbol, uint8 decimals ) external { require(decimals <= 32, 'Token cannot have more than 32 decimals'); require( tokenAddress != IERC20(address(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)] = Asset({ exists: true, assetAddress: address(tokenAddress), symbol: symbol, decimals: decimals, isConfirmed: false, confirmedTimestampInMs: 0 }); } function confirmTokenRegistration( AssetRegistry.Storage storage self, IERC20 tokenAddress, string calldata symbol, uint8 decimals ) external { 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( AssetRegistry.Storage storage self, IERC20 tokenAddress, string calldata symbol ) external { Asset memory asset = self.assetsByAddress[address(tokenAddress)]; require( asset.exists && asset.isConfirmed, 'Registration of token not finalized' ); require( !isStringEqual(symbol, self.nativeAssetSymbol), 'Symbol reserved for native asset' ); // This will prevent swapping assets for previously existing orders uint64 msInOneSecond = 1000; asset.confirmedTimestampInMs = uint64(block.timestamp * msInOneSecond); self.assetsBySymbol[symbol].push(asset); } function skim(address tokenAddress, address feeWallet) external { require(Address.isContract(tokenAddress), 'Invalid token address'); uint256 balance = IERC20(tokenAddress).balanceOf(address(this)); AssetTransfers.transferTo(payable(feeWallet), tokenAddress, balance); } // Accessors // function loadBalanceInAssetUnitsByAddress( AssetRegistry.Storage storage self, address wallet, address assetAddress, BalanceTracking.Storage storage balanceTracking ) external view returns (uint256) { require(wallet != address(0x0), 'Invalid wallet address'); Asset memory asset = loadAssetByAddress(self, assetAddress); return AssetUnitConversions.pipsToAssetUnits( loadBalanceInPipsFromMigrationSourceIfNeeded( wallet, assetAddress, balanceTracking ), asset.decimals ); } function loadBalanceInAssetUnitsBySymbol( AssetRegistry.Storage storage self, address wallet, string calldata assetSymbol, BalanceTracking.Storage storage balanceTracking ) external view returns (uint256) { require(wallet != address(0x0), 'Invalid wallet address'); Asset memory asset = loadAssetBySymbol(self, assetSymbol, getCurrentTimestampInMs()); return AssetUnitConversions.pipsToAssetUnits( loadBalanceInPipsFromMigrationSourceIfNeeded( wallet, asset.assetAddress, balanceTracking ), asset.decimals ); } function loadBalanceInPipsByAddress( address wallet, address assetAddress, BalanceTracking.Storage storage balanceTracking ) external view returns (uint64) { require(wallet != address(0x0), 'Invalid wallet address'); return loadBalanceInPipsFromMigrationSourceIfNeeded( wallet, assetAddress, balanceTracking ); } function loadBalanceInPipsBySymbol( Storage storage self, address wallet, string calldata assetSymbol, BalanceTracking.Storage storage balanceTracking ) external view returns (uint64) { require(wallet != address(0x0), 'Invalid wallet address'); address assetAddress = loadAssetBySymbol(self, assetSymbol, getCurrentTimestampInMs()) .assetAddress; return loadBalanceInPipsFromMigrationSourceIfNeeded( wallet, assetAddress, balanceTracking ); } function loadBalanceInPipsFromMigrationSourceIfNeeded( address wallet, address assetAddress, BalanceTracking.Storage storage balanceTracking ) private view returns (uint64) { BalanceTracking.Balance memory balance = balanceTracking.balancesByWalletAssetPair[wallet][assetAddress]; if ( !balance.isMigrated && address(balanceTracking.migrationSource) != address(0x0) ) { return balanceTracking.migrationSource.loadBalanceInPipsByAddress( wallet, assetAddress ); } return balance.balanceInPips; } /** * @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 (Asset memory) { if (assetAddress == address(0x0)) { return getEthAsset(self.nativeAssetSymbol); } 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 (Asset memory) { if (isStringEqual(self.nativeAssetSymbol, symbol)) { return getEthAsset(self.nativeAssetSymbol); } 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; } // Util // function getCurrentTimestampInMs() internal view returns (uint64) { uint64 msInOneSecond = 1000; return uint64(block.timestamp) * msInOneSecond; } /** * @dev ETH is modeled as an always-confirmed Asset struct for programmatic consistency */ function getEthAsset(string memory nativeAssetSymbol) private pure returns (Asset memory) { return Asset(true, address(0x0), nativeAssetSymbol, 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.8.4; 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 { /** * @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, address to, uint256 quantityInAssetUnits ) internal { uint256 balanceBefore = tokenAddress.balanceOf(to); // Because we check for the expected balance change we can safely ignore the return value of transferFrom tokenAddress.transferFrom(wallet, to, quantityInAssetUnits); uint256 balanceAfter = tokenAddress.balanceOf(to); require( balanceAfter - balanceBefore == quantityInAssetUnits, 'Token contract returned transferFrom success without expected balance change' ); } /** * @dev Transfers ETH or token assets from a contract to a wallet when withdrawing or removing liquidity */ 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 - balanceBefore == quantityInAssetUnits, 'Token contract returned transfer success without expected balance change' ); } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.4; /** * @notice Library helpers for converting asset quantities between asset units and pips */ library AssetUnitConversions { 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) * (uint256(10)**(assetDecimals - 8)); } return uint256(quantityInPips) / (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 / (uint256(10)**(assetDecimals - 8)); } else { quantityInPips = quantityInAssetUnits * (uint256(10)**(8 - assetDecimals)); } require(quantityInPips < 2**64, 'Pip quantity overflows uint64'); return uint64(quantityInPips); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.4; import { AssetRegistry } from './AssetRegistry.sol'; import { AssetUnitConversions } from './AssetUnitConversions.sol'; import { Constants } from './Constants.sol'; import { OrderSide } from './Enums.sol'; import { PoolTradeHelpers } from './PoolTradeHelpers.sol'; import { Asset, HybridTrade, LiquidityAddition, LiquidityChangeExecution, LiquidityRemoval, Order, OrderBookTrade, PoolTrade, Withdrawal } from './Structs.sol'; import { IExchange, ILiquidityProviderToken } from './Interfaces.sol'; library BalanceTracking { using AssetRegistry for AssetRegistry.Storage; using PoolTradeHelpers for PoolTrade; struct Balance { bool isMigrated; uint64 balanceInPips; } struct Storage { mapping(address => mapping(address => Balance)) balancesByWalletAssetPair; // Predecessor Exchange contract from which to lazily migrate balances IExchange migrationSource; } // Depositing // function updateForDeposit( Storage storage self, address wallet, address assetAddress, uint64 quantityInPips ) internal returns (uint64 newBalanceInPips) { Balance storage balance = loadBalanceAndMigrateIfNeeded(self, wallet, assetAddress); balance.balanceInPips += quantityInPips; return balance.balanceInPips; } // Trading // /** * @dev Updates buyer, seller, and fee wallet balances for both assets in trade pair according to * trade parameters */ function updateForOrderBookTrade( Storage storage self, Order memory buy, Order memory sell, OrderBookTrade memory trade, address feeWallet ) internal { Balance storage balance; // Seller gives base asset including fees balance = loadBalanceAndMigrateIfNeeded( self, sell.walletAddress, trade.baseAssetAddress ); balance.balanceInPips -= trade.grossBaseQuantityInPips; // Buyer receives base asset minus fees balance = loadBalanceAndMigrateIfNeeded( self, buy.walletAddress, trade.baseAssetAddress ); balance.balanceInPips += trade.netBaseQuantityInPips; // Buyer gives quote asset including fees balance = loadBalanceAndMigrateIfNeeded( self, buy.walletAddress, trade.quoteAssetAddress ); balance.balanceInPips -= trade.grossQuoteQuantityInPips; // Seller receives quote asset minus fees balance = loadBalanceAndMigrateIfNeeded( self, sell.walletAddress, trade.quoteAssetAddress ); balance.balanceInPips += trade.netQuoteQuantityInPips; // Maker fee to fee wallet balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, trade.makerFeeAssetAddress ); balance.balanceInPips += trade.makerFeeQuantityInPips; // Taker fee to fee wallet balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, trade.takerFeeAssetAddress ); balance.balanceInPips += trade.takerFeeQuantityInPips; } function updateForPoolTrade( Storage storage self, Order memory order, PoolTrade memory poolTrade, address feeWallet ) internal { Balance storage balance; // Debit from order wallet balance = loadBalanceAndMigrateIfNeeded( self, order.walletAddress, poolTrade.getOrderDebitAssetAddress(order.side) ); balance.balanceInPips -= poolTrade.getOrderDebitQuantityInPips(order.side); // Credit to order wallet balance = loadBalanceAndMigrateIfNeeded( self, order.walletAddress, poolTrade.getOrderCreditAssetAddress(order.side) ); balance.balanceInPips += poolTrade.calculateOrderCreditQuantityInPips( order.side ); // Fee wallet receives protocol fee from asset debited from order wallet balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, poolTrade.getOrderDebitAssetAddress(order.side) ); balance.balanceInPips += poolTrade.takerProtocolFeeQuantityInPips; // Fee wallet receives gas fee from asset credited to order wallet balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, poolTrade.getOrderCreditAssetAddress(order.side) ); balance.balanceInPips += poolTrade.takerGasFeeQuantityInPips; // Liquidity pool reserves are updated in LiquidityPoolRegistry } function updateForHybridTradeFees( Storage storage self, HybridTrade memory hybridTrade, address takerWallet, address feeWallet ) internal { Balance storage balance; balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, hybridTrade.orderBookTrade.takerFeeAssetAddress ); balance.balanceInPips += hybridTrade.takerGasFeeQuantityInPips; balance = loadBalanceAndMigrateIfNeeded( self, takerWallet, hybridTrade.orderBookTrade.takerFeeAssetAddress ); balance.balanceInPips -= hybridTrade.takerGasFeeQuantityInPips + hybridTrade.poolTrade.takerPriceCorrectionFeeQuantityInPips; // Liquidity pool reserves are updated in LiquidityPoolRegistry } // Withdrawing // function updateForWithdrawal( Storage storage self, Withdrawal memory withdrawal, address assetAddress, address feeWallet ) internal returns (uint64 newExchangeBalanceInPips) { Balance storage balance; balance = loadBalanceAndMigrateIfNeeded( self, withdrawal.walletAddress, assetAddress ); // Reverts if balance is overdrawn balance.balanceInPips -= withdrawal.grossQuantityInPips; newExchangeBalanceInPips = balance.balanceInPips; if (withdrawal.gasFeeInPips > 0) { balance = loadBalanceAndMigrateIfNeeded(self, feeWallet, assetAddress); balance.balanceInPips += withdrawal.gasFeeInPips; } } // Wallet exits // function updateForExit( Storage storage self, address wallet, address assetAddress ) internal returns (uint64 previousExchangeBalanceInPips) { Balance storage balance; balance = loadBalanceAndMigrateIfNeeded(self, wallet, assetAddress); previousExchangeBalanceInPips = balance.balanceInPips; require(previousExchangeBalanceInPips > 0, 'No balance for asset'); balance.balanceInPips = 0; } // Liquidity pools // function updateForAddLiquidity( Storage storage self, LiquidityAddition memory addition, LiquidityChangeExecution memory execution, address feeWallet, address custodianAddress, ILiquidityProviderToken liquidityProviderToken ) internal returns (uint64 outputLiquidityInPips) { // Base gross debit Balance storage balance = loadBalanceAndMigrateIfNeeded( self, addition.wallet, execution.baseAssetAddress ); balance.balanceInPips -= execution.grossBaseQuantityInPips; // Base fee credit balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, execution.baseAssetAddress ); balance.balanceInPips += execution.grossBaseQuantityInPips - execution.netBaseQuantityInPips; // Quote gross debit balance = loadBalanceAndMigrateIfNeeded( self, addition.wallet, execution.quoteAssetAddress ); balance.balanceInPips -= execution.grossQuoteQuantityInPips; // Quote fee credit balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, execution.quoteAssetAddress ); balance.balanceInPips += execution.grossQuoteQuantityInPips - execution.netQuoteQuantityInPips; // Only add output assets to wallet's balances in the Exchange if Custodian is target if (addition.to == custodianAddress) { balance = loadBalanceAndMigrateIfNeeded( self, addition.wallet, address(liquidityProviderToken) ); balance.balanceInPips += execution.liquidityInPips; } else { outputLiquidityInPips = execution.liquidityInPips; } } function updateForRemoveLiquidity( Storage storage self, LiquidityRemoval memory removal, LiquidityChangeExecution memory execution, address feeWallet, address custodianAddress, ILiquidityProviderToken liquidityProviderToken ) internal returns ( uint64 outputBaseAssetQuantityInPips, uint64 outputQuoteAssetQuantityInPips ) { Balance storage balance; // Base asset updates { // Only add output assets to wallet's balances in the Exchange if Custodian is target if (removal.to == custodianAddress) { // Base net credit balance = loadBalanceAndMigrateIfNeeded( self, removal.wallet, execution.baseAssetAddress ); balance.balanceInPips += execution.netBaseQuantityInPips; } else { outputBaseAssetQuantityInPips = execution.netBaseQuantityInPips; } // Base fee credit balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, execution.baseAssetAddress ); balance.balanceInPips += execution.grossBaseQuantityInPips - execution.netBaseQuantityInPips; } // Quote asset updates { // Only add output assets to wallet's balances in the Exchange if Custodian is target if (removal.to == custodianAddress) { // Quote net credit balance = loadBalanceAndMigrateIfNeeded( self, removal.wallet, execution.quoteAssetAddress ); balance.balanceInPips += execution.netQuoteQuantityInPips; } else { outputQuoteAssetQuantityInPips = execution.netQuoteQuantityInPips; } // Quote fee credit balance = loadBalanceAndMigrateIfNeeded( self, feeWallet, execution.quoteAssetAddress ); balance.balanceInPips += execution.grossQuoteQuantityInPips - execution.netQuoteQuantityInPips; } // Pair token burn { balance = loadBalanceAndMigrateIfNeeded( self, removal.wallet, address(liquidityProviderToken) ); balance.balanceInPips -= execution.liquidityInPips; } } // Helpers // function loadBalanceAndMigrateIfNeeded( Storage storage self, address wallet, address assetAddress ) private returns (Balance storage) { Balance storage balance = self.balancesByWalletAssetPair[wallet][assetAddress]; if (!balance.isMigrated && address(self.migrationSource) != address(0x0)) { balance.balanceInPips = self.migrationSource.loadBalanceInPipsByAddress( wallet, assetAddress ); balance.isMigrated = true; } return balance; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.4; /** * @dev See GOVERNANCE.md for descriptions of fixed parameters and fees */ library Constants { // 100 basis points/percent * 100 percent/total uint64 public constant basisPointsInTotal = 100 * 100; uint64 public constant depositIndexNotSet = 2**64 - 1; uint8 public constant liquidityProviderTokenDecimals = 18; // 1 week at 3s/block uint256 public constant maxChainPropagationPeriod = (7 * 24 * 60 * 60) / 3; // 20% uint64 public constant maxFeeBasisPoints = 20 * 100; // Pool reserve balance ratio above which price dips below 1 pip and can no longer be represented uint64 public constant maxLiquidityPoolReserveRatio = 10**8; // Pool reserve balance below which prices can no longer be represented with full pip precision uint64 public constant minLiquidityPoolReserveInPips = 10**8; // 2% uint64 public constant maxPoolInputFeeBasisPoints = 2 * 100; // 5% uint64 public constant maxPoolOutputAdjustmentBasisPoints = 5 * 100; // 1% uint64 public constant maxPoolPriceCorrectionBasisPoints = 1 * 100; // To convert integer pips to a fractional price shift decimal left by the pip precision of 8 // decimals places uint64 public constant pipPriceMultiplier = 10**8; uint8 public constant signatureHashVersion = 3; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.4; /** * @notice Enums definitions */ // Liquidity pools // enum LiquidityChangeOrigination { OnChain, OffChain } enum LiquidityChangeType { Addition, Removal } enum LiquidityChangeState { NotInitiated, Initiated, Executed } // Order book // 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 } // Withdrawals // enum WithdrawalType { BySymbol, ByAddress }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.4; import { Order, OrderBookTrade, Withdrawal } from './Structs.sol'; /** * @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 (native asset 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 Whistler Exchange contract * * @dev Used for lazy balance migrations from old to new Exchange after upgrade */ interface IExchange { /** * @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); /** * @notice Load the address of the Custodian contract * * @return The address of the Custodian contract */ function loadCustodian() external view returns (ICustodian); } interface ILiquidityProviderToken { function custodian() external returns (ICustodian); function baseAssetAddress() external returns (address); function quoteAssetAddress() external returns (address); function baseAssetSymbol() external returns (string memory); function quoteAssetSymbol() external returns (string memory); function token0() external returns (address); function token1() external returns (address); function burn( address wallet, uint256 liquidity, uint256 baseAssetQuantityInAssetUnits, uint256 quoteAssetQuantityInAssetUnits, address to ) external; function mint( address wallet, uint256 liquidity, uint256 baseAssetQuantityInAssetUnits, uint256 quoteAssetQuantityInAssetUnits, address to ) external; function reverseAssets() external; } interface IWETH9 is IERC20 { receive() external payable; function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.4; import { OrderSide } from './Enums.sol'; import { PoolTrade } from './Structs.sol'; library PoolTradeHelpers { /** * @dev Address of asset order wallet is receiving from pool */ function getOrderCreditAssetAddress( PoolTrade memory self, OrderSide orderSide ) internal pure returns (address) { return orderSide == OrderSide.Buy ? self.baseAssetAddress : self.quoteAssetAddress; } /** * @dev Address of asset order wallet is giving to pool */ function getOrderDebitAssetAddress(PoolTrade memory self, OrderSide orderSide) internal pure returns (address) { return orderSide == OrderSide.Buy ? self.quoteAssetAddress : self.baseAssetAddress; } /** * @dev Quantity in pips of asset that order wallet is receiving from pool */ function calculateOrderCreditQuantityInPips( PoolTrade memory self, OrderSide orderSide ) internal pure returns (uint64) { return ( orderSide == OrderSide.Buy ? self.netBaseQuantityInPips : self.netQuoteQuantityInPips ) - self.takerGasFeeQuantityInPips; } /** * @dev Quantity in pips of asset that order wallet is giving to pool */ function getOrderDebitQuantityInPips( PoolTrade memory self, OrderSide orderSide ) internal pure returns (uint64) { return orderSide == OrderSide.Buy ? self.grossQuoteQuantityInPips : self.grossBaseQuantityInPips; } /** * @dev Quantity in pips of asset that pool receives from order wallet */ function calculatePoolCreditQuantityInPips( PoolTrade memory self, OrderSide orderSide ) internal pure returns (uint64) { return ( orderSide == OrderSide.Buy ? self.netQuoteQuantityInPips : self.netBaseQuantityInPips ) + self.takerPoolFeeQuantityInPips; } /** * @dev Quantity in pips of asset that leaves pool as output */ function getPoolDebitQuantityInPips( PoolTrade memory self, OrderSide orderSide ) internal pure returns (uint64) { return ( orderSide == OrderSide.Buy ? self.netBaseQuantityInPips // Pool gives net base asset plus taker gas fee : self.netQuoteQuantityInPips // Pool gives net quote asset plus taker gas fee ); } /** * @dev Gross quantity received by order wallet */ function getOrderGrossReceivedQuantityInPips( PoolTrade memory self, OrderSide orderSide ) internal pure returns (uint64) { return orderSide == OrderSide.Buy ? self.grossBaseQuantityInPips : self.grossQuoteQuantityInPips; } function calculatePoolOutputAdjustment( PoolTrade memory self, OrderSide orderSide ) internal pure returns (uint64) { return getOrderGrossReceivedQuantityInPips(self, orderSide) - getPoolDebitQuantityInPips(self, orderSide); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.4; import { ILiquidityProviderToken, IWETH9 } from './Interfaces.sol'; import { LiquidityChangeOrigination, OrderSelfTradePrevention, OrderSide, OrderTimeInForce, OrderType, WithdrawalType } from './Enums.sol'; /** * @notice Struct definitions */ /** * @notice State tracking for a hybrid liquidity pool * * @dev Base and quote asset decimals are denormalized here to avoid extra loads from * `AssetRegistry.Storage` */ struct LiquidityPool { // Flag to distinguish from empty struct bool exists; uint64 baseAssetReserveInPips; uint8 baseAssetDecimals; uint64 quoteAssetReserveInPips; uint8 quoteAssetDecimals; ILiquidityProviderToken liquidityProviderToken; } /** * @dev Internal struct capturing user-initiated liquidity addition request parameters */ struct LiquidityAddition { // Must equal `Constants.signatureHashVersion` uint8 signatureHashVersion; // Distinguishes between liquidity additions initated on- or off- chain LiquidityChangeOrigination origination; // UUIDv1 unique to wallet uint128 nonce; address wallet; address assetA; address assetB; uint256 amountADesired; uint256 amountBDesired; uint256 amountAMin; uint256 amountBMin; address to; uint256 deadline; bytes signature; } /** * @notice Internally used struct, return type from `LiquidityPools.addLiquidity` */ struct LiquidityAdditionDepositResult { string assetASymbol; uint64 assetAQuantityInPips; uint64 assetANewExchangeBalanceInPips; uint256 assetANewExchangeBalanceInAssetUnits; string assetBSymbol; uint64 assetBQuantityInPips; uint64 assetBNewExchangeBalanceInPips; uint256 assetBNewExchangeBalanceInAssetUnits; } /** * @notice Internally used struct, return type from `LiquidityPools.removeLiquidity` */ struct LiquidityRemovalDepositResult { address assetAddress; string assetSymbol; uint64 assetQuantityInPips; uint64 assetNewExchangeBalanceInPips; uint256 assetNewExchangeBalanceInAssetUnits; } /** * @dev Internal struct capturing user-initiated liquidity removal request parameters */ struct LiquidityRemoval { // Must equal `Constants.signatureHashVersion` uint8 signatureHashVersion; // Distinguishes between liquidity additions initated on- or off- chain LiquidityChangeOrigination origination; uint128 nonce; address wallet; address assetA; address assetB; uint256 liquidity; uint256 amountAMin; uint256 amountBMin; address payable to; uint256 deadline; bytes signature; } /** * @notice Argument type to `Exchange.executeAddLiquidity` and `Exchange.executeRemoveLiquidity` */ struct LiquidityChangeExecution { address baseAssetAddress; address quoteAssetAddress; uint64 liquidityInPips; // 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 sent to pool for additions or received by wallet for removals uint64 netBaseQuantityInPips; // Net amount of quote asset sent to pool for additions or received by wallet for removals uint64 netQuoteQuantityInPips; } /** * @notice Internally used struct, argument type to `LiquidityPoolAdmin.migrateLiquidityPool` */ struct LiquidityMigration { address token0; address token1; bool isToken1Quote; uint256 desiredLiquidity; address to; IWETH9 WETH; } /** * @notice Internally used struct capturing wallet order nonce invalidations created via `invalidateOrderNonce` */ struct NonceInvalidation { bool exists; uint64 timestampInMs; uint256 effectiveBlockNumber; } /** * @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.executeOrderBookTrade` and `Hashing.getOrderWalletHash` */ struct Order { // Must equal `Constants.signatureHashVersion` uint8 signatureHashVersion; // UUIDv1 unique to wallet uint128 nonce; // Wallet address that placed order and signed hash address walletAddress; // Type of order OrderType orderType; // Order side wallet is on 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 OrderTimeInForce timeInForce; // STP behavior specified by wallet for order OrderSelfTradePrevention selfTradePrevention; // Cancellation time specified by wallet for GTT TIF order uint64 cancelAfter; // The ECDSA signature of the order hash as produced by Hashing.getOrderWalletHash bytes walletSignature; } /** * @notice Argument type for `Exchange.executeOrderBookTrade` specifying execution parameters for matching orders */ struct OrderBookTrade { // 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, inclusive of gas fees 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 OrderSide makerSide; } /** * @notice Argument type for `Exchange.executePoolTrade` specifying execution parameters for an * order against pool liquidity */ struct PoolTrade { // 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; // If wallet is buy side, net amount of quote input to pool used to calculate output; otherwise, // net amount of base asset leaving pool uint64 netBaseQuantityInPips; // If wallet is buy side, net amount of base input to pool used to calculate output; otherwise, // net amount of quote asset leaving pool uint64 netQuoteQuantityInPips; // Fee paid by liquidity taker to pool from sent asset uint64 takerPoolFeeQuantityInPips; // Fee paid by liquidity taker to fee wallet from sent asset uint64 takerProtocolFeeQuantityInPips; // Fee paid by liquidity taker to fee wallet from received asset uint64 takerGasFeeQuantityInPips; // Fee paid by liquidity taker sell to pool taken from pool's quote asset output uint64 takerPriceCorrectionFeeQuantityInPips; } struct HybridTrade { OrderBookTrade orderBookTrade; PoolTrade poolTrade; // Fee paid by liquidity taker to fee wallet from received asset uint64 takerGasFeeQuantityInPips; } /** * @notice Argument type for `Exchange.withdraw` and `Hashing.getWithdrawalWalletHash` */ struct Withdrawal { // Distinguishes between withdrawals by asset symbol or address 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 grossQuantityInPips; // 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 Hashing.getWithdrawalWalletHash bytes walletSignature; }
{ "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "optimizer": { "enabled": true, "runs": 1 }, "evmVersion": "berlin", "metadata": { "bytecodeHash": "ipfs" }, "libraries": { "Exchange.sol": { "AssetRegistry": "0xc2f05d03915E7c2D9038830F7888c97e351dd3dB", "Depositing": "0x116310b243dd287d4285d0e8a34ce3d4adb63dac", "LiquidityPoolAdmin": "0x7a246e4434dd31df784bb88d3443e309e3143adc", "LiquidityPools": "0x0f2c07f4ecc6c9d74d16e735d2a59d00985b1962", "NonceInvalidations": "0x6c539e6143f70408076f35d19e7e549850c021ad", "Trading": "0x4d3250014ea4ecddd857fad48c3d64d2e4f037e1", "Withdrawing": "0xb3af24eeac0ee8b6f5798f8a75e3ecd51b18deb2" }, "AssetRegistry.sol": { "AssetRegistry": "0xc2f05d03915E7c2D9038830F7888c97e351dd3dB" }, "Depositing.sol": { "Depositing": "0x116310b243dd287d4285d0e8a34ce3d4adb63dac" }, "LiquidityPoolAdmin.sol": { "LiquidityPoolAdmin": "0x7a246e4434dd31df784bb88d3443e309e3143adc" }, "LiquidityPools.sol": { "LiquidityPools": "0x0f2c07f4ecc6c9d74d16e735d2a59d00985b1962" }, "NonceInvalidations.sol": { "NonceInvalidations": "0x6c539e6143f70408076f35d19e7e549850c021ad" }, "Trading.sol": { "Trading": "0x4d3250014ea4ecddd857fad48c3d64d2e4f037e1" }, "Withdrawing.sol": { "Withdrawing": "0xb3af24eeac0ee8b6f5798f8a75e3ecd51b18deb2" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract Creation Code
611e4e61003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100825760003560e01c806347ac1b45146100875780635e55073b146100ad578063712b772f146100cf578063922d96e2146100ef578063a2cfc7a91461011a578063a7c5af211461012d578063bde818221461014d578063c6c1fcc01461016d575b600080fd5b61009a610095366004611956565b610180565b6040519081526020015b60405180910390f35b8180156100b957600080fd5b506100cd6100c8366004611a57565b6101e1565b005b8180156100db57600080fd5b506100cd6100ea3660046118de565b61042f565b6101026100fd366004611916565b6104de565b6040516001600160401b0390911681526020016100a4565b61009a61012836600461199d565b61051b565b81801561013957600080fd5b506100cd610148366004611a57565b6105ad565b81801561015957600080fd5b506100cd6101683660046119fe565b6109ae565b61010261017b36600461199d565b610cdf565b60006001600160a01b0384166101b15760405162461bcd60e51b81526004016101a890611bc9565b60405180910390fd5b60006101bd8685610d5e565b90506101d76101cd868686610f88565b826060015161108f565b9695505050505050565b60208160ff1611156102455760405162461bcd60e51b815260206004820152602760248201527f546f6b656e2063616e6e6f742068617665206d6f7265207468616e20333220646044820152666563696d616c7360c81b60648201526084016101a8565b6001600160a01b0384161580159061025d5750833b15155b6102795760405162461bcd60e51b81526004016101a890611b9a565b816102bd5760405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a59081d1bdad95b881cde5b589bdb60621b60448201526064016101a8565b6001600160a01b038416600090815260208690526040902060020154610100900460ff16156102fe5760405162461bcd60e51b81526004016101a890611b69565b6040518060c00160405280600115158152602001856001600160a01b0316815260200184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093855250505060ff8416602080840191909152604080840183905260609093018290526001600160a01b0388811683528982529183902084518154868401516001600160a81b0319909116911515610100600160a81b03191691909117610100919094160292909217825591830151805191926103d8926001850192909101906117c9565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ffff1990921660ff9094169390931717929092161790555050505050565b813b61044d5760405162461bcd60e51b81526004016101a890611b9a565b6040516370a0823160e01b81526000906001600160a01b038416906370a082319061047c903090600401611b55565b60206040518083038186803b15801561049457600080fd5b505afa1580156104a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cc9190611acd565b90506104d9828483611153565b505050565b60006001600160a01b0384166105065760405162461bcd60e51b81526004016101a890611bc9565b610511848484610f88565b90505b9392505050565b60006001600160a01b0385166105435760405162461bcd60e51b81526004016101a890611bc9565b600061058e8786868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058992506113c4915050565b6113d9565b90506105a26101cd87836020015186610f88565b979650505050505050565b6001600160a01b03808516600090815260208781526040808320815160c081018352815460ff811615158252610100900490951692850192909252600182018054939493918401916105fe90611d8f565b80601f016020809104026020016040519081016040528092919081815260200182805461062a90611d8f565b80156106775780601f1061064c57610100808354040283529160200191610677565b820191906000526020600020905b81548152906001019060200180831161065a57829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091506106f35760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016101a8565b8060800151156107155760405162461bcd60e51b81526004016101a890611b69565b610759816040015185858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061173192505050565b61079c5760405162461bcd60e51b81526020600482015260146024820152730a6f2dac4ded8e640c8de40dcdee840dac2e8c6d60631b60448201526064016101a8565b8160ff16816060015160ff16146107ed5760405162461bcd60e51b8152602060048201526015602482015274088cac6d2dac2d8e640c8de40dcdee840dac2e8c6d605b1b60448201526064016101a8565b60016080820152610800426103e8611d07565b6001600160401b031660a08201526001600160a01b038581166000908152602088815260409182902084518154838701516001600160a81b0319909116911515610100600160a81b0319169190911761010091909516029390931783559083015180518493926108779260018501929101906117c9565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ffff1990921660ff90941693909317179290921617905560405160018701906108dc9086908690611b0c565b9081526040805191829003602090810190922080546001818101835560009283529184902085516003909202018054868601516001600160a01b031661010002610100600160a81b0319931515939093166001600160a81b03199091161791909117815591840151805185946109569385019201906117c9565b50606082015160029091018054608084015160a0909401516001600160401b0316620100000262010000600160501b03199415156101000261ffff1990921660ff909416939093171792909216179055505050505050565b6001600160a01b03808416600090815260208681526040808320815160c081018352815460ff811615158252610100900490951692850192909252600182018054939493918401916109ff90611d8f565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2b90611d8f565b8015610a785780601f10610a4d57610100808354040283529160200191610a78565b820191906000526020600020905b815481529060010190602001808311610a5b57829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091508015610ac5575080608001515b610b1d5760405162461bcd60e51b815260206004820152602360248201527f526567697374726174696f6e206f6620746f6b656e206e6f742066696e616c696044820152621e995960ea1b60648201526084016101a8565b610be883838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050600287018054610b6590611d8f565b80601f0160208091040260200160405190810160405280929190818152602001828054610b9190611d8f565b8015610bde5780601f10610bb357610100808354040283529160200191610bde565b820191906000526020600020905b815481529060010190602001808311610bc157829003601f168201915b5050505050611731565b15610c355760405162461bcd60e51b815260206004820181905260248201527f53796d626f6c20726573657276656420666f72206e617469766520617373657460448201526064016101a8565b6103e8610c428142611d07565b6001600160401b031660a08301526040516001870190610c659086908690611b0c565b9081526040805191829003602090810190922080546001818101835560009283529184902086516003909202018054878601516001600160a01b031661010002610100600160a81b0319931515939093166001600160a81b03199091161791909117815591850151805186946109569385019201906117c9565b60006001600160a01b038516610d075760405162461bcd60e51b81526004016101a890611bc9565b6000610d4d8786868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058992506113c4915050565b6020015190506105a2868285610f88565b610d6661184d565b6001600160a01b038216610e1057610e09836002018054610d8690611d8f565b80601f0160208091040260200160405190810160405280929190818152602001828054610db290611d8f565b8015610dff5780601f10610dd457610100808354040283529160200191610dff565b820191906000526020600020905b815481529060010190602001808311610de257829003601f168201915b505050505061178a565b9050610f82565b6001600160a01b03808316600090815260208581526040808320815160c081018352815460ff81161515825261010090049095169285019290925260018201805493949391840191610e6190611d8f565b80601f0160208091040260200160405190810160405280929190818152602001828054610e8d90611d8f565b8015610eda5780601f10610eaf57610100808354040283529160200191610eda565b820191906000526020600020905b815481529060010190602001808311610ebd57829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015280519091508015610f27575080608001515b610f7f5760405162461bcd60e51b8152602060048201526024808201527f4e6f20636f6e6669726d656420617373657420666f756e6420666f72206164646044820152637265737360e01b60648201526084016101a8565b90505b92915050565b6001600160a01b03838116600090815260208381526040808320938616835292815282822083518085019094525460ff81161580158086526101009092046001600160401b031692850192909252919291610fef575060018301546001600160a01b031615155b1561108357600183015460405163dbb3653560e01b81526001600160a01b03878116600483015286811660248301529091169063dbb365359060440160206040518083038186803b15801561104357600080fd5b505afa158015611057573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107b9190611ae5565b915050610514565b60200151949350505050565b600060208260ff1611156110f55760405162461bcd60e51b815260206004820152602760248201527f41737365742063616e6e6f742068617665206d6f7265207468616e20333220646044820152666563696d616c7360c81b60648201526084016101a8565b60088260ff16111561112a5761110c600883611d6c565b61111790600a611c5c565b610e09906001600160401b038516611d07565b611135826008611d6c565b61114090600a611c5c565b610f7f906001600160401b038516611bf9565b6001600160a01b0382166111c8576040516001600160a01b0384169082156108fc029083906000818181858888f193505050506104d95760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016101a8565b6040516370a0823160e01b81526000906001600160a01b038416906370a08231906111f7908790600401611b55565b60206040518083038186803b15801561120f57600080fd5b505afa158015611223573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112479190611acd565b60405163a9059cbb60e01b81526001600160a01b038681166004830152602482018590529192509084169063a9059cbb90604401600060405180830381600087803b15801561129557600080fd5b505af11580156112a9573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b03861691506370a08231906112dc908890600401611b55565b60206040518083038186803b1580156112f457600080fd5b505afa158015611308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132c9190611acd565b9050826113398383611d55565b146113bd5760405162461bcd60e51b815260206004820152604860248201527f546f6b656e20636f6e74726163742072657475726e6564207472616e7366657260448201527f207375636365737320776974686f75742065787065637465642062616c616e6360648201526765206368616e676560c01b608482015260a4016101a8565b5050505050565b60006103e86113d38142611d26565b91505090565b6113e161184d565b6114778460020180546113f390611d8f565b80601f016020809104026020016040519081016040528092919081815260200182805461141f90611d8f565b801561146c5780601f106114415761010080835404028352916020019161146c565b820191906000526020600020905b81548152906001019060200180831161144f57829003601f168201915b505050505084611731565b156114955761148e846002018054610d8690611d8f565b9050610514565b61149d61184d565b600085600101856040516114b19190611b1c565b9081526040519081900360200190205411156116ca5760005b85600101856040516114dc9190611b1c565b9081526040519081900360200190205460ff821610156116c857836001600160401b031686600101866040516115129190611b1c565b90815260200160405180910390208260ff168154811061154257634e487b7160e01b600052603260045260246000fd5b60009182526020909120600390910201600201546201000090046001600160401b0316116116b657856001018560405161157c9190611b1c565b90815260200160405180910390208160ff16815481106115ac57634e487b7160e01b600052603260045260246000fd5b60009182526020918290206040805160c0810182526003909302909101805460ff8116151584526001600160a01b036101009091041693830193909352600183018054929392918401916115ff90611d8f565b80601f016020809104026020016040519081016040528092919081815260200182805461162b90611d8f565b80156116785780601f1061164d57610100808354040283529160200191611678565b820191906000526020600020905b81548152906001019060200180831161165b57829003601f168201915b50505091835250506002919091015460ff8082166020840152610100820416151560408301526201000090046001600160401b031660609091015291505b806116c081611dca565b9150506114ca565b505b805180156116d9575080608001515b6105115760405162461bcd60e51b815260206004820152602360248201527f4e6f20636f6e6669726d656420617373657420666f756e6420666f722073796d604482015262189bdb60ea1b60648201526084016101a8565b6000816040516020016117449190611b1c565b604051602081830303815290604052805190602001208360405160200161176b9190611b1c565b6040516020818303038152906040528051906020012014905092915050565b61179261184d565b506040805160c08101825260018082526000602083018190529282019390935260126060820152608081019290925260a082015290565b8280546117d590611d8f565b90600052602060002090601f0160209004810192826117f7576000855561183d565b82601f1061181057805160ff191683800117855561183d565b8280016001018555821561183d579182015b8281111561183d578251825591602001919060010190611822565b50611849929150611883565b5090565b6040805160c08101825260008082526020820181905260609282018390529181018290526080810182905260a081019190915290565b5b808211156118495760008155600101611884565b60008083601f8401126118a9578182fd5b5081356001600160401b038111156118bf578182fd5b6020830191508360208285010111156118d757600080fd5b9250929050565b600080604083850312156118f0578182fd5b82356118fb81611e00565b9150602083013561190b81611e00565b809150509250929050565b60008060006060848603121561192a578081fd5b833561193581611e00565b9250602084013561194581611e00565b929592945050506040919091013590565b6000806000806080858703121561196b578081fd5b84359350602085013561197d81611e00565b9250604085013561198d81611e00565b9396929550929360600135925050565b6000806000806000608086880312156119b4578081fd5b8535945060208601356119c681611e00565b935060408601356001600160401b038111156119e0578182fd5b6119ec88828901611898565b96999598509660600135949350505050565b60008060008060608587031215611a13578384fd5b843593506020850135611a2581611e00565b925060408501356001600160401b03811115611a3f578283fd5b611a4b87828801611898565b95989497509550505050565b600080600080600060808688031215611a6e578081fd5b853594506020860135611a8081611e00565b935060408601356001600160401b03811115611a9a578182fd5b611aa688828901611898565b909450925050606086013560ff81168114611abf578182fd5b809150509295509295909350565b600060208284031215611ade578081fd5b5051919050565b600060208284031215611af6578081fd5b81516001600160401b0381168114610f7f578182fd5b8183823760009101908152919050565b60008251815b81811015611b3c5760208186018101518583015201611b22565b81811115611b4a5782828501525b509190910192915050565b6001600160a01b0391909116815260200190565b602080825260179082015276151bdad95b88185b1c9958591e48199a5b985b1a5e9959604a1b604082015260600190565b602080825260159082015274496e76616c696420746f6b656e206164647265737360581b604082015260600190565b602080825260169082015275496e76616c69642077616c6c6574206164647265737360501b604082015260600190565b600082611c1457634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115611c54578160001904821115611c3a57611c3a611dea565b80851615611c4757918102915b93841c9390800290611c1e565b509250929050565b6000610f7f60ff841683600082611c7557506001610f82565b81611c8257506000610f82565b8160018114611c985760028114611ca257611cbe565b6001915050610f82565b60ff841115611cb357611cb3611dea565b50506001821b610f82565b5060208310610133831016604e8410600b8410161715611ce1575081810a610f82565b611ceb8383611c19565b8060001904821115611cff57611cff611dea565b029392505050565b6000816000190483118215151615611d2157611d21611dea565b500290565b60006001600160401b0382811684821681151582840482111615611d4c57611d4c611dea565b02949350505050565b600082821015611d6757611d67611dea565b500390565b600060ff821660ff841680821015611d8657611d86611dea565b90039392505050565b600181811c90821680611da357607f821691505b60208210811415611dc457634e487b7160e01b600052602260045260246000fd5b50919050565b600060ff821660ff811415611de157611de1611dea565b60010192915050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114611e1557600080fd5b5056fea2646970667358221220ee5b1903c10e0f99d2fc9f5ab40339811d638c5ae50d0d43583de51a78c2e43e64736f6c63430008040033
Deployed ByteCode Sourcemap
494:8023:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3458:572;;;;;;:::i;:::-;;:::i;:::-;;;12244:25:10;;;12232:2;12217:18;3458:572:1;;;;;;;;877:886;;;;;;;;;;-1:-1:-1;877:886:1;;;;;:::i;:::-;;:::i;:::-;;3150:285;;;;;;;;;;-1:-1:-1;3150:285:1;;;;;:::i;:::-;;:::i;4653:373::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;12450:31:10;;;12432:50;;12420:2;12405:18;4653:373:1;12387:101:10;4034:615:1;;;;;;:::i;:::-;;:::i;1767:722::-;;;;;;;;;;-1:-1:-1;1767:722:1;;;;;:::i;:::-;;:::i;2493:653::-;;;;;;;;;;-1:-1:-1;2493:653:1;;;;;:::i;:::-;;:::i;5030:525::-;;;;;;:::i;:::-;;:::i;3458:572::-;3666:7;-1:-1:-1;;;;;3689:22:1;;3681:57;;;;-1:-1:-1;;;3681:57:1;;;;;;;:::i;:::-;;;;;;;;;3745:18;3766:38;3785:4;3791:12;3766:18;:38::i;:::-;3745:59;;3823:202;3870:123;3926:6;3944:12;3968:15;3870:44;:123::i;:::-;4003:5;:14;;;3823:37;:202::i;:::-;3810:215;3458:572;-1:-1:-1;;;;;;3458:572:1:o;877:886::-;1052:2;1040:8;:14;;;;1032:66;;;;-1:-1:-1;;;1032:66:1;;8086:2:10;1032:66:1;;;8068:21:10;8125:2;8105:18;;;8098:30;8164:34;8144:18;;;8137:62;-1:-1:-1;;;8215:18:10;;;8208:37;8262:19;;1032:66:1;8058:229:10;1032:66:1;-1:-1:-1;;;;;1119:36:1;;;;;;:89;;-1:-1:-1;1078:20:0;;1116:8;;1167:41:1;1104:141;;;;-1:-1:-1;;;1104:141:1;;;;;;;:::i;:::-;1357:24;1349:57;;;;-1:-1:-1;;;1349:57:1;;11111:2:10;1349:57:1;;;11093:21:10;11150:2;11130:18;;;11123:30;-1:-1:-1;;;11169:18:10;;;11162:50;11229:18;;1349:57:1;11083:170:10;1349:57:1;-1:-1:-1;;;;;1428:43:1;;:20;:43;;;;;;;;;;:55;;;;;;;;1427:56;1412:110;;;;-1:-1:-1;;;1412:110:1;;;;;;;:::i;:::-;1575:183;;;;;;;;1597:4;1575:183;;;;;;1631:12;-1:-1:-1;;;;;1575:183:1;;;;;1660:6;;1575:183;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1575:183:1;;;-1:-1:-1;;;1575:183:1;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1529:43:1;;;;;;;;;;;;:229;;;;;;;;-1:-1:-1;;;;;;1529:229:1;;;;;;-1:-1:-1;;;;;;1529:229:1;;;;;;;;;;;;;;;;;;;;;;;:43;;:229;;-1:-1:-1;1529:229:1;;;;;;;;:::i;:::-;-1:-1:-1;1529:229:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1529:229:1;;;-1:-1:-1;;;;;;1529:229:1;;;;;-1:-1:-1;;1529:229:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;877:886:1:o;3150:285::-;1078:20:0;;3220:66:1;;;;-1:-1:-1;;;3220:66:1;;;;;;;:::i;:::-;3311:45;;-1:-1:-1;;;3311:45:1;;3293:15;;-1:-1:-1;;;;;3311:30:1;;;;;:45;;3350:4;;3311:45;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3293:63;;3362:68;3396:9;3408:12;3422:7;3362:25;:68::i;:::-;3150:285;;;:::o;4653:373::-;4815:6;-1:-1:-1;;;;;4837:22:1;;4829:57;;;;-1:-1:-1;;;4829:57:1;;;;;;;:::i;:::-;4906:115;4960:6;4976:12;4998:15;4906:44;:115::i;:::-;4893:128;;4653:373;;;;;;:::o;4034:615::-;4248:7;-1:-1:-1;;;;;4271:22:1;;4263:57;;;;-1:-1:-1;;;4263:57:1;;;;;;;:::i;:::-;4327:18;4354:63;4372:4;4378:11;;4354:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4391:25:1;;-1:-1:-1;4391:23:1;;-1:-1:-1;;4391:25:1:i;:::-;4354:17;:63::i;:::-;4327:90;;4436:208;4483:129;4539:6;4557:5;:18;;;4587:15;4483:44;:129::i;4436:208::-;4423:221;4034:615;-1:-1:-1;;;;;;;4034:615:1:o;1767:722::-;-1:-1:-1;;;;;1954:43:1;;;1933:18;1954:43;;;;;;;;;;;1933:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:18;;:64;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1933:64:1;;;-1:-1:-1;;1933:64:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1933:64:1;;;;;;2011:12;;;;-1:-1:-1;2003:38:1;;;;-1:-1:-1;;;2003:38:1;;7744:2:10;2003:38:1;;;7726:21:10;7783:2;7763:18;;;7756:30;-1:-1:-1;;;7802:18:10;;;7795:43;7855:18;;2003:38:1;7716:163:10;2003:38:1;2056:5;:17;;;2055:18;2047:54;;;;-1:-1:-1;;;2047:54:1;;;;;;;:::i;:::-;2115:35;2129:5;:12;;;2143:6;;2115:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2115:13:1;;-1:-1:-1;;;2115:35:1:i;:::-;2107:68;;;;-1:-1:-1;;;2107:68:1;;6630:2:10;2107:68:1;;;6612:21:10;6669:2;6649:18;;;6642:30;-1:-1:-1;;;6688:18:10;;;6681:50;6748:18;;2107:68:1;6602:170:10;2107:68:1;2207:8;2189:26;;:5;:14;;;:26;;;2181:60;;;;-1:-1:-1;;;2181:60:1;;8494:2:10;2181:60:1;;;8476:21:10;8533:2;8513:18;;;8506:30;-1:-1:-1;;;8552:18:10;;;8545:51;8613:18;;2181:60:1;8466:171:10;2181:60:1;2268:4;2248:17;;;:24;2316:22;:15;2334:4;2316:22;:::i;:::-;-1:-1:-1;;;;;2278:61:1;:28;;;:61;-1:-1:-1;;;;;2388:43:1;;;:20;:43;;;;;;;;;;;;:51;;;;;;;;-1:-1:-1;;;;;;2388:51:1;;;;;;-1:-1:-1;;;;;;2388:51:1;;;;;;;;;;;;;;;;;;;;;;;2278:28;;2388:43;:51;;-1:-1:-1;2388:51:1;;;;;;;:::i;:::-;-1:-1:-1;2388:51:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2388:51:1;;;-1:-1:-1;;;;;;2388:51:1;;;;;-1:-1:-1;;2388:51:1;;;;;;;;;;;;;;;;;;;2445:27;;2388:51;2445:19;;;:27;;2465:6;;;;2445:27;:::i;:::-;;;;;;;;;;;;;;;;;;:39;;;;;;;;-1:-1:-1;2445:39:1;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2445:39:1;;;-1:-1:-1;;;;;;2445:39:1;;;;;;;-1:-1:-1;;;;;;2445:39:1;;;;;;;;;;;;;;;;2478:5;;2445:39;;;;;;;;:::i;:::-;-1:-1:-1;2445:39:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2445:39:1;;;-1:-1:-1;;;;;;2445:39:1;;;;;-1:-1:-1;;2445:39:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;1767:722:1:o;2493:653::-;-1:-1:-1;;;;;2650:43:1;;;2629:18;2650:43;;;;;;;;;;;2629:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:18;;:64;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;2629:64:1;;;-1:-1:-1;;2629:64:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2629:64:1;;;;;;2714:12;;;;-1:-1:-1;2714:33:1;;;;;2730:5;:17;;;2714:33;2699:99;;;;-1:-1:-1;;;2699:99:1;;7340:2:10;2699:99:1;;;7322:21:10;7379:2;7359:18;;;7352:30;7418:34;7398:18;;;7391:62;-1:-1:-1;;;7469:18:10;;;7462:33;7512:19;;2699:99:1;7312:225:10;2699:99:1;2820:45;2834:6;;2820:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;2842:22:1;;;2820:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:13;:45::i;:::-;2819:46;2804:109;;;;-1:-1:-1;;;2804:109:1;;6979:2:10;2804:109:1;;;6961:21:10;;;6998:18;;;6991:30;7057:34;7037:18;;;7030:62;7109:18;;2804:109:1;6951:182:10;2804:109:1;3015:4;3063:31;3015:4;3063:15;:31;:::i;:::-;-1:-1:-1;;;;;3025:70:1;:28;;;:70;3102:27;;:19;;;;:27;;3122:6;;;;3102:27;:::i;:::-;;;;;;;;;;;;;;;;;;:39;;;;;;;;-1:-1:-1;3102:39:1;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3102:39:1;;;-1:-1:-1;;;;;;3102:39:1;;;;;;;-1:-1:-1;;;;;;3102:39:1;;;;;;;;;;;;;;;;3135:5;;3102:39;;;;;;;;:::i;5030:525::-;5224:6;-1:-1:-1;;;;;5246:22:1;;5238:57;;;;-1:-1:-1;;;5238:57:1;;;;;;;:::i;:::-;5302:20;5331:63;5349:4;5355:11;;5331:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5368:25:1;;-1:-1:-1;5368:23:1;;-1:-1:-1;;5368:25:1:i;5331:63::-;:85;;;5302:114;;5435:115;5489:6;5505:12;5527:15;5435:44;:115::i;6291:411::-;6398:12;;:::i;:::-;-1:-1:-1;;;;;6424:28:1;;6420:91;;6469:35;6481:4;:22;;6469:35;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:11;:35::i;:::-;6462:42;;;;6420:91;-1:-1:-1;;;;;6538:34:1;;;6517:18;6538:34;;;;;;;;;;;6517:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:18;;:55;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6517:55:1;;;-1:-1:-1;;6517:55:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6517:55:1;;;;;;6593:12;;;;-1:-1:-1;6593:33:1;;;;;6609:5;:17;;;6593:33;6578:100;;;;-1:-1:-1;;;6578:100:1;;9600:2:10;6578:100:1;;;9582:21:10;9639:2;9619:18;;;9612:30;9678:34;9658:18;;;9651:62;-1:-1:-1;;;9729:18:10;;;9722:34;9773:19;;6578:100:1;9572:226:10;6578:100:1;6692:5;-1:-1:-1;6291:411:1;;;;;:::o;5559:592::-;-1:-1:-1;;;;;5799:49:1;;;5738:6;5799:49;;;;;;;;;;;:63;;;;;;;;;;;5752:110;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5752:110:1;;;;;;;;5738:6;;5752:110;5880:85;;-1:-1:-1;5917:31:1;;;;-1:-1:-1;;;;;5917:31:1;5909:56;;5880:85;5869:243;;;5995:31;;;;:110;;-1:-1:-1;;;5995:110:1;;-1:-1:-1;;;;;6349:15:10;;;5995:110:1;;;6331:34:10;6401:15;;;6381:18;;;6374:43;5995:31:1;;;;:58;;6266:18:10;;5995:110:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5980:125;;;;;5869:243;6125:21;;;;5559:592;-1:-1:-1;;;;5559:592:1:o;196:470:3:-;301:7;343:2;326:13;:19;;;;318:71;;;;-1:-1:-1;;;318:71:3;;10353:2:10;318:71:3;;;10335:21:10;10392:2;10372:18;;;10365:30;10431:34;10411:18;;;10404:62;-1:-1:-1;;;10482:18:10;;;10475:37;10529:19;;318:71:3;10325:229:10;318:71:3;504:1;488:13;:17;;;484:105;;;563:17;579:1;563:13;:17;:::i;:::-;549:32;;557:2;549:32;:::i;:::-;522:60;;-1:-1:-1;;;;;522:23:3;;:60;:::i;484:105::-;642:17;646:13;642:1;:17;:::i;:::-;628:32;;636:2;628:32;:::i;:::-;601:60;;-1:-1:-1;;;;;601:23:3;;:60;:::i;1326:782:2:-;-1:-1:-1;;;;;1460:21:2;;1456:648;;1508:43;;-1:-1:-1;;;;;1508:21:2;;;:43;;;;;1530:20;;1508:43;;;;1530:20;1508:21;:43;;;;;;;1491:99;;;;-1:-1:-1;;;1491:99:2;;10005:2:10;1491:99:2;;;9987:21:10;10044:2;10024:18;;;10017:30;-1:-1:-1;;;10063:18:10;;;10056:49;10122:18;;1491:99:2;9977:169:10;1456:648:2;1635:41;;-1:-1:-1;;;1635:41:2;;1611:21;;-1:-1:-1;;;;;1635:23:2;;;;;:41;;1659:16;;1635:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1793:62;;-1:-1:-1;;;1793:62:2;;-1:-1:-1;;;;;6032:32:10;;;1793:62:2;;;6014:51:10;6081:18;;;6074:34;;;1611:65:2;;-1:-1:-1;1793:22:2;;;;;;5987:18:10;;1793:62:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1887:41:2;;-1:-1:-1;;;1887:41:2;;1864:20;;-1:-1:-1;;;;;;1887:23:2;;;-1:-1:-1;1887:23:2;;:41;;1911:16;;1887:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1864:64;-1:-1:-1;1985:20:2;1953:28;1968:13;1864:64;1953:28;:::i;:::-;:52;1936:161;;;;-1:-1:-1;;;1936:161:2;;11811:2:10;1936:161:2;;;11793:21:10;11850:2;11830:18;;;11823:30;11889:34;11869:18;;;11862:62;11960:34;11940:18;;;11933:62;-1:-1:-1;;;12011:19:10;;;12004:39;12060:19;;1936:161:2;11783:302:10;1936:161:2;1456:648;;1326:782;;;:::o;7798:157:1:-;7856:6;7893:4;7911:39;7893:4;7918:15;7911:39;:::i;:::-;7904:46;;;7798:157;:::o;7066:714::-;7198:12;;:::i;:::-;7222:45;7236:4;:22;;7222:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7260:6;7222:13;:45::i;:::-;7218:108;;;7284:35;7296:4;:22;;7284:35;;;;;:::i;:::-;7277:42;;;;7218:108;7332:18;;:::i;:::-;7397:1;7360:4;:19;;7380:6;7360:27;;;;;;:::i;:::-;;;;;;;;;;;;;;:34;:38;7356:296;;;7413:7;7408:238;7430:4;:19;;7450:6;7430:27;;;;;;:::i;:::-;;;;;;;;;;;;;;:34;7426:38;;;;7408:238;;;7553:13;-1:-1:-1;;;;;7496:70:1;:4;:19;;7516:6;7496:27;;;;;;:::i;:::-;;;;;;;;;;;;;7524:1;7496:30;;;;;;;;-1:-1:-1;;;7496:30:1;;;;;;;;;;;;;;;;;;;;;;:53;;;;;;-1:-1:-1;;;;;7496:53:1;:70;7481:157;;7597:4;:19;;7617:6;7597:27;;;;;;:::i;:::-;;;;;;;;;;;;;7625:1;7597:30;;;;;;;;-1:-1:-1;;;7597:30:1;;;;;;;;;;;;;;;;;;7589:38;;;;;;;;7597:30;;;;;;;7589:38;;;;;;;;;-1:-1:-1;;;;;7589:38:1;;;;;;;;;;;;;;;;;;;7597:30;7589:38;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7589:38:1;;;-1:-1:-1;;7589:38:1;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7589:38:1;;;;;;;-1:-1:-1;7481:157:1;7466:3;;;;:::i;:::-;;;;7408:238;;;;7356:296;7672:12;;:33;;;;;7688:5;:17;;;7672:33;7657:99;;;;-1:-1:-1;;;7657:99:1;;8844:2:10;7657:99:1;;;8826:21:10;8883:2;8863:18;;;8856:30;8922:34;8902:18;;;8895:62;-1:-1:-1;;;8973:18:10;;;8966:33;9016:19;;7657:99:1;8816:225:10;8334:181:1;8425:4;8507:1;8490:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;8480:30;;;;;;8473:1;8456:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;8446:30;;;;;;:64;8439:71;;8334:181;;;;:::o;8061:179::-;8149:12;;:::i;:::-;-1:-1:-1;8178:57:1;;;;;;;;8184:4;8178:57;;;-1:-1:-1;8178:57:1;;;;;;;;;;;;;8223:2;8178:57;;;;;;;;;;;;;;;;8061:179::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;14:376:10;66:8;76:6;130:3;123:4;115:6;111:17;107:27;97:2;;155:8;145;138:26;97:2;-1:-1:-1;185:20:10;;-1:-1:-1;;;;;217:30:10;;214:2;;;267:8;257;250:26;214:2;311:4;303:6;299:17;287:29;;363:3;356:4;347:6;339;335:19;331:30;328:39;325:2;;;380:1;377;370:12;325:2;87:303;;;;;:::o;395:398::-;463:6;471;524:2;512:9;503:7;499:23;495:32;492:2;;;545:6;537;530:22;492:2;589:9;576:23;608:31;633:5;608:31;:::i;:::-;658:5;-1:-1:-1;715:2:10;700:18;;687:32;728:33;687:32;728:33;:::i;:::-;780:7;770:17;;;482:311;;;;;:::o;798:492::-;901:6;909;917;970:2;958:9;949:7;945:23;941:32;938:2;;;991:6;983;976:22;938:2;1035:9;1022:23;1054:31;1079:5;1054:31;:::i;:::-;1104:5;-1:-1:-1;1161:2:10;1146:18;;1133:32;1174:33;1133:32;1174:33;:::i;:::-;928:362;;1226:7;;-1:-1:-1;;;1280:2:10;1265:18;;;;1252:32;;928:362::o;1295:586::-;1432:6;1440;1448;1456;1509:3;1497:9;1488:7;1484:23;1480:33;1477:2;;;1531:6;1523;1516:22;1477:2;1572:9;1559:23;1549:33;;1632:2;1621:9;1617:18;1604:32;1645:31;1670:5;1645:31;:::i;:::-;1695:5;-1:-1:-1;1752:2:10;1737:18;;1724:32;1765:33;1724:32;1765:33;:::i;:::-;1467:414;;;;-1:-1:-1;1817:7:10;;1871:2;1856:18;1843:32;;-1:-1:-1;;1467:414:10:o;1886:754::-;2035:6;2043;2051;2059;2067;2120:3;2108:9;2099:7;2095:23;2091:33;2088:2;;;2142:6;2134;2127:22;2088:2;2183:9;2170:23;2160:33;;2243:2;2232:9;2228:18;2215:32;2256:31;2281:5;2256:31;:::i;:::-;2306:5;-1:-1:-1;2362:2:10;2347:18;;2334:32;-1:-1:-1;;;;;2378:30:10;;2375:2;;;2426:6;2418;2411:22;2375:2;2470:59;2521:7;2512:6;2501:9;2497:22;2470:59;:::i;:::-;2078:562;;;;-1:-1:-1;2548:8:10;2630:2;2615:18;2602:32;;2078:562;-1:-1:-1;;;;2078:562:10:o;2645:674::-;2774:6;2782;2790;2798;2851:2;2839:9;2830:7;2826:23;2822:32;2819:2;;;2872:6;2864;2857:22;2819:2;2913:9;2900:23;2890:33;;2973:2;2962:9;2958:18;2945:32;2986:31;3011:5;2986:31;:::i;:::-;3036:5;-1:-1:-1;3092:2:10;3077:18;;3064:32;-1:-1:-1;;;;;3108:30:10;;3105:2;;;3156:6;3148;3141:22;3105:2;3200:59;3251:7;3242:6;3231:9;3227:22;3200:59;:::i;:::-;2809:510;;;;-1:-1:-1;3278:8:10;-1:-1:-1;;;;2809:510:10:o;3324:850::-;3460:6;3468;3476;3484;3492;3545:3;3533:9;3524:7;3520:23;3516:33;3513:2;;;3567:6;3559;3552:22;3513:2;3608:9;3595:23;3585:33;;3668:2;3657:9;3653:18;3640:32;3681:31;3706:5;3681:31;:::i;:::-;3731:5;-1:-1:-1;3787:2:10;3772:18;;3759:32;-1:-1:-1;;;;;3803:30:10;;3800:2;;;3851:6;3843;3836:22;3800:2;3895:59;3946:7;3937:6;3926:9;3922:22;3895:59;:::i;:::-;3973:8;;-1:-1:-1;3869:85:10;-1:-1:-1;;4060:2:10;4045:18;;4032:32;4108:4;4095:18;;4083:31;;4073:2;;4133:6;4125;4118:22;4073:2;4161:7;4151:17;;;3503:671;;;;;;;;:::o;4179:194::-;4249:6;4302:2;4290:9;4281:7;4277:23;4273:32;4270:2;;;4323:6;4315;4308:22;4270:2;-1:-1:-1;4351:16:10;;4260:113;-1:-1:-1;4260:113:10:o;4378:308::-;4447:6;4500:2;4488:9;4479:7;4475:23;4471:32;4468:2;;;4521:6;4513;4506:22;4468:2;4552:16;;-1:-1:-1;;;;;4597:30:10;;4587:41;;4577:2;;4647:6;4639;4632:22;4691:275;4876:6;4868;4863:3;4850:33;4832:3;4902:16;;4927:15;;;4902:16;4840:126;-1:-1:-1;4840:126:10:o;4971:432::-;5102:3;5140:6;5134:13;5165:3;5177:129;5191:6;5188:1;5185:13;5177:129;;;5289:4;5273:14;;;5269:25;;5263:32;5250:11;;;5243:53;5206:12;5177:129;;;5324:6;5321:1;5318:13;5315:2;;;5359:3;5350:6;5345:3;5341:16;5334:29;5315:2;-1:-1:-1;5381:16:10;;;;;5110:293;-1:-1:-1;;5110:293:10:o;5408:203::-;-1:-1:-1;;;;;5572:32:10;;;;5554:51;;5542:2;5527:18;;5509:102::o;9046:347::-;9248:2;9230:21;;;9287:2;9267:18;;;9260:30;-1:-1:-1;;;9321:2:10;9306:18;;9299:53;9384:2;9369:18;;9220:173::o;10559:345::-;10761:2;10743:21;;;10800:2;10780:18;;;10773:30;-1:-1:-1;;;10834:2:10;10819:18;;10812:51;10895:2;10880:18;;10733:171::o;11258:346::-;11460:2;11442:21;;;11499:2;11479:18;;;11472:30;-1:-1:-1;;;11533:2:10;11518:18;;11511:52;11595:2;11580:18;;11432:172::o;12493:217::-;12533:1;12559;12549:2;;-1:-1:-1;;;12584:31:10;;12638:4;12635:1;12628:15;12666:4;12591:1;12656:15;12549:2;-1:-1:-1;12695:9:10;;12539:171::o;12715:422::-;12804:1;12847:5;12804:1;12861:270;12882:7;12872:8;12869:21;12861:270;;;12941:4;12937:1;12933:6;12929:17;12923:4;12920:27;12917:2;;;12950:18;;:::i;:::-;13000:7;12990:8;12986:22;12983:2;;;13020:16;;;;12983:2;13099:22;;;;13059:15;;;;12861:270;;;12865:3;12779:358;;;;;:::o;13142:140::-;13200:5;13229:47;13270:4;13260:8;13256:19;13250:4;13336:5;13366:8;13356:2;;-1:-1:-1;13407:1:10;13421:5;;13356:2;13455:4;13445:2;;-1:-1:-1;13492:1:10;13506:5;;13445:2;13537:4;13555:1;13550:59;;;;13623:1;13618:130;;;;13530:218;;13550:59;13580:1;13571:10;;13594:5;;;13618:130;13655:3;13645:8;13642:17;13639:2;;;13662:18;;:::i;:::-;-1:-1:-1;;13718:1:10;13704:16;;13733:5;;13530:218;;13832:2;13822:8;13819:16;13813:3;13807:4;13804:13;13800:36;13794:2;13784:8;13781:16;13776:2;13770:4;13767:12;13763:35;13760:77;13757:2;;;-1:-1:-1;13869:19:10;;;13901:5;;13757:2;13948:34;13973:8;13967:4;13948:34;:::i;:::-;14018:6;14014:1;14010:6;14006:19;13997:7;13994:32;13991:2;;;14029:18;;:::i;:::-;14067:20;;13346:747;-1:-1:-1;;;13346:747:10:o;14098:168::-;14138:7;14204:1;14200;14196:6;14192:14;14189:1;14186:21;14181:1;14174:9;14167:17;14163:45;14160:2;;;14211:18;;:::i;:::-;-1:-1:-1;14251:9:10;;14150:116::o;14271:270::-;14310:7;-1:-1:-1;;;;;14380:10:10;;;14410;;;14443:11;;14436:19;14465:12;;;14457:21;;14432:47;14429:2;;;14482:18;;:::i;:::-;14522:13;;14322:219;-1:-1:-1;;;;14322:219:10:o;14546:125::-;14586:4;14614:1;14611;14608:8;14605:2;;;14619:18;;:::i;:::-;-1:-1:-1;14656:9:10;;14595:76::o;14676:195::-;14714:4;14751;14748:1;14744:12;14783:4;14780:1;14776:12;14808:3;14803;14800:12;14797:2;;;14815:18;;:::i;:::-;14852:13;;;14723:148;-1:-1:-1;;;14723:148:10:o;14876:380::-;14955:1;14951:12;;;;14998;;;15019:2;;15073:4;15065:6;15061:17;15051:27;;15019:2;15126;15118:6;15115:14;15095:18;15092:38;15089:2;;;15172:10;15167:3;15163:20;15160:1;15153:31;15207:4;15204:1;15197:15;15235:4;15232:1;15225:15;15089:2;;14931:325;;;:::o;15261:175::-;15298:3;15342:4;15335:5;15331:16;15371:4;15362:7;15359:17;15356:2;;;15379:18;;:::i;:::-;15428:1;15415:15;;15306:130;-1:-1:-1;;15306:130:10:o;15441:127::-;15502:10;15497:3;15493:20;15490:1;15483:31;15533:4;15530:1;15523:15;15557:4;15554:1;15547:15;15573:131;-1:-1:-1;;;;;15648:31:10;;15638:42;;15628:2;;15694:1;15691;15684:12;15628:2;15618:86;:::o
Swarm Source
ipfs://ee5b1903c10e0f99d2fc9f5ab40339811d638c5ae50d0d43583de51a78c2e43e
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.