20M+ users trust MoonPay worldwide. Checkout with your preferred payment method.
Ready to onboard to Ethereum? With MetaMask Portfolio, you're in control.
Don’t invest unless you’re prepared to lose all the money you invest.
Everyday giveaways up to 100 ETH, Lucky Spins. Deposit BONUS 300% and Cashbacks!
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
Slots, Roulette, Poker & more - Proud sponsors of UFC, Everton & StakeF1 team!
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
Anonymous play on awesome games - sign up now for 25 free jackpot spins - worth $100s!
100s of games, generous bonuses, 20+ years of trusted gaming. Join CryptoWins & start winning today!
Overview
ETH Balance
Eth Value
$353.03 (@ $3,399.89/ETH)Token Holdings
Could not find any matches!
- ERC-20 Tokens (99)0 1INCH1INCH Token (1INCH)$0.00@0.36560 AAVEAave Token (AAVE)$0.00@179.660 ABYSSAbyss (ABYSS)$0.00@0.00620 ALEPHaleph.im v2 (ALEPH)$0.00@0.15463.13223933 AMPLAmpleforth (AMPL)$3.79@1.21362.00598434 FORTHAmpleforth G... (FORTH)$1,274.26@3.520 ANTAragon Netwo... (ANT)$0.00@1.564.85527274 BANDBandToken (BAND)$6.89@1.420 BLZBluzelle (BLZ)$0.00@0.13230 BTUBTU Protocol (BTU)$0.00@0.40351.62580484 BZRXbZx Protocol... (BZRX)$0.17@0.003222.26901532 LINKChainLink To... (LINK)$381.02@17.110 CNDCindicator (CND)$0.00@0.00030.00002968 CREAMCream (CREAM)$0.00@17.220 GENDAOstack (GEN)$0.00@0.000 MANADecentraland (MANA)$0.00@0.48920 DFMDeFi on MCW (DFM)$0.00@0.0020 ELFELF (ELF)$0.00@0.42570 ENJEnjinCoin (ENJ)$0.00@0.223620.42231969 LENDEthLend (LEND)$0.78@0.03840 IDEverest ID (ID)$0.00@0.03970 FUSEFuse Token (FUSE)$0.00@0.03220 GVTGenesis Visi... (GVT)101 HEXHEX (HEX)$0.32@0.00321 ISLAInsula (ISLA)$0.03@0.0290 KAIKardiaChain ... (KAI)$0.00@0.00230.00000281 KNCKyberNetwork (KNC)$0.00@0.5980 LOOMLoom (LOOM)$0.00@0.069320.95544787 LRCLoopringCoin... (LRC)$4.19@0.200.33499337 LQTYLQTY (LQTY)$0.42@1.26520 MLNMelon Token (MLN)$0.00@16.38220 OCEANOcean Token (OCEAN)$0.00@0.58210 OMGOMG Network (OMG)$0.00@0.33630 OGNOriginToken (OGN)$0.00@0.11430 PLRPILLAR (PLR)$0.00@0.00440 PNKPinakion (PNK)$0.00@0.01620.00000221 PNTpNetwork Tok... (PNT)$0.00@0.00480 POLYPolymath (POLY)$0.00@0.03633 eQUADQuadrantProt... (eQUAD)$0.01@0.00470 QNTQuant (QNT)$0.00@100.870 QKCQuarkChain T... (QKC)$0.00@0.01010 RAERAE Token (RAE)$0.00@0.85581.22878776 RENRepublic (REN)$0.06@0.04790 REPv2Reputation (REPv2)$0.00@0.62780 REQRequest (REQ)$0.00@0.10770 RSVReserve (RSV)0.01554508 RLCRLC (RLC)$0.03@1.950 SANDSAND (SAND)$0.00@0.39750 KEYSelfKey (KEY)$0.00@0.00350 STSimple Token (ST)$0.00@0.00020 MFGSmart MFG (MFG)$0.00@0.0010.3 EURSSTASIS EURS ... (EURS)$0.32@1.0540.04009052 SUSHISushiToken (SUSHI)$0.04@0.94960 SWRVSwerve DAO T... (SWRV)$0.00@0.00930.0043894 sUSDSynth sUSD (sUSD)$0.00@1.0040.28811237 SNXSynthetix Ne... (SNX)$0.57@1.991.11379365 UBTUniBright (UBT)$0.05@0.04870.05549271 UNIUniswap (UNI)$0.59@10.630.0000191 YFIyearn.financ... (YFI)$0.13@6,866.180.32068746 YFVYFValue (YFV)$0.01@0.0250 ZRXZRX (ZRX)$0.00@0.46560 BNTBancor (BNT)$0.00@0.67290.07072762 BATBAT (BAT)$0.02@0.24460 BUSDBUSD (BUSD)$0.00@0.99590.00007538 COMPCompound (COMP)$0.00@62.880.00444896 CRVCurve DAO To... (CRV)$0.00@0.4815118.37387949 DAIDai Stableco... (DAI)$118.33@0.99970 GNOGnosis (GNO)$0.00@272.260 KNCKyber Networ... (KNC)$0.00@0.59170 MKRMaker (MKR)$0.00@1,634.330 MATICMatic Token (MATIC)$0.00@0.54530 USDPPax Dollar (USDP)$0.00@1.0010 SNTStatusNetwor... (SNT)$0.00@0.0460 PAYTenXPay (PAY)$0.00@0.00816.452732 USDTTether USD (USDT)$6.46@1.0010 TUSDTrueUSD (TUSD)$0.00@1.00113.780402 USDCUSDC (USDC)$113.75@0.99970.00008923 WBTCWrapped BTC (WBTC)$8.75@98,069.000.06858784 ANTAragon0 BAMBamboo (BAM)0 GDCGlobal Digital Content$0.00@0.000 KAIKardiaChain Token0 METMetronome0.00052391 REPReputation$0.00@0.62780 RSRReserve Rights0 STMXStormX0 2KEYTwoKeyEconomy0 VIDTV-ID Token0 VALORValorToken$0.00@0.105599,999ERC20 ***0 MYBMyBit$0.00@0.00020 VIDTVIDT Datalink245.44 TokenERC-20 TOKEN*[Suspicious]4,999 TokenERC-20 TOKEN*[Suspicious]0.7 TokenERC-20 TOKEN*[Suspicious]777 TokenERC-20 TOKEN*[Suspicious]132.84 TokenERC-20 TOKEN*[Spam]856,420,144,564 TokenERC-20 TOKEN*[Spam]856,420,144,564 TokenERC-20 TOKEN*[Spam]NFT Tokens (19)claim rewards on clinkevent.comclinkevent.comERC-1155claim rewards qntnetwork.orgqntnetwork.orgERC-1155claim rewards on snxtoken.comsnxtoken.comERC-1155claim rewards on wrappedbtc.netwrappedbtc.netERC-1155ERC-1155 TOKEN*[Suspicious]ERC-1155 TOKEN*[Spam]ERC-1155 TOKEN*[Spam]ERC-1155 TOKEN*[Spam]ERC-1155 TOKEN*[Spam]ERC-1155 TOKEN*[Spam]ERC-1155 TOKEN*[Spam]
More Info
Private Name Tags
ContractCreator
Multichain Info
1 address found via- Transactions
- Internal Transactions
- Token Transfers (ERC-20)
- NFT Transfers
- Contract
- Events
- Analytics
- Multichain Portfolio
Advanced Filter- Filter by Tx Type:
- Tx
- Internal Tx
- ERC-20
- NFTs
Latest 13 from a total of 13 transactions
Transaction Hash MethodBlockFromToTransfer 10499595 2020-07-21 0:23:39 1586 days ago 1595291019 IN 0.0845809 ETH$287.57 0.00098986 44 Transfer Admin 10418702 2020-07-08 11:54:05 1598 days ago 1594209245 IN 0 ETH$0.00 0.00307236 69 Set Enable 10410610 2020-07-07 6:18:41 1600 days ago 1594102721 IN 0 ETH$0.00 0.00252246 51 Set Enable 10405889 2020-07-06 12:18:40 1600 days ago 1594037920 IN 0 ETH$0.00 0.00058496 40 Set Enable 10404453 2020-07-06 7:07:54 1601 days ago 1594019274 IN 0 ETH$0.00 0.00202786 41 Get And Update N... 10404144 2020-07-06 6:00:33 1601 days ago 1594015233 IN 0 ETH$0.00 0.0011478 31.47 Transfer Admin Q... 10403556 2020-07-06 3:51:32 1601 days ago 1594007492 IN 0 ETH$0.00 0.00085735 27 Set Params 10403551 2020-07-06 3:49:19 1601 days ago 1594007359 IN 0 ETH$0.00 0.00103158 27 Add Kyber Proxy 10403272 2020-07-06 2:50:49 1601 days ago 1594003849 IN 0 ETH$0.00 0.00191705 25 Add Kyber Proxy 10403272 2020-07-06 2:50:49 1601 days ago 1594003849 IN 0 ETH$0.00 0.00229205 25 Set Kyber Dao Co... 10403272 2020-07-06 2:50:49 1601 days ago 1594003849 IN 0 ETH$0.00 0.0023737 25 Set Contracts 10403272 2020-07-06 2:50:49 1601 days ago 1594003849 IN 0 ETH$0.00 0.0037368 25 0x60806040 10403236 2020-07-06 2:41:15 1601 days ago 1594003275 IN 0 ETH$0.00 0.1366602 25 Latest 25 internal transactions (View All)
Advanced mode:Parent Transaction Hash Block From To 21249212 2024-11-23 8:21:59 8 mins ago 1732350119 0.00150608 ETH$5.12 21249212 2024-11-23 8:21:59 8 mins ago 1732350119 1.50457766 ETH$5,115.40 21249212 2024-11-23 8:21:59 8 mins ago 1732350119 1.50608375 ETH$5,120.52 21249191 2024-11-23 8:17:47 12 mins ago 1732349867 0.00099307 ETH$3.38 21249191 2024-11-23 8:17:47 12 mins ago 1732349867 0.99208417 ETH$3,372.98 21249191 2024-11-23 8:17:47 12 mins ago 1732349867 0.99307725 ETH$3,376.35 21249163 2024-11-23 8:12:11 18 mins ago 1732349531 0.0013617 ETH$4.63 21249163 2024-11-23 8:12:11 18 mins ago 1732349531 1.36034266 ETH$4,625.01 21249163 2024-11-23 8:12:11 18 mins ago 1732349531 1.36170436 ETH$4,629.64 21249086 2024-11-23 7:56:47 33 mins ago 1732348607 0.00102356 ETH$3.48 21249086 2024-11-23 7:56:47 33 mins ago 1732348607 1.0225435 ETH$3,476.53 21249086 2024-11-23 7:56:47 33 mins ago 1732348607 1.02356707 ETH$3,480.01 21247886 2024-11-23 3:55:47 4 hrs ago 1732334147 0.00079849 ETH$2.71 21247886 2024-11-23 3:55:47 4 hrs ago 1732334147 0.79769376 ETH$2,712.07 21247886 2024-11-23 3:55:47 4 hrs ago 1732334147 0.79849225 ETH$2,714.78 21247576 2024-11-23 2:53:35 5 hrs ago 1732330415 0.00093599 ETH$3.18 21247576 2024-11-23 2:53:35 5 hrs ago 1732330415 0.93505957 ETH$3,179.10 21247576 2024-11-23 2:53:35 5 hrs ago 1732330415 0.93599556 ETH$3,182.28 21247273 2024-11-23 1:52:47 6 hrs ago 1732326767 0.00082898 ETH$2.82 21247273 2024-11-23 1:52:47 6 hrs ago 1732326767 0.82815309 ETH$2,815.63 21247273 2024-11-23 1:52:47 6 hrs ago 1732326767 0.82898207 ETH$2,818.45 21247237 2024-11-23 1:45:35 6 hrs ago 1732326335 0.0010496 ETH$3.57 21247237 2024-11-23 1:45:35 6 hrs ago 1732326335 1.04855888 ETH$3,564.98 21247237 2024-11-23 1:45:35 6 hrs ago 1732326335 1.04960849 ETH$3,568.55 21247120 2024-11-23 1:22:11 7 hrs ago 1732324931 0.00102356 ETH$3.48 Loading...LoadingSimilar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x9CB7bB6D...61Cc9A794The constructor portion of the code might be different and could alter the actual behaviour of the contractContract Name:KyberNetwork
Compiler Versionv0.6.6+commit.6c089d02
Contract Source Code (Solidity)
- interface IERC20
- - function approve(address _spender, ui ...
- - function transfer(address _to, uint25 ...
- - function transferFrom(
- - function allowance(address _owner, ad ...
- - function balanceOf(address _owner)
- - function decimals()
- - function totalSupply()
- contract PermissionGroupsNoModifie ...
- - function getOperators()
- - function getAlerters()
- - function addAlerter(address newAlerte ...
- - function addOperator(address newOpera ...
- - function claimAdmin()
- - function removeAlerter(address alerte ...
- - function removeOperator(address opera ...
- - function transferAdmin(address newAdm ...
- - function transferAdminQuickly(address ...
- - function onlyAdmin()
- - function onlyAlerter()
- - function onlyOperator()
- contract WithdrawableNoModifiers i ...
- - function withdrawEther(uint256 amount ...
- - function withdrawToken(
- contract Utils5
- - function getUpdateDecimals(IERC20 tok ...
- - function setDecimals(IERC20 token)
- - function getBalance(IERC20 token, add ...
- - function getDecimals(IERC20 token)
- - function calcDestAmount(
- - function calcSrcAmount(
- - function calcDstQty(
- - function calcSrcQty(
- - function calcRateFromQty(
- - function minOf(uint256 x, uint256 y)
- contract ReentrancyGuard
- library SafeMath
- - function add(uint256 a, uint256 b)
- - function sub(uint256 a, uint256 b)
- - function sub(uint256 a, uint256 b, st ...
- - function mul(uint256 a, uint256 b)
- - function div(uint256 a, uint256 b)
- - function div(uint256 a, uint256 b, st ...
- - function mod(uint256 a, uint256 b)
- - function mod(uint256 a, uint256 b, st ...
- - function min(uint256 a, uint256 b)
- library Address
- - function isContract(address account)
- - function sendValue(address payable re ...
- library SafeERC20
- - function safeTransfer(IERC20 token, a ...
- - function safeTransferFrom(IERC20 toke ...
- - function safeApprove(IERC20 token, ad ...
- - function safeIncreaseAllowance(IERC20 ...
- - function safeDecreaseAllowance(IERC20 ...
- - function _callOptionalReturn(IERC20 t ...
- interface IKyberNetwork
- - function tradeWithHintAndFee(
- - function listTokenForReserve(
- - function enabled()
- - function getExpectedRateWithHintAndFe ...
- - function getNetworkData()
- - function maxGasPrice()
- interface IKyberReserve
- - function trade(
- - function getConversionRate(
- interface IKyberFeeHandler
- - function handleFees(
- - function claimReserveRebate(address r ...
- - function claimPlatformFee(address pla ...
- - function claimStakerReward(
- interface IEpochUtils
- - function epochPeriodInSeconds()
- - function firstEpochStartTimestamp()
- - function getCurrentEpochNumber()
- - function getEpochNumber(uint256 times ...
- interface IKyberDao is IEpochUtils
- - function getLatestNetworkFeeDataWithC ...
- - function getLatestBRRDataWithCache()
- - function handleWithdrawal(address sta ...
- - function vote(uint256 campaignID, uin ...
- - function getLatestNetworkFeeData()
- - function shouldBurnRewardForEpoch(uin ...
- - function getPastEpochRewardPercentage ...
- - function getCurrentEpochRewardPercent ...
- interface IKyberNetworkProxy
- - function tradeWithHint(
- - function tradeWithHintAndFee(
- - function trade(
- - function getExpectedRate(
- - function getExpectedRateAfterFee(
- interface IKyberStorage
- - function addKyberProxy(address kyberP ...
- - function removeKyberProxy(address kyb ...
- - function setContracts(address _kyberF ...
- - function setKyberDaoContract(address ...
- - function getReserveId(address reserve ...
- - function getReserveIdsFromAddresses(a ...
- - function getReserveAddressesFromIds(b ...
- - function getReserveIdsPerTokenSrc(IER ...
- - function getReserveAddressesPerTokenS ...
- - function getReserveIdsPerTokenDest(IE ...
- - function getReserveAddressesByReserve ...
- - function getRebateWalletsFromIds(byte ...
- - function getKyberProxies()
- - function getReserveDetailsByAddress(a ...
- - function getReserveDetailsById(bytes3 ...
- - function getFeeAccountedData(bytes32[ ...
- - function getEntitledRebateData(bytes3 ...
- - function getReservesData(bytes32[] ca ...
- - function isKyberProxyAdded()
- interface IKyberMatchingEngine
- - function setNegligibleRateDiffBps(uin ...
- - function setKyberStorage(IKyberStorag ...
- - function getNegligibleRateDiffBps()
- - function getTradingReserves(
- - function doMatch(
- interface IGasHelper
- - function freeGas(
- contract KyberNetwork is Withdrawa ... *
- - function tradeWithHint(
- - function tradeWithHintAndFee(
- - function listTokenForReserve(
- - function listReservesForToken(
- - function setContracts(
- - function setKyberDaoContract(IKyberDa ...
- - function setParams(uint256 _maxGasPri ...
- - function setEnable(bool enable)
- - function addKyberProxy(address kyberP ...
- - function removeKyberProxy(address kyb ...
- - function getExpectedRateWithHintAndFe ...
- - function getExpectedRate(
- - function getNetworkData()
- - function getContracts()
- - function maxGasPrice()
- - function enabled()
- - function getAndUpdateNetworkFee()
- - function handleFees(TradeData memory ...
- - function updateNetworkFee(uint256 exp ...
- - function doReserveTrades(
- - function tradeAndVerifyNetworkBalance ...
- - function trade(TradeData memory trade ...
- - function handleChange(
- - function initTradeInput(
- - function calcRatesAndAmounts(TradeDat ...
- - function calcDestQtyAndMatchReserves(
- - function calcSrcAmountsAndGetRates(
- - function calculateRebates(TradeData m ...
- - function createRebateEntitledList(
- - function validateTradeInput(TradeInpu ...
- - function getNetworkFee()
- - function readNetworkFeeData()
- - function validateFeeInput(TradeInput ...
- - function updateReservesList(ReservesD ...
- - function validateTradeCalcDestQtyAndF ...
- - function calcTradeSrcAmountFromDest(T ...
- - function calcTradeSrcAmount(
/** *Submitted for verification at Etherscan.io on 2020-07-02 */ // File: contracts/sol6/IERC20.sol pragma solidity 0.6.6; interface IERC20 { event Approval(address indexed _owner, address indexed _spender, uint256 _value); function approve(address _spender, uint256 _value) external returns (bool success); function transfer(address _to, uint256 _value) external returns (bool success); function transferFrom( address _from, address _to, uint256 _value ) external returns (bool success); function allowance(address _owner, address _spender) external view returns (uint256 remaining); function balanceOf(address _owner) external view returns (uint256 balance); function decimals() external view returns (uint8 digits); function totalSupply() external view returns (uint256 supply); } // to support backward compatible contract name -- so function signature remains same abstract contract ERC20 is IERC20 { } // File: contracts/sol6/utils/PermissionGroupsNoModifiers.sol pragma solidity 0.6.6; contract PermissionGroupsNoModifiers { address public admin; address public pendingAdmin; mapping(address => bool) internal operators; mapping(address => bool) internal alerters; address[] internal operatorsGroup; address[] internal alertersGroup; uint256 internal constant MAX_GROUP_SIZE = 50; event AdminClaimed(address newAdmin, address previousAdmin); event AlerterAdded(address newAlerter, bool isAdd); event OperatorAdded(address newOperator, bool isAdd); event TransferAdminPending(address pendingAdmin); constructor(address _admin) public { require(_admin != address(0), "admin 0"); admin = _admin; } function getOperators() external view returns (address[] memory) { return operatorsGroup; } function getAlerters() external view returns (address[] memory) { return alertersGroup; } function addAlerter(address newAlerter) public { onlyAdmin(); require(!alerters[newAlerter], "alerter exists"); // prevent duplicates. require(alertersGroup.length < MAX_GROUP_SIZE, "max alerters"); emit AlerterAdded(newAlerter, true); alerters[newAlerter] = true; alertersGroup.push(newAlerter); } function addOperator(address newOperator) public { onlyAdmin(); require(!operators[newOperator], "operator exists"); // prevent duplicates. require(operatorsGroup.length < MAX_GROUP_SIZE, "max operators"); emit OperatorAdded(newOperator, true); operators[newOperator] = true; operatorsGroup.push(newOperator); } /// @dev Allows the pendingAdmin address to finalize the change admin process. function claimAdmin() public { require(pendingAdmin == msg.sender, "not pending"); emit AdminClaimed(pendingAdmin, admin); admin = pendingAdmin; pendingAdmin = address(0); } function removeAlerter(address alerter) public { onlyAdmin(); require(alerters[alerter], "not alerter"); delete alerters[alerter]; for (uint256 i = 0; i < alertersGroup.length; ++i) { if (alertersGroup[i] == alerter) { alertersGroup[i] = alertersGroup[alertersGroup.length - 1]; alertersGroup.pop(); emit AlerterAdded(alerter, false); break; } } } function removeOperator(address operator) public { onlyAdmin(); require(operators[operator], "not operator"); delete operators[operator]; for (uint256 i = 0; i < operatorsGroup.length; ++i) { if (operatorsGroup[i] == operator) { operatorsGroup[i] = operatorsGroup[operatorsGroup.length - 1]; operatorsGroup.pop(); emit OperatorAdded(operator, false); break; } } } /// @dev Allows the current admin to set the pendingAdmin address /// @param newAdmin The address to transfer ownership to function transferAdmin(address newAdmin) public { onlyAdmin(); require(newAdmin != address(0), "new admin 0"); emit TransferAdminPending(newAdmin); pendingAdmin = newAdmin; } /// @dev Allows the current admin to set the admin in one tx. Useful initial deployment. /// @param newAdmin The address to transfer ownership to. function transferAdminQuickly(address newAdmin) public { onlyAdmin(); require(newAdmin != address(0), "admin 0"); emit TransferAdminPending(newAdmin); emit AdminClaimed(newAdmin, admin); admin = newAdmin; } function onlyAdmin() internal view { require(msg.sender == admin, "only admin"); } function onlyAlerter() internal view { require(alerters[msg.sender], "only alerter"); } function onlyOperator() internal view { require(operators[msg.sender], "only operator"); } } // File: contracts/sol6/utils/WithdrawableNoModifiers.sol pragma solidity 0.6.6; contract WithdrawableNoModifiers is PermissionGroupsNoModifiers { constructor(address _admin) public PermissionGroupsNoModifiers(_admin) {} event EtherWithdraw(uint256 amount, address sendTo); event TokenWithdraw(IERC20 token, uint256 amount, address sendTo); /// @dev Withdraw Ethers function withdrawEther(uint256 amount, address payable sendTo) external { onlyAdmin(); (bool success, ) = sendTo.call{value: amount}(""); require(success); emit EtherWithdraw(amount, sendTo); } /// @dev Withdraw all IERC20 compatible tokens /// @param token IERC20 The address of the token contract function withdrawToken( IERC20 token, uint256 amount, address sendTo ) external { onlyAdmin(); token.transfer(sendTo, amount); emit TokenWithdraw(token, amount, sendTo); } } // File: contracts/sol6/utils/Utils5.sol pragma solidity 0.6.6; /** * @title Kyber utility file * mostly shared constants and rate calculation helpers * inherited by most of kyber contracts. * previous utils implementations are for previous solidity versions. */ contract Utils5 { IERC20 internal constant ETH_TOKEN_ADDRESS = IERC20( 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ); uint256 internal constant PRECISION = (10**18); uint256 internal constant MAX_QTY = (10**28); // 10B tokens uint256 internal constant MAX_RATE = (PRECISION * 10**7); // up to 10M tokens per eth uint256 internal constant MAX_DECIMALS = 18; uint256 internal constant ETH_DECIMALS = 18; uint256 constant BPS = 10000; // Basic Price Steps. 1 step = 0.01% uint256 internal constant MAX_ALLOWANCE = uint256(-1); // token.approve inifinite mapping(IERC20 => uint256) internal decimals; function getUpdateDecimals(IERC20 token) internal returns (uint256) { if (token == ETH_TOKEN_ADDRESS) return ETH_DECIMALS; // save storage access uint256 tokenDecimals = decimals[token]; // moreover, very possible that old tokens have decimals 0 // these tokens will just have higher gas fees. if (tokenDecimals == 0) { tokenDecimals = token.decimals(); decimals[token] = tokenDecimals; } return tokenDecimals; } function setDecimals(IERC20 token) internal { if (decimals[token] != 0) return; //already set if (token == ETH_TOKEN_ADDRESS) { decimals[token] = ETH_DECIMALS; } else { decimals[token] = token.decimals(); } } /// @dev get the balance of a user. /// @param token The token type /// @return The balance function getBalance(IERC20 token, address user) internal view returns (uint256) { if (token == ETH_TOKEN_ADDRESS) { return user.balance; } else { return token.balanceOf(user); } } function getDecimals(IERC20 token) internal view returns (uint256) { if (token == ETH_TOKEN_ADDRESS) return ETH_DECIMALS; // save storage access uint256 tokenDecimals = decimals[token]; // moreover, very possible that old tokens have decimals 0 // these tokens will just have higher gas fees. if (tokenDecimals == 0) return token.decimals(); return tokenDecimals; } function calcDestAmount( IERC20 src, IERC20 dest, uint256 srcAmount, uint256 rate ) internal view returns (uint256) { return calcDstQty(srcAmount, getDecimals(src), getDecimals(dest), rate); } function calcSrcAmount( IERC20 src, IERC20 dest, uint256 destAmount, uint256 rate ) internal view returns (uint256) { return calcSrcQty(destAmount, getDecimals(src), getDecimals(dest), rate); } function calcDstQty( uint256 srcQty, uint256 srcDecimals, uint256 dstDecimals, uint256 rate ) internal pure returns (uint256) { require(srcQty <= MAX_QTY, "srcQty > MAX_QTY"); require(rate <= MAX_RATE, "rate > MAX_RATE"); if (dstDecimals >= srcDecimals) { require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS"); return (srcQty * rate * (10**(dstDecimals - srcDecimals))) / PRECISION; } else { require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS"); return (srcQty * rate) / (PRECISION * (10**(srcDecimals - dstDecimals))); } } function calcSrcQty( uint256 dstQty, uint256 srcDecimals, uint256 dstDecimals, uint256 rate ) internal pure returns (uint256) { require(dstQty <= MAX_QTY, "dstQty > MAX_QTY"); require(rate <= MAX_RATE, "rate > MAX_RATE"); //source quantity is rounded up. to avoid dest quantity being too low. uint256 numerator; uint256 denominator; if (srcDecimals >= dstDecimals) { require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS"); numerator = (PRECISION * dstQty * (10**(srcDecimals - dstDecimals))); denominator = rate; } else { require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS"); numerator = (PRECISION * dstQty); denominator = (rate * (10**(dstDecimals - srcDecimals))); } return (numerator + denominator - 1) / denominator; //avoid rounding down errors } function calcRateFromQty( uint256 srcAmount, uint256 destAmount, uint256 srcDecimals, uint256 dstDecimals ) internal pure returns (uint256) { require(srcAmount <= MAX_QTY, "srcAmount > MAX_QTY"); require(destAmount <= MAX_QTY, "destAmount > MAX_QTY"); if (dstDecimals >= srcDecimals) { require((dstDecimals - srcDecimals) <= MAX_DECIMALS, "dst - src > MAX_DECIMALS"); return ((destAmount * PRECISION) / ((10**(dstDecimals - srcDecimals)) * srcAmount)); } else { require((srcDecimals - dstDecimals) <= MAX_DECIMALS, "src - dst > MAX_DECIMALS"); return ((destAmount * PRECISION * (10**(srcDecimals - dstDecimals))) / srcAmount); } } function minOf(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? y : x; } } // File: contracts/sol6/utils/zeppelin/ReentrancyGuard.sol pragma solidity 0.6.6; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ contract ReentrancyGuard { bool private _notEntered; constructor () internal { // Storing an initial non-zero value makes deployment a bit more // expensive, but in exchange the refund on every call to nonReentrant // will be lower in amount. Since refunds are capped to a percetange of // the total transaction's gas, it is best to keep them low in cases // like this one, to increase the likelihood of the full refund coming // into effect. _notEntered = true; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } } // File: contracts/sol6/utils/zeppelin/SafeMath.sol pragma solidity 0.6.6; /** * @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) { // Solidity only automatically asserts when dividing by 0 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; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } } // File: contracts/sol6/utils/zeppelin/Address.sol pragma solidity 0.6.6; /** * @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) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @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"); } } // File: contracts/sol6/utils/zeppelin/SafeERC20.sol pragma solidity 0.6.6; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/sol6/IKyberNetwork.sol pragma solidity 0.6.6; interface IKyberNetwork { event KyberTrade( IERC20 indexed src, IERC20 indexed dest, uint256 ethWeiValue, uint256 networkFeeWei, uint256 customPlatformFeeWei, bytes32[] t2eIds, bytes32[] e2tIds, uint256[] t2eSrcAmounts, uint256[] e2tSrcAmounts, uint256[] t2eRates, uint256[] e2tRates ); function tradeWithHintAndFee( address payable trader, IERC20 src, uint256 srcAmount, IERC20 dest, address payable destAddress, uint256 maxDestAmount, uint256 minConversionRate, address payable platformWallet, uint256 platformFeeBps, bytes calldata hint ) external payable returns (uint256 destAmount); function listTokenForReserve( address reserve, IERC20 token, bool add ) external; function enabled() external view returns (bool); function getExpectedRateWithHintAndFee( IERC20 src, IERC20 dest, uint256 srcQty, uint256 platformFeeBps, bytes calldata hint ) external view returns ( uint256 expectedRateAfterNetworkFee, uint256 expectedRateAfterAllFees ); function getNetworkData() external view returns ( uint256 negligibleDiffBps, uint256 networkFeeBps, uint256 expiryTimestamp ); function maxGasPrice() external view returns (uint256); } // File: contracts/sol6/IKyberReserve.sol pragma solidity 0.6.6; interface IKyberReserve { function trade( IERC20 srcToken, uint256 srcAmount, IERC20 destToken, address payable destAddress, uint256 conversionRate, bool validate ) external payable returns (bool); function getConversionRate( IERC20 src, IERC20 dest, uint256 srcQty, uint256 blockNumber ) external view returns (uint256); } // File: contracts/sol6/IKyberFeeHandler.sol pragma solidity 0.6.6; interface IKyberFeeHandler { event RewardPaid(address indexed staker, uint256 indexed epoch, IERC20 indexed token, uint256 amount); event RebatePaid(address indexed rebateWallet, IERC20 indexed token, uint256 amount); event PlatformFeePaid(address indexed platformWallet, IERC20 indexed token, uint256 amount); event KncBurned(uint256 kncTWei, IERC20 indexed token, uint256 amount); function handleFees( IERC20 token, address[] calldata eligibleWallets, uint256[] calldata rebatePercentages, address platformWallet, uint256 platformFee, uint256 networkFee ) external payable; function claimReserveRebate(address rebateWallet) external returns (uint256); function claimPlatformFee(address platformWallet) external returns (uint256); function claimStakerReward( address staker, uint256 epoch ) external returns(uint amount); } // File: contracts/sol6/Dao/IEpochUtils.sol pragma solidity 0.6.6; interface IEpochUtils { function epochPeriodInSeconds() external view returns (uint256); function firstEpochStartTimestamp() external view returns (uint256); function getCurrentEpochNumber() external view returns (uint256); function getEpochNumber(uint256 timestamp) external view returns (uint256); } // File: contracts/sol6/IKyberDao.sol pragma solidity 0.6.6; interface IKyberDao is IEpochUtils { event Voted(address indexed staker, uint indexed epoch, uint indexed campaignID, uint option); function getLatestNetworkFeeDataWithCache() external returns (uint256 feeInBps, uint256 expiryTimestamp); function getLatestBRRDataWithCache() external returns ( uint256 burnInBps, uint256 rewardInBps, uint256 rebateInBps, uint256 epoch, uint256 expiryTimestamp ); function handleWithdrawal(address staker, uint256 penaltyAmount) external; function vote(uint256 campaignID, uint256 option) external; function getLatestNetworkFeeData() external view returns (uint256 feeInBps, uint256 expiryTimestamp); function shouldBurnRewardForEpoch(uint256 epoch) external view returns (bool); /** * @dev return staker's reward percentage in precision for a past epoch only * fee handler should call this function when a staker wants to claim reward * return 0 if staker has no votes or stakes */ function getPastEpochRewardPercentageInPrecision(address staker, uint256 epoch) external view returns (uint256); /** * @dev return staker's reward percentage in precision for the current epoch * reward percentage is not finalized until the current epoch is ended */ function getCurrentEpochRewardPercentageInPrecision(address staker) external view returns (uint256); } // File: contracts/sol6/IKyberNetworkProxy.sol pragma solidity 0.6.6; interface IKyberNetworkProxy { event ExecuteTrade( address indexed trader, IERC20 src, IERC20 dest, address destAddress, uint256 actualSrcAmount, uint256 actualDestAmount, address platformWallet, uint256 platformFeeBps ); /// @notice backward compatible function tradeWithHint( ERC20 src, uint256 srcAmount, ERC20 dest, address payable destAddress, uint256 maxDestAmount, uint256 minConversionRate, address payable walletId, bytes calldata hint ) external payable returns (uint256); function tradeWithHintAndFee( IERC20 src, uint256 srcAmount, IERC20 dest, address payable destAddress, uint256 maxDestAmount, uint256 minConversionRate, address payable platformWallet, uint256 platformFeeBps, bytes calldata hint ) external payable returns (uint256 destAmount); function trade( IERC20 src, uint256 srcAmount, IERC20 dest, address payable destAddress, uint256 maxDestAmount, uint256 minConversionRate, address payable platformWallet ) external payable returns (uint256); /// @notice backward compatible /// @notice Rate units (10 ** 18) => destQty (twei) / srcQty (twei) * 10 ** 18 function getExpectedRate( ERC20 src, ERC20 dest, uint256 srcQty ) external view returns (uint256 expectedRate, uint256 worstRate); function getExpectedRateAfterFee( IERC20 src, IERC20 dest, uint256 srcQty, uint256 platformFeeBps, bytes calldata hint ) external view returns (uint256 expectedRate); } // File: contracts/sol6/IKyberStorage.sol pragma solidity 0.6.6; interface IKyberStorage { enum ReserveType {NONE, FPR, APR, BRIDGE, UTILITY, CUSTOM, ORDERBOOK, LAST} function addKyberProxy(address kyberProxy, uint256 maxApprovedProxies) external; function removeKyberProxy(address kyberProxy) external; function setContracts(address _kyberFeeHandler, address _kyberMatchingEngine) external; function setKyberDaoContract(address _kyberDao) external; function getReserveId(address reserve) external view returns (bytes32 reserveId); function getReserveIdsFromAddresses(address[] calldata reserveAddresses) external view returns (bytes32[] memory reserveIds); function getReserveAddressesFromIds(bytes32[] calldata reserveIds) external view returns (address[] memory reserveAddresses); function getReserveIdsPerTokenSrc(IERC20 token) external view returns (bytes32[] memory reserveIds); function getReserveAddressesPerTokenSrc(IERC20 token, uint256 startIndex, uint256 endIndex) external view returns (address[] memory reserveAddresses); function getReserveIdsPerTokenDest(IERC20 token) external view returns (bytes32[] memory reserveIds); function getReserveAddressesByReserveId(bytes32 reserveId) external view returns (address[] memory reserveAddresses); function getRebateWalletsFromIds(bytes32[] calldata reserveIds) external view returns (address[] memory rebateWallets); function getKyberProxies() external view returns (IKyberNetworkProxy[] memory); function getReserveDetailsByAddress(address reserve) external view returns ( bytes32 reserveId, address rebateWallet, ReserveType resType, bool isFeeAccountedFlag, bool isEntitledRebateFlag ); function getReserveDetailsById(bytes32 reserveId) external view returns ( address reserveAddress, address rebateWallet, ReserveType resType, bool isFeeAccountedFlag, bool isEntitledRebateFlag ); function getFeeAccountedData(bytes32[] calldata reserveIds) external view returns (bool[] memory feeAccountedArr); function getEntitledRebateData(bytes32[] calldata reserveIds) external view returns (bool[] memory entitledRebateArr); function getReservesData(bytes32[] calldata reserveIds, IERC20 src, IERC20 dest) external view returns ( bool areAllReservesListed, bool[] memory feeAccountedArr, bool[] memory entitledRebateArr, IKyberReserve[] memory reserveAddresses); function isKyberProxyAdded() external view returns (bool); } // File: contracts/sol6/IKyberMatchingEngine.sol pragma solidity 0.6.6; interface IKyberMatchingEngine { enum ProcessWithRate {NotRequired, Required} function setNegligibleRateDiffBps(uint256 _negligibleRateDiffBps) external; function setKyberStorage(IKyberStorage _kyberStorage) external; function getNegligibleRateDiffBps() external view returns (uint256); function getTradingReserves( IERC20 src, IERC20 dest, bool isTokenToToken, bytes calldata hint ) external view returns ( bytes32[] memory reserveIds, uint256[] memory splitValuesBps, ProcessWithRate processWithRate ); function doMatch( IERC20 src, IERC20 dest, uint256[] calldata srcAmounts, uint256[] calldata feesAccountedDestBps, uint256[] calldata rates ) external view returns (uint256[] memory reserveIndexes); } // File: contracts/sol6/IGasHelper.sol pragma solidity 0.6.6; interface IGasHelper { function freeGas( address platformWallet, IERC20 src, IERC20 dest, uint256 tradeWei, bytes32[] calldata t2eReserveIds, bytes32[] calldata e2tReserveIds ) external; } // File: contracts/sol6/KyberNetwork.sol pragma solidity 0.6.6; /** * @title kyberNetwork main contract * Interacts with contracts: * kyberDao: to retrieve fee data * kyberFeeHandler: accumulates and distributes trade fees * kyberMatchingEngine: parse user hint and run reserve matching algorithm * kyberStorage: store / access reserves, token listings and contract addresses * kyberReserve(s): query rate and trade */ contract KyberNetwork is WithdrawableNoModifiers, Utils5, IKyberNetwork, ReentrancyGuard { using SafeERC20 for IERC20; struct NetworkFeeData { uint64 expiryTimestamp; uint16 feeBps; } /// @notice Stores work data for reserves (either for token -> eth, or eth -> token) /// @dev Variables are in-place, ie. reserve with addresses[i] has id of ids[i], offers rate of rates[i], etc. /// @param addresses List of reserve addresses selected for the trade /// @param ids List of reserve ids, to be used for KyberTrade event /// @param rates List of rates that were offered by the reserves /// @param isFeeAccountedFlags List of reserves requiring users to pay network fee /// @param isEntitledRebateFlags List of reserves eligible for rebates /// @param splitsBps List of proportions of trade amount allocated to the reserves. /// If there is only 1 reserve, then it should have a value of 10000 bps /// @param srcAmounts Source amount per reserve. /// @param decimals Token decimals. Src decimals when for src -> eth, dest decimals when eth -> dest struct ReservesData { IKyberReserve[] addresses; bytes32[] ids; uint256[] rates; bool[] isFeeAccountedFlags; bool[] isEntitledRebateFlags; uint256[] splitsBps; uint256[] srcAmounts; uint256 decimals; } /// @notice Main trade data structure, is initialised and used for the entire trade flow /// @param input Initialised when initTradeInput is called. Stores basic trade info /// @param tokenToEth Stores information about reserves that were selected for src -> eth side of trade /// @param ethToToken Stores information about reserves that were selected for eth -> dest side of trade /// @param tradeWei Trade amount in ether wei, before deducting fees. /// @param networkFeeWei Network fee in ether wei. For t2t trades, it can go up to 200% of networkFeeBps /// @param platformFeeWei Platform fee in ether wei /// @param networkFeeBps Network fee bps determined by kyberDao, or default value /// @param numEntitledRebateReserves No. of reserves that are eligible for rebates /// @param feeAccountedBps Proportion of this trade that fee is accounted to, in BPS. Up to 2 * BPS struct TradeData { TradeInput input; ReservesData tokenToEth; ReservesData ethToToken; uint256 tradeWei; uint256 networkFeeWei; uint256 platformFeeWei; uint256 networkFeeBps; uint256 numEntitledRebateReserves; uint256 feeAccountedBps; // what part of this trade is fee paying. for token -> token - up to 200% } struct TradeInput { address payable trader; IERC20 src; uint256 srcAmount; IERC20 dest; address payable destAddress; uint256 maxDestAmount; uint256 minConversionRate; address platformWallet; uint256 platformFeeBps; } uint256 internal constant PERM_HINT_GET_RATE = 1 << 255; // for backwards compatibility uint256 internal constant DEFAULT_NETWORK_FEE_BPS = 25; // till we read value from kyberDao uint256 internal constant MAX_APPROVED_PROXIES = 2; // limit number of proxies that can trade here IKyberFeeHandler internal kyberFeeHandler; IKyberDao internal kyberDao; IKyberMatchingEngine internal kyberMatchingEngine; IKyberStorage internal kyberStorage; IGasHelper internal gasHelper; NetworkFeeData internal networkFeeData; // data is feeBps and expiry timestamp uint256 internal maxGasPriceValue = 50 * 1000 * 1000 * 1000; // 50 gwei bool internal isEnabled = false; // is network enabled mapping(address => bool) internal kyberProxyContracts; event EtherReceival(address indexed sender, uint256 amount); event KyberFeeHandlerUpdated(IKyberFeeHandler newKyberFeeHandler); event KyberMatchingEngineUpdated(IKyberMatchingEngine newKyberMatchingEngine); event GasHelperUpdated(IGasHelper newGasHelper); event KyberDaoUpdated(IKyberDao newKyberDao); event KyberNetworkParamsSet(uint256 maxGasPrice, uint256 negligibleRateDiffBps); event KyberNetworkSetEnable(bool isEnabled); event KyberProxyAdded(address kyberProxy); event KyberProxyRemoved(address kyberProxy); event ListedReservesForToken( IERC20 indexed token, address[] reserves, bool add ); constructor(address _admin, IKyberStorage _kyberStorage) public WithdrawableNoModifiers(_admin) { updateNetworkFee(now, DEFAULT_NETWORK_FEE_BPS); kyberStorage = _kyberStorage; } receive() external payable { emit EtherReceival(msg.sender, msg.value); } /// @notice Backward compatible function /// @notice Use token address ETH_TOKEN_ADDRESS for ether /// @dev Trade from src to dest token and sends dest token to destAddress /// @param trader Address of the taker side of this trade /// @param src Source token /// @param srcAmount Amount of src tokens in twei /// @param dest Destination token /// @param destAddress Address to send tokens to /// @param maxDestAmount A limit on the amount of dest tokens in twei /// @param minConversionRate The minimal conversion rate. If actual rate is lower, trade reverts /// @param walletId Platform wallet address for receiving fees /// @param hint Advanced instructions for running the trade /// @return destAmount Amount of actual dest tokens in twei function tradeWithHint( address payable trader, ERC20 src, uint256 srcAmount, ERC20 dest, address payable destAddress, uint256 maxDestAmount, uint256 minConversionRate, address payable walletId, bytes calldata hint ) external payable returns (uint256 destAmount) { TradeData memory tradeData = initTradeInput({ trader: trader, src: src, dest: dest, srcAmount: srcAmount, destAddress: destAddress, maxDestAmount: maxDestAmount, minConversionRate: minConversionRate, platformWallet: walletId, platformFeeBps: 0 }); return trade(tradeData, hint); } /// @notice Use token address ETH_TOKEN_ADDRESS for ether /// @dev Trade from src to dest token and sends dest token to destAddress /// @param trader Address of the taker side of this trade /// @param src Source token /// @param srcAmount Amount of src tokens in twei /// @param dest Destination token /// @param destAddress Address to send tokens to /// @param maxDestAmount A limit on the amount of dest tokens in twei /// @param minConversionRate The minimal conversion rate. If actual rate is lower, trade reverts /// @param platformWallet Platform wallet address for receiving fees /// @param platformFeeBps Part of the trade that is allocated as fee to platform wallet. Ex: 1000 = 10% /// @param hint Advanced instructions for running the trade /// @return destAmount Amount of actual dest tokens in twei function tradeWithHintAndFee( address payable trader, IERC20 src, uint256 srcAmount, IERC20 dest, address payable destAddress, uint256 maxDestAmount, uint256 minConversionRate, address payable platformWallet, uint256 platformFeeBps, bytes calldata hint ) external payable override returns (uint256 destAmount) { TradeData memory tradeData = initTradeInput({ trader: trader, src: src, dest: dest, srcAmount: srcAmount, destAddress: destAddress, maxDestAmount: maxDestAmount, minConversionRate: minConversionRate, platformWallet: platformWallet, platformFeeBps: platformFeeBps }); return trade(tradeData, hint); } /// @notice Can be called only by kyberStorage /// @dev Allow or prevent to trade token -> eth for a reserve /// @param reserve The reserve address /// @param token Token address /// @param add If true, then give reserve token allowance, otherwise set zero allowance function listTokenForReserve( address reserve, IERC20 token, bool add ) external override { require(msg.sender == address(kyberStorage), "only kyberStorage"); if (add) { token.safeApprove(reserve, MAX_ALLOWANCE); setDecimals(token); } else { token.safeApprove(reserve, 0); } } /// @notice Can be called only by operator /// @dev Allow or prevent to trade token -> eth for list of reserves /// Useful for migration to new network contract /// Call storage to get list of reserves supporting token -> eth /// @param token Token address /// @param startIndex start index in reserves list /// @param endIndex end index in reserves list (can be larger) /// @param add If true, then give reserve token allowance, otherwise set zero allowance function listReservesForToken( IERC20 token, uint256 startIndex, uint256 endIndex, bool add ) external { onlyOperator(); if (startIndex > endIndex) { // no need to do anything return; } address[] memory reserves = kyberStorage.getReserveAddressesPerTokenSrc( token, startIndex, endIndex ); if (reserves.length == 0) { // no need to do anything return; } for(uint i = 0; i < reserves.length; i++) { if (add) { token.safeApprove(reserves[i], MAX_ALLOWANCE); setDecimals(token); } else { token.safeApprove(reserves[i], 0); } } emit ListedReservesForToken(token, reserves, add); } function setContracts( IKyberFeeHandler _kyberFeeHandler, IKyberMatchingEngine _kyberMatchingEngine, IGasHelper _gasHelper ) external virtual { onlyAdmin(); if (kyberFeeHandler != _kyberFeeHandler) { kyberFeeHandler = _kyberFeeHandler; emit KyberFeeHandlerUpdated(_kyberFeeHandler); } if (kyberMatchingEngine != _kyberMatchingEngine) { kyberMatchingEngine = _kyberMatchingEngine; emit KyberMatchingEngineUpdated(_kyberMatchingEngine); } if ((_gasHelper != IGasHelper(0)) && (_gasHelper != gasHelper)) { gasHelper = _gasHelper; emit GasHelperUpdated(_gasHelper); } kyberStorage.setContracts(address(_kyberFeeHandler), address(_kyberMatchingEngine)); require(_kyberFeeHandler != IKyberFeeHandler(0)); require(_kyberMatchingEngine != IKyberMatchingEngine(0)); } function setKyberDaoContract(IKyberDao _kyberDao) external { // enable setting null kyberDao address onlyAdmin(); if (kyberDao != _kyberDao) { kyberDao = _kyberDao; kyberStorage.setKyberDaoContract(address(_kyberDao)); emit KyberDaoUpdated(_kyberDao); } } function setParams(uint256 _maxGasPrice, uint256 _negligibleRateDiffBps) external { onlyAdmin(); maxGasPriceValue = _maxGasPrice; kyberMatchingEngine.setNegligibleRateDiffBps(_negligibleRateDiffBps); emit KyberNetworkParamsSet(maxGasPriceValue, _negligibleRateDiffBps); } function setEnable(bool enable) external { onlyAdmin(); if (enable) { require(kyberFeeHandler != IKyberFeeHandler(0)); require(kyberMatchingEngine != IKyberMatchingEngine(0)); require(kyberStorage.isKyberProxyAdded()); } isEnabled = enable; emit KyberNetworkSetEnable(isEnabled); } /// @dev No. of kyberProxies is capped function addKyberProxy(address kyberProxy) external virtual { onlyAdmin(); kyberStorage.addKyberProxy(kyberProxy, MAX_APPROVED_PROXIES); require(kyberProxy != address(0)); require(!kyberProxyContracts[kyberProxy]); kyberProxyContracts[kyberProxy] = true; emit KyberProxyAdded(kyberProxy); } function removeKyberProxy(address kyberProxy) external virtual { onlyAdmin(); kyberStorage.removeKyberProxy(kyberProxy); require(kyberProxyContracts[kyberProxy]); kyberProxyContracts[kyberProxy] = false; emit KyberProxyRemoved(kyberProxy); } /// @dev gets the expected rates when trading src -> dest token, with / without fees /// @param src Source token /// @param dest Destination token /// @param srcQty Amount of src tokens in twei /// @param platformFeeBps Part of the trade that is allocated as fee to platform wallet. Ex: 1000 = 10% /// @param hint Advanced instructions for running the trade /// @return rateWithNetworkFee Rate after deducting network fee but excluding platform fee /// @return rateWithAllFees = actual rate. Rate after accounting for both network and platform fees function getExpectedRateWithHintAndFee( IERC20 src, IERC20 dest, uint256 srcQty, uint256 platformFeeBps, bytes calldata hint ) external view override returns ( uint256 rateWithNetworkFee, uint256 rateWithAllFees ) { if (src == dest) return (0, 0); TradeData memory tradeData = initTradeInput({ trader: payable(address(0)), src: src, dest: dest, srcAmount: (srcQty == 0) ? 1 : srcQty, destAddress: payable(address(0)), maxDestAmount: 2**255, minConversionRate: 0, platformWallet: payable(address(0)), platformFeeBps: platformFeeBps }); tradeData.networkFeeBps = getNetworkFee(); uint256 destAmount; (destAmount, rateWithNetworkFee) = calcRatesAndAmounts(tradeData, hint); rateWithAllFees = calcRateFromQty( tradeData.input.srcAmount, destAmount, tradeData.tokenToEth.decimals, tradeData.ethToToken.decimals ); } /// @notice Backward compatible API /// @dev Gets the expected and slippage rate for exchanging src -> dest token /// @dev worstRate is hardcoded to be 3% lower of expectedRate /// @param src Source token /// @param dest Destination token /// @param srcQty Amount of src tokens in twei /// @return expectedRate for a trade after deducting network fee. /// @return worstRate for a trade. Calculated to be expectedRate * 97 / 100 function getExpectedRate( ERC20 src, ERC20 dest, uint256 srcQty ) external view returns (uint256 expectedRate, uint256 worstRate) { if (src == dest) return (0, 0); uint256 qty = srcQty & ~PERM_HINT_GET_RATE; TradeData memory tradeData = initTradeInput({ trader: payable(address(0)), src: src, dest: dest, srcAmount: (qty == 0) ? 1 : qty, destAddress: payable(address(0)), maxDestAmount: 2**255, minConversionRate: 0, platformWallet: payable(address(0)), platformFeeBps: 0 }); tradeData.networkFeeBps = getNetworkFee(); (, expectedRate) = calcRatesAndAmounts(tradeData, ""); worstRate = (expectedRate * 97) / 100; // backward compatible formula } /// @notice Returns some data about the network /// @param negligibleDiffBps Negligible rate difference (in basis pts) when searching best rate /// @param networkFeeBps Network fees to be charged (in basis pts) /// @param expiryTimestamp Timestamp for which networkFeeBps will expire, /// and needs to be updated by calling kyberDao contract / set to default function getNetworkData() external view override returns ( uint256 negligibleDiffBps, uint256 networkFeeBps, uint256 expiryTimestamp ) { (networkFeeBps, expiryTimestamp) = readNetworkFeeData(); negligibleDiffBps = kyberMatchingEngine.getNegligibleRateDiffBps(); return (negligibleDiffBps, networkFeeBps, expiryTimestamp); } function getContracts() external view returns ( IKyberFeeHandler kyberFeeHandlerAddress, IKyberDao kyberDaoAddress, IKyberMatchingEngine kyberMatchingEngineAddress, IKyberStorage kyberStorageAddress, IGasHelper gasHelperAddress, IKyberNetworkProxy[] memory kyberProxyAddresses ) { return ( kyberFeeHandler, kyberDao, kyberMatchingEngine, kyberStorage, gasHelper, kyberStorage.getKyberProxies() ); } /// @notice returns the max gas price allowable for trades function maxGasPrice() external view override returns (uint256) { return maxGasPriceValue; } /// @notice returns status of the network. If disabled, trades cannot happen. function enabled() external view override returns (bool) { return isEnabled; } /// @notice Gets network fee from the kyberDao (or use default). /// For trade function, so that data can be updated and cached. /// @dev Note that this function can be triggered by anyone, so that /// the first trader of a new epoch can avoid incurring extra gas costs function getAndUpdateNetworkFee() public returns (uint256 networkFeeBps) { uint256 expiryTimestamp; (networkFeeBps, expiryTimestamp) = readNetworkFeeData(); if (expiryTimestamp < now && kyberDao != IKyberDao(0)) { (networkFeeBps, expiryTimestamp) = kyberDao.getLatestNetworkFeeDataWithCache(); updateNetworkFee(expiryTimestamp, networkFeeBps); } } /// @notice Calculates platform fee and reserve rebate percentages for the trade. /// Transfers eth and rebate wallet data to kyberFeeHandler function handleFees(TradeData memory tradeData) internal { uint256 sentFee = tradeData.networkFeeWei + tradeData.platformFeeWei; //no need to handle fees if total fee is zero if (sentFee == 0) return; // update reserve eligibility and rebate percentages ( address[] memory rebateWallets, uint256[] memory rebatePercentBps ) = calculateRebates(tradeData); // send total fee amount to fee handler with reserve data kyberFeeHandler.handleFees{value: sentFee}( ETH_TOKEN_ADDRESS, rebateWallets, rebatePercentBps, tradeData.input.platformWallet, tradeData.platformFeeWei, tradeData.networkFeeWei ); } function updateNetworkFee(uint256 expiryTimestamp, uint256 feeBps) internal { require(expiryTimestamp < 2**64, "expiry overflow"); require(feeBps < BPS / 2, "fees exceed BPS"); networkFeeData.expiryTimestamp = uint64(expiryTimestamp); networkFeeData.feeBps = uint16(feeBps); } /// @notice Use token address ETH_TOKEN_ADDRESS for ether /// @dev Do one trade with each reserve in reservesData, verifying network balance /// as expected to ensure reserves take correct src amount /// @param src Source token /// @param dest Destination token /// @param destAddress Address to send tokens to /// @param reservesData reservesData to trade /// @param expectedDestAmount Amount to be transferred to destAddress /// @param srcDecimals Decimals of source token /// @param destDecimals Decimals of destination token function doReserveTrades( IERC20 src, IERC20 dest, address payable destAddress, ReservesData memory reservesData, uint256 expectedDestAmount, uint256 srcDecimals, uint256 destDecimals ) internal virtual { if (src == dest) { // eth -> eth, need not do anything except for token -> eth: transfer eth to destAddress if (destAddress != (address(this))) { (bool success, ) = destAddress.call{value: expectedDestAmount}(""); require(success, "send dest qty failed"); } return; } tradeAndVerifyNetworkBalance( reservesData, src, dest, srcDecimals, destDecimals ); if (destAddress != address(this)) { // for eth -> token / token -> token, transfer tokens to destAddress dest.safeTransfer(destAddress, expectedDestAmount); } } /// @dev call trade from reserves and verify balances /// @param reservesData reservesData to trade /// @param src Source token of trade /// @param dest Destination token of trade /// @param srcDecimals Decimals of source token /// @param destDecimals Decimals of destination token function tradeAndVerifyNetworkBalance( ReservesData memory reservesData, IERC20 src, IERC20 dest, uint256 srcDecimals, uint256 destDecimals ) internal { // only need to verify src balance if src is not eth uint256 srcBalanceBefore = (src == ETH_TOKEN_ADDRESS) ? 0 : getBalance(src, address(this)); uint256 destBalanceBefore = getBalance(dest, address(this)); for(uint256 i = 0; i < reservesData.addresses.length; i++) { uint256 callValue = (src == ETH_TOKEN_ADDRESS) ? reservesData.srcAmounts[i] : 0; require( reservesData.addresses[i].trade{value: callValue}( src, reservesData.srcAmounts[i], dest, address(this), reservesData.rates[i], true ), "reserve trade failed" ); uint256 balanceAfter; if (src != ETH_TOKEN_ADDRESS) { // verify src balance only if it is not eth balanceAfter = getBalance(src, address(this)); // verify correct src amount is taken if (srcBalanceBefore >= balanceAfter && srcBalanceBefore - balanceAfter > reservesData.srcAmounts[i]) { revert("reserve takes high amount"); } srcBalanceBefore = balanceAfter; } // verify correct dest amount is received uint256 expectedDestAmount = calcDstQty( reservesData.srcAmounts[i], srcDecimals, destDecimals, reservesData.rates[i] ); balanceAfter = getBalance(dest, address(this)); if (balanceAfter < destBalanceBefore || balanceAfter - destBalanceBefore < expectedDestAmount) { revert("reserve returns low amount"); } destBalanceBefore = balanceAfter; } } /// @notice Use token address ETH_TOKEN_ADDRESS for ether /// @dev Trade API for kyberNetwork /// @param tradeData Main trade data object for trade info to be stored function trade(TradeData memory tradeData, bytes memory hint) internal virtual nonReentrant returns (uint256 destAmount) { tradeData.networkFeeBps = getAndUpdateNetworkFee(); validateTradeInput(tradeData.input); uint256 rateWithNetworkFee; (destAmount, rateWithNetworkFee) = calcRatesAndAmounts(tradeData, hint); require(rateWithNetworkFee > 0, "trade invalid, if hint involved, try parseHint API"); require(rateWithNetworkFee < MAX_RATE, "rate > MAX_RATE"); require(rateWithNetworkFee >= tradeData.input.minConversionRate, "rate < min rate"); uint256 actualSrcAmount; if (destAmount > tradeData.input.maxDestAmount) { // notice tradeData passed by reference and updated destAmount = tradeData.input.maxDestAmount; actualSrcAmount = calcTradeSrcAmountFromDest(tradeData); } else { actualSrcAmount = tradeData.input.srcAmount; } // token -> eth doReserveTrades( tradeData.input.src, ETH_TOKEN_ADDRESS, address(this), tradeData.tokenToEth, tradeData.tradeWei, tradeData.tokenToEth.decimals, ETH_DECIMALS ); // eth -> token doReserveTrades( ETH_TOKEN_ADDRESS, tradeData.input.dest, tradeData.input.destAddress, tradeData.ethToToken, destAmount, ETH_DECIMALS, tradeData.ethToToken.decimals ); handleChange( tradeData.input.src, tradeData.input.srcAmount, actualSrcAmount, tradeData.input.trader ); handleFees(tradeData); emit KyberTrade({ src: tradeData.input.src, dest: tradeData.input.dest, ethWeiValue: tradeData.tradeWei, networkFeeWei: tradeData.networkFeeWei, customPlatformFeeWei: tradeData.platformFeeWei, t2eIds: tradeData.tokenToEth.ids, e2tIds: tradeData.ethToToken.ids, t2eSrcAmounts: tradeData.tokenToEth.srcAmounts, e2tSrcAmounts: tradeData.ethToToken.srcAmounts, t2eRates: tradeData.tokenToEth.rates, e2tRates: tradeData.ethToToken.rates }); if (gasHelper != IGasHelper(0)) { (bool success, ) = address(gasHelper).call( abi.encodeWithSignature( "freeGas(address,address,address,uint256,bytes32[],bytes32[])", tradeData.input.platformWallet, tradeData.input.src, tradeData.input.dest, tradeData.tradeWei, tradeData.tokenToEth.ids, tradeData.ethToToken.ids ) ); // remove compilation warning success; } return (destAmount); } /// @notice If user maxDestAmount < actual dest amount, actualSrcAmount will be < srcAmount /// Calculate the change, and send it back to the user function handleChange( IERC20 src, uint256 srcAmount, uint256 requiredSrcAmount, address payable trader ) internal { if (requiredSrcAmount < srcAmount) { // if there is "change" send back to trader if (src == ETH_TOKEN_ADDRESS) { (bool success, ) = trader.call{value: (srcAmount - requiredSrcAmount)}(""); require(success, "Send change failed"); } else { src.safeTransfer(trader, (srcAmount - requiredSrcAmount)); } } } function initTradeInput( address payable trader, IERC20 src, IERC20 dest, uint256 srcAmount, address payable destAddress, uint256 maxDestAmount, uint256 minConversionRate, address payable platformWallet, uint256 platformFeeBps ) internal view returns (TradeData memory tradeData) { tradeData.input.trader = trader; tradeData.input.src = src; tradeData.input.srcAmount = srcAmount; tradeData.input.dest = dest; tradeData.input.destAddress = destAddress; tradeData.input.maxDestAmount = maxDestAmount; tradeData.input.minConversionRate = minConversionRate; tradeData.input.platformWallet = platformWallet; tradeData.input.platformFeeBps = platformFeeBps; tradeData.tokenToEth.decimals = getDecimals(src); tradeData.ethToToken.decimals = getDecimals(dest); } /// @notice This function does all calculations to find trade dest amount without accounting /// for maxDestAmount. Part of this process includes: /// - Call kyberMatchingEngine to parse hint and get an optional reserve list to trade. /// - Query reserve rates and call kyberMatchingEngine to use best reserve. /// - Calculate trade values and fee values. /// This function should set all TradeData information so that it can be later used without /// any ambiguity /// @param tradeData Main trade data object for trade info to be stored /// @param hint Advanced user instructions for the trade function calcRatesAndAmounts(TradeData memory tradeData, bytes memory hint) internal view returns (uint256 destAmount, uint256 rateWithNetworkFee) { validateFeeInput(tradeData.input, tradeData.networkFeeBps); // token -> eth: find best reserves match and calculate wei amount tradeData.tradeWei = calcDestQtyAndMatchReserves( tradeData.input.src, ETH_TOKEN_ADDRESS, tradeData.input.srcAmount, tradeData, tradeData.tokenToEth, hint ); require(tradeData.tradeWei <= MAX_QTY, "Trade wei > MAX_QTY"); if (tradeData.tradeWei == 0) { return (0, 0); } // calculate fees tradeData.platformFeeWei = (tradeData.tradeWei * tradeData.input.platformFeeBps) / BPS; tradeData.networkFeeWei = (((tradeData.tradeWei * tradeData.networkFeeBps) / BPS) * tradeData.feeAccountedBps) / BPS; assert(tradeData.tradeWei >= (tradeData.networkFeeWei + tradeData.platformFeeWei)); // eth -> token: find best reserves match and calculate trade dest amount uint256 actualSrcWei = tradeData.tradeWei - tradeData.networkFeeWei - tradeData.platformFeeWei; destAmount = calcDestQtyAndMatchReserves( ETH_TOKEN_ADDRESS, tradeData.input.dest, actualSrcWei, tradeData, tradeData.ethToToken, hint ); tradeData.networkFeeWei = (((tradeData.tradeWei * tradeData.networkFeeBps) / BPS) * tradeData.feeAccountedBps) / BPS; rateWithNetworkFee = calcRateFromQty( tradeData.input.srcAmount * (BPS - tradeData.input.platformFeeBps) / BPS, destAmount, tradeData.tokenToEth.decimals, tradeData.ethToToken.decimals ); } /// @notice Get trading reserves, source amounts, and calculate dest qty /// Store information into tradeData function calcDestQtyAndMatchReserves( IERC20 src, IERC20 dest, uint256 srcAmount, TradeData memory tradeData, ReservesData memory reservesData, bytes memory hint ) internal view returns (uint256 destAmount) { if (src == dest) { return srcAmount; } IKyberMatchingEngine.ProcessWithRate processWithRate; // get reserve list from kyberMatchingEngine (reservesData.ids, reservesData.splitsBps, processWithRate) = kyberMatchingEngine.getTradingReserves( src, dest, (tradeData.input.src != ETH_TOKEN_ADDRESS) && (tradeData.input.dest != ETH_TOKEN_ADDRESS), hint ); bool areAllReservesListed; (areAllReservesListed, reservesData.isFeeAccountedFlags, reservesData.isEntitledRebateFlags, reservesData.addresses) = kyberStorage.getReservesData(reservesData.ids, src, dest); if(!areAllReservesListed) { return 0; } require(reservesData.ids.length == reservesData.splitsBps.length, "bad split array"); require(reservesData.ids.length == reservesData.isFeeAccountedFlags.length, "bad fee array"); require(reservesData.ids.length == reservesData.isEntitledRebateFlags.length, "bad rebate array"); require(reservesData.ids.length == reservesData.addresses.length, "bad addresses array"); // calculate src trade amount per reserve and query rates // set data in reservesData struct uint256[] memory feesAccountedDestBps = calcSrcAmountsAndGetRates( reservesData, src, dest, srcAmount, tradeData ); // if matching engine requires processing with rate data. call doMatch and update reserve list if (processWithRate == IKyberMatchingEngine.ProcessWithRate.Required) { uint256[] memory selectedIndexes = kyberMatchingEngine.doMatch( src, dest, reservesData.srcAmounts, feesAccountedDestBps, reservesData.rates ); updateReservesList(reservesData, selectedIndexes); } // calculate dest amount and fee paying data of this part (t2e or e2t) destAmount = validateTradeCalcDestQtyAndFeeData(src, reservesData, tradeData); } /// @notice Calculates source amounts per reserve. Does get rate call function calcSrcAmountsAndGetRates( ReservesData memory reservesData, IERC20 src, IERC20 dest, uint256 srcAmount, TradeData memory tradeData ) internal view returns (uint256[] memory feesAccountedDestBps) { uint256 numReserves = reservesData.ids.length; uint256 srcAmountAfterFee; uint256 destAmountFeeBps; if (src == ETH_TOKEN_ADDRESS) { // @notice srcAmount is after deducting fees from tradeWei // @notice using tradeWei to calculate fee so eth -> token symmetric to token -> eth srcAmountAfterFee = srcAmount - (tradeData.tradeWei * tradeData.networkFeeBps / BPS); } else { srcAmountAfterFee = srcAmount; destAmountFeeBps = tradeData.networkFeeBps; } reservesData.srcAmounts = new uint256[](numReserves); reservesData.rates = new uint256[](numReserves); feesAccountedDestBps = new uint256[](numReserves); // iterate reserve list. validate data. calculate srcAmount according to splits and fee data. for (uint256 i = 0; i < numReserves; i++) { require( reservesData.splitsBps[i] > 0 && reservesData.splitsBps[i] <= BPS, "invalid split bps" ); if (reservesData.isFeeAccountedFlags[i]) { reservesData.srcAmounts[i] = srcAmountAfterFee * reservesData.splitsBps[i] / BPS; feesAccountedDestBps[i] = destAmountFeeBps; } else { reservesData.srcAmounts[i] = (srcAmount * reservesData.splitsBps[i]) / BPS; } // get rate with calculated src amount reservesData.rates[i] = reservesData.addresses[i].getConversionRate( src, dest, reservesData.srcAmounts[i], block.number ); } } function calculateRebates(TradeData memory tradeData) internal view returns (address[] memory rebateWallets, uint256[] memory rebatePercentBps) { rebateWallets = new address[](tradeData.numEntitledRebateReserves); rebatePercentBps = new uint256[](tradeData.numEntitledRebateReserves); if (tradeData.numEntitledRebateReserves == 0) { return (rebateWallets, rebatePercentBps); } uint256 index; bytes32[] memory rebateReserveIds = new bytes32[](tradeData.numEntitledRebateReserves); // token -> eth index = createRebateEntitledList( rebateReserveIds, rebatePercentBps, tradeData.tokenToEth, index, tradeData.feeAccountedBps ); // eth -> token createRebateEntitledList( rebateReserveIds, rebatePercentBps, tradeData.ethToToken, index, tradeData.feeAccountedBps ); rebateWallets = kyberStorage.getRebateWalletsFromIds(rebateReserveIds); } function createRebateEntitledList( bytes32[] memory rebateReserveIds, uint256[] memory rebatePercentBps, ReservesData memory reservesData, uint256 index, uint256 feeAccountedBps ) internal pure returns (uint256) { uint256 _index = index; for (uint256 i = 0; i < reservesData.isEntitledRebateFlags.length; i++) { if (reservesData.isEntitledRebateFlags[i]) { rebateReserveIds[_index] = reservesData.ids[i]; rebatePercentBps[_index] = (reservesData.splitsBps[i] * BPS) / feeAccountedBps; _index++; } } return _index; } /// @dev Checks a trade input validity, including correct src amounts /// @param input Trade input structure function validateTradeInput(TradeInput memory input) internal view { require(isEnabled, "network disabled"); require(kyberProxyContracts[msg.sender], "bad sender"); require(tx.gasprice <= maxGasPriceValue, "gas price"); require(input.srcAmount <= MAX_QTY, "srcAmt > MAX_QTY"); require(input.srcAmount != 0, "0 srcAmt"); require(input.destAddress != address(0), "dest add 0"); require(input.src != input.dest, "src = dest"); if (input.src == ETH_TOKEN_ADDRESS) { require(msg.value == input.srcAmount); // kyberProxy issues message here } else { require(msg.value == 0); // kyberProxy issues message here // funds should have been moved to this contract already. require(input.src.balanceOf(address(this)) >= input.srcAmount, "no tokens"); } } /// @notice Gets the network fee from kyberDao (or use default). View function for getExpectedRate function getNetworkFee() internal view returns (uint256 networkFeeBps) { uint256 expiryTimestamp; (networkFeeBps, expiryTimestamp) = readNetworkFeeData(); if (expiryTimestamp < now && kyberDao != IKyberDao(0)) { (networkFeeBps, expiryTimestamp) = kyberDao.getLatestNetworkFeeData(); } } function readNetworkFeeData() internal view returns (uint256 feeBps, uint256 expiryTimestamp) { feeBps = uint256(networkFeeData.feeBps); expiryTimestamp = uint256(networkFeeData.expiryTimestamp); } /// @dev Checks fee input validity, including correct src amounts /// @param input Trade input structure /// @param networkFeeBps Network fee in bps. function validateFeeInput(TradeInput memory input, uint256 networkFeeBps) internal pure { require(input.platformFeeBps < BPS, "platformFee high"); require(input.platformFeeBps + networkFeeBps + networkFeeBps < BPS, "fees high"); } /// @notice Update reserve data with selected reserves from kyberMatchingEngine function updateReservesList(ReservesData memory reservesData, uint256[] memory selectedIndexes) internal pure { uint256 numReserves = selectedIndexes.length; require(numReserves <= reservesData.addresses.length, "doMatch: too many reserves"); IKyberReserve[] memory reserveAddresses = new IKyberReserve[](numReserves); bytes32[] memory reserveIds = new bytes32[](numReserves); uint256[] memory splitsBps = new uint256[](numReserves); bool[] memory isFeeAccountedFlags = new bool[](numReserves); bool[] memory isEntitledRebateFlags = new bool[](numReserves); uint256[] memory srcAmounts = new uint256[](numReserves); uint256[] memory rates = new uint256[](numReserves); // update participating resevres and all data (rates, srcAmounts, feeAcounted etc.) for (uint256 i = 0; i < numReserves; i++) { reserveAddresses[i] = reservesData.addresses[selectedIndexes[i]]; reserveIds[i] = reservesData.ids[selectedIndexes[i]]; splitsBps[i] = reservesData.splitsBps[selectedIndexes[i]]; isFeeAccountedFlags[i] = reservesData.isFeeAccountedFlags[selectedIndexes[i]]; isEntitledRebateFlags[i] = reservesData.isEntitledRebateFlags[selectedIndexes[i]]; srcAmounts[i] = reservesData.srcAmounts[selectedIndexes[i]]; rates[i] = reservesData.rates[selectedIndexes[i]]; } // update values reservesData.addresses = reserveAddresses; reservesData.ids = reserveIds; reservesData.splitsBps = splitsBps; reservesData.isFeeAccountedFlags = isFeeAccountedFlags; reservesData.isEntitledRebateFlags = isEntitledRebateFlags; reservesData.rates = rates; reservesData.srcAmounts = srcAmounts; } /// @notice Verify split values bps and reserve ids, /// then calculate the destQty from srcAmounts and rates /// @dev Each split bps must be in range (0, BPS] /// @dev Total split bps must be 100% /// @dev Reserve ids must be increasing function validateTradeCalcDestQtyAndFeeData( IERC20 src, ReservesData memory reservesData, TradeData memory tradeData ) internal pure returns (uint256 totalDestAmount) { uint256 totalBps; uint256 srcDecimals = (src == ETH_TOKEN_ADDRESS) ? ETH_DECIMALS : reservesData.decimals; uint256 destDecimals = (src == ETH_TOKEN_ADDRESS) ? reservesData.decimals : ETH_DECIMALS; for (uint256 i = 0; i < reservesData.addresses.length; i++) { if (i > 0 && (uint256(reservesData.ids[i]) <= uint256(reservesData.ids[i - 1]))) { return 0; // ids are not in increasing order } totalBps += reservesData.splitsBps[i]; uint256 destAmount = calcDstQty( reservesData.srcAmounts[i], srcDecimals, destDecimals, reservesData.rates[i] ); if (destAmount == 0) { return 0; } totalDestAmount += destAmount; if (reservesData.isFeeAccountedFlags[i]) { tradeData.feeAccountedBps += reservesData.splitsBps[i]; if (reservesData.isEntitledRebateFlags[i]) { tradeData.numEntitledRebateReserves++; } } } if (totalBps != BPS) { return 0; } } /// @notice Recalculates tradeWei, network and platform fees, and actual source amount needed for the trade /// in the event actualDestAmount > maxDestAmount function calcTradeSrcAmountFromDest(TradeData memory tradeData) internal pure virtual returns (uint256 actualSrcAmount) { uint256 weiAfterDeductingFees; if (tradeData.input.dest != ETH_TOKEN_ADDRESS) { weiAfterDeductingFees = calcTradeSrcAmount( tradeData.tradeWei - tradeData.platformFeeWei - tradeData.networkFeeWei, ETH_DECIMALS, tradeData.ethToToken.decimals, tradeData.input.maxDestAmount, tradeData.ethToToken ); } else { weiAfterDeductingFees = tradeData.input.maxDestAmount; } // reverse calculation, because we are working backwards uint256 newTradeWei = (weiAfterDeductingFees * BPS * BPS) / ((BPS * BPS) - (tradeData.networkFeeBps * tradeData.feeAccountedBps + tradeData.input.platformFeeBps * BPS)); tradeData.tradeWei = minOf(newTradeWei, tradeData.tradeWei); // recalculate network and platform fees based on tradeWei tradeData.networkFeeWei = (((tradeData.tradeWei * tradeData.networkFeeBps) / BPS) * tradeData.feeAccountedBps) / BPS; tradeData.platformFeeWei = (tradeData.tradeWei * tradeData.input.platformFeeBps) / BPS; if (tradeData.input.src != ETH_TOKEN_ADDRESS) { actualSrcAmount = calcTradeSrcAmount( tradeData.input.srcAmount, tradeData.tokenToEth.decimals, ETH_DECIMALS, tradeData.tradeWei, tradeData.tokenToEth ); } else { actualSrcAmount = tradeData.tradeWei; } assert(actualSrcAmount <= tradeData.input.srcAmount); } /// @notice Recalculates srcAmounts and stores into tradingReserves, given the new destAmount. /// Uses the original proportion of srcAmounts and rates to determine new split destAmounts, /// then calculate the respective srcAmounts /// @dev Due to small rounding errors, will fallback to current src amounts if new src amount is greater function calcTradeSrcAmount( uint256 srcAmount, uint256 srcDecimals, uint256 destDecimals, uint256 destAmount, ReservesData memory reservesData ) internal pure returns (uint256 newSrcAmount) { uint256 totalWeightedDestAmount; for (uint256 i = 0; i < reservesData.srcAmounts.length; i++) { totalWeightedDestAmount += reservesData.srcAmounts[i] * reservesData.rates[i]; } uint256[] memory newSrcAmounts = new uint256[](reservesData.srcAmounts.length); uint256 destAmountSoFar; uint256 currentSrcAmount; uint256 destAmountSplit; for (uint256 i = 0; i < reservesData.srcAmounts.length; i++) { currentSrcAmount = reservesData.srcAmounts[i]; require(destAmount * currentSrcAmount * reservesData.rates[i] / destAmount == currentSrcAmount * reservesData.rates[i], "multiplication overflow"); destAmountSplit = i == (reservesData.srcAmounts.length - 1) ? (destAmount - destAmountSoFar) : (destAmount * currentSrcAmount * reservesData.rates[i]) / totalWeightedDestAmount; destAmountSoFar += destAmountSplit; newSrcAmounts[i] = calcSrcQty( destAmountSplit, srcDecimals, destDecimals, reservesData.rates[i] ); if (newSrcAmounts[i] > currentSrcAmount) { // revert back to use current src amounts return srcAmount; } newSrcAmount += newSrcAmounts[i]; } // new src amounts are used only when all of them aren't greater then current srcAmounts reservesData.srcAmounts = newSrcAmounts; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"contract IKyberStorage","name":"_kyberStorage","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"}],"name":"AdminClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAlerter","type":"address"},{"indexed":false,"internalType":"bool","name":"isAdd","type":"bool"}],"name":"AlerterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EtherReceival","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sendTo","type":"address"}],"name":"EtherWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IGasHelper","name":"newGasHelper","type":"address"}],"name":"GasHelperUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IKyberDao","name":"newKyberDao","type":"address"}],"name":"KyberDaoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IKyberFeeHandler","name":"newKyberFeeHandler","type":"address"}],"name":"KyberFeeHandlerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IKyberMatchingEngine","name":"newKyberMatchingEngine","type":"address"}],"name":"KyberMatchingEngineUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"negligibleRateDiffBps","type":"uint256"}],"name":"KyberNetworkParamsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"KyberNetworkSetEnable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"kyberProxy","type":"address"}],"name":"KyberProxyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"kyberProxy","type":"address"}],"name":"KyberProxyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"src","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"dest","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethWeiValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"networkFeeWei","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"customPlatformFeeWei","type":"uint256"},{"indexed":false,"internalType":"bytes32[]","name":"t2eIds","type":"bytes32[]"},{"indexed":false,"internalType":"bytes32[]","name":"e2tIds","type":"bytes32[]"},{"indexed":false,"internalType":"uint256[]","name":"t2eSrcAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"e2tSrcAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"t2eRates","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"e2tRates","type":"uint256[]"}],"name":"KyberTrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address[]","name":"reserves","type":"address[]"},{"indexed":false,"internalType":"bool","name":"add","type":"bool"}],"name":"ListedReservesForToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOperator","type":"address"},{"indexed":false,"internalType":"bool","name":"isAdd","type":"bool"}],"name":"OperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sendTo","type":"address"}],"name":"TokenWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingAdmin","type":"address"}],"name":"TransferAdminPending","type":"event"},{"inputs":[{"internalType":"address","name":"newAlerter","type":"address"}],"name":"addAlerter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"kyberProxy","type":"address"}],"name":"addKyberProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOperator","type":"address"}],"name":"addOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAlerters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAndUpdateNetworkFee","outputs":[{"internalType":"uint256","name":"networkFeeBps","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getContracts","outputs":[{"internalType":"contract IKyberFeeHandler","name":"kyberFeeHandlerAddress","type":"address"},{"internalType":"contract IKyberDao","name":"kyberDaoAddress","type":"address"},{"internalType":"contract IKyberMatchingEngine","name":"kyberMatchingEngineAddress","type":"address"},{"internalType":"contract IKyberStorage","name":"kyberStorageAddress","type":"address"},{"internalType":"contract IGasHelper","name":"gasHelperAddress","type":"address"},{"internalType":"contract IKyberNetworkProxy[]","name":"kyberProxyAddresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"src","type":"address"},{"internalType":"contract ERC20","name":"dest","type":"address"},{"internalType":"uint256","name":"srcQty","type":"uint256"}],"name":"getExpectedRate","outputs":[{"internalType":"uint256","name":"expectedRate","type":"uint256"},{"internalType":"uint256","name":"worstRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"src","type":"address"},{"internalType":"contract IERC20","name":"dest","type":"address"},{"internalType":"uint256","name":"srcQty","type":"uint256"},{"internalType":"uint256","name":"platformFeeBps","type":"uint256"},{"internalType":"bytes","name":"hint","type":"bytes"}],"name":"getExpectedRateWithHintAndFee","outputs":[{"internalType":"uint256","name":"rateWithNetworkFee","type":"uint256"},{"internalType":"uint256","name":"rateWithAllFees","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNetworkData","outputs":[{"internalType":"uint256","name":"negligibleDiffBps","type":"uint256"},{"internalType":"uint256","name":"networkFeeBps","type":"uint256"},{"internalType":"uint256","name":"expiryTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"endIndex","type":"uint256"},{"internalType":"bool","name":"add","type":"bool"}],"name":"listReservesForToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"reserve","type":"address"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"bool","name":"add","type":"bool"}],"name":"listTokenForReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxGasPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"alerter","type":"address"}],"name":"removeAlerter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"kyberProxy","type":"address"}],"name":"removeKyberProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"removeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IKyberFeeHandler","name":"_kyberFeeHandler","type":"address"},{"internalType":"contract IKyberMatchingEngine","name":"_kyberMatchingEngine","type":"address"},{"internalType":"contract IGasHelper","name":"_gasHelper","type":"address"}],"name":"setContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"setEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IKyberDao","name":"_kyberDao","type":"address"}],"name":"setKyberDaoContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxGasPrice","type":"uint256"},{"internalType":"uint256","name":"_negligibleRateDiffBps","type":"uint256"}],"name":"setParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"trader","type":"address"},{"internalType":"contract ERC20","name":"src","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"contract ERC20","name":"dest","type":"address"},{"internalType":"address payable","name":"destAddress","type":"address"},{"internalType":"uint256","name":"maxDestAmount","type":"uint256"},{"internalType":"uint256","name":"minConversionRate","type":"uint256"},{"internalType":"address payable","name":"walletId","type":"address"},{"internalType":"bytes","name":"hint","type":"bytes"}],"name":"tradeWithHint","outputs":[{"internalType":"uint256","name":"destAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"trader","type":"address"},{"internalType":"contract IERC20","name":"src","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"contract IERC20","name":"dest","type":"address"},{"internalType":"address payable","name":"destAddress","type":"address"},{"internalType":"uint256","name":"maxDestAmount","type":"uint256"},{"internalType":"uint256","name":"minConversionRate","type":"uint256"},{"internalType":"address payable","name":"platformWallet","type":"address"},{"internalType":"uint256","name":"platformFeeBps","type":"uint256"},{"internalType":"bytes","name":"hint","type":"bytes"}],"name":"tradeWithHintAndFee","outputs":[{"internalType":"uint256","name":"destAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdminQuickly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"sendTo","type":"address"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sendTo","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Deployed Bytecode
0x6080604052600436106101d15760003560e01c80637bb0ea82116100f7578063ac8a584a11610095578063c43190f511610064578063c43190f514610929578063ce56c454146109e5578063dbe2dc9b14610a1e578063f851a44014610a335761020e565b8063ac8a584a1461079b578063b3066d49146107ce578063c0324c7714610813578063c3a2a93a146108435761020e565b8063809a9e55116100d1578063809a9e55146106395780638881654e146106955780638ff68a80146106c85780639870d7fe146107685761020e565b80637bb0ea82146105aa5780637c423f54146105f1578063803d58c8146106065761020e565b80633de39c111161016f57806375829def1161013e57806375829def146105035780637726bed31461053657806377f50f97146105625780637acc8678146105775761020e565b80633de39c1114610455578063408ee7fe1461046a57806352dd35b91461049d5780636ff277de146104d05761020e565b806326782247116101ab578063267822471461033757806327a099d81461036857806332c8bd9f146103cd5780633ccdbb28146104125761020e565b806301a12fd314610213578063088322ef14610248578063238dafe01461030e5761020e565b3661020e5760408051348152905133917f75f33ed68675112c77094e7c5b073890598be1d23e27cd7f6907b4a7d98ac619919081900360200190a2005b600080fd5b34801561021f57600080fd5b506102466004803603602081101561023657600080fd5b50356001600160a01b0316610a48565b005b6102fc600480360361012081101561025f57600080fd5b6001600160a01b03823581169260208101358216926040820135926060830135811692608081013582169260a08201359260c08301359260e0810135909116918101906101208101610100820135600160201b8111156102be57600080fd5b8201836020820111156102d057600080fd5b803590602001918460018302840111600160201b831117156102f157600080fd5b509092509050610bf4565b60408051918252519081900360200190f35b34801561031a57600080fd5b50610323610c62565b604080519115158252519081900360200190f35b34801561034357600080fd5b5061034c610c6b565b604080516001600160a01b039092168252519081900360200190f35b34801561037457600080fd5b5061037d610c7a565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103b95781810151838201526020016103a1565b505050509050019250505060405180910390f35b3480156103d957600080fd5b50610246600480360360608110156103f057600080fd5b506001600160a01b038135811691602081013590911690604001351515610cdc565b34801561041e57600080fd5b506102466004803603606081101561043557600080fd5b506001600160a01b03813581169160208101359160409091013516610d8b565b34801561046157600080fd5b506102fc610e6e565b34801561047657600080fd5b506102466004803603602081101561048d57600080fd5b50356001600160a01b0316610e74565b3480156104a957600080fd5b50610246600480360360208110156104c057600080fd5b50356001600160a01b0316610fcb565b3480156104dc57600080fd5b50610246600480360360208110156104f357600080fd5b50356001600160a01b03166110d4565b34801561050f57600080fd5b506102466004803603602081101561052657600080fd5b50356001600160a01b03166111ad565b34801561054257600080fd5b506102466004803603602081101561055957600080fd5b5035151561125c565b34801561056e57600080fd5b50610246611368565b34801561058357600080fd5b506102466004803603602081101561059a57600080fd5b50356001600160a01b0316611428565b3480156105b657600080fd5b50610246600480360360808110156105cd57600080fd5b506001600160a01b038135169060208101359060408101359060600135151561151b565b3480156105fd57600080fd5b5061037d611789565b34801561061257600080fd5b506102466004803603602081101561062957600080fd5b50356001600160a01b03166117e9565b34801561064557600080fd5b5061067c6004803603606081101561065c57600080fd5b506001600160a01b038135811691602081013590911690604001356118d4565b6040805192835260208301919091528051918290030190f35b3480156106a157600080fd5b506106aa61198e565b60408051938452602084019290925282820152519081900360600190f35b3480156106d457600080fd5b5061067c600480360360a08110156106eb57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b81111561072a57600080fd5b82018360208201111561073c57600080fd5b803590602001918460018302840111600160201b8311171561075d57600080fd5b509092509050611a17565b34801561077457600080fd5b506102466004803603602081101561078b57600080fd5b50356001600160a01b0316611afa565b3480156107a757600080fd5b50610246600480360360208110156107be57600080fd5b50356001600160a01b0316611c53565b3480156107da57600080fd5b50610246600480360360608110156107f157600080fd5b506001600160a01b038135811691602081013582169160409091013516611dfc565b34801561081f57600080fd5b506102466004803603604081101561083657600080fd5b5080359060200135611ffd565b34801561084f57600080fd5b506108586120af565b60405180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156109105781810151838201526020016108f8565b5050505090500197505050505050505060405180910390f35b6102fc600480360361014081101561094057600080fd5b6001600160a01b03823581169260208101358216926040820135926060830135811692608081013582169260a08201359260c08301359260e08101359091169161010082013591908101906101408101610120820135600160201b8111156109a757600080fd5b8201836020820111156109b957600080fd5b803590602001918460018302840111600160201b831117156109da57600080fd5b5090925090506121fe565b3480156109f157600080fd5b5061024660048036036040811015610a0857600080fd5b50803590602001356001600160a01b031661226c565b348015610a2a57600080fd5b506102fc61231a565b348015610a3f57600080fd5b5061034c6123d2565b610a506123e1565b6001600160a01b03811660009081526003602052604090205460ff16610aab576040805162461bcd60e51b815260206004820152600b60248201526a3737ba1030b632b93a32b960a91b604482015290519081900360640190fd5b6001600160a01b0381166000908152600360205260408120805460ff191690555b600554811015610bf057816001600160a01b031660058281548110610aed57fe5b6000918252602090912001546001600160a01b03161415610be857600580546000198101908110610b1a57fe5b600091825260209091200154600580546001600160a01b039092169183908110610b4057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506005805480610b7957fe5b60008281526020808220830160001990810180546001600160a01b0319169055909201909255604080516001600160a01b03861681529182019290925281517f5611bf3e417d124f97bf2c788843ea8bb502b66079fbee02158ef30b172cb762929181900390910190a1610bf0565b600101610acc565b5050565b6000610bfe615e0e565b610c108c8c8b8d8c8c8c8c600061242f565b9050610c528185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124c592505050565b9c9b505050505050505050505050565b600e5460ff1690565b6001546001600160a01b031681565b60606004805480602002602001604051908101604052809291908181526020018280548015610cd257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cb4575b5050505050905090565b600a546001600160a01b03163314610d3b576040805162461bcd60e51b815260206004820152601160248201527f6f6e6c79206b7962657253746f72616765000000000000000000000000000000604482015290519081900360640190fd5b8015610d6b57610d5d6001600160a01b0383168460001963ffffffff612b6c16565b610d6682612c7f565b610d86565b610d866001600160a01b03831684600063ffffffff612b6c16565b505050565b610d936123e1565b826001600160a01b031663a9059cbb82846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610df357600080fd5b505af1158015610e07573d6000803e3d6000fd5b505050506040513d6020811015610e1d57600080fd5b5050604080516001600160a01b0380861682526020820185905283168183015290517f72cb8a894ddb372ceec3d2a7648d86f17d5a15caae0e986c53109b8a9a9385e69181900360600190a1505050565b600d5490565b610e7c6123e1565b6001600160a01b03811660009081526003602052604090205460ff1615610edb576040805162461bcd60e51b815260206004820152600e60248201526d616c65727465722065786973747360901b604482015290519081900360640190fd5b600554603211610f21576040805162461bcd60e51b815260206004820152600c60248201526b6d617820616c65727465727360a01b604482015290519081900360640190fd5b604080516001600160a01b03831681526001602082015281517f5611bf3e417d124f97bf2c788843ea8bb502b66079fbee02158ef30b172cb762929181900390910190a16001600160a01b03166000818152600360205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b0319169091179055565b610fd36123e1565b600a54604080516307f442e160e01b81526001600160a01b03848116600483015260026024830152915191909216916307f442e191604480830192600092919082900301818387803b15801561102857600080fd5b505af115801561103c573d6000803e3d6000fd5b505050506001600160a01b03811661105357600080fd5b6001600160a01b0381166000908152600f602052604090205460ff161561107957600080fd5b6001600160a01b0381166000818152600f6020908152604091829020805460ff19166001179055815192835290517f0b008ff10c7e378a96d6566635e1aa748886d16fb87659faee2aa20608fec8159281900390910190a150565b6110dc6123e1565b6008546001600160a01b038281169116146111aa57600880546001600160a01b0319166001600160a01b03838116918217909255600a54604080516337f93bef60e11b8152600481019390935251921691636ff277de9160248082019260009290919082900301818387803b15801561115457600080fd5b505af1158015611168573d6000803e3d6000fd5b5050604080516001600160a01b038516815290517f16a2e1af8449067f38aa765b54d479785c94d8ebdfbba7b410e3488b0877c1e49350908190036020019150a15b50565b6111b56123e1565b6001600160a01b0381166111fe576040805162461bcd60e51b815260206004820152600b60248201526a06e65772061646d696e20360ac1b604482015290519081900360640190fd5b604080516001600160a01b038316815290517f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc409181900360200190a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b6112646123e1565b801561131c5760075461010090046001600160a01b031661128457600080fd5b6009546001600160a01b031661129957600080fd5b600a60009054906101000a90046001600160a01b03166001600160a01b031663aa1da48a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112e757600080fd5b505afa1580156112fb573d6000803e3d6000fd5b505050506040513d602081101561131157600080fd5b505161131c57600080fd5b600e805460ff191682151517908190556040805160ff90921615158252517f8a846a525e22497042ee2f99423a8ff8bbb831d3ae5384692bf6040f591c1eba916020908290030190a150565b6001546001600160a01b031633146113b5576040805162461bcd60e51b815260206004820152600b60248201526a6e6f742070656e64696e6760a81b604482015290519081900360640190fd5b600154600054604080516001600160a01b03938416815292909116602083015280517f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6114306123e1565b6001600160a01b038116611475576040805162461bcd60e51b8152602060048201526007602482015266061646d696e20360cc1b604482015290519081900360640190fd5b604080516001600160a01b038316815290517f3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc409181900360200190a1600054604080516001600160a01b038085168252909216602083015280517f65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed9281900390910190a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b611523612d69565b8183111561153057611783565b600a5460408051636ac48ac160e11b81526001600160a01b03878116600483015260248201879052604482018690529151606093929092169163d589158291606480820192600092909190829003018186803b15801561158f57600080fd5b505afa1580156115a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156115cc57600080fd5b8101908080516040519392919084600160201b8211156115eb57600080fd5b90830190602082018581111561160057600080fd5b82518660208202830111600160201b8211171561161c57600080fd5b82525081516020918201928201910280838360005b83811015611649578181015183820152602001611631565b5050505090500160405250505090508051600014156116685750611783565b60005b81518110156116f55782156116bb576116ad82828151811061168957fe5b6020026020010151600019886001600160a01b0316612b6c9092919063ffffffff16565b6116b686612c7f565b6116ed565b6116ed8282815181106116ca57fe5b60200260200101516000886001600160a01b0316612b6c9092919063ffffffff16565b60010161166b565b50846001600160a01b03167fd4b0877e3beef91cd767680ac04114217ec7c9cb3a4705c03fc8061de81168fc8284604051808060200183151515158152602001828103825284818151815260200191508051906020019060200280838360005b8381101561176d578181015183820152602001611755565b50505050905001935050505060405180910390a2505b50505050565b60606005805480602002602001604051908101604052809291908181526020018280548015610cd2576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610cb4575050505050905090565b6117f16123e1565b600a5460408051631007ab1960e31b81526001600160a01b0384811660048301529151919092169163803d58c891602480830192600092919082900301818387803b15801561183f57600080fd5b505af1158015611853573d6000803e3d6000fd5b505050506001600160a01b0381166000908152600f602052604090205460ff1661187c57600080fd5b6001600160a01b0381166000818152600f6020908152604091829020805460ff19169055815192835290517fbb9ee888852ae070b75270fa50ea2845ba32102d3a96842c7c416d12aad2f4879281900390910190a150565b600080836001600160a01b0316856001600160a01b031614156118fc57506000905080611986565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316611927615e0e565b61194e60008888851561193a578561193d565b60015b6000600160ff1b600080600061242f565b9050611958612dbd565b60c0820152604080516020810190915260008152611977908290612e5f565b94505060646061850204925050505b935093915050565b600080600061199b61301d565b60095460408051635e89189d60e11b815290519395509193506001600160a01b03169163bd12313a91600480820192602092909190829003018186803b1580156119e457600080fd5b505afa1580156119f8573d6000803e3d6000fd5b505050506040513d6020811015611a0e57600080fd5b50519250909192565b600080866001600160a01b0316886001600160a01b03161415611a3f57506000905080611aef565b611a47615e0e565b611a6d60008a8a8a15611a5a578a611a5d565b60015b6000600160ff1b6000808e61242f565b9050611a77612dbd565b60c0820152604080516020601f8701819004810282018101909252858152600091611abe9184918990899081908401838280828437600092019190915250612e5f92505050565b8095508192505050611aea82600001516040015182846020015160e00151856040015160e0015161303b565b925050505b965096945050505050565b611b026123e1565b6001600160a01b03811660009081526002602052604090205460ff1615611b62576040805162461bcd60e51b815260206004820152600f60248201526e6f70657261746f722065786973747360881b604482015290519081900360640190fd5b600454603211611ba9576040805162461bcd60e51b815260206004820152600d60248201526c6d6178206f70657261746f727360981b604482015290519081900360640190fd5b604080516001600160a01b03831681526001602082015281517f091a7a4b85135fdd7e8dbc18b12fabe5cc191ea867aa3c2e1a24a102af61d58b929181900390910190a16001600160a01b03166000818152600260205260408120805460ff191660019081179091556004805491820181559091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319169091179055565b611c5b6123e1565b6001600160a01b03811660009081526002602052604090205460ff16611cb7576040805162461bcd60e51b815260206004820152600c60248201526b3737ba1037b832b930ba37b960a11b604482015290519081900360640190fd5b6001600160a01b0381166000908152600260205260408120805460ff191690555b600454811015610bf057816001600160a01b031660048281548110611cf957fe5b6000918252602090912001546001600160a01b03161415611df457600480546000198101908110611d2657fe5b600091825260209091200154600480546001600160a01b039092169183908110611d4c57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506004805480611d8557fe5b60008281526020808220830160001990810180546001600160a01b0319169055909201909255604080516001600160a01b03861681529182019290925281517f091a7a4b85135fdd7e8dbc18b12fabe5cc191ea867aa3c2e1a24a102af61d58b929181900390910190a1610bf0565b600101611cd8565b611e046123e1565b6007546001600160a01b038481166101009092041614611e8557600780546001600160a01b038516610100810274ffffffffffffffffffffffffffffffffffffffff00199092169190911790915560408051918252517f5128fc9be01065f3cabe4c8b72796eb6b8a00284f39a2390cd71e91b509f90b69181900360200190a15b6009546001600160a01b03838116911614611eec57600980546001600160a01b0384166001600160a01b0319909116811790915560408051918252517f92b5317eb7846d2e62df8ff23b97a564e012e63defef32777f017249f76bf2649181900360200190a15b6001600160a01b03811615801590611f125750600b546001600160a01b03828116911614155b15611f6957600b80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f95ba6becebde78de944071b522d81414292f67e3d95db7d9df46bb8e8b3da8b89181900360200190a15b600a546040805163d8952a4960e01b81526001600160a01b03868116600483015285811660248301529151919092169163d8952a4991604480830192600092919082900301818387803b158015611fbf57600080fd5b505af1158015611fd3573d6000803e3d6000fd5b505050506001600160a01b038316611fea57600080fd5b6001600160a01b038216610d8657600080fd5b6120056123e1565b600d8290556009546040805163120b888360e31b81526004810184905290516001600160a01b039092169163905c44189160248082019260009290919082900301818387803b15801561205757600080fd5b505af115801561206b573d6000803e3d6000fd5b5050600d54604080519182526020820185905280517fc1e6729d7fd9a615adc03ebe7d8ff15649d8eed7516bf6c30538a1e722bb1975945091829003019150a15050565b600754600854600954600a54600b546040805163fa006d9360e01b8152905160009687968796879687966060966101009095046001600160a01b0390811696948116959381169492811693911691839163fa006d93916004808301928c929190829003018186803b15801561212357600080fd5b505afa158015612137573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561216057600080fd5b8101908080516040519392919084600160201b82111561217f57600080fd5b90830190602082018581111561219457600080fd5b82518660208202830111600160201b821117156121b057600080fd5b82525081516020918201928201910280838360005b838110156121dd5781810151838201526020016121c5565b50505050905001604052505050955095509550955095509550909192939495565b6000612208615e0e565b6122198d8d8c8e8d8d8d8d8d61242f565b905061225b8185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124c592505050565b9d9c50505050505050505050505050565b6122746123e1565b6040516000906001600160a01b0383169084908381818185875af1925050503d80600081146122bf576040519150601f19603f3d011682016040523d82523d6000602084013e6122c4565b606091505b50509050806122d257600080fd5b604080518481526001600160a01b038416602082015281517fec47e7ed86c86774d1a72c19f35c639911393fe7c1a34031fdbd260890da90de929181900390910190a1505050565b60008061232561301d565b9092509050428110801561234357506008546001600160a01b031615155b156123ce5760085460408051639833afaf60e01b815281516001600160a01b0390931692639833afaf926004808401939192918290030181600087803b15801561238c57600080fd5b505af11580156123a0573d6000803e3d6000fd5b505050506040513d60408110156123b657600080fd5b50805160209091015190925090506123ce81836131f0565b5090565b6000546001600160a01b031681565b6000546001600160a01b0316331461242d576040805162461bcd60e51b815260206004820152600a60248201526937b7363c9030b236b4b760b11b604482015290519081900360640190fd5b565b612437615e0e565b80516001600160a01b03808c1690915281518a8216602090910152815160400188905281518982166060909101528151878216608090910152815160a001869052815160c001859052815190841660e09091015280516101000182905261249d896132c4565b602082015160e001526124af886132c4565b604082015160e001529998505050505050505050565b60075460009060ff1661251f576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6007805460ff1916905561253161231a565b60c0840152825161254190613384565b600061254d8484612e5f565b90925090508061258e5760405162461bcd60e51b8152600401808060200182810382526032815260200180615f1e6032913960400191505060405180910390fd5b6a084595161401484a00000081106125df576040805162461bcd60e51b815260206004820152600f60248201526e72617465203e204d41585f5241544560881b604482015290519081900360640190fd5b835160c0015181101561262b576040805162461bcd60e51b815260206004820152600f60248201526e72617465203c206d696e207261746560881b604482015290519081900360640190fd5b835160a0015160009083111561265357845160a00151925061264c856136b0565b905061265b565b508351604001515b612691856000015160200151600080516020615efe83398151915230886020015189606001518a6020015160e0015160126137fe565b6126cb600080516020615efe83398151915286600001516060015187600001516080015188604001518760128b6040015160e001516137fe565b84516020810151604082015191516126e592908490613915565b6126ee85613a06565b8460000151606001516001600160a01b03168560000151602001516001600160a01b03167f30bbea603a7b36858fe5e3ec6ba5ff59dde039d02120d758eacfaed01520577d876060015188608001518960a001518a60200151602001518b60400151602001518c6020015160c001518d6040015160c001518e60200151604001518f6040015160400151604051808a815260200189815260200188815260200180602001806020018060200180602001806020018060200187810387528d818151815260200191508051906020019060200280838360005b838110156127de5781810151838201526020016127c6565b5050505090500187810386528c818151815260200191508051906020019060200280838360005b8381101561281d578181015183820152602001612805565b5050505090500187810385528b818151815260200191508051906020019060200280838360005b8381101561285c578181015183820152602001612844565b5050505090500187810384528a818151815260200191508051906020019060200280838360005b8381101561289b578181015183820152602001612883565b50505050905001878103835289818151815260200191508051906020019060200280838360005b838110156128da5781810151838201526020016128c2565b50505050905001878103825288818151815260200191508051906020019060200280838360005b83811015612919578181015183820152602001612901565b505050509050019f5050505050505050505050505050505060405180910390a3600b546001600160a01b031615612b57576000600b60009054906101000a90046001600160a01b03166001600160a01b0316866000015160e0015187600001516020015188600001516060015189606001518a60200151602001518b604001516020015160405160240180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015612a32578181015183820152602001612a1a565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015612a71578181015183820152602001612a59565b50505050905001985050505050505050506040516020818303038152906040526315fc3ba560e21b6001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518082805190602001908083835b60208310612aeb5780518252601f199092019160209182019101612acc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612b4d576040519150601f19603f3d011682016040523d82523d6000602084013e612b52565b606091505b505050505b50506007805460ff1916600117905592915050565b801580612bf2575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015612bc457600080fd5b505afa158015612bd8573d6000803e3d6000fd5b505050506040513d6020811015612bee57600080fd5b5051155b612c2d5760405162461bcd60e51b8152600401808060200182810382526036815260200180615f7a6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610d86908490613b8c565b6001600160a01b03811660009081526006602052604090205415612ca2576111aa565b6001600160a01b038116600080516020615efe8339815191521415612ce2576001600160a01b0381166000908152600660205260409020601290556111aa565b806001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612d1b57600080fd5b505afa158015612d2f573d6000803e3d6000fd5b505050506040513d6020811015612d4557600080fd5b50516001600160a01b038216600090815260066020526040902060ff909116905550565b3360009081526002602052604090205460ff1661242d576040805162461bcd60e51b815260206004820152600d60248201526c37b7363c9037b832b930ba37b960991b604482015290519081900360640190fd5b600080612dc861301d565b90925090504281108015612de657506008546001600160a01b031615155b156123ce576008546040805163056f534b60e51b815281516001600160a01b039093169263adea696092600480840193919291829003018186803b158015612e2d57600080fd5b505afa158015612e41573d6000803e3d6000fd5b505050506040513d6040811015612e5757600080fd5b505192915050565b600080612e7484600001518560c00151613d44565b612ea4846000015160200151600080516020615efe83398151915286600001516040015187886020015188613ddd565b606085018190526b204fce5e3e250261100000001015612f0b576040805162461bcd60e51b815260206004820152601360248201527f547261646520776569203e204d41585f51545900000000000000000000000000604482015290519081900360640190fd5b6060840151612f1f57506000905080613016565b83516101000151606085015161271091020460a085015261010084015160c085015160608601516127109291839102040281612f5757fe5b046080850181905260a0850151606086015191011115612f7357fe5b60008460a001518560800151866060015103039050612fb0600080516020615efe8339815191528660000151606001518388896040015189613ddd565b92506127108561010001516127108760c0015188606001510281612fd057fe5b040281612fd957fe5b04608086015284516101008101516040909101516130129161271091908203020484876020015160e00151886040015160e0015161303b565b9150505b9250929050565b600c5461ffff600160401b8204169167ffffffffffffffff90911690565b60006b204fce5e3e2502611000000085111561309e576040805162461bcd60e51b815260206004820152601360248201527f737263416d6f756e74203e204d41585f51545900000000000000000000000000604482015290519081900360640190fd5b6b204fce5e3e250261100000008411156130ff576040805162461bcd60e51b815260206004820152601460248201527f64657374416d6f756e74203e204d41585f515459000000000000000000000000604482015290519081900360640190fd5b82821061317b5760128383031115613159576040805162461bcd60e51b8152602060048201526018602482015277647374202d20737263203e204d41585f444543494d414c5360401b604482015290519081900360640190fd5b84838303600a0a02670de0b6b3a764000085028161317357fe5b0490506131e8565b601282840311156131ce576040805162461bcd60e51b8152602060048201526018602482015277737263202d20647374203e204d41585f444543494d414c5360401b604482015290519081900360640190fd5b84828403600a0a670de0b6b3a76400008602028161317357fe5b949350505050565b600160401b821061323a576040805162461bcd60e51b815260206004820152600f60248201526e657870697279206f766572666c6f7760881b604482015290519081900360640190fd5b6113888110613282576040805162461bcd60e51b815260206004820152600f60248201526e66656573206578636565642042505360881b604482015290519081900360640190fd5b600c805461ffff909216600160401b0269ffff00000000000000001967ffffffffffffffff90941667ffffffffffffffff199093169290921792909216179055565b60006001600160a01b038216600080516020615efe83398151915214156132ed5750601261337f565b6001600160a01b0382166000908152600660205260409020548061337c57826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561334457600080fd5b505afa158015613358573d6000803e3d6000fd5b505050506040513d602081101561336e57600080fd5b505160ff16915061337f9050565b90505b919050565b600e5460ff166133ce576040805162461bcd60e51b815260206004820152601060248201526f1b995d1ddbdc9ac8191a5cd8589b195960821b604482015290519081900360640190fd5b336000908152600f602052604090205460ff1661341f576040805162461bcd60e51b815260206004820152600a6024820152693130b21039b2b73232b960b11b604482015290519081900360640190fd5b600d543a1115613462576040805162461bcd60e51b815260206004820152600960248201526867617320707269636560b81b604482015290519081900360640190fd5b6b204fce5e3e25026110000000816040015111156134ba576040805162461bcd60e51b815260206004820152601060248201526f737263416d74203e204d41585f51545960801b604482015290519081900360640190fd5b60408101516134fb576040805162461bcd60e51b81526020600482015260086024820152670c081cdc98d05b5d60c21b604482015290519081900360640190fd5b60808101516001600160a01b0316613547576040805162461bcd60e51b815260206004820152600a6024820152690646573742061646420360b41b604482015290519081900360640190fd5b80606001516001600160a01b031681602001516001600160a01b031614156135a3576040805162461bcd60e51b815260206004820152600a6024820152691cdc98c80f4819195cdd60b21b604482015290519081900360640190fd5b60208101516001600160a01b0316600080516020615efe83398151915214156135db57806040015134146135d657600080fd5b6111aa565b34156135e657600080fd5b806040015181602001516001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561364557600080fd5b505afa158015613659573d6000803e3d6000fd5b505050506040513d602081101561366f57600080fd5b505110156111aa576040805162461bcd60e51b81526020600482015260096024820152686e6f20746f6b656e7360b81b604482015290519081900360640190fd5b80516060015160009081906001600160a01b0316600080516020615efe833981519152146137115761370a83608001518460a00151856060015103036012856040015160e00151866000015160a001518760400151614714565b9050613719565b50815160a001515b600061271084600001516101000151028461010001518560c001510201612710800203612710808402028161374a57fe5b04905061375b818560600151614953565b6060850181905261010085015160c086015161271092028290040204608085015283516101000151606085015161271091020460a08501528351602001516001600160a01b0316600080516020615efe833981519152146137e057835160400151602085015160e081015160608701516137d9939260129190614714565b92506137e8565b836060015192505b8351604001518311156137f757fe5b5050919050565b856001600160a01b0316876001600160a01b031614156138d5576001600160a01b03851630146138d0576040516000906001600160a01b0387169085908381818185875af1925050503d8060008114613873576040519150601f19603f3d011682016040523d82523d6000602084013e613878565b606091505b50509050806138ce576040805162461bcd60e51b815260206004820152601460248201527f73656e64206465737420717479206661696c6564000000000000000000000000604482015290519081900360640190fd5b505b61390c565b6138e2848888858561496d565b6001600160a01b038516301461390c5761390c6001600160a01b038716868563ffffffff614cac16565b50505050505050565b82821015611783576001600160a01b038416600080516020615efe83398151915214156139ea576040516000906001600160a01b03831690848603908381818185875af1925050503d8060008114613989576040519150601f19603f3d011682016040523d82523d6000602084013e61398e565b606091505b50509050806139e4576040805162461bcd60e51b815260206004820152601260248201527f53656e64206368616e6765206661696c65640000000000000000000000000000604482015290519081900360640190fd5b50611783565b6117836001600160a01b0385168284860363ffffffff614cac16565b60a081015160808201510180613a1c57506111aa565b606080613a2884614cfe565b91509150600760019054906101000a90046001600160a01b03166001600160a01b031663b7c5ab4184600080516020615efe8339815191528585896000015160e001518a60a001518b608001516040518863ffffffff1660e01b815260040180876001600160a01b03166001600160a01b031681526020018060200180602001866001600160a01b03166001600160a01b03168152602001858152602001848152602001838103835288818151815260200191508051906020019060200280838360005b83811015613b04578181015183820152602001613aec565b50505050905001838103825287818151815260200191508051906020019060200280838360005b83811015613b43578181015183820152602001613b2b565b50505050905001985050505050505050506000604051808303818588803b158015613b6d57600080fd5b505af1158015613b81573d6000803e3d6000fd5b505050505050505050565b613b9e826001600160a01b0316614f73565b613bef576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310613c2d5780518252601f199092019160209182019101613c0e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c8f576040519150601f19603f3d011682016040523d82523d6000602084013e613c94565b606091505b509150915081613ceb576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561178357808060200190516020811015613d0757600080fd5b50516117835760405162461bcd60e51b815260040180806020018281038252602a815260200180615f50602a913960400191505060405180910390fd5b61271082610100015110613d92576040805162461bcd60e51b815260206004820152601060248201526f0e0d8c2e8ccdee4da8ccaca40d0d2ced60831b604482015290519081900360640190fd5b6127108182846101000151010110610bf0576040805162461bcd60e51b81526020600482015260096024820152680cccacae640d0d2ced60bb1b604482015290519081900360640190fd5b6000856001600160a01b0316876001600160a01b03161415613e0057508361470a565b6009548451602001516000916001600160a01b039081169163910ffc71918b918b9116600080516020615efe83398151915214801590613e5c57508851606001516001600160a01b0316600080516020615efe83398151915214155b6040516001600160e01b031960e086901b1681526001600160a01b0380851660048301908152908416602483015282151560448301526080606483019081528a5160848401528a518b9360a40190602085019080838360005b83811015613ecd578181015183820152602001613eb5565b50505050905090810190601f168015613efa5780820380516001836020036101000a031916815260200191505b509550505050505060006040518083038186803b158015613f1a57600080fd5b505afa158015613f2e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526060811015613f5757600080fd5b8101908080516040519392919084600160201b821115613f7657600080fd5b908301906020820185811115613f8b57600080fd5b82518660208202830111600160201b82111715613fa757600080fd5b82525081516020918201928201910280838360005b83811015613fd4578181015183820152602001613fbc565b5050505090500160405260200180516040519392919084600160201b821115613ffc57600080fd5b90830190602082018581111561401157600080fd5b82518660208202830111600160201b8211171561402d57600080fd5b82525081516020918201928201910280838360005b8381101561405a578181015183820152602001614042565b5050505090500160405260200180519060200190929190505050866020018760a0018295508390528390525050506000600a60009054906101000a90046001600160a01b03166001600160a01b03166350dceb7486602001518b8b6040518463ffffffff1660e01b81526004018080602001846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828103825285818151815260200191508051906020019060200280838360005b8381101561413457818101518382015260200161411c565b5050505090500194505050505060006040518083038186803b15801561415957600080fd5b505afa15801561416d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052608081101561419657600080fd5b815160208301805160405192949293830192919084600160201b8211156141bc57600080fd5b9083019060208201858111156141d157600080fd5b82518660208202830111600160201b821117156141ed57600080fd5b82525081516020918201928201910280838360005b8381101561421a578181015183820152602001614202565b5050505090500160405260200180516040519392919084600160201b82111561424257600080fd5b90830190602082018581111561425757600080fd5b82518660208202830111600160201b8211171561427357600080fd5b82525081516020918201928201910280838360005b838110156142a0578181015183820152602001614288565b5050505090500160405260200180516040519392919084600160201b8211156142c857600080fd5b9083019060208201858111156142dd57600080fd5b82518660208202830111600160201b821117156142f957600080fd5b82525081516020918201928201910280838360005b8381101561432657818101518382015260200161430e565b505050509190910160405250505090895250608088015260608701529050806143545760009250505061470a565b8460a0015151856020015151146143a4576040805162461bcd60e51b815260206004820152600f60248201526e6261642073706c697420617272617960881b604482015290519081900360640190fd5b846060015151856020015151146143f2576040805162461bcd60e51b815260206004820152600d60248201526c6261642066656520617272617960981b604482015290519081900360640190fd5b84608001515185602001515114614443576040805162461bcd60e51b815260206004820152601060248201526f6261642072656261746520617272617960801b604482015290519081900360640190fd5b8451516020860151511461449e576040805162461bcd60e51b815260206004820152601360248201527f6261642061646472657373657320617272617900000000000000000000000000604482015290519081900360640190fd5b60606144ad868b8b8b8b614fac565b905060018360018111156144bd57fe5b14156146f9576060600960009054906101000a90046001600160a01b03166001600160a01b03166384d174bc8c8c8a60c00151868c604001516040518663ffffffff1660e01b815260040180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561457d578181015183820152602001614565565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156145bc5781810151838201526020016145a4565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156145fb5781810151838201526020016145e3565b505050509050019850505050505050505060006040518083038186803b15801561462457600080fd5b505afa158015614638573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561466157600080fd5b8101908080516040519392919084600160201b82111561468057600080fd5b90830190602082018581111561469557600080fd5b82518660208202830111600160201b821117156146b157600080fd5b82525081516020918201928201910280838360005b838110156146de5781810151838201526020016146c6565b5050505090500160405250505090506146f78782615335565b505b6147048a87896157b2565b93505050505b9695505050505050565b600080805b8360c0015151811015614768578360400151818151811061473657fe5b60200260200101518460c00151828151811061474e57fe5b602002602001015102820191508080600101915050614719565b5060608360c001515167ffffffffffffffff8111801561478757600080fd5b506040519080825280602002602001820160405280156147b1578160200160208202803683370190505b50905060008080805b8760c001515181101561493f578760c0015181815181106147d757fe5b60200260200101519250876040015181815181106147f157fe5b60200260200101518302898960400151838151811061480c57fe5b6020026020010151858c02028161481f57fe5b0414614872576040805162461bcd60e51b815260206004820152601760248201527f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000604482015290519081900360640190fd5b60018860c00151510381146148ab57858860400151828151811061489257fe5b6020026020010151848b0202816148a557fe5b046148af565b8389035b915081840193506148d9828c8c8b6040015185815181106148cc57fe5b6020026020010151615975565b8582815181106148e557fe5b602002602001018181525050828582815181106148fe57fe5b6020026020010151111561491a578b965050505050505061494a565b84818151811061492657fe5b60200260200101518701965080806001019150506147ba565b5050505060c0840152505b95945050505050565b60008183116149625782614964565b815b90505b92915050565b60006001600160a01b038516600080516020615efe8339815191521461499c576149978530615b17565b61499f565b60005b905060006149ad8530615b17565b905060005b875151811015614ca25760006001600160a01b038816600080516020615efe833981519152146149e35760006149fc565b8860c0015182815181106149f357fe5b60200260200101515b905088600001518281518110614a0e57fe5b60200260200101516001600160a01b0316636cf69811828a8c60c001518681518110614a3657fe5b60200260200101518b308f604001518981518110614a5057fe5b602090810291909101810151604080516001600160e01b031960e08b901b1681526001600160a01b039788166004820152602481019690965293861660448601529190941660648401526084830152600160a48301525160c4808301939282900301818588803b158015614ac357600080fd5b505af1158015614ad7573d6000803e3d6000fd5b50505050506040513d6020811015614aee57600080fd5b5051614b41576040805162461bcd60e51b815260206004820152601460248201527f72657365727665207472616465206661696c6564000000000000000000000000604482015290519081900360640190fd5b60006001600160a01b038916600080516020615efe83398151915214614beb57614b6b8930615b17565b9050808510158015614b9557508960c001518381518110614b8857fe5b6020026020010151818603115b15614be7576040805162461bcd60e51b815260206004820152601960248201527f726573657276652074616b6573206869676820616d6f756e7400000000000000604482015290519081900360640190fd5b8094505b6000614c278b60c001518581518110614c0057fe5b602002602001015189898e604001518881518110614c1a57fe5b6020026020010151615bd2565b9050614c338930615b17565b915084821080614c44575080858303105b15614c96576040805162461bcd60e51b815260206004820152601a60248201527f726573657276652072657475726e73206c6f7720616d6f756e74000000000000604482015290519081900360640190fd5b509250506001016149b2565b5050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610d86908490613b8c565b6060808260e0015167ffffffffffffffff81118015614d1c57600080fd5b50604051908082528060200260200182016040528015614d46578160200160208202803683370190505b5091508260e0015167ffffffffffffffff81118015614d6457600080fd5b50604051908082528060200260200182016040528015614d8e578160200160208202803683370190505b5090508260e0015160001415614da357614f6e565b600060608460e0015167ffffffffffffffff81118015614dc257600080fd5b50604051908082528060200260200182016040528015614dec578160200160208202803683370190505b509050614e058184876020015185896101000151615d59565b9150614e1d8184876040015185896101000151615d59565b50600a5460405163051e7cc760e11b81526020600482018181528451602484015284516001600160a01b0390941693630a3cf98e9386938392604490920191818601910280838360005b83811015614e7f578181015183820152602001614e67565b505050509050019250505060006040518083038186803b158015614ea257600080fd5b505afa158015614eb6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015614edf57600080fd5b8101908080516040519392919084600160201b821115614efe57600080fd5b908301906020820185811115614f1357600080fd5b82518660208202830111600160201b82111715614f2f57600080fd5b82525081516020918201928201910280838360005b83811015614f5c578181015183820152602001614f44565b50505050905001604052505050935050505b915091565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906131e8575050151592915050565b6020850151516060906000806001600160a01b038816600080516020615efe8339815191521415614ff6576127108560c0015186606001510281614fec57fe5b0486039150615000565b505060c083015184905b8267ffffffffffffffff8111801561501757600080fd5b50604051908082528060200260200182016040528015615041578160200160208202803683370190505b5060c08a01528267ffffffffffffffff8111801561505e57600080fd5b50604051908082528060200260200182016040528015615088578160200160208202803683370190505b5060408a01528267ffffffffffffffff811180156150a557600080fd5b506040519080825280602002602001820160405280156150cf578160200160208202803683370190505b50935060005b838110156153285760008a60a0015182815181106150ef57fe5b602002602001015111801561511d57506127108a60a00151828151811061511257fe5b602002602001015111155b61516e576040805162461bcd60e51b815260206004820152601160248201527f696e76616c69642073706c697420627073000000000000000000000000000000604482015290519081900360640190fd5b8960600151818151811061517e57fe5b6020026020010151156151ea576127108a60a00151828151811061519e57fe5b60200260200101518402816151af57fe5b048a60c0015182815181106151c057fe5b602002602001018181525050818582815181106151d957fe5b60200260200101818152505061522c565b6127108a60a0015182815181106151fd57fe5b602002602001015188028161520e57fe5b048a60c00151828151811061521f57fe5b6020026020010181815250505b895180518290811061523a57fe5b60200260200101516001600160a01b0316637cd442728a8a8d60c00151858151811061526257fe5b6020026020010151436040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200182815260200194505050505060206040518083038186803b1580156152d857600080fd5b505afa1580156152ec573d6000803e3d6000fd5b505050506040513d602081101561530257600080fd5b505160408b015180518390811061531557fe5b60209081029190910101526001016150d5565b5050505095945050505050565b805182515181111561538e576040805162461bcd60e51b815260206004820152601a60248201527f646f4d617463683a20746f6f206d616e79207265736572766573000000000000604482015290519081900360640190fd5b60608167ffffffffffffffff811180156153a757600080fd5b506040519080825280602002602001820160405280156153d1578160200160208202803683370190505b50905060608267ffffffffffffffff811180156153ed57600080fd5b50604051908082528060200260200182016040528015615417578160200160208202803683370190505b50905060608367ffffffffffffffff8111801561543357600080fd5b5060405190808252806020026020018201604052801561545d578160200160208202803683370190505b50905060608467ffffffffffffffff8111801561547957600080fd5b506040519080825280602002602001820160405280156154a3578160200160208202803683370190505b50905060608567ffffffffffffffff811180156154bf57600080fd5b506040519080825280602002602001820160405280156154e9578160200160208202803683370190505b50905060608667ffffffffffffffff8111801561550557600080fd5b5060405190808252806020026020018201604052801561552f578160200160208202803683370190505b50905060608767ffffffffffffffff8111801561554b57600080fd5b50604051908082528060200260200182016040528015615575578160200160208202803683370190505b50905060005b8881101561577f578a600001518a828151811061559457fe5b6020026020010151815181106155a657fe5b60200260200101518882815181106155ba57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508a602001518a82815181106155eb57fe5b6020026020010151815181106155fd57fe5b602002602001015187828151811061561157fe5b6020026020010181815250508a60a001518a828151811061562e57fe5b60200260200101518151811061564057fe5b602002602001015186828151811061565457fe5b6020026020010181815250508a606001518a828151811061567157fe5b60200260200101518151811061568357fe5b602002602001015185828151811061569757fe5b6020026020010190151590811515815250508a608001518a82815181106156ba57fe5b6020026020010151815181106156cc57fe5b60200260200101518482815181106156e057fe5b6020026020010190151590811515815250508a60c001518a828151811061570357fe5b60200260200101518151811061571557fe5b602002602001015183828151811061572957fe5b6020026020010181815250508a604001518a828151811061574657fe5b60200260200101518151811061575857fe5b602002602001015182828151811061576c57fe5b602090810291909101015260010161557b565b50958952602089019490945260a088019290925260608701526080860152604085019190915260c0909301929092525050565b600080806001600160a01b038616600080516020615efe833981519152146157de578460e001516157e1565b60125b905060006001600160a01b038716600080516020615efe8339815191521461580a576012615810565b8560e001515b905060005b8651518110156159545760008111801561586657508660200151600182038151811061583d57fe5b602002602001015160001c8760200151828151811061585857fe5b602002602001015160001c11155b1561587857600094505050505061596e565b8660a00151818151811061588857fe5b60200260200101518401935060006158c38860c0015183815181106158a957fe5b602002602001015185858b604001518681518110614c1a57fe5b9050806158d85760009550505050505061596e565b8086019550876060015182815181106158ed57fe5b60200260200101511561594b578760a00151828151811061590a57fe5b6020026020010151876101000181815101915081815250508760800151828151811061593257fe5b60200260200101511561594b5760e08701805160010190525b50600101615815565b50612710831461596a576000935050505061596e565b5050505b9392505050565b60006b204fce5e3e250261100000008511156159cb576040805162461bcd60e51b815260206004820152601060248201526f647374517479203e204d41585f51545960801b604482015290519081900360640190fd5b6a084595161401484a000000821115615a1d576040805162461bcd60e51b815260206004820152600f60248201526e72617465203e204d41585f5241544560881b604482015290519081900360640190fd5b600080848610615a945760128587031115615a7a576040805162461bcd60e51b8152602060048201526018602482015277737263202d20647374203e204d41585f444543494d414c5360401b604482015290519081900360640190fd5b5050828403600a0a8502670de0b6b3a76400000282615afd565b60128686031115615ae7576040805162461bcd60e51b8152602060048201526018602482015277647374202d20737263203e204d41585f444543494d414c5360401b604482015290519081900360640190fd5b5050670de0b6b3a76400008502848403600a0a83025b8060018284010381615b0b57fe5b04979650505050505050565b60006001600160a01b038316600080516020615efe8339815191521415615b4957506001600160a01b03811631614967565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015615b9f57600080fd5b505afa158015615bb3573d6000803e3d6000fd5b505050506040513d6020811015615bc957600080fd5b50519050614967565b60006b204fce5e3e25026110000000851115615c28576040805162461bcd60e51b815260206004820152601060248201526f737263517479203e204d41585f51545960801b604482015290519081900360640190fd5b6a084595161401484a000000821115615c7a576040805162461bcd60e51b815260206004820152600f60248201526e72617465203e204d41585f5241544560881b604482015290519081900360640190fd5b838310615cec5760128484031115615cd4576040805162461bcd60e51b8152602060048201526018602482015277647374202d20737263203e204d41585f444543494d414c5360401b604482015290519081900360640190fd5b670de0b6b3a7640000858302858503600a0a02613173565b60128385031115615d3f576040805162461bcd60e51b8152602060048201526018602482015277737263202d20647374203e204d41585f444543494d414c5360401b604482015290519081900360640190fd5b828403600a0a670de0b6b3a7640000028286028161317357fe5b600082815b856080015151811015615e035785608001518181518110615d7b57fe5b602002602001015115615dfb5785602001518181518110615d9857fe5b6020026020010151888381518110615dac57fe5b602002602001018181525050836127108760a001518381518110615dcc57fe5b60200260200101510281615ddc57fe5b04878381518110615de957fe5b60209081029190910101526001909101905b600101615d5e565b509695505050505050565b604051806101200160405280615e22615e6c565b8152602001615e2f615eb8565b8152602001615e3c615eb8565b81526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915290565b6040518061010001604052806060815260200160608152602001606081526020016060815260200160608152602001606081526020016060815260200160008152509056fe000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee747261646520696e76616c69642c2069662068696e7420696e766f6c7665642c2074727920706172736548696e74204150495361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212209837ac8c78168c99ffeec8ad9c6978d5a3d7e8fe46c2159b336d66b149d2cc5064736f6c63430006060033
Deployed Bytecode Sourcemap
38297:48308:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43125:36;;;43151:9;43125:36;;;;43139:10;;43125:36;;;;;;;;;;38297:48308;;12:1:-1;9;2:12;3023:493:0;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3023:493:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3023:493:0;-1:-1:-1;;;;;3023:493:0;;:::i;:::-;;43985:782;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;43985:782:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;43985:782:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;43985:782:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;43985:782:0;;-1:-1:-1;43985:782:0;-1:-1:-1;43985:782:0;:::i;:::-;;;;;;;;;;;;;;;;56201:92;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56201:92:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;1114:27;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1114:27:0;;;:::i;:::-;;;;-1:-1:-1;;;;;1114:27:0;;;;;;;;;;;;;;1746:105;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1746:105:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1746:105:0;;;;;;;;;;;;;;;;;46809:390;;5:9:-1;2:2;;;27:1;24;17:12;2:2;46809:390:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;46809:390:0;;;;;;;;;;;;;;;;;;;:::i;5906:235::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5906:235:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;5906:235:0;;;;;;;;;;;;;;;;;:::i;56004:106::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56004:106:0;;;:::i;1970:359::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1970:359:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1970:359:0;-1:-1:-1;;;;;1970:359:0;;:::i;50671:353::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;50671:353:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;50671:353:0;-1:-1:-1;;;;;50671:353:0;;:::i;49580:335::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;49580:335:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;49580:335:0;-1:-1:-1;;;;;49580:335:0;;:::i;4174:215::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4174:215:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;4174:215:0;-1:-1:-1;;;;;4174:215:0;;:::i;50243:376::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;50243:376:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;50243:376:0;;;;:::i;2801:214::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2801:214:0;;;:::i;4554:256::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4554:256:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;4554:256:0;-1:-1:-1;;;;;4554:256:0;;:::i;47716:877::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;47716:877:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;47716:877:0;;;;;;;;;;;;;;;;;;;;:::i;1859:103::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1859:103:0;;;:::i;51032:299::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;51032:299:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;51032:299:0;-1:-1:-1;;;;;51032:299:0;;:::i;53596:870::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;53596:870:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;53596:870:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;54862:444;;5:9:-1;2:2;;;27:1;24;17:12;2:2;54862:444:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;51929:1190;;5:9:-1;2:2;;;27:1;24;17:12;2:2;51929:1190:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;51929:1190:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;51929:1190:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;51929:1190:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;51929:1190:0;;-1:-1:-1;51929:1190:0;-1:-1:-1;51929:1190:0;:::i;2337:372::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2337:372:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;2337:372:0;-1:-1:-1;;;;;2337:372:0;;:::i;3524:509::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3524:509:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3524:509:0;-1:-1:-1;;;;;3524:509:0;;:::i;48601:971::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;48601:971:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;48601:971:0;;;;;;;;;;;;;;;;;;;:::i;49923:312::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;49923:312:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;49923:312:0;;;;;;;:::i;55314:618::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;55314:618:0;;;:::i;:::-;;;;;-1:-1:-1;;;;;55314:618:0;-1:-1:-1;;;;;55314:618:0;;;;;;-1:-1:-1;;;;;55314:618:0;-1:-1:-1;;;;;55314:618:0;;;;;;-1:-1:-1;;;;;55314:618:0;-1:-1:-1;;;;;55314:618:0;;;;;;-1:-1:-1;;;;;55314:618:0;-1:-1:-1;;;;;55314:618:0;;;;;;-1:-1:-1;;;;;55314:618:0;-1:-1:-1;;;;;55314:618:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;55314:618:0;;;;;;;;;;;;;;;;;;;;;;45652:857;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;45652:857:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;45652:857:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;45652:857:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;45652:857:0;;-1:-1:-1;45652:857:0;-1:-1:-1;45652:857:0;:::i;5549:234::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5549:234:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5549:234:0;;;;;;-1:-1:-1;;;;;5549:234:0;;:::i;56599:418::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56599:418:0;;;:::i;1087:20::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1087:20:0;;;:::i;3023:493::-;3081:11;:9;:11::i;:::-;-1:-1:-1;;;;;3111:17:0;;;;;;:8;:17;;;;;;;;3103:41;;;;;-1:-1:-1;;;3103:41:0;;;;;;;;;;;;-1:-1:-1;;;3103:41:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;3162:17:0;;;;;;:8;:17;;;;;3155:24;;-1:-1:-1;;3155:24:0;;;3192:317;3216:13;:20;3212:24;;3192:317;;;3282:7;-1:-1:-1;;;;;3262:27:0;:13;3276:1;3262:16;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3262:16:0;:27;3258:240;;;3329:13;3343:20;;-1:-1:-1;;3343:24:0;;;3329:39;;;;;;;;;;;;;;;;3310:13;:16;;-1:-1:-1;;;;;3329:39:0;;;;3324:1;;3310:16;;;;;;;;;;;;;;:58;;;;;-1:-1:-1;;;;;3310:58:0;;;;;-1:-1:-1;;;;;3310:58:0;;;;;;3387:13;:19;;;;;;;;;;;;;;;;;-1:-1:-1;;3387:19:0;;;;;-1:-1:-1;;;;;;3387:19:0;;;;;;;;;3430:28;;;-1:-1:-1;;;;;3430:28:0;;;;;;;;;;;;;;;;;;;;;;;;3477:5;;3258:240;3238:3;;3192:317;;;;3023:493;:::o;43985:782::-;44314:18;44345:26;;:::i;:::-;44374:343;44412:6;44438:3;44462:4;44492:9;44529:11;44570:13;44617:17;44665:8;44704:1;44374:14;:343::i;:::-;44345:372;;44737:22;44743:9;44754:4;;44737:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;44737:5:0;;-1:-1:-1;;;44737:22:0:i;:::-;44730:29;43985:782;-1:-1:-1;;;;;;;;;;;;43985:782:0:o;56201:92::-;56276:9;;;;56201:92;:::o;1114:27::-;;;-1:-1:-1;;;;;1114:27:0;;:::o;1746:105::-;1793:16;1829:14;1822:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1822:21:0;;;;;;;;;;;;;;;;;;;;;;;1746:105;:::o;46809:390::-;46972:12;;-1:-1:-1;;;;;46972:12:0;46950:10;:35;46942:65;;;;;-1:-1:-1;;;46942:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;47024:3;47020:172;;;47044:41;-1:-1:-1;;;;;47044:17:0;;47062:7;-1:-1:-1;;47044:41:0;:17;:41;:::i;:::-;47100:18;47112:5;47100:11;:18::i;:::-;47020:172;;;47151:29;-1:-1:-1;;;;;47151:17:0;;47169:7;47178:1;47151:29;:17;:29;:::i;:::-;46809:390;;;:::o;5906:235::-;6029:11;:9;:11::i;:::-;6051:5;-1:-1:-1;;;;;6051:14:0;;6066:6;6074;6051:30;;;;;;;;;;;;;-1:-1:-1;;;;;6051:30:0;-1:-1:-1;;;;;6051:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;6051:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6051:30:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;6097:36:0;;;-1:-1:-1;;;;;6097:36:0;;;;;6051:30;6097:36;;;;;;;;;;;;;;;;;;;;;;5906:235;;;:::o;56004:106::-;56086:16;;56004:106;:::o;1970:359::-;2028:11;:9;:11::i;:::-;-1:-1:-1;;;;;2059:20:0;;;;;;:8;:20;;;;;;;;2058:21;2050:48;;;;;-1:-1:-1;;;2050:48:0;;;;;;;;;;;;-1:-1:-1;;;2050:48:0;;;;;;;;;;;;;;;2140:13;:20;1369:2;-1:-1:-1;2132:62:0;;;;;-1:-1:-1;;;2132:62:0;;;;;;;;;;;;-1:-1:-1;;;2132:62:0;;;;;;;;;;;;;;;2212:30;;;-1:-1:-1;;;;;2212:30:0;;;;2237:4;2212:30;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2253:20:0;;;;;:8;:20;;;;;:27;;-1:-1:-1;;2253:27:0;2276:4;2253:27;;;;;;2291:13;27:10:-1;;23:18;;;45:23;;2291:30:0;;;;;;;-1:-1:-1;;;;;;2291:30:0;;;;;;1970:359::o;50671:353::-;50742:11;:9;:11::i;:::-;50764:12;;:60;;;-1:-1:-1;;;50764:60:0;;-1:-1:-1;;;;;50764:60:0;;;;;;;41605:1;50764:60;;;;;;:12;;;;;:26;;:60;;;;;:12;;:60;;;;;;;:12;;:60;;;2:2:-1;;;;27:1;24;17:12;2:2;50764:60:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;;50843:24:0;;50835:33;;12:1:-1;9;2:12;50835:33:0;-1:-1:-1;;;;;50888:31:0;;;;;;:19;:31;;;;;;;;50887:32;50879:41;;12:1:-1;9;2:12;50879:41:0;-1:-1:-1;;;;;50933:31:0;;;;;;:19;:31;;;;;;;;;:38;;-1:-1:-1;;50933:38:0;50967:4;50933:38;;;50989:27;;;;;;;;;;;;;;;;;50671:353;:::o;49580:335::-;49699:11;:9;:11::i;:::-;49725:8;;-1:-1:-1;;;;;49725:21:0;;;:8;;:21;49721:187;;49763:8;:20;;-1:-1:-1;;;;;;49763:20:0;-1:-1:-1;;;;;49763:20:0;;;;;;;;;49798:12;;:52;;;-1:-1:-1;;;49798:52:0;;;;;;;;;;:12;;;:32;;:52;;;;;-1:-1:-1;;49798:52:0;;;;;;;;-1:-1:-1;49798:12:0;:52;;;2:2:-1;;;;27:1;24;17:12;2:2;49798:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;49870:26:0;;;-1:-1:-1;;;;;49870:26:0;;;;;;;;-1:-1:-1;49870:26:0;;;;;;;-1:-1:-1;49870:26:0;49721:187;49580:335;:::o;4174:215::-;4233:11;:9;:11::i;:::-;-1:-1:-1;;;;;4263:22:0;;4255:46;;;;;-1:-1:-1;;;4255:46:0;;;;;;;;;;;;-1:-1:-1;;;4255:46:0;;;;;;;;;;;;;;;4317:30;;;-1:-1:-1;;;;;4317:30:0;;;;;;;;;;;;;;;4358:12;:23;;-1:-1:-1;;;;;;4358:23:0;-1:-1:-1;;;;;4358:23:0;;;;;;;;;;4174:215::o;50243:376::-;50295:11;:9;:11::i;:::-;50323:6;50319:212;;;50354:15;;;;;-1:-1:-1;;;;;50354:15:0;50346:47;;12:1:-1;9;2:12;50346:47:0;50416:19;;-1:-1:-1;;;;;50416:19:0;50408:55;;12:1:-1;9;2:12;50408:55:0;50486:12;;;;;;;;;-1:-1:-1;;;;;50486:12:0;-1:-1:-1;;;;;50486:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;50486:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;50486:32:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;50486:32:0;50478:41;;12:1:-1;9;2:12;50478:41:0;50543:9;:18;;-1:-1:-1;;50543:18:0;;;;;;;;;50579:32;;;50543:18;50601:9;;;50579:32;;;;;;;;;;;;;;;50243:376;:::o;2801:214::-;2849:12;;-1:-1:-1;;;;;2849:12:0;2865:10;2849:26;2841:50;;;;;-1:-1:-1;;;2841:50:0;;;;;;;;;;;;-1:-1:-1;;;2841:50:0;;;;;;;;;;;;;;;2920:12;;;2934:5;2907:33;;;-1:-1:-1;;;;;2920:12:0;;;2907:33;;2934:5;;;;2907:33;;;;;;;;;;;;;;;;2959:12;;;;2951:20;;-1:-1:-1;;;;;;2951:20:0;;;-1:-1:-1;;;;;2959:12:0;;2951:20;;;;2982:25;;;2801:214::o;4554:256::-;4620:11;:9;:11::i;:::-;-1:-1:-1;;;;;4650:22:0;;4642:42;;;;;-1:-1:-1;;;4642:42:0;;;;;;;;;;;;-1:-1:-1;;;4642:42:0;;;;;;;;;;;;;;;4700:30;;;-1:-1:-1;;;;;4700:30:0;;;;;;;;;;;;;;;4769:5;;4746:29;;;-1:-1:-1;;;;;4746:29:0;;;;;4769:5;;;4746:29;;;;;;;;;;;;;;;;4786:5;:16;;-1:-1:-1;;;;;;4786:16:0;-1:-1:-1;;;;;4786:16:0;;;;;;;;;;4554:256::o;47716:877::-;47871:14;:12;:14::i;:::-;47915:8;47902:10;:21;47898:99;;;47979:7;;47898:99;48037:12;;:96;;;-1:-1:-1;;;48037:96:0;;-1:-1:-1;;;;;48037:96:0;;;;;;;;;;;;;;;;;;;;;48009:25;;48037:12;;;;;:43;;:96;;;;;:12;;:96;;;;;;;;:12;:96;;;2:2:-1;;;;27:1;24;17:12;2:2;48037:96:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48037:96:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;48037:96:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;15:2;7:11;;4:2;;;31:1;28;21:12;4:2;48037:96:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;48037:96:0;;421:4:-1;412:14;;;;48037:96:0;;;;;412:14:-1;48037:96:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;48037:96:0;;;;;;;;;;;48009:124;;48150:8;:15;48169:1;48150:20;48146:98;;;48226:7;;;48146:98;48260:6;48256:268;48276:8;:15;48272:1;:19;48256:268;;;48317:3;48313:200;;;48341:45;48359:8;48368:1;48359:11;;;;;;;;;;;;;;-1:-1:-1;;48341:5:0;-1:-1:-1;;;;;48341:17:0;;;:45;;;;;:::i;:::-;48405:18;48417:5;48405:11;:18::i;:::-;48313:200;;;48464:33;48482:8;48491:1;48482:11;;;;;;;;;;;;;;48495:1;48464:5;-1:-1:-1;;;;;48464:17:0;;;:33;;;;;:::i;:::-;48293:3;;48256:268;;;;48564:5;-1:-1:-1;;;;;48541:44:0;;48571:8;48581:3;48541:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;48541:44:0;;;;;;;;;;;;;;;;;;47716:877;;;;;;:::o;1859:103::-;1905:16;1941:13;1934:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1934:20:0;;;;;;;;;;;;;;;;;;;;;;1859:103;:::o;51032:299::-;51106:11;:9;:11::i;:::-;51130:12;;:41;;;-1:-1:-1;;;51130:41:0;;-1:-1:-1;;;;;51130:41:0;;;;;;;;;:12;;;;;:29;;:41;;;;;:12;;:41;;;;;;;:12;;:41;;;2:2:-1;;;;27:1;24;17:12;2:2;51130:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;;51192:31:0;;;;;;:19;:31;;;;;;;;51184:40;;12:1:-1;9;2:12;51184:40:0;-1:-1:-1;;;;;51237:31:0;;51271:5;51237:31;;;:19;:31;;;;;;;;;:39;;-1:-1:-1;;51237:39:0;;;51294:29;;;;;;;;;;;;;;;;;51032:299;:::o;53596:870::-;53717:20;53739:17;53780:4;-1:-1:-1;;;;;53773:11:0;:3;-1:-1:-1;;;;;53773:11:0;;53769:30;;;-1:-1:-1;53794:1:0;;-1:-1:-1;53794:1:0;53786:13;;53769:30;53833:19;53824:28;;53865:26;;:::i;:::-;53894:363;53948:1;53971:3;53995:4;54026:8;;54025:20;;54042:3;54025:20;;;54038:1;54025:20;54089:1;-1:-1:-1;;;54162:1:0;54210;54244;53894:14;:363::i;:::-;53865:392;;54296:15;:13;:15::i;:::-;54270:23;;;:41;54343:34;;;;;;;;;-1:-1:-1;54343:34:0;;;;54270:9;;54343:19;:34::i;:::-;54324:53;-1:-1:-1;;54424:3:0;54418:2;54403:17;;54402:25;;-1:-1:-1;;;53596:870:0;;;;;;;:::o;54862:444::-;54970:25;55010:21;55046:23;55132:20;:18;:20::i;:::-;55183:19;;:46;;;-1:-1:-1;;;55183:46:0;;;;55097:55;;-1:-1:-1;55097:55:0;;-1:-1:-1;;;;;;55183:19:0;;:44;;:46;;;;;;;;;;;;;;;:19;:46;;;2:2:-1;;;;27:1;24;17:12;2:2;55183:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55183:46:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;55183:46:0;;-1:-1:-1;54862:444:0;;;:::o;51929:1190::-;52188:26;52229:23;52291:4;-1:-1:-1;;;;;52284:11:0;:3;-1:-1:-1;;;;;52284:11:0;;52280:30;;;-1:-1:-1;52305:1:0;;-1:-1:-1;52305:1:0;52297:13;;52280:30;52323:26;;:::i;:::-;52352:382;52406:1;52429:3;52453:4;52484:11;;52483:26;;52503:6;52483:26;;;52499:1;52483:26;52553:1;-1:-1:-1;;;52626:1:0;52674;52708:14;52352;:382::i;:::-;52323:411;;52773:15;:13;:15::i;:::-;52747:23;;;:41;52865:36;;;;;;;;;;;;;;;;;;;;;;52801:18;;52865:36;;52747:9;;52896:4;;;;;;52865:36;;52896:4;;;;52865:36;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;52865:19:0;;-1:-1:-1;;;52865:36:0:i;:::-;52830:71;;;;;;;;52932:179;52962:9;:15;;;:25;;;53002:10;53027:9;:20;;;:29;;;53071:9;:20;;;:29;;;52932:15;:179::i;:::-;52914:197;;51929:1190;;;;;;;;;;;;:::o;2337:372::-;2397:11;:9;:11::i;:::-;-1:-1:-1;;;;;2428:22:0;;;;;;:9;:22;;;;;;;;2427:23;2419:51;;;;;-1:-1:-1;;;2419:51:0;;;;;;;;;;;;-1:-1:-1;;;2419:51:0;;;;;;;;;;;;;;;2512:14;:21;1369:2;-1:-1:-1;2504:64:0;;;;;-1:-1:-1;;;2504:64:0;;;;;;;;;;;;-1:-1:-1;;;2504:64:0;;;;;;;;;;;;;;;2586:32;;;-1:-1:-1;;;;;2586:32:0;;;;2613:4;2586:32;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2629:22:0;;;;;:9;:22;;;;;:29;;-1:-1:-1;;2629:29:0;2654:4;2629:29;;;;;;2669:14;27:10:-1;;23:18;;;45:23;;2669:32:0;;;;;;;-1:-1:-1;;;;;;2669:32:0;;;;;;2337:372::o;3524:509::-;3584:11;:9;:11::i;:::-;-1:-1:-1;;;;;3614:19:0;;;;;;:9;:19;;;;;;;;3606:44;;;;;-1:-1:-1;;;3606:44:0;;;;;;;;;;;;-1:-1:-1;;;3606:44:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;3668:19:0;;;;;;:9;:19;;;;;3661:26;;-1:-1:-1;;3661:26:0;;;3700:326;3724:14;:21;3720:25;;3700:326;;;3792:8;-1:-1:-1;;;;;3771:29:0;:14;3786:1;3771:17;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3771:17:0;:29;3767:248;;;3841:14;3856:21;;-1:-1:-1;;3856:25:0;;;3841:41;;;;;;;;;;;;;;;;3821:14;:17;;-1:-1:-1;;;;;3841:41:0;;;;3836:1;;3821:17;;;;;;;;;;;;;;:61;;;;;-1:-1:-1;;;;;3821:61:0;;;;;-1:-1:-1;;;;;3821:61:0;;;;;;3901:14;:20;;;;;;;;;;;;;;;;;-1:-1:-1;;3901:20:0;;;;;-1:-1:-1;;;;;;3901:20:0;;;;;;;;;3945:30;;;-1:-1:-1;;;;;3945:30:0;;;;;;;;;;;;;;;;;;;;;;;;3994:5;;3767:248;3747:3;;3700:326;;48601:971;48786:11;:9;:11::i;:::-;48814:15;;-1:-1:-1;;;;;48814:35:0;;;:15;;;;;:35;48810:162;;48866:15;:34;;-1:-1:-1;;;;;48866:34:0;;;;;-1:-1:-1;;48866:34:0;;;;;;;;;;48920:40;;;;;;;;;;;;;;;;48810:162;48988:19;;-1:-1:-1;;;;;48988:43:0;;;:19;;:43;48984:186;;49048:19;:42;;-1:-1:-1;;;;;49048:42:0;;-1:-1:-1;;;;;;49048:42:0;;;;;;;;49110:48;;;;;;;;;;;;;;;;48984:186;-1:-1:-1;;;;;49187:27:0;;;;;;49186:58;;-1:-1:-1;49234:9:0;;-1:-1:-1;;;;;49220:23:0;;;49234:9;;49220:23;;49186:58;49182:161;;;49261:9;:22;;-1:-1:-1;;;;;49261:22:0;;-1:-1:-1;;;;;;49261:22:0;;;;;;;;49303:28;;;;;;;;;;;;;;;;49182:161;49355:12;;:83;;;-1:-1:-1;;;49355:83:0;;-1:-1:-1;;;;;49355:83:0;;;;;;;;;;;;;;;;:12;;;;;:25;;:83;;;;;:12;;:83;;;;;;;:12;;:83;;;2:2:-1;;;;27:1;24;17:12;2:2;49355:83:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;;49457:39:0;;49449:48;;12:1:-1;9;2:12;49449:48:0;-1:-1:-1;;;;;49516:47:0;;49508:56;;12:1:-1;9;2:12;49923:312:0;50016:11;:9;:11::i;:::-;50038:16;:31;;;50080:19;;:68;;;-1:-1:-1;;;50080:68:0;;;;;;;;;;-1:-1:-1;;;;;50080:19:0;;;;:44;;:68;;;;;:19;;:68;;;;;;;;:19;;:68;;;2:2:-1;;;;27:1;24;17:12;2:2;50080:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;50186:16:0;;50164:63;;;;;;;;;;;;;;;;-1:-1:-1;50164:63:0;;;;;;-1:-1:-1;50164:63:0;49923:312;;:::o;55314:618::-;55745:15;;55775:8;;55798:19;;55832:12;;55859:9;;55883:30;;;-1:-1:-1;;;55883:30:0;;;;55402:39;;;;;;;;;;55648:47;;55745:15;;;;-1:-1:-1;;;;;55745:15:0;;;;55775:8;;;;55798:19;;;;55832:12;;;;55859:9;;;55832:12;;55883:28;;:30;;;;;55402:39;;55883:30;;;;;;;55832:12;55883:30;;;2:2:-1;;;;27:1;24;17:12;2:2;55883:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55883:30:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;55883:30:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;15:2;7:11;;4:2;;;31:1;28;21:12;4:2;55883:30:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;55883:30:0;;421:4:-1;412:14;;;;55883:30:0;;;;;412:14:-1;55883:30:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;55883:30:0;;;;;;;;;;;55723:201;;;;;;;;;;;;55314:618;;;;;;:::o;45652:857::-;46037:18;46068:26;;:::i;:::-;46097:362;46135:6;46161:3;46185:4;46215:9;46252:11;46293:13;46340:17;46388:14;46433;46097;:362::i;:::-;46068:391;;46479:22;46485:9;46496:4;;46479:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;46479:5:0;;-1:-1:-1;;;46479:22:0:i;:::-;46472:29;45652:857;-1:-1:-1;;;;;;;;;;;;;45652:857:0:o;5549:234::-;5632:11;:9;:11::i;:::-;5673:30;;5655:12;;-1:-1:-1;;;;;5673:11:0;;;5692:6;;5655:12;5673:30;5655:12;5673:30;5692:6;5673:11;:30;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;5654:49:0;;;5722:7;5714:16;;12:1:-1;9;2:12;5714:16:0;5746:29;;;;;;-1:-1:-1;;;;;5746:29:0;;;;;;;;;;;;;;;;;;;5549:234;;;:::o;56599:418::-;56649:21;56683:23;56754:20;:18;:20::i;:::-;56719:55;;-1:-1:-1;56719:55:0;-1:-1:-1;56809:3:0;56791:21;;:49;;;;-1:-1:-1;56816:8:0;;-1:-1:-1;;;;;56816:8:0;:24;;56791:49;56787:223;;;56892:8;;:43;;;-1:-1:-1;;;56892:43:0;;;;-1:-1:-1;;;;;56892:8:0;;;;:41;;:43;;;;;;;;;;;;;:8;;:43;;;2:2:-1;;;;27:1;24;17:12;2:2;56892:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56892:43:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;56892:43:0;;;;;;;;;-1:-1:-1;56892:43:0;-1:-1:-1;56950:48:0;56892:43;;56950:16;:48::i;:::-;56599:418;;:::o;1087:20::-;;;-1:-1:-1;;;;;1087:20:0;;:::o;4818:96::-;4886:5;;-1:-1:-1;;;;;4886:5:0;4872:10;:19;4864:42;;;;;-1:-1:-1;;;4864:42:0;;;;;;;;;;;;-1:-1:-1;;;4864:42:0;;;;;;;;;;;;;;;4818:96::o;66370:947::-;66708:26;;:::i;:::-;66747:15;;-1:-1:-1;;;;;66747:31:0;;;;;;66789:15;;:25;;;:19;;;;:25;66825:15;;:25;;:37;;;66873:15;;:27;;;:20;;;;:27;66911:15;;:41;;;:27;;;;:41;66963:15;;:29;;:45;;;67019:15;;:33;;:53;;;67083:15;;:47;;;:30;;;;:47;67141:15;;:30;;:47;;;67233:16;66811:3;67233:11;:16::i;:::-;67201:20;;;;:29;;:48;67292:17;67304:4;67292:11;:17::i;:::-;67260:20;;;;:29;;:49;:9;66370:947;-1:-1:-1;;;;;;;;;66370:947:0:o;62520:3091::-;13742:11;;62657:18;;13742:11;;13734:55;;;;;-1:-1:-1;;;13734:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;13867:11;:19;;-1:-1:-1;;13867:19:0;;;62719:24:::1;:22;:24::i;:::-;62693:23;::::0;::::1;:50:::0;62775:15;;62756:35:::1;::::0;:18:::1;:35::i;:::-;62804:26;62876:36;62896:9;62907:4;62876:19;:36::i;:::-;62841:71:::0;;-1:-1:-1;62841:71:0;-1:-1:-1;62933:22:0;62925:85:::1;;;;-1:-1:-1::0;;;62925:85:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6729:17:::0;63029:29;::::1;63021:57;;;::::0;;-1:-1:-1;;;63021:57:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;63021:57:0;;;;;;;;;;;;;::::1;;63119:15:::0;;:33:::1;;::::0;63097:55;::::1;;63089:83;;;::::0;;-1:-1:-1;;;63089:83:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;63089:83:0;;;;;;;;;;;;;::::1;;63238:15:::0;;:29:::1;;::::0;63185:23:::1;::::0;63225:42;::::1;63221:328;;;63362:15:::0;;:29:::1;;::::0;;-1:-1:-1;63424:37:0::1;63362:9:::0;63424:26:::1;:37::i;:::-;63406:55;;63221:328;;;-1:-1:-1::0;63512:15:0;;:25:::1;;::::0;63221:328:::1;63586:259;63616:9;:15;;;:19;;;-1:-1:-1::0;;;;;;;;;;;63690:4:0::1;63710:9;:20;;;63745:9;:18;;;63778:9;:20;;;:29;;;6873:2;63586:15;:259::i;:::-;63883:266;-1:-1:-1::0;;;;;;;;;;;63945:9:0::1;:15;;;:20;;;63980:9;:15;;;:27;;;64022:9;:20;;;64057:10;6873:2;64109:9;:20;;;:29;;;63883:15;:266::i;:::-;64189:15:::0;;:19:::1;::::0;::::1;::::0;64223:25:::1;::::0;::::1;::::0;64293:22;;64162:164:::1;::::0;64223:25;64263:15;;64162:12:::1;:164::i;:::-;64339:21;64350:9;64339:10;:21::i;:::-;64449:9;:15;;;:20;;;-1:-1:-1::0;;;;;64378:581:0::1;64409:9;:15;;;:19;;;-1:-1:-1::0;;;;;64378:581:0::1;;64497:9;:18;;;64545:9;:23;;;64605:9;:24;;;64652:9;:20;;;:24;;;64699:9;:20;;;:24;;;64753:9;:20;;;:31;;;64814:9;:20;;;:31;;;64870:9;:20;;;:26;;;64921:9;:20;;;:26;;;64378:581;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;64378:581:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;64378:581:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;64378:581:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;64378:581:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;64378:581:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;64378:581:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64976:9;::::0;-1:-1:-1;;;;;64976:9:0::1;:26:::0;64972:600:::1;;65020:12;65046:9;;;;;;;;;-1:-1:-1::0;;;;;65046:9:0::1;-1:-1:-1::0;;;;;65038:23:0::1;65211:9;:15;;;:30;;;65264:9;:15;;;:19;;;65306:9;:15;;;:20;;;65349:9;:18;;;65390:9;:20;;;:24;;;65437:9;:20;;;:24;;;65080:400;;;;;;-1:-1:-1::0;;;;;65080:400:0::1;-1:-1:-1::0;;;;;65080:400:0::1;;;;;;-1:-1:-1::0;;;;;65080:400:0::1;-1:-1:-1::0;;;;;65080:400:0::1;;;;;;-1:-1:-1::0;;;;;65080:400:0::1;-1:-1:-1::0;;;;;65080:400:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;65080:400:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::1;84:18:::0;71:11;;::::1;64:39:::0;52:2:::1;45:10;8:100;;;12:14;65080:400:0;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;65080:400:0;;;-1:-1:-1::0;;;;;;;;65080:400:0::1;;38:4:-1;29:7;25:18;67:10;61:17;-1:-1:::0;;;;;199:8:::1;192:4;186;182:15;179:29;167:10;160:49;0:215;;;65080:400:0;65038:457;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10:::0;;164:23;;-1:-1;;139:12;;;;98:2:::1;89:12:::0;;::::1;::::0;114::::1;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;65038:457:0;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;-1:-1:::0;;;;64972:600:0::1;-1:-1:-1::0;;14047:11:0;:18;;-1:-1:-1;;14047:18:0;14061:4;14047:18;;;62520:3091;;-1:-1:-1;;62520:3091:0:o;23409:622::-;23779:10;;;23778:62;;-1:-1:-1;23795:39:0;;;-1:-1:-1;;;23795:39:0;;23819:4;23795:39;;;;-1:-1:-1;;;;;23795:39:0;;;;;;;;;:15;;;;;;:39;;;;;;;;;;;;;;;:15;:39;;;2:2:-1;;;;27:1;24;17:12;2:2;23795:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;23795:39:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;23795:39:0;:44;23778:62;23770:152;;;;-1:-1:-1;;;23770:152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23960:62;;;-1:-1:-1;;;;;23960:62:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;23960:62:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;23933:90:0;;23953:5;;23933:19;:90::i;7612:277::-;-1:-1:-1;;;;;7671:15:0;;;;;;:8;:15;;;;;;:20;7667:33;;7693:7;;7667:33;-1:-1:-1;;;;;7730:26:0;;-1:-1:-1;;;;;;;;;;;7730:26:0;7726:156;;;-1:-1:-1;;;;;7773:15:0;;;;;;:8;:15;;;;;6873:2;7773:30;;7726:156;;;7854:5;-1:-1:-1;;;;;7854:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7854:16:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7854:16:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;7854:16:0;-1:-1:-1;;;;;7836:15:0;;;;;;:8;7854:16;7836:15;;;;:34;;;;;;7612:277;:::o;5031:104::-;5098:10;5088:21;;;;:9;:21;;;;;;;;5080:47;;;;;-1:-1:-1;;;5080:47:0;;;;;;;;;;;;-1:-1:-1;;;5080:47:0;;;;;;;;;;;;;;77633:342;77681:21;77715:23;77784:20;:18;:20::i;:::-;77749:55;;-1:-1:-1;77749:55:0;-1:-1:-1;77839:3:0;77821:21;;:49;;;;-1:-1:-1;77846:8:0;;-1:-1:-1;;;;;77846:8:0;:24;;77821:49;77817:151;;;77922:8;;:34;;;-1:-1:-1;;;77922:34:0;;;;-1:-1:-1;;;;;77922:8:0;;;;:32;;:34;;;;;;;;;;;;;:8;:34;;;2:2:-1;;;;27:1;24;17:12;2:2;77922:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77922:34:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;77922:34:0;;77633:342;-1:-1:-1;;77633:342:0:o;68008:1982::-;68134:18;68154:26;68198:58;68215:9;:15;;;68232:9;:23;;;68198:16;:58::i;:::-;68366:222;68408:9;:15;;;:19;;;-1:-1:-1;;;;;;;;;;;68474:9:0;:15;;;:25;;;68514:9;68538;:20;;;68573:4;68366:27;:222::i;:::-;68345:18;;;:243;;;6663:6;-1:-1:-1;68609:29:0;68601:61;;;;;-1:-1:-1;;;68601:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;68677:18;;;;68673:69;;-1:-1:-1;68725:1:0;;-1:-1:-1;68725:1:0;68717:13;;68673:69;68830:15;;:30;;;68809:18;;;;6905:5;;68809:51;68808:59;68781:24;;;:86;68975:25;;;;68941:23;;;;68920:18;;;;6905:5;;68975:25;6905:5;;68920:44;68919:52;68918:82;68917:103;;;;;;68878:23;;;:142;;;69089:24;;;;69040:18;;;;69063:50;;-1:-1:-1;69040:74:0;69033:82;;;;69211:20;69307:9;:24;;;69268:9;:23;;;69234:9;:18;;;:57;:97;69211:120;;69357:210;-1:-1:-1;;;;;;;;;;;69431:9:0;:15;;;:20;;;69466:12;69493:9;69517;:20;;;69552:4;69357:27;:210::i;:::-;69344:223;;6905:5;69677:9;:25;;;6905:5;69643:9;:23;;;69622:9;:18;;;:44;69621:52;;;;;;69620:82;69619:103;;;;;;69580:23;;;:142;69821:15;;:30;;;;69786:25;;;;;69756:226;;6905:5;;69815:36;;;69786:66;:72;69873:10;69898:9;:20;;;:29;;;69942:9;:20;;;:29;;;69756:15;:226::i;:::-;69735:247;;68008:1982;;;;;;;:::o;77983:220::-;78105:14;:21;;-1:-1:-1;;;78105:21:0;;;;78164:30;;;;;77983:220::o;10946:775::-;11118:7;6663:6;11146:9;:20;;11138:52;;;;;-1:-1:-1;;;11138:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;6663:6;11209:10;:21;;11201:54;;;;;-1:-1:-1;;;11201:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;11287:11;11272;:26;11268:446;;6823:2;11338:11;11324;:25;11323:43;;11315:80;;;;;-1:-1:-1;;;11315:80:0;;;;;;;;;;;;-1:-1:-1;;;11315:80:0;;;;;;;;;;;;;;;11482:9;11466:11;11452;:25;11447:2;:31;11446:45;6612:6;11419:10;:22;11418:74;;;;;;11410:83;;;;11268:446;6823:2;11549:11;11535;:25;11534:43;;11526:80;;;;;-1:-1:-1;;;11526:80:0;;;;;;;;;;;;-1:-1:-1;;;11526:80:0;;;;;;;;;;;;;;;11692:9;11675:11;11661;:25;11656:2;:31;6612:6;11630:10;:22;:58;11629:72;;;;11268:446;10946:775;;;;;;:::o;57991:319::-;-1:-1:-1;;;58086:15:0;:23;58078:51;;;;;-1:-1:-1;;;58078:51:0;;;;;;;;;;;;-1:-1:-1;;;58078:51:0;;;;;;;;;;;;;;;58157:7;58148:16;;58140:44;;;;;-1:-1:-1;;;58140:44:0;;;;;;;;;;;;-1:-1:-1;;;58140:44:0;;;;;;;;;;;;;;;58197:14;:56;;58264:38;;;;-1:-1:-1;;;58264:38:0;-1:-1:-1;;58197:56:0;;;;-1:-1:-1;;58197:56:0;;;;;;;58264:38;;;;;;;57991:319::o;8249:426::-;8307:7;-1:-1:-1;;;;;8331:26:0;;-1:-1:-1;;;;;;;;;;;8331:26:0;8327:51;;;-1:-1:-1;6873:2:0;8359:19;;8327:51;-1:-1:-1;;;;;8436:15:0;;8412:21;8436:15;;;:8;:15;;;;;;8591:18;8587:47;;8618:5;-1:-1:-1;;;;;8618:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8618:16:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8618:16:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;8618:16:0;8611:23;;;-1:-1:-1;8611:23:0;;-1:-1:-1;8611:23:0;8587:47;8654:13;-1:-1:-1;8249:426:0;;;;:::o;76626:895::-;76717:9;;;;76709:38;;;;;-1:-1:-1;;;76709:38:0;;;;;;;;;;;;-1:-1:-1;;;76709:38:0;;;;;;;;;;;;;;;76786:10;76766:31;;;;:19;:31;;;;;;;;76758:54;;;;;-1:-1:-1;;;76758:54:0;;;;;;;;;;;;-1:-1:-1;;;76758:54:0;;;;;;;;;;;;;;;76846:16;;76831:11;:31;;76823:53;;;;;-1:-1:-1;;;76823:53:0;;;;;;;;;;;;-1:-1:-1;;;76823:53:0;;;;;;;;;;;;;;;6663:6;76895:5;:15;;;:26;;76887:55;;;;;-1:-1:-1;;;76887:55:0;;;;;;;;;;;;-1:-1:-1;;;76887:55:0;;;;;;;;;;;;;;;76961:15;;;;76953:41;;;;;-1:-1:-1;;;76953:41:0;;;;;;;;;;;;-1:-1:-1;;;76953:41:0;;;;;;;;;;;;;;;77013:17;;;;-1:-1:-1;;;;;77013:31:0;77005:54;;;;;-1:-1:-1;;;77005:54:0;;;;;;;;;;;;-1:-1:-1;;;77005:54:0;;;;;;;;;;;;;;;77091:5;:10;;;-1:-1:-1;;;;;77078:23:0;:5;:9;;;-1:-1:-1;;;;;77078:23:0;;;77070:46;;;;;-1:-1:-1;;;77070:46:0;;;;;;;;;;;;-1:-1:-1;;;77070:46:0;;;;;;;;;;;;;;;77133:9;;;;-1:-1:-1;;;;;77133:30:0;-1:-1:-1;;;;;;;;;;;77133:30:0;77129:385;;;77201:5;:15;;;77188:9;:28;77180:37;;12:1:-1;9;2:12;77180:37:0;77129:385;;;77292:9;:14;77284:23;;12:1:-1;9;2:12;77284:23:0;77473:5;:15;;;77435:5;:9;;;-1:-1:-1;;;;;77435:19:0;;77463:4;77435:34;;;;;;;;;;;;;-1:-1:-1;;;;;77435:34:0;-1:-1:-1;;;;;77435:34:0;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;77435:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77435:34:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;77435:34:0;:53;;77427:75;;;;;-1:-1:-1;;;77427:75:0;;;;;;;;;;;;-1:-1:-1;;;77427:75:0;;;;;;;;;;;;;;82479:1890;82695:15;;:20;;;82610:23;;;;-1:-1:-1;;;;;82695:41:0;-1:-1:-1;;;;;;;;;;;82695:41:0;82691:473;;82777:289;82862:9;:23;;;82835:9;:24;;;82814:9;:18;;;:45;:71;6873:2;82935:9;:20;;;:29;;;82983:9;:15;;;:29;;;83031:9;:20;;;82777:18;:289::i;:::-;82753:313;;82691:473;;;-1:-1:-1;83123:15:0;;:29;;;82691:473;83242:19;6905:5;83449:9;:15;;;:30;;;:53;83404:9;:25;;;83361:9;:23;;;:68;:141;6905:5;;83330:9;83329:174;6905:5;;83278:21;:27;:33;83277:227;;;;;;83242:262;;83536:38;83542:11;83555:9;:18;;;83536:5;:38::i;:::-;83515:18;;;:59;;;83750:25;;;;83716:23;;;;6905:5;;83695:44;83694:52;;;83693:82;83692:103;83653:23;;;:142;83855:15;;:30;;;83834:18;;;;6905:5;;83834:51;83833:59;83806:24;;;:86;83909:15;;:19;;;-1:-1:-1;;;;;83909:40:0;-1:-1:-1;;;;;;;;;;;83909:40:0;83905:392;;84021:15;;:25;;;84065:20;;;;:29;;;;84144:18;;;;83984:232;;84021:25;6873:2;;84144:18;83984;:232::i;:::-;83966:250;;83905:392;;;84267:9;:18;;;84249:36;;83905:392;84335:15;;:25;;;84316:44;;;84309:52;;;;82479:1890;;;;;:::o;58901:1027::-;59196:4;-1:-1:-1;;;;;59189:11:0;:3;-1:-1:-1;;;;;59189:11:0;;59185:362;;;-1:-1:-1;;;;;59323:30:0;;59347:4;59323:30;59319:196;;59393:47;;59375:12;;-1:-1:-1;;;;;59393:16:0;;;59417:18;;59375:12;59393:47;59375:12;59393:47;59417:18;59393:16;:47;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;59374:66:0;;;59467:7;59459:40;;;;;-1:-1:-1;;;59459:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59319:196;;59529:7;;59185:362;59559:156;59602:12;59629:3;59647:4;59666:11;59692:12;59559:28;:156::i;:::-;-1:-1:-1;;;;;59732:28:0;;59755:4;59732:28;59728:193;;59859:50;-1:-1:-1;;;;;59859:17:0;;59877:11;59890:18;59859:50;:17;:50;:::i;:::-;58901:1027;;;;;;;:::o;65776:586::-;65967:9;65947:17;:29;65943:412;;;-1:-1:-1;;;;;66054:24:0;;-1:-1:-1;;;;;;;;;;;66054:24:0;66050:294;;;66118:55;;66100:12;;-1:-1:-1;;;;;66118:11:0;;;66138:29;;;;66100:12;66118:55;66100:12;66118:55;66138:29;66118:11;:55;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;66099:74:0;;;66200:7;66192:38;;;;;-1:-1:-1;;;66192:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;66050:294;;;;66271:57;-1:-1:-1;;;;;66271:16:0;;66288:6;66297:29;;;66271:57;:16;:57;:::i;57181:802::-;57293:24;;;;57267:23;;;;:50;57387:12;57383:38;;57414:7;;;57383:38;57510:30;57555:33;57602:27;57619:9;57602:16;:27::i;:::-;57495:134;;;;57709:15;;;;;;;;;-1:-1:-1;;;;;57709:15:0;-1:-1:-1;;;;;57709:26:0;;57743:7;-1:-1:-1;;;;;;;;;;;57798:13:0;57826:16;57857:9;:15;;;:30;;;57902:9;:24;;;57941:9;:23;;;57709:266;;;;;;;;;;;;;-1:-1:-1;;;;;57709:266:0;-1:-1:-1;;;;;57709:266:0;;;;;;;;;;;;-1:-1:-1;;;;;57709:266:0;-1:-1:-1;;;;;57709:266:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57709:266:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57709:266:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;57709:266:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57709:266:0;;;;;57181:802;;;;:::o;25055:1115::-;25660:27;25668:5;-1:-1:-1;;;;;25660:25:0;;:27::i;:::-;25652:71;;;;;-1:-1:-1;;;25652:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;25797:12;25811:23;25846:5;-1:-1:-1;;;;;25838:19:0;25858:4;25838:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;25838:25:0;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;25796:67:0;;;;25882:7;25874:52;;;;;-1:-1:-1;;;25874:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25943:17;;:21;25939:224;;26085:10;26074:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;26074:30:0;26066:85;;;;-1:-1:-1;;;26066:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78376:253;6905:5;78483;:20;;;:26;78475:55;;;;;-1:-1:-1;;;78475:55:0;;;;;;;;;;;;-1:-1:-1;;;78475:55:0;;;;;;;;;;;;;;;6905:5;78588:13;78572;78549:5;:20;;;:36;:52;:58;78541:80;;;;;-1:-1:-1;;;78541:80:0;;;;;;;;;;;;-1:-1:-1;;;78541:80:0;;;;;;;;;;;;;;70118:2477;70364:18;70406:4;-1:-1:-1;;;;;70399:11:0;:3;-1:-1:-1;;;;;70399:11:0;;70395:60;;;-1:-1:-1;70434:9:0;70427:16;;70395:60;70661:19;;70752:15;;:19;;;70467:52;;-1:-1:-1;;;;;70661:19:0;;;;:38;;70714:3;;70732:4;;70752:40;-1:-1:-1;;;;;;;;;;;70752:40:0;;;;70751:89;;-1:-1:-1;70798:15:0;;:20;;;-1:-1:-1;;;;;70798:41:0;-1:-1:-1;;;;;;;;;;;70798:41:0;;70751:89;70661:209;;-1:-1:-1;;;;;;70661:209:0;;;;;;;-1:-1:-1;;;;;70661:209:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70855:4;;70661:209;;;;;;;;;;-1:-1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;70661:209:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;70661:209:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;70661:209:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;70661:209:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;15:2;7:11;;4:2;;;31:1;28;21:12;4:2;70661:209:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;70661:209:0;;421:4:-1;412:14;;;;70661:209:0;;;;;412:14:-1;70661:209:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;70661:209:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;70661:209:0;;421:4:-1;412:14;;;;70661:209:0;;;;;412:14:-1;70661:209:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;70661:209:0;;;;;;;;;;;;;;;;;;;;;;70587:12;:16;;70605:12;:22;;70586:284;;;;;;;;;;;;70881:25;71049:12;;;;;;;;;-1:-1:-1;;;;;71049:12:0;-1:-1:-1;;;;;71049:28:0;;71078:12;:16;;;71096:3;71101:4;71049:57;;;;;;;;;;;;;;;;-1:-1:-1;;;;;71049:57:0;-1:-1:-1;;;;;71049:57:0;;;;;;-1:-1:-1;;;;;71049:57:0;-1:-1:-1;;;;;71049:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;71049:57:0;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71049:57:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;71049:57:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;71049:57:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;15:3;7:12;;4:2;;;32:1;29;22:12;4:2;71049:57:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:20;;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;71049:57:0;;421:4:-1;412:14;;;;71049:57:0;;;;;412:14:-1;71049:57:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;71049:57:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;71049:57:0;;421:4:-1;412:14;;;;71049:57:0;;;;;412:14:-1;71049:57:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;71049:57:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;71049:57:0;;421:4:-1;412:14;;;;71049:57:0;;;;;412:14:-1;71049:57:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;-1:-1;;;;71049:57:0;;;;;;-1:-1:-1;;;70917:189:0;;;-1:-1:-1;70974:34:0;;;70917:189;70940:32;;;70917:189;;-1:-1:-1;70917:189:0;71119:61;;71167:1;71160:8;;;;;;71119:61;71227:12;:22;;;:29;71200:12;:16;;;:23;:56;71192:84;;;;;-1:-1:-1;;;71192:84:0;;;;;;;;;;;;-1:-1:-1;;;71192:84:0;;;;;;;;;;;;;;;71322:12;:32;;;:39;71295:12;:16;;;:23;:66;71287:92;;;;;-1:-1:-1;;;71287:92:0;;;;;;;;;;;;-1:-1:-1;;;71287:92:0;;;;;;;;;;;;;;;71425:12;:34;;;:41;71398:12;:16;;;:23;:68;71390:97;;;;;-1:-1:-1;;;71390:97:0;;;;;;;;;;;;-1:-1:-1;;;71390:97:0;;;;;;;;;;;;;;;71533:22;;:29;71506:16;;;;:23;:56;71498:88;;;;;-1:-1:-1;;;71498:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;71710:37;71750:148;71790:12;71817:3;71835:4;71854:9;71878;71750:25;:148::i;:::-;71710:188;-1:-1:-1;72038:45:0;72019:15;:64;;;;;;;;;72015:403;;;72100:32;72135:19;;;;;;;;;-1:-1:-1;;;;;72135:19:0;-1:-1:-1;;;;;72135:27:0;;72181:3;72203:4;72226:12;:23;;;72268:20;72307:12;:18;;;72135:205;;;;;;;;;;;;;-1:-1:-1;;;;;72135:205:0;-1:-1:-1;;;;;72135:205:0;;;;;;-1:-1:-1;;;;;72135:205:0;-1:-1:-1;;;;;72135:205:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;72135:205:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;72135:205:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;72135:205:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;72135:205:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;72135:205:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;72135:205:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;15:2;7:11;;4:2;;;31:1;28;21:12;4:2;72135:205:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;72135:205:0;;421:4:-1;412:14;;;;72135:205:0;;;;;412:14:-1;72135:205:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;72135:205:0;;;;;;;;;;;72100:240;;72357:49;72376:12;72390:15;72357:18;:49::i;:::-;72015:403;;72523:64;72558:3;72563:12;72577:9;72523:34;:64::i;:::-;72510:77;;70118:2477;;;;;;;;;;;;:::o;84743:1859::-;84962:20;;;85037:165;85061:12;:23;;;:30;85057:1;:34;85037:165;;;85169:12;:18;;;85188:1;85169:21;;;;;;;;;;;;;;85140:12;:23;;;85164:1;85140:26;;;;;;;;;;;;;;:50;85113:77;;;;85093:3;;;;;;;85037:165;;;;85214:30;85261:12;:23;;;:30;85247:45;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;85247:45:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;85247:45:0;-1:-1:-1;85214:78:0;-1:-1:-1;85303:23:0;;;;85408:1039;85432:12;:23;;;:30;85428:1;:34;85408:1039;;;85503:12;:23;;;85527:1;85503:26;;;;;;;;;;;;;;85484:45;;85663:12;:18;;;85682:1;85663:21;;;;;;;;;;;;;;85644:16;:40;85608:10;85584:12;:18;;;85603:1;85584:21;;;;;;;;;;;;;;85565:16;85552:10;:29;:53;:66;;;;;;:132;85544:186;;;;;-1:-1:-1;;;85544:186:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;85802:1;85769:12;:23;;;:30;:34;85763:1;:41;:213;;85953:23;85907:12;:18;;;85926:1;85907:21;;;;;;;;;;;;;;85888:16;85875:10;:29;:53;85874:102;;;;;;85763:213;;;85838:15;85825:10;:28;85763:213;85745:231;;86010:15;85991:34;;;;86061:160;86090:15;86124:11;86154:12;86185;:18;;;86204:1;86185:21;;;;;;;;;;;;;;86061:10;:160::i;:::-;86042:13;86056:1;86042:16;;;;;;;;;;;;;:179;;;;;86259:16;86240:13;86254:1;86240:16;;;;;;;;;;;;;;:35;86236:151;;;86362:9;86355:16;;;;;;;;;;86236:151;86419:13;86433:1;86419:16;;;;;;;;;;;;;;86403:32;;;;85464:3;;;;;;;85408:1039;;;-1:-1:-1;;;;86555:23:0;;;:39;-1:-1:-1;84743:1859:0;;;;;;;;:::o;11729:108::-;11789:7;11820:1;11816;:5;:13;;11828:1;11816:13;;;11824:1;11816:13;11809:20;;11729:108;;;;;:::o;60248:2083::-;60527:24;-1:-1:-1;;;;;60555:24:0;;-1:-1:-1;;;;;;;;;;;60555:24:0;60554:63;;60587:30;60598:3;60611:4;60587:10;:30::i;:::-;60554:63;;;60583:1;60554:63;60527:90;;60628:25;60656:31;60667:4;60681;60656:10;:31::i;:::-;60628:59;-1:-1:-1;60704:9:0;60700:1624;60723:22;;:29;60719:33;;60700:1624;;;60774:17;-1:-1:-1;;;;;60795:24:0;;-1:-1:-1;;;;;;;;;;;60795:24:0;60794:59;;60852:1;60794:59;;;60823:12;:23;;;60847:1;60823:26;;;;;;;;;;;;;;60794:59;60774:79;;60894:12;:22;;;60917:1;60894:25;;;;;;;;;;;;;;-1:-1:-1;;;;;60894:31:0;;60933:9;60966:3;60992:12;:23;;;61016:1;60992:26;;;;;;;;;;;;;;61041:4;61076;61104:12;:18;;;61123:1;61104:21;;;;;;;;;;;;;;;;;;;60894:277;;;-1:-1:-1;;;;;;60894:277:0;;;;;;;-1:-1:-1;;;;;60894:277:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61148:4;60894:277;;;;;;;;;;61104:21;60894:277;;;;;;;;;;2:2:-1;;;;27:1;24;17:12;2:2;60894:277:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60894:277:0;;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;60894:277:0;60868:359;;;;;-1:-1:-1;;;60868:359:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61244:20;-1:-1:-1;;;;;61283:24:0;;-1:-1:-1;;;;;;;;;;;61283:24:0;61279:474;;61404:30;61415:3;61428:4;61404:10;:30::i;:::-;61389:45;;61532:12;61512:16;:32;;:96;;;;;61582:12;:23;;;61606:1;61582:26;;;;;;;;;;;;;;61567:12;61548:16;:31;:60;61512:96;61508:180;;;61633:35;;;-1:-1:-1;;;61633:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;61508:180;61725:12;61706:31;;61279:474;61824:26;61853:171;61882:12;:23;;;61906:1;61882:26;;;;;;;;;;;;;;61927:11;61957:12;61988;:18;;;62007:1;61988:21;;;;;;;;;;;;;;61853:10;:171::i;:::-;61824:200;;62054:31;62065:4;62079;62054:10;:31::i;:::-;62039:46;;62119:17;62104:12;:32;:89;;;;62175:18;62155:17;62140:12;:32;:53;62104:89;62100:166;;;62214:36;;;-1:-1:-1;;;62214:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;62100:166;-1:-1:-1;62300:12:0;-1:-1:-1;;60754:3:0;;60700:1624;;;;60248:2083;;;;;;;:::o;23011:177::-;23121:58;;;-1:-1:-1;;;;;23121:58:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;23121:58:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;23094:86:0;;23114:5;;23094:19;:86::i;74668:1138::-;74772:30;74804:33;74885:9;:35;;;74871:50;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;74871:50:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;74871:50:0;;74855:66;;74965:9;:35;;;74951:50;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;74951:50:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;74951:50:0;;74932:69;;75016:9;:35;;;75055:1;75016:40;75012:113;;;75073:40;;75012:113;75137:13;75161:33;75211:9;:35;;;75197:50;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;75197:50:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;75197:50:0;;75161:86;;75293:192;75332:16;75363;75394:9;:20;;;75429:5;75449:9;:25;;;75293:24;:192::i;:::-;75285:200;;75523:192;75562:16;75593;75624:9;:20;;;75659:5;75679:9;:25;;;75523:24;:192::i;:::-;-1:-1:-1;75744:12:0;;:54;;-1:-1:-1;;;75744:54:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;75744:12:0;;;;:36;;75781:16;;75744:54;;;;;;;;;;;;;;;:12;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;75744:54:0;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;75744:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;75744:54:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;75744:54:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;15:2;7:11;;4:2;;;31:1;28;21:12;4:2;75744:54:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;75744:54:0;;421:4:-1;412:14;;;;75744:54:0;;;;;412:14:-1;75744:54:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;75744:54:0;;;;;;;;;;;75728:70;;74668:1138;;;;;;:::o;20407:619::-;20467:4;20935:20;;20778:66;20975:23;;;;;;:42;;-1:-1:-1;;21002:15:0;;;20967:51;-1:-1:-1;;20407:619:0:o;72678:1982::-;72966:16;;;;:23;72894:37;;72944:19;;-1:-1:-1;;;;;73077:24:0;;-1:-1:-1;;;;;;;;;;;73077:24:0;73073:449;;;6905:5;73360:9;:23;;;73339:9;:18;;;:44;:50;;;;;;73308:9;:82;73288:102;;73073:449;;;-1:-1:-1;;73487:23:0;;;;73444:9;;73073:449;73574:11;73560:26;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;73560:26:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;73560:26:0;-1:-1:-1;73534:23:0;;;:52;73632:11;73618:26;;;2:2:-1;;;;27:1;24;17:12;2:2;73618:26:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;73618:26:0;-1:-1:-1;73597:18:0;;;:47;73692:11;73678:26;;;2:2:-1;;;;27:1;24;17:12;2:2;73678:26:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;73678:26:0;-1:-1:-1;73655:49:0;-1:-1:-1;73825:9:0;73820:833;73844:11;73840:1;:15;73820:833;;;73931:1;73903:12;:22;;;73926:1;73903:25;;;;;;;;;;;;;;:29;:65;;;;;6905:5;73936:12;:22;;;73959:1;73936:25;;;;;;;;;;;;;;:32;;73903:65;73877:144;;;;;-1:-1:-1;;;73877:144:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;74042:12;:32;;;74075:1;74042:35;;;;;;;;;;;;;;74038:332;;;6905:5;74147:12;:22;;;74170:1;74147:25;;;;;;;;;;;;;;74127:17;:45;:51;;;;;;74098:12;:23;;;74122:1;74098:26;;;;;;;;;;;;;:80;;;;;74223:16;74197:20;74218:1;74197:23;;;;;;;;;;;;;:42;;;;;74038:332;;;6905:5;74322:12;:22;;;74345:1;74322:25;;;;;;;;;;;;;;74310:9;:37;74309:45;;;;;;74280:12;:23;;;74304:1;74280:26;;;;;;;;;;;;;:74;;;;;74038:332;74462:22;;:25;;74485:1;;74462:25;;;;;;;;;;;;-1:-1:-1;;;;;74462:43:0;;74524:3;74546:4;74569:12;:23;;;74593:1;74569:26;;;;;;;;;;;;;;74614:12;74462:179;;;;;;;;;;;;;-1:-1:-1;;;;;74462:179:0;-1:-1:-1;;;;;74462:179:0;;;;;;-1:-1:-1;;;;;74462:179:0;-1:-1:-1;;;;;74462:179:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;74462:179:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;74462:179:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;74462:179:0;74438:18;;;;:21;;74457:1;;74438:21;;;;;;;;;;;;;;;:203;73857:3;;73820:833;;;;72678:1982;;;;;;;;;;:::o;78722:1869::-;78888:22;;78946;;:29;78931:44;;;78923:83;;;;;-1:-1:-1;;;78923:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;79019:39;79081:11;79061:32;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79061:32:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;79061:32:0;;79019:74;;79104:27;79148:11;79134:26;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79134:26:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;79134:26:0;;79104:56;;79171:26;79214:11;79200:26;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79200:26:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;79200:26:0;;79171:55;;79237:33;79284:11;79273:23;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79273:23:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;79273:23:0;;79237:59;;79307:35;79356:11;79345:23;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79345:23:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;79345:23:0;;79307:61;;79379:27;79423:11;79409:26;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79409:26:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;79409:26:0;;79379:56;;79446:22;79485:11;79471:26;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;79471:26:0;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;144:17;;-1:-1;79471:26:0;-1:-1:-1;79446:51:0;-1:-1:-1;79608:9:0;79603:598;79627:11;79623:1;:15;79603:598;;;79682:12;:22;;;79705:15;79721:1;79705:18;;;;;;;;;;;;;;79682:42;;;;;;;;;;;;;;79660:16;79677:1;79660:19;;;;;;;;;;;;;:64;-1:-1:-1;;;;;79660:64:0;;;-1:-1:-1;;;;;79660:64:0;;;;;79755:12;:16;;;79772:15;79788:1;79772:18;;;;;;;;;;;;;;79755:36;;;;;;;;;;;;;;79739:10;79750:1;79739:13;;;;;;;;;;;;;:52;;;;;79821:12;:22;;;79844:15;79860:1;79844:18;;;;;;;;;;;;;;79821:42;;;;;;;;;;;;;;79806:9;79816:1;79806:12;;;;;;;;;;;;;:57;;;;;79903:12;:32;;;79936:15;79952:1;79936:18;;;;;;;;;;;;;;79903:52;;;;;;;;;;;;;;79878:19;79898:1;79878:22;;;;;;;;;;;;;:77;;;;;;;;;;;79997:12;:34;;;80032:15;80048:1;80032:18;;;;;;;;;;;;;;79997:54;;;;;;;;;;;;;;79970:21;79992:1;79970:24;;;;;;;;;;;;;:81;;;;;;;;;;;80082:12;:23;;;80106:15;80122:1;80106:18;;;;;;;;;;;;;;80082:43;;;;;;;;;;;;;;80066:10;80077:1;80066:13;;;;;;;;;;;;;:59;;;;;80151:12;:18;;;80170:15;80186:1;80170:18;;;;;;;;;;;;;;80151:38;;;;;;;;;;;;;;80140:5;80146:1;80140:8;;;;;;;;;;;;;;;;;:49;79640:3;;79603:598;;;-1:-1:-1;80239:41:0;;;80291:16;;;:29;;;;80331:22;;;:34;;;;80376:32;;;:54;80441:34;;;:58;-1:-1:-1;80510:18:0;;:26;;;;80547:23;;;;:36;;;;-1:-1:-1;;78722:1869:0:o;80866:1437::-;81041:23;;;-1:-1:-1;;;;;81127:24:0;;-1:-1:-1;;;;;;;;;;;81127:24:0;81126:65;;81170:12;:21;;;81126:65;;;6873:2;81126:65;81104:87;-1:-1:-1;81202:20:0;-1:-1:-1;;;;;81226:24:0;;-1:-1:-1;;;;;;;;;;;81226:24:0;81225:65;;6873:2;81225:65;;;81254:12;:21;;;81225:65;81202:88;-1:-1:-1;81316:9:0;81311:917;81335:22;;:29;81331:33;;81311:917;;;81394:1;81390;:5;:75;;;;;81440:12;:16;;;81461:1;81457;:5;81440:23;;;;;;;;;;;;;;81432:32;;81408:12;:16;;;81425:1;81408:19;;;;;;;;;;;;;;81400:28;;:64;;81390:75;81386:159;;;81493:1;81486:8;;;;;;;;81386:159;81571:12;:22;;;81594:1;81571:25;;;;;;;;;;;;;;81559:37;;;;81613:18;81634:171;81663:12;:23;;;81687:1;81663:26;;;;;;;;;;;;;;81708:11;81738:12;81769;:18;;;81788:1;81769:21;;;;;;;81634:171;81613:192;-1:-1:-1;81824:15:0;81820:64;;81867:1;81860:8;;;;;;;;;81820:64;81917:10;81898:29;;;;81948:12;:32;;;81981:1;81948:35;;;;;;;;;;;;;;81944:273;;;82033:12;:22;;;82056:1;82033:25;;;;;;;;;;;;;;82004:9;:25;;:54;;;;;;;;;;;82083:12;:34;;;82118:1;82083:37;;;;;;;;;;;;;;82079:123;;;82145:35;;;:37;;;;;;82079:123;-1:-1:-1;81366:3:0;;81311:917;;;;6905:5;82244:8;:15;82240:56;;82283:1;82276:8;;;;;;;82240:56;80866:1437;;;;;;;;;:::o;9925:1013::-;10083:7;6663:6;10111;:17;;10103:46;;;;;-1:-1:-1;;;10103:46:0;;;;;;;;;;;;-1:-1:-1;;;10103:46:0;;;;;;;;;;;;;;;6729:17;10168:16;;;10160:44;;;;;-1:-1:-1;;;10160:44:0;;;;;;;;;;;;-1:-1:-1;;;10160:44:0;;;;;;;;;;;;;;;10297:17;10325:19;10374:11;10359;:26;10355:486;;6823:2;10425:11;10411;:25;10410:43;;10402:80;;;;;-1:-1:-1;;;10402:80:0;;;;;;;;;;;;-1:-1:-1;;;10402:80:0;;;;;;;;;;;;;;;-1:-1:-1;;10537:25:0;;;10532:2;:31;10510:54;;6612:6;10510:54;10594:4;10355:486;;;6823:2;10654:11;10640;:25;10639:43;;10631:80;;;;;-1:-1:-1;;;10631:80:0;;;;;;;;;;;;-1:-1:-1;;;10631:80:0;;;;;;;;;;;;;;;-1:-1:-1;;6612:6:0;10739:18;;10801:25;;;10796:2;:31;10788:40;;10355:486;10890:11;10885:1;10871:11;10859:9;:23;:27;10858:43;;;;;;;9925:1013;-1:-1:-1;;;;;;;9925:1013:0:o;8004:237::-;8075:7;-1:-1:-1;;;;;8099:26:0;;-1:-1:-1;;;;;;;;;;;8099:26:0;8095:139;;;-1:-1:-1;;;;;;8149:12:0;;;8142:19;;8095:139;8201:5;-1:-1:-1;;;;;8201:15:0;;8217:4;8201:21;;;;;;;;;;;;;-1:-1:-1;;;;;8201:21:0;-1:-1:-1;;;;;8201:21:0;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8201:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8201:21:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;8201:21:0;;-1:-1:-1;8194:28:0;;9194:723;9352:7;6663:6;9380;:17;;9372:46;;;;;-1:-1:-1;;;9372:46:0;;;;;;;;;;;;-1:-1:-1;;;9372:46:0;;;;;;;;;;;;;;;6729:17;9437:16;;;9429:44;;;;;-1:-1:-1;;;9429:44:0;;;;;;;;;;;;-1:-1:-1;;;9429:44:0;;;;;;;;;;;;;;;9505:11;9490;:26;9486:424;;6823:2;9556:11;9542;:25;9541:43;;9533:80;;;;;-1:-1:-1;;;9533:80:0;;;;;;;;;;;;-1:-1:-1;;;9533:80:0;;;;;;;;;;;;;;;6612:6;9636:13;;;9658:25;;;9653:2;:31;9636:49;9635:63;;9486:424;6823:2;9754:11;9740;:25;9739:43;;9731:80;;;;;-1:-1:-1;;;9731:80:0;;;;;;;;;;;;-1:-1:-1;;;9731:80:0;;;;;;;;;;;;;;;9884:11;9870;:25;9865:2;:31;6612:6;9852:45;9843:4;9834:6;:13;9833:65;;;;75814:685;76067:7;76104:5;76067:7;76122:346;76146:12;:34;;;:41;76142:1;:45;76122:346;;;76213:12;:34;;;76248:1;76213:37;;;;;;;;;;;;;;76209:248;;;76298:12;:16;;;76315:1;76298:19;;;;;;;;;;;;;;76271:16;76288:6;76271:24;;;;;;;;;;;;;:46;;;;;76399:15;6905:5;76364:12;:22;;;76387:1;76364:25;;;;;;;;;;;;;;:31;76363:51;;;;;;76336:16;76353:6;76336:24;;;;;;;;;;;;;;;;;:78;76433:8;;;;;76209:248;76189:3;;76122:346;;;-1:-1:-1;76485:6:0;75814:685;-1:-1:-1;;;;;;75814:685:0:o;38297:48308::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;38297:48308:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://9837ac8c78168c99ffeec8ad9c6978d5a3d7e8fe46c2159b336d66b149d2cc50
Loading...LoadingLoading...Loading
Loading...Loading
Loading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingLoading...LoadingMultichain Portfolio | 30 Chains
Chain Token Portfolio % Price Amount Value ETH 55.92% $3.52 362.006 $1,274.26 ETH 16.72% $17.11 22.269 $381.02 ETH Ether (ETH)15.49% $3,399.89 0.1038 $353.03 ETH 5.19% $0.999671 118.3739 $118.33 ETH 4.99% $0.99974 113.7804 $113.75 ETH 0.38% $98,069 0.00008923 $8.75 ETH 0.30% $1.42 4.8553 $6.89 ETH 0.28% $1 6.4527 $6.46 ETH 0.18% $0.200004 20.9554 $4.19 ETH 0.17% $1.21 3.1322 $3.79 ETH 0.03% $0.038371 20.4223 $0.7836 ETH 0.03% $10.63 0.0555 $0.5898 ETH 0.03% $1.99 0.2881 $0.5733 ETH 0.02% $1.27 0.335 $0.4238 ETH 0.01% $0.003152 101 $0.3183 ETH 0.01% $1.05 0.3 $0.3162 ETH <0.01% $0.003228 51.6258 $0.1666 ETH <0.01% $6,866.18 0.0000191 $0.1311 BSC 0.22% $5.12 1 $5.12 Loading...Loading[ Download: CSV Export ][ Download: CSV Export ]A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.
Address QR Code
My Address - Private Name Tag or Note
My Name Tag:
Private Name Tags (up to 35 characters) can be used for easy identification of addressesPrivate Note:
A private note (up to 500 characters) can be attached to this address.
Please DO NOT store any passwords or private keys here.Compiler specific version warnings:
The compiled contract might be susceptible to MissingSideEffectsOnSelectorAccess (low-severity), AbiReencodingHeadOverflowWithStaticArrayCleanup (medium-severity), DirtyBytesArrayToStorage (low-severity), NestedCalldataArrayAbiReencodingSizeValidation (very low-severity), SignedImmutables (very low-severity), ABIDecodeTwoDimensionalArrayMemory (very low-severity), KeccakCaching (medium-severity), EmptyByteArrayCopy (medium-severity), DynamicArrayCleanup (medium-severity), MissingEscapingInFormatting (very low-severity), ArraySliceDynamicallyEncodedBaseType (very low-severity), ImplicitConstructorCallvalueCheck (very low-severity) Solidity Compiler Bugs.
Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.Connect a Wallet
Connecting wallet for read function is optional, useful if you want to call certain functions or simply use your wallet's node.SignIn
Address Cards
To use this feature, please login to your Etherscan account and return to this page.Before You Copy
Transaction Private Note
This website uses cookies to improve your experience. By continuing to use this website, you agree to its Terms and Privacy Policy.