Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0.01308413830226 ETH
Eth Value
$44.36 (@ $3,390.34/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 26,546 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute | 21469606 | 16 mins ago | IN | 0 ETH | 0.00185677 | ||||
Execute | 21469522 | 32 mins ago | IN | 0 ETH | 0.00179663 | ||||
Execute | 21469468 | 43 mins ago | IN | 0 ETH | 0.00170998 | ||||
Execute | 21469428 | 51 mins ago | IN | 0 ETH | 0.00134287 | ||||
Execute | 21469352 | 1 hr ago | IN | 0 ETH | 0.00161814 | ||||
Execute | 21469313 | 1 hr ago | IN | 0 ETH | 0.00192336 | ||||
Execute | 21469173 | 1 hr ago | IN | 0 ETH | 0.00160519 | ||||
Execute | 21469004 | 2 hrs ago | IN | 0 ETH | 0.00212696 | ||||
Execute | 21468832 | 2 hrs ago | IN | 0 ETH | 0.00220162 | ||||
Execute | 21468729 | 3 hrs ago | IN | 0 ETH | 0.0035617 | ||||
Execute | 21468688 | 3 hrs ago | IN | 0 ETH | 0.00230886 | ||||
Execute | 21468626 | 3 hrs ago | IN | 0 ETH | 0.00246519 | ||||
Execute | 21468579 | 3 hrs ago | IN | 0 ETH | 0.00218308 | ||||
Execute | 21468560 | 3 hrs ago | IN | 0 ETH | 0.00220191 | ||||
Execute | 21468501 | 3 hrs ago | IN | 0 ETH | 0.00250553 | ||||
Execute | 21468488 | 4 hrs ago | IN | 0 ETH | 0.00309824 | ||||
Execute | 21468476 | 4 hrs ago | IN | 0 ETH | 0.00307644 | ||||
Execute | 21468464 | 4 hrs ago | IN | 0 ETH | 0.00266396 | ||||
Execute | 21468388 | 4 hrs ago | IN | 0 ETH | 0.0030063 | ||||
Execute | 21468345 | 4 hrs ago | IN | 0 ETH | 0.00300436 | ||||
Execute | 21468312 | 4 hrs ago | IN | 0 ETH | 0.00266856 | ||||
Execute | 21468305 | 4 hrs ago | IN | 0 ETH | 0.00259237 | ||||
Execute | 21468298 | 4 hrs ago | IN | 0 ETH | 0.00252293 | ||||
Execute | 21468286 | 4 hrs ago | IN | 0 ETH | 0.00284456 | ||||
Execute | 21468280 | 4 hrs ago | IN | 0 ETH | 0.00258123 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21469606 | 16 mins ago | 0.00421638 ETH | ||||
21469606 | 16 mins ago | 0.00238205 ETH | ||||
21469589 | 19 mins ago | 0.00654206 ETH | ||||
21469543 | 28 mins ago | 0.00654206 ETH | ||||
21469522 | 32 mins ago | 0.00431384 ETH | ||||
21469522 | 32 mins ago | 0.00230562 ETH | ||||
21469468 | 43 mins ago | 0.00438163 ETH | ||||
21469468 | 43 mins ago | 0.00228257 ETH | ||||
21469454 | 46 mins ago | 0.00659843 ETH | ||||
21469428 | 51 mins ago | 0.00497515 ETH | ||||
21469428 | 51 mins ago | 0.00168906 ETH | ||||
21469370 | 1 hr ago | 0.00661946 ETH | ||||
21469352 | 1 hr ago | 0.00464766 ETH | ||||
21469352 | 1 hr ago | 0.00201654 ETH | ||||
21469313 | 1 hr ago | 0.00442202 ETH | ||||
21469313 | 1 hr ago | 0.00227005 ETH | ||||
21469310 | 1 hr ago | 0.00666421 ETH | ||||
21469272 | 1 hr ago | 0.00666421 ETH | ||||
21469196 | 1 hr ago | 0.00666421 ETH | ||||
21469173 | 1 hr ago | 0.00451816 ETH | ||||
21469173 | 1 hr ago | 0.0021739 ETH | ||||
21469158 | 1 hr ago | 0.00669207 ETH | ||||
21469019 | 2 hrs ago | 0.00669207 ETH | ||||
21469004 | 2 hrs ago | 0.00446134 ETH | ||||
21469004 | 2 hrs ago | 0.00224366 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
TwapDelay
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import './interfaces/ITwapPair.sol'; import './interfaces/ITwapDelay.sol'; import './interfaces/IWETH.sol'; import './libraries/SafeMath.sol'; import './libraries/Orders.sol'; import './libraries/TokenShares.sol'; import './libraries/AddLiquidity.sol'; import './libraries/WithdrawHelper.sol'; import './libraries/ExecutionHelper.sol'; import './interfaces/ITwapFactoryGovernor.sol'; contract TwapDelay is ITwapDelay { using SafeMath for uint256; using Orders for Orders.Data; using TokenShares for TokenShares.Data; Orders.Data internal orders; TokenShares.Data internal tokenShares; uint256 private constant ORDER_CANCEL_TIME = 24 hours; uint256 private constant BOT_EXECUTION_TIME = 20 minutes; address public override owner; address public override factoryGovernor; address public constant RELAYER_ADDRESS = 0xd17b3c9784510E33cD5B87b490E79253BcD81e2E; mapping(address => bool) public override isBot; constructor(address _factoryGovernor, address _bot) { _setOwner(msg.sender); _setFactoryGovernor(_factoryGovernor); _setBot(_bot, true); orders.gasPrice = tx.gasprice; _emitEventWithDefaults(); } function getTransferGasCost(address token) external pure override returns (uint256 gasCost) { return Orders.getTransferGasCost(token); } function getDepositDisabled(address pair) external view override returns (bool) { return orders.getDepositDisabled(pair); } function getWithdrawDisabled(address pair) external view override returns (bool) { return orders.getWithdrawDisabled(pair); } function getBuyDisabled(address pair) external view override returns (bool) { return orders.getBuyDisabled(pair); } function getSellDisabled(address pair) external view override returns (bool) { return orders.getSellDisabled(pair); } function getOrderStatus( uint256 orderId, uint256 validAfterTimestamp ) external view override returns (Orders.OrderStatus) { return orders.getOrderStatus(orderId, validAfterTimestamp); } uint256 private locked = 1; modifier lock() { require(locked == 1, 'TD06'); locked = 2; _; locked = 1; } function factory() external pure override returns (address) { return Orders.FACTORY_ADDRESS; } function totalShares(address token) external view override returns (uint256) { return tokenShares.totalShares[token]; } // returns wrapped native currency for particular blockchain (WETH or WMATIC) function weth() external pure override returns (address) { return TokenShares.WETH_ADDRESS; } function relayer() external pure override returns (address) { return RELAYER_ADDRESS; } function isNonRebasingToken(address token) external pure override returns (bool) { return TokenShares.isNonRebasing(token); } function delay() external pure override returns (uint256) { return Orders.DELAY; } function lastProcessedOrderId() external view returns (uint256) { return orders.lastProcessedOrderId; } function newestOrderId() external view returns (uint256) { return orders.newestOrderId; } function isOrderCanceled(uint256 orderId) external view returns (bool) { return orders.canceled[orderId]; } function maxGasLimit() external pure override returns (uint256) { return Orders.MAX_GAS_LIMIT; } function maxGasPriceImpact() external pure override returns (uint256) { return Orders.MAX_GAS_PRICE_IMPACT; } function gasPriceInertia() external pure override returns (uint256) { return Orders.GAS_PRICE_INERTIA; } function gasPrice() external view override returns (uint256) { return orders.gasPrice; } function setOrderTypesDisabled( address pair, Orders.OrderType[] calldata orderTypes, bool disabled ) external override { require(msg.sender == owner, 'TD00'); orders.setOrderTypesDisabled(pair, orderTypes, disabled); } function setOwner(address _owner) external override { require(msg.sender == owner, 'TD00'); _setOwner(_owner); } function _setOwner(address _owner) internal { require(_owner != owner, 'TD01'); require(_owner != address(0), 'TD02'); owner = _owner; emit OwnerSet(_owner); } function setFactoryGovernor(address _factoryGovernor) external override { require(msg.sender == owner, 'TD00'); _setFactoryGovernor(_factoryGovernor); } function _setFactoryGovernor(address _factoryGovernor) internal { require(_factoryGovernor != factoryGovernor, 'TD01'); require(_factoryGovernor != address(0), 'TD02'); factoryGovernor = _factoryGovernor; emit FactoryGovernorSet(_factoryGovernor); } function setBot(address _bot, bool _isBot) external override { require(msg.sender == owner, 'TD00'); _setBot(_bot, _isBot); } function _setBot(address _bot, bool _isBot) internal { require(_isBot != isBot[_bot], 'TD01'); isBot[_bot] = _isBot; emit BotSet(_bot, _isBot); } function deposit( Orders.DepositParams calldata depositParams ) external payable override lock returns (uint256 orderId) { orders.deposit(depositParams, tokenShares); return orders.newestOrderId; } function withdraw( Orders.WithdrawParams calldata withdrawParams ) external payable override lock returns (uint256 orderId) { orders.withdraw(withdrawParams); return orders.newestOrderId; } function sell(Orders.SellParams calldata sellParams) external payable override lock returns (uint256 orderId) { orders.sell(sellParams, tokenShares); return orders.newestOrderId; } function relayerSell( Orders.SellParams calldata sellParams ) external payable override lock returns (uint256 orderId) { require(msg.sender == RELAYER_ADDRESS, 'TD00'); orders.relayerSell(sellParams, tokenShares); return orders.newestOrderId; } function buy(Orders.BuyParams calldata buyParams) external payable override lock returns (uint256 orderId) { orders.buy(buyParams, tokenShares); return orders.newestOrderId; } /// @dev This implementation processes orders sequentially and skips orders that have already been executed. /// If it encounters an order that is not yet valid, it stops execution since subsequent orders will also be invalid /// at the time. function execute(Orders.Order[] calldata _orders) external payable override lock { uint256 ordersLength = _orders.length; uint256 gasBefore = gasleft(); bool orderExecuted; bool senderCanExecute = isBot[msg.sender] || isBot[address(0)]; for (uint256 i; i < ordersLength; ++i) { if (_orders[i].orderId <= orders.lastProcessedOrderId) { continue; } if (orders.canceled[_orders[i].orderId]) { orders.dequeueOrder(_orders[i].orderId); continue; } orders.verifyOrder(_orders[i]); uint256 validAfterTimestamp = _orders[i].validAfterTimestamp; if (validAfterTimestamp >= block.timestamp) { break; } require(senderCanExecute || block.timestamp >= validAfterTimestamp + BOT_EXECUTION_TIME, 'TD00'); orderExecuted = true; if (_orders[i].orderType == Orders.OrderType.Deposit) { executeDeposit(_orders[i]); } else if (_orders[i].orderType == Orders.OrderType.Withdraw) { executeWithdraw(_orders[i]); } else if (_orders[i].orderType == Orders.OrderType.Sell) { executeSell(_orders[i]); } else if (_orders[i].orderType == Orders.OrderType.Buy) { executeBuy(_orders[i]); } } if (orderExecuted) { orders.updateGasPrice(gasBefore.sub(gasleft())); } } /// @dev The `order` must be verified by calling `Orders.verifyOrder` before calling this function. function executeDeposit(Orders.Order calldata order) internal { uint256 gasStart = gasleft(); orders.dequeueOrder(order.orderId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: order.gasLimit.sub( Orders.DEPOSIT_ORDER_BASE_COST + Orders.getTransferGasCost(order.token0) + Orders.getTransferGasCost(order.token1) ) }(abi.encodeWithSelector(this._executeDeposit.selector, order)); bool refundSuccess = true; if (!executionSuccess) { refundSuccess = refundTokens( order.to, order.token0, order.value0, order.token1, order.value1, order.unwrap, false ); } finalizeOrder(refundSuccess); (uint256 gasUsed, uint256 ethRefund) = refund(order.gasLimit, order.gasPrice, gasStart, order.to); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } /// @dev The `order` must be verified by calling `Orders.verifyOrder` before calling this function. function executeWithdraw(Orders.Order calldata order) internal { uint256 gasStart = gasleft(); orders.dequeueOrder(order.orderId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: order.gasLimit.sub(Orders.WITHDRAW_ORDER_BASE_COST + Orders.PAIR_TRANSFER_COST) }(abi.encodeWithSelector(this._executeWithdraw.selector, order)); bool refundSuccess = true; if (!executionSuccess) { (address pair, ) = Orders.getPair(order.token0, order.token1); refundSuccess = Orders.refundLiquidity(pair, order.to, order.liquidity, this._refundLiquidity.selector); } finalizeOrder(refundSuccess); (uint256 gasUsed, uint256 ethRefund) = refund(order.gasLimit, order.gasPrice, gasStart, order.to); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } /// @dev The `order` must be verified by calling `Orders.verifyOrder` before calling this function. function executeSell(Orders.Order calldata order) internal { uint256 gasStart = gasleft(); orders.dequeueOrder(order.orderId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: order.gasLimit.sub(Orders.SELL_ORDER_BASE_COST + Orders.getTransferGasCost(order.token0)) }(abi.encodeWithSelector(this._executeSell.selector, order)); bool refundSuccess = true; if (!executionSuccess) { refundSuccess = refundToken(order.token0, order.to, order.value0, order.unwrap, false); } finalizeOrder(refundSuccess); (uint256 gasUsed, uint256 ethRefund) = refund(order.gasLimit, order.gasPrice, gasStart, order.to); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } /// @dev The `order` must be verified by calling `Orders.verifyOrder` before calling this function. function executeBuy(Orders.Order calldata order) internal { uint256 gasStart = gasleft(); orders.dequeueOrder(order.orderId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: order.gasLimit.sub(Orders.BUY_ORDER_BASE_COST + Orders.getTransferGasCost(order.token0)) }(abi.encodeWithSelector(this._executeBuy.selector, order)); bool refundSuccess = true; if (!executionSuccess) { refundSuccess = refundToken(order.token0, order.to, order.value0, order.unwrap, false); } finalizeOrder(refundSuccess); (uint256 gasUsed, uint256 ethRefund) = refund(order.gasLimit, order.gasPrice, gasStart, order.to); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } function finalizeOrder(bool refundSuccess) private { if (!refundSuccess) { orders.markRefundFailed(); } else { orders.forgetLastProcessedOrder(); } } function refund( uint256 gasLimit, uint256 gasPriceInOrder, uint256 gasStart, address to ) private returns (uint256 gasUsed, uint256 leftOver) { uint256 feeCollected = gasLimit.mul(gasPriceInOrder); gasUsed = gasStart.sub(gasleft()).add(Orders.REFUND_BASE_COST); uint256 actualRefund = Math.min(feeCollected, gasUsed.mul(orders.gasPrice)); leftOver = feeCollected.sub(actualRefund); require(refundEth(msg.sender, actualRefund), 'TD40'); refundEth(payable(to), leftOver); } function refundEth(address payable to, uint256 value) internal returns (bool success) { if (value == 0) { return true; } success = TransferHelper.transferETH(to, value, Orders.getTransferGasCost(Orders.NATIVE_CURRENCY_SENTINEL)); emit EthRefund(to, success, value); } function refundToken( address token, address to, uint256 share, bool unwrap, bool forwardAllGas ) private returns (bool) { if (share == 0) { return true; } (bool success, bytes memory data) = address(this).call{ gas: forwardAllGas ? gasleft() : Orders.TOKEN_REFUND_BASE_COST + Orders.getTransferGasCost(token) }(abi.encodeWithSelector(this._refundToken.selector, token, to, share, unwrap)); if (!success) { emit Orders.RefundFailed(to, token, share, data); } return success; } function refundTokens( address to, address token0, uint256 share0, address token1, uint256 share1, bool unwrap, bool forwardAllGas ) private returns (bool) { (bool success, bytes memory data) = address(this).call{ gas: forwardAllGas ? gasleft() : 2 * Orders.TOKEN_REFUND_BASE_COST + Orders.getTransferGasCost(token0) + Orders.getTransferGasCost(token1) }(abi.encodeWithSelector(this._refundTokens.selector, to, token0, share0, token1, share1, unwrap)); if (!success) { emit Orders.RefundFailed(to, token0, share0, data); emit Orders.RefundFailed(to, token1, share1, data); } return success; } function _refundTokens( address to, address token0, uint256 share0, address token1, uint256 share1, bool unwrap ) external payable { // no need to check sender, because it is checked in _refundToken _refundToken(token0, to, share0, unwrap); _refundToken(token1, to, share1, unwrap); } function _refundToken(address token, address to, uint256 share, bool unwrap) public payable { require(msg.sender == address(this), 'TD00'); if (token == TokenShares.WETH_ADDRESS && unwrap) { uint256 amount = tokenShares.sharesToAmount(token, share, 0, to); IWETH(TokenShares.WETH_ADDRESS).withdraw(amount); TransferHelper.safeTransferETH(to, amount, Orders.getTransferGasCost(Orders.NATIVE_CURRENCY_SENTINEL)); } else { TransferHelper.safeTransfer(token, to, tokenShares.sharesToAmount(token, share, 0, to)); } } function _refundLiquidity(address pair, address to, uint256 liquidity) external payable { require(msg.sender == address(this), 'TD00'); return TransferHelper.safeTransfer(pair, to, liquidity); } function _executeDeposit(Orders.Order calldata order) external payable { require(msg.sender == address(this), 'TD00'); (address pairAddress, ) = Orders.getPair(order.token0, order.token1); ITwapPair(pairAddress).sync(); ITwapFactoryGovernor(factoryGovernor).distributeFees(order.token0, order.token1, pairAddress); ITwapPair(pairAddress).sync(); ExecutionHelper.executeDeposit(order, pairAddress, getTolerance(pairAddress), tokenShares); } function _executeWithdraw(Orders.Order calldata order) external payable { require(msg.sender == address(this), 'TD00'); (address pairAddress, ) = Orders.getPair(order.token0, order.token1); ITwapPair(pairAddress).sync(); ITwapFactoryGovernor(factoryGovernor).distributeFees(order.token0, order.token1, pairAddress); ITwapPair(pairAddress).sync(); ExecutionHelper.executeWithdraw(order); } function _executeBuy(Orders.Order calldata order) external payable { require(msg.sender == address(this), 'TD00'); (address pairAddress, ) = Orders.getPair(order.token0, order.token1); ExecutionHelper.ExecuteBuySellParams memory orderParams; orderParams.order = order; orderParams.pairAddress = pairAddress; orderParams.pairTolerance = getTolerance(pairAddress); ITwapPair(pairAddress).sync(); ExecutionHelper.executeBuy(orderParams, tokenShares); } function _executeSell(Orders.Order calldata order) external payable { require(msg.sender == address(this), 'TD00'); (address pairAddress, ) = Orders.getPair(order.token0, order.token1); ExecutionHelper.ExecuteBuySellParams memory orderParams; orderParams.order = order; orderParams.pairAddress = pairAddress; orderParams.pairTolerance = getTolerance(pairAddress); ITwapPair(pairAddress).sync(); ExecutionHelper.executeSell(orderParams, tokenShares); } /// @dev The `order` must be verified by calling `Orders.verifyOrder` before calling this function. function performRefund(Orders.Order calldata order, bool shouldRefundEth) internal { bool canOwnerRefund = order.validAfterTimestamp.add(365 days) < block.timestamp; if (order.orderType == Orders.OrderType.Deposit) { address to = canOwnerRefund ? owner : order.to; require( refundTokens(to, order.token0, order.value0, order.token1, order.value1, order.unwrap, true), 'TD14' ); if (shouldRefundEth) { require(refundEth(payable(to), order.gasPrice.mul(order.gasLimit)), 'TD40'); } } else if (order.orderType == Orders.OrderType.Withdraw) { (address pair, ) = Orders.getPair(order.token0, order.token1); address to = canOwnerRefund ? owner : order.to; require(Orders.refundLiquidity(pair, to, order.liquidity, this._refundLiquidity.selector), 'TD14'); if (shouldRefundEth) { require(refundEth(payable(to), order.gasPrice.mul(order.gasLimit)), 'TD40'); } } else if (order.orderType == Orders.OrderType.Sell) { address to = canOwnerRefund ? owner : order.to; require(refundToken(order.token0, to, order.value0, order.unwrap, true), 'TD14'); if (shouldRefundEth) { require(refundEth(payable(to), order.gasPrice.mul(order.gasLimit)), 'TD40'); } } else if (order.orderType == Orders.OrderType.Buy) { address to = canOwnerRefund ? owner : order.to; require(refundToken(order.token0, to, order.value0, order.unwrap, true), 'TD14'); if (shouldRefundEth) { require(refundEth(payable(to), order.gasPrice.mul(order.gasLimit)), 'TD40'); } } else { return; } orders.forgetOrder(order.orderId); } function retryRefund(Orders.Order calldata order) external override lock { orders.verifyOrder(order); require(orders.refundFailed[order.orderId], 'TD21'); performRefund(order, false); } function cancelOrder(Orders.Order calldata order) external override lock { orders.verifyOrder(order); require( orders.getOrderStatus(order.orderId, order.validAfterTimestamp) == Orders.OrderStatus.EnqueuedReady, 'TD52' ); require(order.validAfterTimestamp.sub(Orders.DELAY).add(ORDER_CANCEL_TIME) < block.timestamp, 'TD1C'); orders.canceled[order.orderId] = true; performRefund(order, true); } function syncPair(address token0, address token1) external override returns (address pairAddress) { require(msg.sender == factoryGovernor, 'TD00'); (pairAddress, ) = Orders.getPair(token0, token1); ITwapPair(pairAddress).sync(); } function _emitEventWithDefaults() internal { emit MaxGasLimitSet(Orders.MAX_GAS_LIMIT); emit GasPriceInertiaSet(Orders.GAS_PRICE_INERTIA); emit MaxGasPriceImpactSet(Orders.MAX_GAS_PRICE_IMPACT); emit DelaySet(Orders.DELAY); emit RelayerSet(RELAYER_ADDRESS); emit ToleranceSet(0x2fe16Dd18bba26e457B7dD2080d5674312b026a2, 0); emit ToleranceSet(0x048f0e7ea2CFD522a4a058D1b1bDd574A0486c46, 0); emit ToleranceSet(0x37F6dF71b40c50b2038329CaBf5FDa3682Df1ebF, 0); emit ToleranceSet(0x6ec472b613012a492693697FA551420E60567eA7, 0); emit ToleranceSet(0x43f0E5f2304F261DfA5359a0b74Ff030E498D904, 0); emit ToleranceSet(0xD66f214fB49f81Ac5610e0339A351D7e1c67c35e, 0); emit ToleranceSet(0xD4d2140eD70DCF8794A986F0CFD07560ee738C71, 4); emit ToleranceSet(0x29b57D56a114aE5BE3c129240898B3321A70A300, 0); emit ToleranceSet(0x61fA1CEe13CEEAF20C30611c5e6dA48c595F7dB2, 0); emit ToleranceSet(0x045950A37c59d75496BB4Af68c05f9066A4C7e27, 0); emit ToleranceSet(0xbEE7Ef1adfaa628536Ebc0C1EBF082DbDC27265F, 0); emit ToleranceSet(0x51baDc1622C63d1E448A4F1aC1DC008b8a27Fe67, 0); emit ToleranceSet(0x0e52DB138Df9CE54Bc9D9330f418015eD512830A, 0); emit ToleranceSet(0xDDE7684D88E0B482B2b455936fe0D22dd48CDcb3, 0); emit ToleranceSet(0x43102f07414D95eF71EC9aEbA011b8595BA010D0, 0); emit TransferGasCostSet(Orders.NATIVE_CURRENCY_SENTINEL, Orders.ETHER_TRANSFER_CALL_COST); emit TransferGasCostSet(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, 31000); emit TransferGasCostSet(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, 42000); emit TransferGasCostSet(0xdAC17F958D2ee523a2206206994597C13D831ec7, 66000); emit TransferGasCostSet(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599, 34000); emit TransferGasCostSet(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B, 31000); emit TransferGasCostSet(0x6B3595068778DD592e39A122f4f5a5cF09C90fE2, 31000); emit TransferGasCostSet(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84, 68000); emit TransferGasCostSet(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0, 31000); emit TransferGasCostSet(0xD33526068D116cE69F19A9ee46F0bd304F21A51f, 31000); emit TransferGasCostSet(0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2, 40000); emit TransferGasCostSet(0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32, 149000); emit TransferGasCostSet(0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2, 34000); emit TransferGasCostSet(0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984, 37000); emit TransferGasCostSet(0x514910771AF9Ca656af840dff83E8264EcF986CA, 32000); emit TransferGasCostSet(0x3c3a81e81dc49A522A592e7622A7E711c06bf354, 34000); emit NonRebasingTokenSet(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, true); emit NonRebasingTokenSet(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, true); emit NonRebasingTokenSet(0xdAC17F958D2ee523a2206206994597C13D831ec7, true); emit NonRebasingTokenSet(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599, true); emit NonRebasingTokenSet(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B, true); emit NonRebasingTokenSet(0x6B3595068778DD592e39A122f4f5a5cF09C90fE2, true); emit NonRebasingTokenSet(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84, false); emit NonRebasingTokenSet(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0, true); emit NonRebasingTokenSet(0xD33526068D116cE69F19A9ee46F0bd304F21A51f, true); emit NonRebasingTokenSet(0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2, true); emit NonRebasingTokenSet(0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32, true); emit NonRebasingTokenSet(0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2, true); emit NonRebasingTokenSet(0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984, true); emit NonRebasingTokenSet(0x514910771AF9Ca656af840dff83E8264EcF986CA, true); emit NonRebasingTokenSet(0x3c3a81e81dc49A522A592e7622A7E711c06bf354, true); } // constant mapping for tolerance function getTolerance(address pair) public virtual view override returns (uint16 tolerance) { if (pair == 0xD4d2140eD70DCF8794A986F0CFD07560ee738C71) return 4; return 0; } receive() external payable {} }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 interface IERC20 { event Approval(address indexed owner, address indexed spender, uint256 value); event Transfer(address indexed from, address indexed to, uint256 value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 interface IReserves { function getReserves() external view returns (uint112 reserve0, uint112 reserve1); function getFees() external view returns (uint256 fee0, uint256 fee1); }
pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import '../libraries/Orders.sol'; interface ITwapDelay { event OrderExecuted(uint256 indexed id, bool indexed success, bytes data, uint256 gasSpent, uint256 ethRefunded); event EthRefund(address indexed to, bool indexed success, uint256 value); event OwnerSet(address owner); event FactoryGovernorSet(address factoryGovernor); event BotSet(address bot, bool isBot); event DelaySet(uint256 delay); event RelayerSet(address relayer); event MaxGasLimitSet(uint256 maxGasLimit); event GasPriceInertiaSet(uint256 gasPriceInertia); event MaxGasPriceImpactSet(uint256 maxGasPriceImpact); event TransferGasCostSet(address token, uint256 gasCost); event ToleranceSet(address pair, uint16 amount); event NonRebasingTokenSet(address token, bool isNonRebasing); function factory() external view returns (address); function factoryGovernor() external view returns (address); function relayer() external view returns (address); function owner() external view returns (address); function isBot(address bot) external view returns (bool); function getTolerance(address pair) external view returns (uint16); function isNonRebasingToken(address token) external view returns (bool); function gasPriceInertia() external view returns (uint256); function gasPrice() external view returns (uint256); function maxGasPriceImpact() external view returns (uint256); function maxGasLimit() external view returns (uint256); function delay() external view returns (uint256); function totalShares(address token) external view returns (uint256); function weth() external view returns (address); function getTransferGasCost(address token) external pure returns (uint256); function getDepositDisabled(address pair) external view returns (bool); function getWithdrawDisabled(address pair) external view returns (bool); function getBuyDisabled(address pair) external view returns (bool); function getSellDisabled(address pair) external view returns (bool); function getOrderStatus(uint256 orderId, uint256 validAfterTimestamp) external view returns (Orders.OrderStatus); function setOrderTypesDisabled(address pair, Orders.OrderType[] calldata orderTypes, bool disabled) external; function setOwner(address _owner) external; function setFactoryGovernor(address _factoryGovernor) external; function setBot(address _bot, bool _isBot) external; function deposit(Orders.DepositParams memory depositParams) external payable returns (uint256 orderId); function withdraw(Orders.WithdrawParams memory withdrawParams) external payable returns (uint256 orderId); function sell(Orders.SellParams memory sellParams) external payable returns (uint256 orderId); function relayerSell(Orders.SellParams memory sellParams) external payable returns (uint256 orderId); function buy(Orders.BuyParams memory buyParams) external payable returns (uint256 orderId); function execute(Orders.Order[] calldata orders) external payable; function retryRefund(Orders.Order calldata order) external; function cancelOrder(Orders.Order calldata order) external; function syncPair(address token0, address token1) external returns (address pairAddress); }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import './IERC20.sol'; interface ITwapERC20 is IERC20 { function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint256); function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function increaseAllowance(address spender, uint256 addedValue) external returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 interface ITwapFactory { event PairCreated(address indexed token0, address indexed token1, address pair, uint256); event OwnerSet(address owner); function owner() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint256) external view returns (address pair); function allPairsLength() external view returns (uint256); function createPair(address tokenA, address tokenB, address oracle, address trader) external returns (address pair); function setOwner(address) external; function setMintFee(address tokenA, address tokenB, uint256 fee) external; function setBurnFee(address tokenA, address tokenB, uint256 fee) external; function setSwapFee(address tokenA, address tokenB, uint256 fee) external; function setOracle(address tokenA, address tokenB, address oracle) external; function setTrader(address tokenA, address tokenB, address trader) external; function collect(address tokenA, address tokenB, address to) external; function withdraw(address tokenA, address tokenB, uint256 amount, address to) external; }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 interface ITwapFactoryGovernor { event FactorySet(address factory); event DelaySet(address delay); event ProtocolFeeRatioSet(uint256 protocolFeeRatio); event EthTransferCostSet(uint256 ethTransferCost); event FeeDistributed(address indexed token, address indexed pair, uint256 lpAmount, uint256 protocolAmount); event OwnerSet(address owner); event WithdrawToken(address token, address to, uint256 amount); function owner() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint256) external view returns (address pair); function allPairsLength() external view returns (uint256); function factory() external view returns (address); function delay() external view returns (address); function protocolFeeRatio() external view returns (uint256); function ethTransferCost() external view returns (uint256); function setFactoryOwner(address) external; function setFactory(address) external; function setOwner(address) external; function setMintFee(address tokenA, address tokenB, uint256 fee) external; function setBurnFee(address tokenA, address tokenB, uint256 fee) external; function setSwapFee(address tokenA, address tokenB, uint256 fee) external; function setOracle(address tokenA, address tokenB, address oracle) external; function setTrader(address tokenA, address tokenB, address trader) external; function setDelay(address) external; function setProtocolFeeRatio(uint256 _protocolFeeRatio) external; function setEthTransferCost(uint256 _ethTransferCost) external; function createPair(address tokenA, address tokenB, address oracle, address trader) external returns (address pair); function collectFees(address tokenA, address tokenB, address to) external; function withdrawLiquidity(address tokenA, address tokenB, uint256 amount, address to) external; function withdrawToken(address token, uint256 amount, address to) external; function distributeFees(address tokenA, address tokenB) external; function distributeFees(address tokenA, address tokenB, address pairAddress) external; function feesToDistribute( address tokenA, address tokenB ) external view returns (uint256 fee0ToDistribute, uint256 fee1ToDistribute); }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 interface ITwapOracle { event OwnerSet(address owner); event UniswapPairSet(address uniswapPair); function decimalsConverter() external view returns (int256); function xDecimals() external view returns (uint8); function yDecimals() external view returns (uint8); function owner() external view returns (address); function uniswapPair() external view returns (address); function getPriceInfo() external view returns (uint256 priceAccumulator, uint256 priceTimestamp); function getSpotPrice() external view returns (uint256); function getAveragePrice(uint256 priceAccumulator, uint256 priceTimestamp) external view returns (uint256); function setOwner(address _owner) external; function setUniswapPair(address _uniswapPair) external; function tradeX( uint256 xAfter, uint256 xBefore, uint256 yBefore, bytes calldata data ) external view returns (uint256 yAfter); function tradeY( uint256 yAfter, uint256 yBefore, uint256 xBefore, bytes calldata data ) external view returns (uint256 xAfter); function depositTradeXIn( uint256 xLeft, uint256 xBefore, uint256 yBefore, bytes calldata data ) external view returns (uint256 xIn); function depositTradeYIn( uint256 yLeft, uint256 yBefore, uint256 xBefore, bytes calldata data ) external view returns (uint256 yIn); function getSwapAmount0Out( uint256 swapFee, uint256 amount1In, bytes calldata data ) external view returns (uint256 amount0Out); function getSwapAmount1Out( uint256 swapFee, uint256 amount0In, bytes calldata data ) external view returns (uint256 amount1Out); function getSwapAmountInMaxOut( bool inverse, uint256 swapFee, uint256 _amountOut, bytes calldata data ) external view returns (uint256 amountIn, uint256 amountOut); function getSwapAmountInMinOut( bool inverse, uint256 swapFee, uint256 _amountOut, bytes calldata data ) external view returns (uint256 amountIn, uint256 amountOut); }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import './ITwapERC20.sol'; import './IReserves.sol'; interface ITwapPair is ITwapERC20, IReserves { event Mint(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 liquidityOut, address indexed to); event Burn(address indexed sender, uint256 amount0Out, uint256 amount1Out, uint256 liquidityIn, address indexed to); event Swap( address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to ); event SetMintFee(uint256 fee); event SetBurnFee(uint256 fee); event SetSwapFee(uint256 fee); event SetOracle(address account); event SetTrader(address trader); function MINIMUM_LIQUIDITY() external pure returns (uint256); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function oracle() external view returns (address); function trader() external view returns (address); function mintFee() external view returns (uint256); function setMintFee(uint256 fee) external; function mint(address to) external returns (uint256 liquidity); function burnFee() external view returns (uint256); function setBurnFee(uint256 fee) external; function burn(address to) external returns (uint256 amount0, uint256 amount1); function swapFee() external view returns (uint256); function setSwapFee(uint256 fee) external; function setOracle(address account) external; function setTrader(address account) external; function collect(address to) external; function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external; function sync() external; function initialize(address _token0, address _token1, address _oracle, address _trader) external; function getSwapAmount0In(uint256 amount1Out, bytes calldata data) external view returns (uint256 swapAmount0In); function getSwapAmount1In(uint256 amount0Out, bytes calldata data) external view returns (uint256 swapAmount1In); function getSwapAmount0Out(uint256 amount1In, bytes calldata data) external view returns (uint256 swapAmount0Out); function getSwapAmount1Out(uint256 amount0In, bytes calldata data) external view returns (uint256 swapAmount1Out); function getDepositAmount0In(uint256 amount0, bytes calldata data) external view returns (uint256 depositAmount0In); function getDepositAmount1In(uint256 amount1, bytes calldata data) external view returns (uint256 depositAmount1In); }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import './TransferHelper.sol'; import './SafeMath.sol'; import './Math.sol'; import '../interfaces/ITwapPair.sol'; import '../interfaces/ITwapOracle.sol'; library AddLiquidity { using SafeMath for uint256; function addLiquidity( address pair, uint256 amount0Desired, uint256 amount1Desired ) internal view returns (uint256 amount0, uint256 amount1, uint256 swapToken) { if (amount0Desired == 0 || amount1Desired == 0) { if (amount0Desired > 0) { swapToken = 1; } else if (amount1Desired > 0) { swapToken = 2; } return (0, 0, swapToken); } (uint256 reserve0, uint256 reserve1) = ITwapPair(pair).getReserves(); if (reserve0 == 0 && reserve1 == 0) { (amount0, amount1) = (amount0Desired, amount1Desired); } else { require(reserve0 > 0 && reserve1 > 0, 'AL07'); uint256 amount1Optimal = amount0Desired.mul(reserve1) / reserve0; if (amount1Optimal <= amount1Desired) { swapToken = 2; (amount0, amount1) = (amount0Desired, amount1Optimal); } else { uint256 amount0Optimal = amount1Desired.mul(reserve0) / reserve1; assert(amount0Optimal <= amount0Desired); swapToken = 1; (amount0, amount1) = (amount0Optimal, amount1Desired); } uint256 totalSupply = ITwapPair(pair).totalSupply(); uint256 liquidityOut = Math.min(amount0.mul(totalSupply) / reserve0, amount1.mul(totalSupply) / reserve1); if (liquidityOut == 0) { amount0 = 0; amount1 = 0; } } } function addLiquidityAndMint( address pair, address to, address token0, address token1, uint256 amount0Desired, uint256 amount1Desired ) external returns (uint256 amount0Left, uint256 amount1Left, uint256 swapToken) { uint256 amount0; uint256 amount1; (amount0, amount1, swapToken) = addLiquidity(pair, amount0Desired, amount1Desired); if (amount0 == 0 || amount1 == 0) { return (amount0Desired, amount1Desired, swapToken); } TransferHelper.safeTransfer(token0, pair, amount0); TransferHelper.safeTransfer(token1, pair, amount1); ITwapPair(pair).mint(to); amount0Left = amount0Desired.sub(amount0); amount1Left = amount1Desired.sub(amount1); } function swapDeposit0( address pair, address token0, uint256 amount0, uint256 minSwapPrice, uint16 tolerance, bytes calldata data ) external returns (uint256 amount0Left, uint256 amount1Left) { uint256 amount0In = ITwapPair(pair).getDepositAmount0In(amount0, data); amount1Left = ITwapPair(pair).getSwapAmount1Out(amount0In, data).sub(tolerance); if (amount1Left == 0) { return (amount0, amount1Left); } uint256 price = getPrice(amount0In, amount1Left, pair); require(minSwapPrice == 0 || price >= minSwapPrice, 'AL15'); TransferHelper.safeTransfer(token0, pair, amount0In); ITwapPair(pair).swap(0, amount1Left, address(this), data); amount0Left = amount0.sub(amount0In); } function swapDeposit1( address pair, address token1, uint256 amount1, uint256 maxSwapPrice, uint16 tolerance, bytes calldata data ) external returns (uint256 amount0Left, uint256 amount1Left) { uint256 amount1In = ITwapPair(pair).getDepositAmount1In(amount1, data); amount0Left = ITwapPair(pair).getSwapAmount0Out(amount1In, data).sub(tolerance); if (amount0Left == 0) { return (amount0Left, amount1); } uint256 price = getPrice(amount0Left, amount1In, pair); require(maxSwapPrice == 0 || price <= maxSwapPrice, 'AL16'); TransferHelper.safeTransfer(token1, pair, amount1In); ITwapPair(pair).swap(amount0Left, 0, address(this), data); amount1Left = amount1.sub(amount1In); } function getPrice(uint256 amount0, uint256 amount1, address pair) internal view returns (uint256) { ITwapOracle oracle = ITwapOracle(ITwapPair(pair).oracle()); return amount1.mul(uint256(oracle.decimalsConverter())).div(amount0); } function _refundDeposit(address to, address token0, address token1, uint256 amount0, uint256 amount1) internal { if (amount0 > 0) { TransferHelper.safeTransfer(token0, to, amount0); } if (amount1 > 0) { TransferHelper.safeTransfer(token1, to, amount1); } } }
pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import '../interfaces/ITwapOracle.sol'; import '../interfaces/ITwapPair.sol'; import '../interfaces/IWETH.sol'; import '../libraries/SafeMath.sol'; import '../libraries/Orders.sol'; import '../libraries/TokenShares.sol'; import '../libraries/AddLiquidity.sol'; import '../libraries/WithdrawHelper.sol'; library ExecutionHelper { using SafeMath for uint256; using TransferHelper for address; using Orders for Orders.Data; using TokenShares for TokenShares.Data; uint256 private constant ORDER_LIFESPAN = 48 hours; struct ExecuteBuySellParams { Orders.Order order; address pairAddress; uint16 pairTolerance; } function executeDeposit( Orders.Order calldata order, address pairAddress, uint16 pairTolerance, TokenShares.Data storage tokenShares ) external { require(order.validAfterTimestamp + ORDER_LIFESPAN >= block.timestamp, 'EH04'); (uint256 amount0Left, uint256 amount1Left, uint256 swapToken) = _initialDeposit( order, pairAddress, tokenShares ); if (order.swap && swapToken != 0) { bytes memory data = encodePriceInfo(pairAddress, order.priceAccumulator, order.timestamp); if (amount0Left != 0 && swapToken == 1) { uint256 extraAmount1; (amount0Left, extraAmount1) = AddLiquidity.swapDeposit0( pairAddress, order.token0, amount0Left, order.minSwapPrice, pairTolerance, data ); amount1Left = amount1Left.add(extraAmount1); } else if (amount1Left != 0 && swapToken == 2) { uint256 extraAmount0; (extraAmount0, amount1Left) = AddLiquidity.swapDeposit1( pairAddress, order.token1, amount1Left, order.maxSwapPrice, pairTolerance, data ); amount0Left = amount0Left.add(extraAmount0); } } if (amount0Left != 0 && amount1Left != 0) { (amount0Left, amount1Left, ) = AddLiquidity.addLiquidityAndMint( pairAddress, order.to, order.token0, order.token1, amount0Left, amount1Left ); } AddLiquidity._refundDeposit(order.to, order.token0, order.token1, amount0Left, amount1Left); } function _initialDeposit( Orders.Order calldata order, address pairAddress, TokenShares.Data storage tokenShares ) private returns (uint256 amount0Left, uint256 amount1Left, uint256 swapToken) { uint256 amount0Desired = tokenShares.sharesToAmount(order.token0, order.value0, order.amountLimit0, order.to); uint256 amount1Desired = tokenShares.sharesToAmount(order.token1, order.value1, order.amountLimit1, order.to); (amount0Left, amount1Left, swapToken) = AddLiquidity.addLiquidityAndMint( pairAddress, order.to, order.token0, order.token1, amount0Desired, amount1Desired ); } function executeWithdraw(Orders.Order calldata order) external { require(order.validAfterTimestamp + ORDER_LIFESPAN >= block.timestamp, 'EH04'); (address pairAddress, ) = Orders.getPair(order.token0, order.token1); TransferHelper.safeTransfer(pairAddress, pairAddress, order.liquidity); uint256 wethAmount; uint256 amount0; uint256 amount1; if (order.unwrap && (order.token0 == TokenShares.WETH_ADDRESS || order.token1 == TokenShares.WETH_ADDRESS)) { bool success; (success, wethAmount, amount0, amount1) = WithdrawHelper.withdrawAndUnwrap( order.token0, order.token1, pairAddress, TokenShares.WETH_ADDRESS, order.to, Orders.getTransferGasCost(Orders.NATIVE_CURRENCY_SENTINEL) ); if (!success) { TokenShares.onUnwrapFailed(order.to, wethAmount); } } else { (amount0, amount1) = ITwapPair(pairAddress).burn(order.to); } require(amount0 >= order.value0 && amount1 >= order.value1, 'EH03'); } function executeBuy(ExecuteBuySellParams memory orderParams, TokenShares.Data storage tokenShares) external { require(orderParams.order.validAfterTimestamp + ORDER_LIFESPAN >= block.timestamp, 'EH04'); uint256 amountInMax = tokenShares.sharesToAmount( orderParams.order.token0, orderParams.order.value0, orderParams.order.amountLimit0, orderParams.order.to ); bytes memory priceInfo = encodePriceInfo( orderParams.pairAddress, orderParams.order.priceAccumulator, orderParams.order.timestamp ); uint256 amountIn; uint256 amountOut; uint256 reserveOut; bool inverted = orderParams.order.inverted; { // scope for reserve out logic, avoids stack too deep errors (uint112 reserve0, uint112 reserve1) = ITwapPair(orderParams.pairAddress).getReserves(); // subtract 1 to prevent reserve going to 0 reserveOut = uint256(inverted ? reserve0 : reserve1).sub(1); } { // scope for partial fill logic, avoids stack too deep errors address oracle = ITwapPair(orderParams.pairAddress).oracle(); uint256 swapFee = ITwapPair(orderParams.pairAddress).swapFee(); (amountIn, amountOut) = ITwapOracle(oracle).getSwapAmountInMaxOut( inverted, swapFee, orderParams.order.value1, priceInfo ); uint256 amountInMaxScaled; if (amountOut > reserveOut) { amountInMaxScaled = amountInMax.mul(reserveOut).ceil_div(orderParams.order.value1); (amountIn, amountOut) = ITwapOracle(oracle).getSwapAmountInMinOut( inverted, swapFee, reserveOut, priceInfo ); } else { amountInMaxScaled = amountInMax; amountOut = orderParams.order.value1; // Truncate to desired out } require(amountInMaxScaled >= amountIn, 'EH08'); if (amountInMax > amountIn) { if (orderParams.order.token0 == TokenShares.WETH_ADDRESS && orderParams.order.unwrap) { forceEtherTransfer(orderParams.order.to, amountInMax.sub(amountIn)); } else { TransferHelper.safeTransfer( orderParams.order.token0, orderParams.order.to, amountInMax.sub(amountIn) ); } } TransferHelper.safeTransfer(orderParams.order.token0, orderParams.pairAddress, amountIn); } amountOut = amountOut.sub(orderParams.pairTolerance); uint256 amount0Out; uint256 amount1Out; if (inverted) { amount0Out = amountOut; } else { amount1Out = amountOut; } if (orderParams.order.token1 == TokenShares.WETH_ADDRESS && orderParams.order.unwrap) { ITwapPair(orderParams.pairAddress).swap(amount0Out, amount1Out, address(this), priceInfo); forceEtherTransfer(orderParams.order.to, amountOut); } else { ITwapPair(orderParams.pairAddress).swap(amount0Out, amount1Out, orderParams.order.to, priceInfo); } } function executeSell(ExecuteBuySellParams memory orderParams, TokenShares.Data storage tokenShares) external { require(orderParams.order.validAfterTimestamp + ORDER_LIFESPAN >= block.timestamp, 'EH04'); bytes memory priceInfo = encodePriceInfo( orderParams.pairAddress, orderParams.order.priceAccumulator, orderParams.order.timestamp ); uint256 amountOut = _executeSellHelper(orderParams, priceInfo, tokenShares); (uint256 amount0Out, uint256 amount1Out) = orderParams.order.inverted ? (amountOut, uint256(0)) : (uint256(0), amountOut); if (orderParams.order.token1 == TokenShares.WETH_ADDRESS && orderParams.order.unwrap) { ITwapPair(orderParams.pairAddress).swap(amount0Out, amount1Out, address(this), priceInfo); forceEtherTransfer(orderParams.order.to, amountOut); } else { ITwapPair(orderParams.pairAddress).swap(amount0Out, amount1Out, orderParams.order.to, priceInfo); } } function _executeSellHelper( ExecuteBuySellParams memory orderParams, bytes memory priceInfo, TokenShares.Data storage tokenShares ) internal returns (uint256 amountOut) { uint256 reserveOut; { // scope for determining reserve out, avoids stack too deep errors (uint112 reserve0, uint112 reserve1) = ITwapPair(orderParams.pairAddress).getReserves(); // subtract 1 to prevent reserve going to 0 reserveOut = uint256(orderParams.order.inverted ? reserve0 : reserve1).sub(1); } { // scope for calculations, avoids stack too deep errors address oracle = ITwapPair(orderParams.pairAddress).oracle(); uint256 swapFee = ITwapPair(orderParams.pairAddress).swapFee(); uint256 amountIn = tokenShares.sharesToAmount( orderParams.order.token0, orderParams.order.value0, orderParams.order.amountLimit0, orderParams.order.to ); amountOut = orderParams.order.inverted ? ITwapOracle(oracle).getSwapAmount0Out(swapFee, amountIn, priceInfo) : ITwapOracle(oracle).getSwapAmount1Out(swapFee, amountIn, priceInfo); uint256 amountOutMinScaled; if (amountOut > reserveOut) { amountOutMinScaled = orderParams.order.value1.mul(reserveOut).div(amountOut); uint256 _amountIn = amountIn; (amountIn, amountOut) = ITwapOracle(oracle).getSwapAmountInMinOut( orderParams.order.inverted, swapFee, reserveOut, priceInfo ); if (orderParams.order.token0 == TokenShares.WETH_ADDRESS && orderParams.order.unwrap) { forceEtherTransfer(orderParams.order.to, _amountIn.sub(amountIn)); } else { TransferHelper.safeTransfer( orderParams.order.token0, orderParams.order.to, _amountIn.sub(amountIn) ); } } else { amountOutMinScaled = orderParams.order.value1; } amountOut = amountOut.sub(orderParams.pairTolerance); require(amountOut >= amountOutMinScaled, 'EH37'); TransferHelper.safeTransfer(orderParams.order.token0, orderParams.pairAddress, amountIn); } } function encodePriceInfo( address pairAddress, uint256 priceAccumulator, uint256 priceTimestamp ) internal view returns (bytes memory data) { uint256 price = ITwapOracle(ITwapPair(pairAddress).oracle()).getAveragePrice(priceAccumulator, priceTimestamp); // Pack everything as 32 bytes / uint256 to simplify decoding data = abi.encode(price); } function forceEtherTransfer(address to, uint256 amount) internal { IWETH(TokenShares.WETH_ADDRESS).withdraw(amount); (bool success, ) = to.call{ value: amount, gas: Orders.getTransferGasCost(Orders.NATIVE_CURRENCY_SENTINEL) }( '' ); if (!success) { TokenShares.onUnwrapFailed(to, amount); } } }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 // a library for performing various math operations library Math { function min(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x < y ? x : y; } function max(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x > y ? x : y; } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } }
pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import './SafeMath.sol'; import '../libraries/Math.sol'; import '../interfaces/ITwapFactory.sol'; import '../interfaces/ITwapPair.sol'; import '../interfaces/ITwapOracle.sol'; import '../libraries/TokenShares.sol'; library Orders { using SafeMath for uint256; using TokenShares for TokenShares.Data; using TransferHelper for address; enum OrderType { Empty, Deposit, Withdraw, Sell, Buy } enum OrderStatus { NonExistent, EnqueuedWaiting, EnqueuedReady, ExecutedSucceeded, ExecutedFailed, Canceled } event DepositEnqueued(uint256 indexed orderId, Order order); event WithdrawEnqueued(uint256 indexed orderId, Order order); event SellEnqueued(uint256 indexed orderId, Order order); event BuyEnqueued(uint256 indexed orderId, Order order); event OrderTypesDisabled(address pair, Orders.OrderType[] orderTypes, bool disabled); event RefundFailed(address indexed to, address indexed token, uint256 amount, bytes data); // Note on gas estimation for the full order execution in the UI: // Add (*_ORDER_BASE_COST + token transfer costs) to the actual gas usage // of the TwapDelay._execute* functions when updating gas cost in the UI. // Remember that ETH unwrap is part of those functions. It is optional, // but also needs to be included in the estimate. uint256 public constant ETHER_TRANSFER_COST = ETHER_TRANSFER_CALL_COST + 2600 + 1504; // Std cost + EIP-2929 acct access cost + Gnosis Safe receive ETH cost uint256 private constant BOT_ETHER_TRANSFER_COST = 10_000; uint256 private constant BUFFER_COST = 10_000; uint256 private constant ORDER_EXECUTED_EVENT_COST = 3700; uint256 private constant EXECUTE_PREPARATION_COST = 30_000; // dequeue + gas calculation before calls to _execute* functions uint256 public constant ETHER_TRANSFER_CALL_COST = 10_000; uint256 public constant PAIR_TRANSFER_COST = 55_000; uint256 public constant REFUND_BASE_COST = BOT_ETHER_TRANSFER_COST + ETHER_TRANSFER_COST + BUFFER_COST + ORDER_EXECUTED_EVENT_COST; uint256 private constant ORDER_BASE_COST = EXECUTE_PREPARATION_COST + REFUND_BASE_COST; uint256 public constant TOKEN_REFUND_BASE_COST = 20_000; // cost of performing token refund logic (excluding token transfer) uint256 public constant DEPOSIT_ORDER_BASE_COST = ORDER_BASE_COST + 2 * TOKEN_REFUND_BASE_COST; uint256 public constant WITHDRAW_ORDER_BASE_COST = ORDER_BASE_COST; uint256 public constant SELL_ORDER_BASE_COST = ORDER_BASE_COST + TOKEN_REFUND_BASE_COST; uint256 public constant BUY_ORDER_BASE_COST = ORDER_BASE_COST + TOKEN_REFUND_BASE_COST; // Masks used for setting order disabled // Different bits represent different order types uint8 private constant DEPOSIT_MASK = uint8(1 << uint8(OrderType.Deposit)); // 00000010 uint8 private constant WITHDRAW_MASK = uint8(1 << uint8(OrderType.Withdraw)); // 00000100 uint8 private constant SELL_MASK = uint8(1 << uint8(OrderType.Sell)); // 00001000 uint8 private constant BUY_MASK = uint8(1 << uint8(OrderType.Buy)); // 00010000 address public constant FACTORY_ADDRESS = 0xC480b33eE5229DE3FbDFAD1D2DCD3F3BAD0C56c6; uint256 public constant MAX_GAS_LIMIT = 5000000; uint256 public constant GAS_PRICE_INERTIA = 20000000; uint256 public constant MAX_GAS_PRICE_IMPACT = 1000000; uint256 public constant DELAY = 1800; address public constant NATIVE_CURRENCY_SENTINEL = address(0); // A sentinel value for the native currency to distinguish it from ERC20 tokens struct Data { uint256 newestOrderId; uint256 lastProcessedOrderId; mapping(uint256 => bytes32) orderQueue; uint256 gasPrice; mapping(uint256 => bool) canceled; // Bit on specific positions indicates whether order type is disabled (1) or enabled (0) on specific pair mapping(address => uint8) orderTypesDisabled; mapping(uint256 => bool) refundFailed; } struct Order { uint256 orderId; OrderType orderType; bool inverted; uint256 validAfterTimestamp; bool unwrap; uint256 timestamp; uint256 gasLimit; uint256 gasPrice; uint256 liquidity; uint256 value0; // Deposit: share0, Withdraw: amount0Min, Sell: shareIn, Buy: shareInMax uint256 value1; // Deposit: share1, Withdraw: amount1Min, Sell: amountOutMin, Buy: amountOut address token0; // Sell: tokenIn, Buy: tokenIn address token1; // Sell: tokenOut, Buy: tokenOut address to; uint256 minSwapPrice; uint256 maxSwapPrice; bool swap; uint256 priceAccumulator; uint256 amountLimit0; uint256 amountLimit1; } function getOrderStatus( Data storage data, uint256 orderId, uint256 validAfterTimestamp ) internal view returns (OrderStatus) { if (orderId > data.newestOrderId) { return OrderStatus.NonExistent; } if (data.canceled[orderId]) { return OrderStatus.Canceled; } if (data.refundFailed[orderId]) { return OrderStatus.ExecutedFailed; } if (data.orderQueue[orderId] == bytes32(0)) { return OrderStatus.ExecutedSucceeded; } if (validAfterTimestamp >= block.timestamp) { return OrderStatus.EnqueuedWaiting; } return OrderStatus.EnqueuedReady; } function getPair(address tokenA, address tokenB) internal view returns (address pair, bool inverted) { pair = ITwapFactory(FACTORY_ADDRESS).getPair(tokenA, tokenB); require(pair != address(0), 'OS17'); inverted = tokenA > tokenB; } function getDepositDisabled(Data storage data, address pair) internal view returns (bool) { return data.orderTypesDisabled[pair] & DEPOSIT_MASK != 0; } function getWithdrawDisabled(Data storage data, address pair) internal view returns (bool) { return data.orderTypesDisabled[pair] & WITHDRAW_MASK != 0; } function getSellDisabled(Data storage data, address pair) internal view returns (bool) { return data.orderTypesDisabled[pair] & SELL_MASK != 0; } function getBuyDisabled(Data storage data, address pair) internal view returns (bool) { return data.orderTypesDisabled[pair] & BUY_MASK != 0; } function setOrderTypesDisabled( Data storage data, address pair, Orders.OrderType[] calldata orderTypes, bool disabled ) external { uint256 orderTypesLength = orderTypes.length; uint8 currentSettings = data.orderTypesDisabled[pair]; uint8 combinedMask; for (uint256 i; i < orderTypesLength; ++i) { Orders.OrderType orderType = orderTypes[i]; require(orderType != Orders.OrderType.Empty, 'OS32'); // zeros with 1 bit set at position specified by orderType // e.g. for SELL order type // mask for SELL = 00001000 // combinedMask = 00000110 (DEPOSIT and WITHDRAW masks set in previous iterations) // the result of OR = 00001110 (DEPOSIT, WITHDRAW and SELL combined mask) combinedMask = combinedMask | uint8(1 << uint8(orderType)); } // set/unset a bit accordingly to 'disabled' value if (disabled) { // OR operation to disable order // e.g. for disable DEPOSIT // currentSettings = 00010100 (BUY and WITHDRAW disabled) // mask for DEPOSIT = 00000010 // the result of OR = 00010110 currentSettings = currentSettings | combinedMask; } else { // AND operation with a mask negation to enable order // e.g. for enable DEPOSIT // currentSettings = 00010100 (BUY and WITHDRAW disabled) // 0xff = 11111111 // mask for Deposit = 00000010 // mask negation = 11111101 // the result of AND = 00010100 currentSettings = currentSettings & (combinedMask ^ 0xff); } require(currentSettings != data.orderTypesDisabled[pair], 'OS01'); data.orderTypesDisabled[pair] = currentSettings; emit OrderTypesDisabled(pair, orderTypes, disabled); } function markRefundFailed(Data storage data) internal { data.refundFailed[data.lastProcessedOrderId] = true; } /// @dev The passed in order.oderId is ignored and overwritten with the correct value, i.e. an updated data.newestOrderId. /// This is done to ensure atomicity of these two actions while optimizing gas usage - adding an order to the queue and incrementing /// data.newestOrderId (which should not be done anywhere else in the contract). /// Must only be called on verified orders. function enqueueOrder(Data storage data, Order memory order) internal { order.orderId = ++data.newestOrderId; data.orderQueue[order.orderId] = getOrderDigest(order); } struct DepositParams { address token0; address token1; uint256 amount0; uint256 amount1; uint256 minSwapPrice; uint256 maxSwapPrice; bool wrap; bool swap; address to; uint256 gasLimit; uint32 submitDeadline; } function deposit( Data storage data, DepositParams calldata depositParams, TokenShares.Data storage tokenShares ) external { checkOrderParams( depositParams.to, depositParams.gasLimit, depositParams.submitDeadline, DEPOSIT_ORDER_BASE_COST + getTransferGasCost(depositParams.token0) + getTransferGasCost(depositParams.token1) ); require(depositParams.amount0 != 0 || depositParams.amount1 != 0, 'OS25'); (address pairAddress, bool inverted) = getPair(depositParams.token0, depositParams.token1); require(!getDepositDisabled(data, pairAddress), 'OS46'); { // scope for value, avoids stack too deep errors uint256 value = msg.value; // allocate gas refund if (depositParams.wrap) { if (depositParams.token0 == TokenShares.WETH_ADDRESS) { value = msg.value.sub(depositParams.amount0, 'OS1E'); } else if (depositParams.token1 == TokenShares.WETH_ADDRESS) { value = msg.value.sub(depositParams.amount1, 'OS1E'); } } allocateGasRefund(data, value, depositParams.gasLimit); } uint256 shares0 = tokenShares.amountToShares( inverted ? depositParams.token1 : depositParams.token0, inverted ? depositParams.amount1 : depositParams.amount0, depositParams.wrap ); uint256 shares1 = tokenShares.amountToShares( inverted ? depositParams.token0 : depositParams.token1, inverted ? depositParams.amount0 : depositParams.amount1, depositParams.wrap ); (uint256 priceAccumulator, uint256 timestamp) = ITwapOracle(ITwapPair(pairAddress).oracle()).getPriceInfo(); Order memory order = Order( 0, OrderType.Deposit, inverted, timestamp + DELAY, // validAfterTimestamp depositParams.wrap, timestamp, depositParams.gasLimit, data.gasPrice, 0, // liquidity shares0, shares1, inverted ? depositParams.token1 : depositParams.token0, inverted ? depositParams.token0 : depositParams.token1, depositParams.to, depositParams.minSwapPrice, depositParams.maxSwapPrice, depositParams.swap, priceAccumulator, inverted ? depositParams.amount1 : depositParams.amount0, inverted ? depositParams.amount0 : depositParams.amount1 ); enqueueOrder(data, order); emit DepositEnqueued(order.orderId, order); } struct WithdrawParams { address token0; address token1; uint256 liquidity; uint256 amount0Min; uint256 amount1Min; bool unwrap; address to; uint256 gasLimit; uint32 submitDeadline; } function withdraw(Data storage data, WithdrawParams calldata withdrawParams) external { (address pair, bool inverted) = getPair(withdrawParams.token0, withdrawParams.token1); require(!getWithdrawDisabled(data, pair), 'OS0A'); checkOrderParams( withdrawParams.to, withdrawParams.gasLimit, withdrawParams.submitDeadline, WITHDRAW_ORDER_BASE_COST + PAIR_TRANSFER_COST ); require(withdrawParams.liquidity != 0, 'OS22'); allocateGasRefund(data, msg.value, withdrawParams.gasLimit); pair.safeTransferFrom(msg.sender, address(this), withdrawParams.liquidity); Order memory order = Order( 0, OrderType.Withdraw, inverted, block.timestamp + DELAY, // validAfterTimestamp withdrawParams.unwrap, 0, // timestamp withdrawParams.gasLimit, data.gasPrice, withdrawParams.liquidity, inverted ? withdrawParams.amount1Min : withdrawParams.amount0Min, inverted ? withdrawParams.amount0Min : withdrawParams.amount1Min, inverted ? withdrawParams.token1 : withdrawParams.token0, inverted ? withdrawParams.token0 : withdrawParams.token1, withdrawParams.to, 0, // minSwapPrice 0, // maxSwapPrice false, // swap 0, // priceAccumulator 0, // amountLimit0 0 // amountLimit1 ); enqueueOrder(data, order); emit WithdrawEnqueued(order.orderId, order); } struct SellParams { address tokenIn; address tokenOut; uint256 amountIn; uint256 amountOutMin; bool wrapUnwrap; address to; uint256 gasLimit; uint32 submitDeadline; } function sell(Data storage data, SellParams calldata sellParams, TokenShares.Data storage tokenShares) external { checkOrderParams( sellParams.to, sellParams.gasLimit, sellParams.submitDeadline, SELL_ORDER_BASE_COST + getTransferGasCost(sellParams.tokenIn) ); (address pairAddress, bool inverted) = sellHelper(data, sellParams); (uint256 priceAccumulator, uint256 timestamp) = ITwapOracle(ITwapPair(pairAddress).oracle()).getPriceInfo(); uint256 shares = tokenShares.amountToShares(sellParams.tokenIn, sellParams.amountIn, sellParams.wrapUnwrap); Order memory order = Order( 0, OrderType.Sell, inverted, timestamp + DELAY, // validAfterTimestamp sellParams.wrapUnwrap, timestamp, sellParams.gasLimit, data.gasPrice, 0, // liquidity shares, sellParams.amountOutMin, sellParams.tokenIn, sellParams.tokenOut, sellParams.to, 0, // minSwapPrice 0, // maxSwapPrice false, // swap priceAccumulator, sellParams.amountIn, 0 // amountLimit1 ); enqueueOrder(data, order); emit SellEnqueued(order.orderId, order); } function relayerSell( Data storage data, SellParams calldata sellParams, TokenShares.Data storage tokenShares ) external { checkOrderParams( sellParams.to, sellParams.gasLimit, sellParams.submitDeadline, SELL_ORDER_BASE_COST + getTransferGasCost(sellParams.tokenIn) ); (, bool inverted) = sellHelper(data, sellParams); uint256 shares = tokenShares.amountToSharesWithoutTransfer( sellParams.tokenIn, sellParams.amountIn, sellParams.wrapUnwrap ); Order memory order = Order( 0, OrderType.Sell, inverted, block.timestamp + DELAY, // validAfterTimestamp false, // Never wrap/unwrap block.timestamp, sellParams.gasLimit, data.gasPrice, 0, // liquidity shares, sellParams.amountOutMin, sellParams.tokenIn, sellParams.tokenOut, sellParams.to, 0, // minSwapPrice 0, // maxSwapPrice false, // swap 0, // priceAccumulator - oracleV3 pairs don't need priceAccumulator sellParams.amountIn, 0 // amountLimit1 ); enqueueOrder(data, order); emit SellEnqueued(order.orderId, order); } function sellHelper( Data storage data, SellParams calldata sellParams ) internal returns (address pairAddress, bool inverted) { require(sellParams.amountIn != 0, 'OS24'); (pairAddress, inverted) = getPair(sellParams.tokenIn, sellParams.tokenOut); require(!getSellDisabled(data, pairAddress), 'OS13'); // allocate gas refund uint256 value = msg.value; if (sellParams.wrapUnwrap && sellParams.tokenIn == TokenShares.WETH_ADDRESS) { value = msg.value.sub(sellParams.amountIn, 'OS1E'); } allocateGasRefund(data, value, sellParams.gasLimit); } struct BuyParams { address tokenIn; address tokenOut; uint256 amountInMax; uint256 amountOut; bool wrapUnwrap; address to; uint256 gasLimit; uint32 submitDeadline; } function buy(Data storage data, BuyParams calldata buyParams, TokenShares.Data storage tokenShares) external { checkOrderParams( buyParams.to, buyParams.gasLimit, buyParams.submitDeadline, BUY_ORDER_BASE_COST + getTransferGasCost(buyParams.tokenIn) ); require(buyParams.amountOut != 0, 'OS23'); (address pairAddress, bool inverted) = getPair(buyParams.tokenIn, buyParams.tokenOut); require(!getBuyDisabled(data, pairAddress), 'OS49'); uint256 value = msg.value; // allocate gas refund if (buyParams.tokenIn == TokenShares.WETH_ADDRESS && buyParams.wrapUnwrap) { value = msg.value.sub(buyParams.amountInMax, 'OS1E'); } allocateGasRefund(data, value, buyParams.gasLimit); uint256 shares = tokenShares.amountToShares(buyParams.tokenIn, buyParams.amountInMax, buyParams.wrapUnwrap); (uint256 priceAccumulator, uint256 timestamp) = ITwapOracle(ITwapPair(pairAddress).oracle()).getPriceInfo(); Order memory order = Order( 0, OrderType.Buy, inverted, timestamp + DELAY, // validAfterTimestamp buyParams.wrapUnwrap, timestamp, buyParams.gasLimit, data.gasPrice, 0, // liquidity shares, buyParams.amountOut, buyParams.tokenIn, buyParams.tokenOut, buyParams.to, 0, // minSwapPrice 0, // maxSwapPrice false, // swap priceAccumulator, buyParams.amountInMax, 0 // amountLimit1 ); enqueueOrder(data, order); emit BuyEnqueued(order.orderId, order); } function checkOrderParams(address to, uint256 gasLimit, uint32 submitDeadline, uint256 minGasLimit) private view { require(submitDeadline >= block.timestamp, 'OS04'); require(gasLimit <= MAX_GAS_LIMIT, 'OS3E'); require(gasLimit >= minGasLimit, 'OS3D'); require(to != address(0), 'OS26'); } function allocateGasRefund(Data storage data, uint256 value, uint256 gasLimit) private returns (uint256 futureFee) { futureFee = data.gasPrice.mul(gasLimit); require(value >= futureFee, 'OS1E'); if (value > futureFee) { TransferHelper.safeTransferETH(msg.sender, value - futureFee, getTransferGasCost(NATIVE_CURRENCY_SENTINEL)); } } function updateGasPrice(Data storage data, uint256 gasUsed) external { uint256 scale = Math.min(gasUsed, MAX_GAS_PRICE_IMPACT); data.gasPrice = data.gasPrice.mul(GAS_PRICE_INERTIA.sub(scale)).add(tx.gasprice.mul(scale)).div( GAS_PRICE_INERTIA ); } function refundLiquidity(address pair, address to, uint256 liquidity, bytes4 selector) internal returns (bool) { if (liquidity == 0) { return true; } (bool success, bytes memory data) = address(this).call{ gas: PAIR_TRANSFER_COST }( abi.encodeWithSelector(selector, pair, to, liquidity, false) ); if (!success) { emit RefundFailed(to, pair, liquidity, data); } return success; } function dequeueOrder(Data storage data, uint256 orderId) internal { ++data.lastProcessedOrderId; require(orderId == data.lastProcessedOrderId, 'OS72'); } function forgetOrder(Data storage data, uint256 orderId) internal { delete data.orderQueue[orderId]; } function forgetLastProcessedOrder(Data storage data) internal { delete data.orderQueue[data.lastProcessedOrderId]; } function getOrderDigest(Order memory order) internal pure returns (bytes32) { // Used to avoid the 'stack too deep' error. bytes memory partialOrderData = abi.encodePacked( order.orderId, order.orderType, order.inverted, order.validAfterTimestamp, order.unwrap, order.timestamp, order.gasLimit, order.gasPrice, order.liquidity, order.value0, order.value1, order.token0, order.token1, order.to ); return keccak256( abi.encodePacked( partialOrderData, order.minSwapPrice, order.maxSwapPrice, order.swap, order.priceAccumulator, order.amountLimit0, order.amountLimit1 ) ); } function verifyOrder(Data storage data, Order memory order) external view { require(getOrderDigest(order) == data.orderQueue[order.orderId], 'OS71'); } // constant mapping for transferGasCost /** * @dev This function should either return a default value != 0 or revert. */ function getTransferGasCost(address token) internal pure returns (uint256) { if (token == NATIVE_CURRENCY_SENTINEL) return ETHER_TRANSFER_CALL_COST; if (token == 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) return 31000; if (token == 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) return 42000; if (token == 0xdAC17F958D2ee523a2206206994597C13D831ec7) return 66000; if (token == 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599) return 34000; if (token == 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B) return 31000; if (token == 0x6B3595068778DD592e39A122f4f5a5cF09C90fE2) return 31000; if (token == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) return 68000; if (token == 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0) return 31000; if (token == 0xD33526068D116cE69F19A9ee46F0bd304F21A51f) return 31000; if (token == 0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2) return 40000; if (token == 0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32) return 149000; if (token == 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2) return 34000; if (token == 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984) return 37000; if (token == 0x514910771AF9Ca656af840dff83E8264EcF986CA) return 32000; if (token == 0x3c3a81e81dc49A522A592e7622A7E711c06bf354) return 34000; return 60000; } }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) library SafeMath { int256 private constant _INT256_MIN = -2 ** 255; function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x, 'SM4E'); } function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { z = sub(x, y, 'SM12'); } function sub(uint256 x, uint256 y, string memory message) internal pure returns (uint256 z) { require((z = x - y) <= x, message); } function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { require(y == 0 || (z = x * y) / y == x, 'SM2A'); } function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, 'SM43'); return a / b; } function ceil_div(uint256 a, uint256 b) internal pure returns (uint256 c) { c = div(a, b); if (a != mul(b, c)) { return add(c, 1); } } function toUint32(uint256 n) internal pure returns (uint32) { require(n <= type(uint32).max, 'SM50'); return uint32(n); } function toUint64(uint256 n) internal pure returns (uint64) { require(n <= type(uint64).max, 'SM54'); return uint64(n); } function toUint112(uint256 n) internal pure returns (uint112) { require(n <= type(uint112).max, 'SM51'); return uint112(n); } function toInt256(uint256 unsigned) internal pure returns (int256 signed) { require(unsigned <= uint256(type(int256).max), 'SM34'); signed = int256(unsigned); } // int256 function add(int256 a, int256 b) internal pure returns (int256 c) { c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a), 'SM4D'); } function sub(int256 a, int256 b) internal pure returns (int256 c) { c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a), 'SM11'); } function mul(int256 a, int256 b) internal pure returns (int256 c) { // 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; } require(!(a == -1 && b == _INT256_MIN), 'SM29'); c = a * b; require(c / a == b, 'SM29'); } function div(int256 a, int256 b) internal pure returns (int256) { require(b != 0, 'SM43'); require(!(b == -1 && a == _INT256_MIN), 'SM42'); return a / b; } function neg_floor_div(int256 a, int256 b) internal pure returns (int256 c) { c = div(a, b); if ((a < 0 && b > 0) || (a >= 0 && b < 0)) { if (a != mul(b, c)) { c = sub(c, 1); } } } }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import '../interfaces/IERC20.sol'; import '../interfaces/IWETH.sol'; import './SafeMath.sol'; import './TransferHelper.sol'; library TokenShares { using SafeMath for uint256; using TransferHelper for address; uint256 private constant PRECISION = 10 ** 18; uint256 private constant TOLERANCE = 10 ** 18 + 10 ** 16; uint256 private constant TOTAL_SHARES_PRECISION = 10 ** 18; event UnwrapFailed(address to, uint256 amount); // represents wrapped native currency (WETH or WMATIC) address public constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; struct Data { mapping(address => uint256) totalShares; } function sharesToAmount( Data storage data, address token, uint256 share, uint256 amountLimit, address refundTo ) external returns (uint256) { if (share == 0) { return 0; } if (token == WETH_ADDRESS || isNonRebasing(token)) { return share; } uint256 totalTokenShares = data.totalShares[token]; require(totalTokenShares >= share, 'TS3A'); uint256 balance = IERC20(token).balanceOf(address(this)); uint256 value = balance.mul(share).div(totalTokenShares); data.totalShares[token] = totalTokenShares.sub(share); if (amountLimit > 0) { uint256 amountLimitWithTolerance = amountLimit.mul(TOLERANCE).div(PRECISION); if (value > amountLimitWithTolerance) { TransferHelper.safeTransfer(token, refundTo, value.sub(amountLimitWithTolerance)); return amountLimitWithTolerance; } } return value; } function amountToShares(Data storage data, address token, uint256 amount, bool wrap) external returns (uint256) { if (amount == 0) { return 0; } if (token == WETH_ADDRESS) { if (wrap) { require(msg.value >= amount, 'TS03'); IWETH(token).deposit{ value: amount }(); } else { token.safeTransferFrom(msg.sender, address(this), amount); } return amount; } else if (isNonRebasing(token)) { token.safeTransferFrom(msg.sender, address(this), amount); return amount; } else { uint256 balanceBefore = IERC20(token).balanceOf(address(this)); token.safeTransferFrom(msg.sender, address(this), amount); uint256 balanceAfter = IERC20(token).balanceOf(address(this)); return amountToSharesHelper(data, token, balanceBefore, balanceAfter); } } function amountToSharesWithoutTransfer( Data storage data, address token, uint256 amount, bool wrap ) external returns (uint256) { if (token == WETH_ADDRESS) { if (wrap) { // require(msg.value >= amount, 'TS03'); // Duplicate check in TwapRelayer.sell IWETH(token).deposit{ value: amount }(); } return amount; } else if (isNonRebasing(token)) { return amount; } else { uint256 balanceAfter = IERC20(token).balanceOf(address(this)); uint256 balanceBefore = balanceAfter.sub(amount); return amountToSharesHelper(data, token, balanceBefore, balanceAfter); } } function amountToSharesHelper( Data storage data, address token, uint256 balanceBefore, uint256 balanceAfter ) internal returns (uint256) { uint256 totalTokenShares = data.totalShares[token]; require(balanceBefore > 0 || totalTokenShares == 0, 'TS30'); require(balanceAfter > balanceBefore, 'TS2C'); if (balanceBefore > 0) { if (totalTokenShares == 0) { totalTokenShares = balanceBefore.mul(TOTAL_SHARES_PRECISION); } uint256 newShares = totalTokenShares.mul(balanceAfter).div(balanceBefore); require(balanceAfter < type(uint256).max.div(newShares), 'TS73'); // to prevent overflow at execution data.totalShares[token] = newShares; return newShares - totalTokenShares; } else { totalTokenShares = balanceAfter.mul(TOTAL_SHARES_PRECISION); require(totalTokenShares < type(uint256).max.div(totalTokenShares), 'TS73'); // to prevent overflow at execution data.totalShares[token] = totalTokenShares; return totalTokenShares; } } function onUnwrapFailed(address to, uint256 amount) external { emit UnwrapFailed(to, amount); IWETH(WETH_ADDRESS).deposit{ value: amount }(); TransferHelper.safeTransfer(WETH_ADDRESS, to, amount); } // constant mapping for nonRebasingToken function isNonRebasing(address token) internal pure returns (bool) { if (token == 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) return true; if (token == 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) return true; if (token == 0xdAC17F958D2ee523a2206206994597C13D831ec7) return true; if (token == 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599) return true; if (token == 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B) return true; if (token == 0x6B3595068778DD592e39A122f4f5a5cF09C90fE2) return true; if (token == 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0) return true; if (token == 0xD33526068D116cE69F19A9ee46F0bd304F21A51f) return true; if (token == 0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2) return true; if (token == 0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32) return true; if (token == 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2) return true; if (token == 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984) return true; if (token == 0x514910771AF9Ca656af840dff83E8264EcF986CA) return true; if (token == 0x3c3a81e81dc49A522A592e7622A7E711c06bf354) return true; return false; } }
pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove(address token, address to, uint256 value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TH4B'); } function safeTransfer(address token, address to, uint256 value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TH05'); } function safeTransferFrom(address token, address from, address to, uint256 value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TH0E'); } function safeTransferETH(address to, uint256 value, uint256 gasLimit) internal { (bool success, ) = to.call{ value: value, gas: gasLimit }(''); require(success, 'TH3F'); } function transferETH(address to, uint256 value, uint256 gasLimit) internal returns (bool success) { (success, ) = to.call{ value: value, gas: gasLimit }(''); } }
pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 import '../interfaces/ITwapPair.sol'; import '../interfaces/IWETH.sol'; import './Orders.sol'; library WithdrawHelper { using SafeMath for uint256; function _transferToken(uint256 balanceBefore, address token, address to) internal { uint256 tokenAmount = IERC20(token).balanceOf(address(this)).sub(balanceBefore); TransferHelper.safeTransfer(token, to, tokenAmount); } // unwraps wrapped native currency function _unwrapWeth(uint256 ethAmount, address weth, address to, uint256 gasLimit) internal returns (bool) { IWETH(weth).withdraw(ethAmount); (bool success, ) = to.call{ value: ethAmount, gas: gasLimit }(''); return success; } function withdrawAndUnwrap( address token0, address token1, address pair, address weth, address to, uint256 gasLimit ) external returns (bool, uint256, uint256, uint256) { bool isToken0Weth = token0 == weth; address otherToken = isToken0Weth ? token1 : token0; uint256 balanceBefore = IERC20(otherToken).balanceOf(address(this)); (uint256 amount0, uint256 amount1) = ITwapPair(pair).burn(address(this)); _transferToken(balanceBefore, otherToken, to); bool success = _unwrapWeth(isToken0Weth ? amount0 : amount1, weth, to, gasLimit); return (success, isToken0Weth ? amount0 : amount1, amount0, amount1); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/libraries/ExecutionHelper.sol": { "ExecutionHelper": "0x4a1dbc839b4ebad8db9058e856e90cb41dffce1f" }, "contracts/libraries/Orders.sol": { "Orders": "0x465e0b6518603e0d75b4737dac052845cf855925" }, "contracts/libraries/TokenShares.sol": { "TokenShares": "0xe92b1734fc37f8acc950d0d13a41475372958730" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_factoryGovernor","type":"address"},{"internalType":"address","name":"_bot","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"bot","type":"address"},{"indexed":false,"internalType":"bool","name":"isBot","type":"bool"}],"name":"BotSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"DelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"EthRefund","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"factoryGovernor","type":"address"}],"name":"FactoryGovernorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"gasPriceInertia","type":"uint256"}],"name":"GasPriceInertiaSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxGasLimit","type":"uint256"}],"name":"MaxGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxGasPriceImpact","type":"uint256"}],"name":"MaxGasPriceImpactSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"isNonRebasing","type":"bool"}],"name":"NonRebasingTokenSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"gasSpent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethRefunded","type":"uint256"}],"name":"OrderExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint16","name":"amount","type":"uint16"}],"name":"ToleranceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasCost","type":"uint256"}],"name":"TransferGasCostSet","type":"event"},{"inputs":[],"name":"RELAYER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"inverted","type":"bool"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"value0","type":"uint256"},{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"uint256","name":"priceAccumulator","type":"uint256"},{"internalType":"uint256","name":"amountLimit0","type":"uint256"},{"internalType":"uint256","name":"amountLimit1","type":"uint256"}],"internalType":"struct Orders.Order","name":"order","type":"tuple"}],"name":"_executeBuy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"inverted","type":"bool"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"value0","type":"uint256"},{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"uint256","name":"priceAccumulator","type":"uint256"},{"internalType":"uint256","name":"amountLimit0","type":"uint256"},{"internalType":"uint256","name":"amountLimit1","type":"uint256"}],"internalType":"struct Orders.Order","name":"order","type":"tuple"}],"name":"_executeDeposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"inverted","type":"bool"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"value0","type":"uint256"},{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"uint256","name":"priceAccumulator","type":"uint256"},{"internalType":"uint256","name":"amountLimit0","type":"uint256"},{"internalType":"uint256","name":"amountLimit1","type":"uint256"}],"internalType":"struct Orders.Order","name":"order","type":"tuple"}],"name":"_executeSell","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"inverted","type":"bool"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"value0","type":"uint256"},{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"uint256","name":"priceAccumulator","type":"uint256"},{"internalType":"uint256","name":"amountLimit0","type":"uint256"},{"internalType":"uint256","name":"amountLimit1","type":"uint256"}],"internalType":"struct Orders.Order","name":"order","type":"tuple"}],"name":"_executeWithdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"name":"_refundLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"share","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"}],"name":"_refundToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"uint256","name":"share0","type":"uint256"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint256","name":"share1","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"}],"name":"_refundTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bool","name":"wrapUnwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint32","name":"submitDeadline","type":"uint32"}],"internalType":"struct Orders.BuyParams","name":"buyParams","type":"tuple"}],"name":"buy","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"inverted","type":"bool"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"value0","type":"uint256"},{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"uint256","name":"priceAccumulator","type":"uint256"},{"internalType":"uint256","name":"amountLimit0","type":"uint256"},{"internalType":"uint256","name":"amountLimit1","type":"uint256"}],"internalType":"struct Orders.Order","name":"order","type":"tuple"}],"name":"cancelOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"wrap","type":"bool"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint32","name":"submitDeadline","type":"uint32"}],"internalType":"struct Orders.DepositParams","name":"depositParams","type":"tuple"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"inverted","type":"bool"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"value0","type":"uint256"},{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"uint256","name":"priceAccumulator","type":"uint256"},{"internalType":"uint256","name":"amountLimit0","type":"uint256"},{"internalType":"uint256","name":"amountLimit1","type":"uint256"}],"internalType":"struct Orders.Order[]","name":"_orders","type":"tuple[]"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"factoryGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPriceInertia","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"getBuyDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"getDepositDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"}],"name":"getOrderStatus","outputs":[{"internalType":"enum Orders.OrderStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"getSellDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"getTolerance","outputs":[{"internalType":"uint16","name":"tolerance","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTransferGasCost","outputs":[{"internalType":"uint256","name":"gasCost","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"getWithdrawDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isNonRebasingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"isOrderCanceled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastProcessedOrderId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxGasPriceImpact","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"newestOrderId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"relayer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"wrapUnwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint32","name":"submitDeadline","type":"uint32"}],"internalType":"struct Orders.SellParams","name":"sellParams","type":"tuple"}],"name":"relayerSell","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"inverted","type":"bool"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"value0","type":"uint256"},{"internalType":"uint256","name":"value1","type":"uint256"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"swap","type":"bool"},{"internalType":"uint256","name":"priceAccumulator","type":"uint256"},{"internalType":"uint256","name":"amountLimit0","type":"uint256"},{"internalType":"uint256","name":"amountLimit1","type":"uint256"}],"internalType":"struct Orders.Order","name":"order","type":"tuple"}],"name":"retryRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"wrapUnwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint32","name":"submitDeadline","type":"uint32"}],"internalType":"struct Orders.SellParams","name":"sellParams","type":"tuple"}],"name":"sell","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_bot","type":"address"},{"internalType":"bool","name":"_isBot","type":"bool"}],"name":"setBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factoryGovernor","type":"address"}],"name":"setFactoryGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"enum Orders.OrderType[]","name":"orderTypes","type":"uint8[]"},{"internalType":"bool","name":"disabled","type":"bool"}],"name":"setOrderTypesDisabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"}],"name":"syncPair","outputs":[{"internalType":"address","name":"pairAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint32","name":"submitDeadline","type":"uint32"}],"internalType":"struct Orders.WithdrawParams","name":"withdrawParams","type":"tuple"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040526001600b553480156200001657600080fd5b50604051620053da380380620053da833981016040819052620000399162000f28565b620000443362000072565b6200004f826200012d565b6200005c816001620001d4565b3a6003556200006a6200027a565b505062001009565b6008546001600160a01b0382811691161415620000ac5760405162461bcd60e51b8152600401620000a39062000fc4565b60405180910390fd5b6001600160a01b038116620000d55760405162461bcd60e51b8152600401620000a39062000fe2565b600880546001600160a01b0319166001600160a01b0383161790556040517f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe2906200012290839062000f5f565b60405180910390a150565b6009546001600160a01b03828116911614156200015e5760405162461bcd60e51b8152600401620000a39062000fc4565b6001600160a01b038116620001875760405162461bcd60e51b8152600401620000a39062000fe2565b600980546001600160a01b0319166001600160a01b0383161790556040517f99db624faf5b574db8409c17138c4894a18b552e2cd1dbe8c70b375a02748b66906200012290839062000f5f565b6001600160a01b0382166000908152600a602052604090205460ff1615158115151415620002165760405162461bcd60e51b8152600401620000a39062000fc4565b6001600160a01b0382166000908152600a602052604090819020805460ff1916831515179055517f70af441dbb427737e6a5ef2cf5b664321011765ce1d19ce4a69cd024e69d4f2f906200026e908490849062000f73565b60405180910390a15050565b7f664d00954017f8b1153ec0813e86deff4b0eabd0548b1de8a6993f4549e0d42c624c4b40604051620002ae919062001000565b60405180910390a17fc93fa9fe410a29e605394838b98dd2b3b4b790b4f45b67dd8c0ddcdd149c4a746301312d00604051620002eb919062001000565b60405180910390a17f536bed877ca8a6a35942227bd9830bfa713b5822f6c5172a85fb51033975391c620f424060405162000327919062001000565b60405180910390a17f63e09f16584208fba1fc7ff64c62b00f07bec177c0d97ca6689891b1e77a35c761070860405162000362919062001000565b60405180910390a17fb7041340e0c2a075059bf0488a71c767724be15dae8e737f8460007325e8d85773d17b3c9784510e33cd5b87b490e79253bcd81e2e604051620003af919062000f5f565b60405180910390a1600080516020620053ba833981519152732fe16dd18bba26e457b7dd2080d5674312b026a26000604051620003ee92919062000f8e565b60405180910390a1600080516020620053ba83398151915273048f0e7ea2cfd522a4a058d1b1bdd574a0486c4660006040516200042d92919062000f8e565b60405180910390a1600080516020620053ba8339815191527337f6df71b40c50b2038329cabf5fda3682df1ebf60006040516200046c92919062000f8e565b60405180910390a1600080516020620053ba833981519152736ec472b613012a492693697fa551420e60567ea76000604051620004ab92919062000f8e565b60405180910390a1600080516020620053ba8339815191527343f0e5f2304f261dfa5359a0b74ff030e498d9046000604051620004ea92919062000f8e565b60405180910390a1600080516020620053ba83398151915273d66f214fb49f81ac5610e0339a351d7e1c67c35e60006040516200052992919062000f8e565b60405180910390a1600080516020620053ba83398151915273d4d2140ed70dcf8794a986f0cfd07560ee738c7160046040516200056892919062000f8e565b60405180910390a1600080516020620053ba8339815191527329b57d56a114ae5be3c129240898b3321a70a3006000604051620005a792919062000f8e565b60405180910390a1600080516020620053ba8339815191527361fa1cee13ceeaf20c30611c5e6da48c595f7db26000604051620005e692919062000f8e565b60405180910390a1600080516020620053ba83398151915273045950a37c59d75496bb4af68c05f9066a4c7e2760006040516200062592919062000f8e565b60405180910390a1600080516020620053ba83398151915273bee7ef1adfaa628536ebc0c1ebf082dbdc27265f60006040516200066492919062000f8e565b60405180910390a1600080516020620053ba8339815191527351badc1622c63d1e448a4f1ac1dc008b8a27fe676000604051620006a392919062000f8e565b60405180910390a1600080516020620053ba833981519152730e52db138df9ce54bc9d9330f418015ed512830a6000604051620006e292919062000f8e565b60405180910390a1600080516020620053ba83398151915273dde7684d88e0b482b2b455936fe0d22dd48cdcb360006040516200072192919062000f8e565b60405180910390a1600080516020620053ba8339815191527343102f07414d95ef71ec9aeba011b8595ba010d060006040516200076092919062000f8e565b60405180910390a16000805160206200539a83398151915260006127106040516200078d92919062000fab565b60405180910390a16000805160206200539a83398151915273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2617918604051620007cd92919062000fab565b60405180910390a16000805160206200539a83398151915273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4861a4106040516200080d92919062000fab565b60405180910390a16000805160206200539a83398151915273dac17f958d2ee523a2206206994597c13d831ec7620101d06040516200084e92919062000fab565b60405180910390a16000805160206200539a833981519152732260fac5e5542a773aa44fbcfedf7c193bc2c5996184d06040516200088e92919062000fab565b60405180910390a16000805160206200539a833981519152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b617918604051620008ce92919062000fab565b60405180910390a16000805160206200539a833981519152736b3595068778dd592e39a122f4f5a5cf09c90fe26179186040516200090e92919062000fab565b60405180910390a16000805160206200539a83398151915273ae7ab96520de3a18e5e111b5eaab095312d7fe84620109a06040516200094f92919062000fab565b60405180910390a16000805160206200539a833981519152737f39c581f595b53c5cb19bd0b3f8da6c935e2ca06179186040516200098f92919062000fab565b60405180910390a16000805160206200539a83398151915273d33526068d116ce69f19a9ee46f0bd304f21a51f617918604051620009cf92919062000fab565b60405180910390a16000805160206200539a8339815191527348c3399719b582dd63eb5aadf12a40b4c3f52fa2619c4060405162000a0f92919062000fab565b60405180910390a16000805160206200539a833981519152735a98fcbea516cf06857215779fd812ca3bef1b326202460860405162000a5092919062000fab565b60405180910390a16000805160206200539a833981519152739f8f72aa9304c8b593d555f12ef6589cc3a579a26184d060405162000a9092919062000fab565b60405180910390a16000805160206200539a833981519152731f9840a85d5af5bf1d1762f925bdaddc4201f98461908860405162000ad092919062000fab565b60405180910390a16000805160206200539a83398151915273514910771af9ca656af840dff83e8264ecf986ca617d0060405162000b1092919062000fab565b60405180910390a16000805160206200539a833981519152733c3a81e81dc49a522a592e7622a7e711c06bf3546184d060405162000b5092919062000fab565b60405180910390a16000805160206200537a83398151915273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2600160405162000b8f92919062000f73565b60405180910390a16000805160206200537a83398151915273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48600160405162000bce92919062000f73565b60405180910390a16000805160206200537a83398151915273dac17f958d2ee523a2206206994597c13d831ec7600160405162000c0d92919062000f73565b60405180910390a16000805160206200537a833981519152732260fac5e5542a773aa44fbcfedf7c193bc2c599600160405162000c4c92919062000f73565b60405180910390a16000805160206200537a833981519152734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b600160405162000c8b92919062000f73565b60405180910390a16000805160206200537a833981519152736b3595068778dd592e39a122f4f5a5cf09c90fe2600160405162000cca92919062000f73565b60405180910390a16000805160206200537a83398151915273ae7ab96520de3a18e5e111b5eaab095312d7fe84600060405162000d0992919062000f73565b60405180910390a16000805160206200537a833981519152737f39c581f595b53c5cb19bd0b3f8da6c935e2ca0600160405162000d4892919062000f73565b60405180910390a16000805160206200537a83398151915273d33526068d116ce69f19a9ee46f0bd304f21a51f600160405162000d8792919062000f73565b60405180910390a16000805160206200537a8339815191527348c3399719b582dd63eb5aadf12a40b4c3f52fa2600160405162000dc692919062000f73565b60405180910390a16000805160206200537a833981519152735a98fcbea516cf06857215779fd812ca3bef1b32600160405162000e0592919062000f73565b60405180910390a16000805160206200537a833981519152739f8f72aa9304c8b593d555f12ef6589cc3a579a2600160405162000e4492919062000f73565b60405180910390a16000805160206200537a833981519152731f9840a85d5af5bf1d1762f925bdaddc4201f984600160405162000e8392919062000f73565b60405180910390a16000805160206200537a83398151915273514910771af9ca656af840dff83e8264ecf986ca600160405162000ec292919062000f73565b60405180910390a16000805160206200537a833981519152733c3a81e81dc49a522a592e7622a7e711c06bf354600160405162000f0192919062000f73565b60405180910390a1565b80516001600160a01b038116811462000f2357600080fd5b919050565b6000806040838503121562000f3b578182fd5b62000f468362000f0b565b915062000f566020840162000f0b565b90509250929050565b6001600160a01b0391909116815260200190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b0392909216825261ffff16602082015260400190565b6001600160a01b03929092168252602082015260400190565b6020808252600490820152635444303160e01b604082015260600190565b6020808252600490820152632a22181960e11b604082015260600190565b90815260200190565b61436180620010196000396000f3fe60806040526004361061026b5760003560e01c80638da5cb5b11610144578063ceb0981f116100b6578063e677e6c21161007a578063e677e6c214610686578063e6a0cc9414610699578063e88e0aab146106ae578063ee859d28146106c1578063ef381b33146106e1578063fe173b97146106f657610272565b8063ceb0981f146105f1578063d14533441461061e578063e30a49931461063e578063e5b1be6514610653578063e5e7988e1461066657610272565b8063b038555311610108578063b038555314610556578063ba4d531214610583578063bf6b874e14610596578063c45a0155146105b6578063c9cd9760146105cb578063cdfd7ca9146105de57610272565b80638da5cb5b146104db578063953556e2146104f05780639718f627146105035780639d08ebb514610523578063af482b581461053657610272565b80634d847865116101dd5780635e45da23116101a15780635e45da23146104545780636a42b8f8146104695780636de3c67c1461047e57806377632ec2146104935780637d7a7569146104b35780638406c079146104c657610272565b80634d847865146103cc5780635051349a146103ec57806356e56dcc1461040c578063576b332b1461042c57806357a62a4f1461043f57610272565b80633bbac5791161022f5780633bbac579146103315780633ed76f17146103515780633fc8cef31461036457806348d8d3881461037957806348f80c16146103995780634c016016146103ac57610272565b806313af40351461027757806320a68fab146102995780632c391c7b146102cf578063342aa8b5146102ef57806337b1b9581461030f57610272565b3661027257005b600080fd5b34801561028357600080fd5b50610297610292366004613518565b61070b565b005b3480156102a557600080fd5b506102b96102b4366004613518565b61074a565b6040516102c69190613ccf565b60405180910390f35b3480156102db57600080fd5b506102b96102ea366004613518565b61075e565b3480156102fb57600080fd5b5061029761030a36600461370b565b610769565b34801561031b57600080fd5b506103246107a1565b6040516102c69190613c00565b34801561033d57600080fd5b506102b961034c366004613518565b6107b0565b61029761035f3660046135c8565b6107c5565b34801561037057600080fd5b506103246107e5565b34801561038557600080fd5b50610324610394366004613550565b6107fd565b6102976103a736600461373f565b610892565b3480156103b857600080fd5b506102b96103c7366004613518565b610c4c565b3480156103d857600080fd5b506102976103e7366004613683565b610c58565b6103ff6103fa3660046137e4565b610cf8565b6040516102c69190614284565b34801561041857600080fd5b50610297610427366004613812565b610d9b565b6103ff61043a36600461394d565b610eda565b34801561044b57600080fd5b506103ff610f3d565b34801561046057600080fd5b506103ff610f44565b34801561047557600080fd5b506103ff610f4b565b34801561048a57600080fd5b506103ff610f51565b34801561049f57600080fd5b506102b96104ae36600461395f565b610f59565b6102976104c1366004613812565b610f6e565b3480156104d257600080fd5b506103246110c4565b3480156104e757600080fd5b506103246110dc565b6103ff6104fe3660046137e4565b6110eb565b34801561050f57600080fd5b506103ff61051e366004613518565b611182565b6103ff610531366004613800565b61118d565b34801561054257600080fd5b506102b9610551366004613518565b6111f3565b34801561056257600080fd5b50610576610571366004613518565b6111ff565b6040516102c69190614275565b6103ff6105913660046137e4565b611236565b3480156105a257600080fd5b506103ff6105b1366004613518565b61129c565b3480156105c257600080fd5b506103246112b7565b6102976105d9366004613588565b6112cf565b6102976105ec366004613812565b6112fe565b3480156105fd57600080fd5b5061061161060c36600461398f565b6114c8565b6040516102c69190613cff565b34801561062a57600080fd5b50610297610639366004613812565b6114de565b34801561064a57600080fd5b506103ff6115ab565b610297610661366004613633565b6115b1565b34801561067257600080fd5b506102b9610681366004613518565b6117bb565b610297610694366004613812565b6117c7565b3480156106a557600080fd5b506103ff611974565b6102976106bc366004613812565b61197a565b3480156106cd57600080fd5b506102976106dc366004613518565b611a84565b3480156106ed57600080fd5b50610324611ab7565b34801561070257600080fd5b506103ff611acf565b6008546001600160a01b0316331461073e5760405162461bcd60e51b815260040161073590613d8b565b60405180910390fd5b61074781611ad5565b50565b60006107568183611b7f565b90505b919050565b600061075682611bb3565b6008546001600160a01b031633146107935760405162461bcd60e51b815260040161073590613d8b565b61079d8282611e2b565b5050565b6009546001600160a01b031681565b600a6020526000908152604090205460ff1681565b6107d1858786846115b1565b6107dd838784846115b1565b505050505050565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b6009546000906001600160a01b0316331461082a5760405162461bcd60e51b815260040161073590613d8b565b6108348383611ecc565b5080915050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561087457600080fd5b505af1158015610888573d6000803e3d6000fd5b5050505092915050565b600b546001146108b45760405162461bcd60e51b815260040161073590613d13565b6002600b558060005a336000908152600a602052604081205491925090819060ff168061090b575060008052600a6020527f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e35460ff165b905060005b84811015610bc35760015487878381811061092757fe5b90506102800201600001351161093c57610bbb565b6004600088888481811061094c57fe5b61028002919091013582525060208101919091526040016000205460ff16156109955761099087878381811061097e57fe5b60009261028090910201359050611fa0565b610bbb565b73465e0b6518603e0d75b4737dac052845cf855925632e548b5b60008989858181106109bd57fe5b905061028002016040518363ffffffff1660e01b81526004016109e1929190613fdd565b60006040518083038186803b1580156109f957600080fd5b505af4158015610a0d573d6000803e3d6000fd5b505050506000878783818110610a1f57fe5b90506102800201606001359050428110610a395750610bc3565b8280610a4957506104b081014210155b610a655760405162461bcd60e51b815260040161073590613d8b565b6001935083888884818110610a7657fe5b905061028002016020016020810190610a8f91906137ca565b6004811115610a9a57fe5b1415610ac057610abb888884818110610aaf57fe5b90506102800201611fcc565b610bb9565b6002888884818110610ace57fe5b905061028002016020016020810190610ae791906137ca565b6004811115610af257fe5b1415610b1357610abb888884818110610b0757fe5b905061028002016121ad565b6003888884818110610b2157fe5b905061028002016020016020810190610b3a91906137ca565b6004811115610b4557fe5b1415610b6657610abb888884818110610b5a57fe5b905061028002016122dc565b6004888884818110610b7457fe5b905061028002016020016020810190610b8d91906137ca565b6004811115610b9857fe5b1415610bb957610bb9888884818110610bad57fe5b90506102800201612405565b505b600101610910565b508115610c3f5773465e0b6518603e0d75b4737dac052845cf855925639db74df16000610bf15a879061244c565b6040518363ffffffff1660e01b8152600401610c0e92919061409d565b60006040518083038186803b158015610c2657600080fd5b505af4158015610c3a573d6000803e3d6000fd5b505050505b50506001600b5550505050565b60006107568183612475565b6008546001600160a01b03163314610c825760405162461bcd60e51b815260040161073590613d8b565b604051638a6ade6360e01b815273465e0b6518603e0d75b4737dac052845cf85592590638a6ade6390610cc2906000908890889088908890600401613e5d565b60006040518083038186803b158015610cda57600080fd5b505af4158015610cee573d6000803e3d6000fd5b5050505050505050565b6000600b54600114610d1c5760405162461bcd60e51b815260040161073590613d13565b6002600b5560405162c44ff160e31b815273465e0b6518603e0d75b4737dac052845cf855925906306227f8890610d5d906000908690600790600401613ecf565b60006040518083038186803b158015610d7557600080fd5b505af4158015610d89573d6000803e3d6000fd5b50506000546001600b55949350505050565b600b54600114610dbd5760405162461bcd60e51b815260040161073590613d13565b6002600b55604051632e548b5b60e01b815273465e0b6518603e0d75b4737dac052845cf85592590632e548b5b90610dfc906000908590600401613fdd565b60006040518083038186803b158015610e1457600080fd5b505af4158015610e28573d6000803e3d6000fd5b5060029250610e35915050565b610e4660008335606085013561247e565b6005811115610e5157fe5b14610e6e5760405162461bcd60e51b815260040161073590613e03565b42610e8c62015180610e86606085013561070861244c565b9061250b565b10610ea95760405162461bcd60e51b815260040161073590613d31565b80356000908152600460205260409020805460ff19166001908117909155610ed290829061254c565b506001600b55565b6000600b54600114610efe5760405162461bcd60e51b815260040161073590613d13565b6002600b55604051636587992160e01b815273465e0b6518603e0d75b4737dac052845cf85592590636587992190610d5d906000908690600401613ff2565b620f424090565b624c4b4090565b61070890565b6301312d0090565b60009081526004602052604090205460ff1690565b333014610f8d5760405162461bcd60e51b815260040161073590613d8b565b6000610fbb610fa461018084016101608501613518565b610fb66101a085016101808601613518565b611ecc565b509050610fc66133e0565b610fd536849003840184613824565b81526001600160a01b0382166020820152610fef826111ff565b816040019061ffff16908161ffff1681525050816001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561103d57600080fd5b505af1158015611051573d6000803e3d6000fd5b50506040516383dc420b60e01b8152734a1dbc839b4ebad8db9058e856e90cb41dffce1f92506383dc420b915061108f9084906007906004016140d7565b60006040518083038186803b1580156110a757600080fd5b505af41580156110bb573d6000803e3d6000fd5b50505050505050565b73d17b3c9784510e33cd5b87b490e79253bcd81e2e90565b6008546001600160a01b031681565b6000600b5460011461110f5760405162461bcd60e51b815260040161073590613d13565b6002600b553373d17b3c9784510e33cd5b87b490e79253bcd81e2e146111475760405162461bcd60e51b815260040161073590613d8b565b604051621dd40d60e01b815273465e0b6518603e0d75b4737dac052845cf85592590621dd40d90610d5d906000908690600790600401613ecf565b60006107568261281e565b6000600b546001146111b15760405162461bcd60e51b815260040161073590613d13565b6002600b55604051638f0e6bef60e01b815273465e0b6518603e0d75b4737dac052845cf85592590638f0e6bef90610d5d906000908690600790600401613ef3565b60006107568183612af5565b600073d4d2140ed70dcf8794a986f0cfd07560ee738c716001600160a01b038316141561122e57506004610759565b506000919050565b6000600b5460011461125a5760405162461bcd60e51b815260040161073590613d13565b6002600b5560405163758e99b360e01b815273465e0b6518603e0d75b4737dac052845cf8559259063758e99b390610d5d906000908690600790600401613ecf565b6001600160a01b031660009081526007602052604090205490565b73c480b33ee5229de3fbdfad1d2dcd3f3bad0c56c690565b3330146112ee5760405162461bcd60e51b815260040161073590613d8b565b6112f9838383612afe565b505050565b33301461131d5760405162461bcd60e51b815260040161073590613d8b565b6000611334610fa461018084016101608501613518565b509050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561137257600080fd5b505af1158015611386573d6000803e3d6000fd5b50506009546001600160a01b03169150638a34ffa290506113af61018085016101608601613518565b6113c16101a086016101808701613518565b846040518463ffffffff1660e01b81526004016113e093929190613c2e565b600060405180830381600087803b1580156113fa57600080fd5b505af115801561140e573d6000803e3d6000fd5b50505050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b5050604051636491033560e11b8152734a1dbc839b4ebad8db9058e856e90cb41dffce1f925063c922066a915061149c90859060040161422c565b60006040518083038186803b1580156114b457600080fd5b505af41580156107dd573d6000803e3d6000fd5b60006114d581848461247e565b90505b92915050565b600b546001146115005760405162461bcd60e51b815260040161073590613d13565b6002600b55604051632e548b5b60e01b815273465e0b6518603e0d75b4737dac052845cf85592590632e548b5b9061153f906000908590600401613fdd565b60006040518083038186803b15801561155757600080fd5b505af415801561156b573d6000803e3d6000fd5b505050813560009081526006602052604090205460ff1690506115a05760405162461bcd60e51b815260040161073590613d6d565b610ed281600061254c565b60005490565b3330146115d05760405162461bcd60e51b815260040161073590613d8b565b6001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21480156115f95750805b1561171757604051632a359a6d60e21b815260009073e92b1734fc37f8acc950d0d13a414753729587309063a8d669b490611641906007908990889087908b906004016140ab565b60206040518083038186803b15801561165957600080fd5b505af415801561166d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116919190613977565b604051632e1a7d4d60e01b815290915073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d906116cb908490600401614284565b600060405180830381600087803b1580156116e557600080fd5b505af11580156116f9573d6000803e3d6000fd5b50505050611711848261170c600061281e565b612c50565b506117b5565b604051632a359a6d60e21b81526117b5908590859073e92b1734fc37f8acc950d0d13a414753729587309063a8d669b4906117609060079086908a9060009088906004016140ab565b60206040518083038186803b15801561177857600080fd5b505af415801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b09190613977565b612afe565b50505050565b60006107568183612ce2565b3330146117e65760405162461bcd60e51b815260040161073590613d8b565b60006117fd610fa461018084016101608501613518565b509050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561183b57600080fd5b505af115801561184f573d6000803e3d6000fd5b50506009546001600160a01b03169150638a34ffa2905061187861018085016101608601613518565b61188a6101a086016101808701613518565b846040518463ffffffff1660e01b81526004016118a993929190613c2e565b600060405180830381600087803b1580156118c357600080fd5b505af11580156118d7573d6000803e3d6000fd5b50505050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561191657600080fd5b505af115801561192a573d6000803e3d6000fd5b50505050734a1dbc839b4ebad8db9058e856e90cb41dffce1f632c9745af8383611953856111ff565b60076040518563ffffffff1660e01b815260040161149c949392919061423b565b60015490565b3330146119995760405162461bcd60e51b815260040161073590613d8b565b60006119b0610fa461018084016101608501613518565b5090506119bb6133e0565b6119ca36849003840184613824565b81526001600160a01b03821660208201526119e4826111ff565b816040019061ffff16908161ffff1681525050816001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611a3257600080fd5b505af1158015611a46573d6000803e3d6000fd5b5050604051630287b3a760e31b8152734a1dbc839b4ebad8db9058e856e90cb41dffce1f925063143d9d38915061108f9084906007906004016140d7565b6008546001600160a01b03163314611aae5760405162461bcd60e51b815260040161073590613d8b565b61074781612ceb565b73d17b3c9784510e33cd5b87b490e79253bcd81e2e81565b60035490565b6008546001600160a01b0382811691161415611b035760405162461bcd60e51b815260040161073590613da9565b6001600160a01b038116611b295760405162461bcd60e51b815260040161073590613e3f565b600880546001600160a01b0319166001600160a01b0383161790556040517f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe290611b74908390613c00565b60405180910390a150565b600060025b6001600160a01b0383166000908152600585016020526040902054600160ff9283161b16161515905092915050565b600073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0383161415611be257506001610759565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0383161415611c0f57506001610759565b73dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0383161415611c3c57506001610759565b732260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0383161415611c6957506001610759565b734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b0383161415611c9657506001610759565b736b3595068778dd592e39a122f4f5a5cf09c90fe26001600160a01b0383161415611cc357506001610759565b737f39c581f595b53c5cb19bd0b3f8da6c935e2ca06001600160a01b0383161415611cf057506001610759565b73d33526068d116ce69f19a9ee46f0bd304f21a51f6001600160a01b0383161415611d1d57506001610759565b7348c3399719b582dd63eb5aadf12a40b4c3f52fa26001600160a01b0383161415611d4a57506001610759565b735a98fcbea516cf06857215779fd812ca3bef1b326001600160a01b0383161415611d7757506001610759565b739f8f72aa9304c8b593d555f12ef6589cc3a579a26001600160a01b0383161415611da457506001610759565b731f9840a85d5af5bf1d1762f925bdaddc4201f9846001600160a01b0383161415611dd157506001610759565b73514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0383161415611dfe57506001610759565b733c3a81e81dc49a522a592e7622a7e711c06bf3546001600160a01b038316141561122e57506001610759565b6001600160a01b0382166000908152600a602052604090205460ff1615158115151415611e6a5760405162461bcd60e51b815260040161073590613da9565b6001600160a01b0382166000908152600a602052604090819020805460ff1916831515179055517f70af441dbb427737e6a5ef2cf5b664321011765ce1d19ce4a69cd024e69d4f2f90611ec09084908490613cb4565b60405180910390a15050565b60405163e6a4390560e01b8152600090819073c480b33ee5229de3fbdfad1d2dcd3f3bad0c56c69063e6a4390590611f0a9087908790600401613c14565b60206040518083038186803b158015611f2257600080fd5b505afa158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613534565b91506001600160a01b038216611f825760405162461bcd60e51b815260040161073590613de5565b826001600160a01b0316846001600160a01b03161190509250929050565b6001808301805490910190819055811461079d5760405162461bcd60e51b815260040161073590613e21565b60005a9050611fdd60008335611fa0565b60008030612024611ffe611ff96101a088016101808901613518565b61281e565b612013611ff961018089016101608a01613518565b60c088013591016201a51c0161244c565b60405163733bf36160e11b9061203e90889060240161422c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161207c9190613be4565b60006040518083038160008787f1925050503d80600081146120ba576040519150601f19603f3d011682016040523d82523d6000602084013e6120bf565b606091505b50909250905060018261212b576121286120e16101c087016101a08801613518565b6120f361018088016101608901613518565b61012088013561210b6101a08a016101808b01613518565b6101408a013561212160a08c0160808d016137b0565b6000612d8a565b90505b61213481612ee5565b60008061215c60c088013560e0890135886121576101c08c016101a08d01613518565b612f03565b915091508415156000600101547ff0cc99aeb224e65869630a14e23683d20b9c535c00427b50024ce8b6b21d35c386858560405161219c93929190613cda565b60405180910390a350505050505050565b60005a90506121be60008335611fa0565b600080306121d360c08601356201dfb461244c565b60405163cdfd7ca960e01b906121ed90889060240161422c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161222b9190613be4565b60006040518083038160008787f1925050503d8060008114612269576040519150601f19603f3d011682016040523d82523d6000602084013e61226e565b606091505b50909250905060018261212b5760006122a461229261018088016101608901613518565b610fb66101a089016101808a01613518565b5090506122d0816122bd6101c089016101a08a01613518565b61010089013563064e6cbb60e51b612f93565b91505061213481612ee5565b60005a90506122ed60008335611fa0565b60008030612319612309611ff961018088016101608901613518565b60c087013590620156fc0161244c565b60405163e88e0aab60e01b9061233390889060240161422c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516123719190613be4565b60006040518083038160008787f1925050503d80600081146123af576040519150601f19603f3d011682016040523d82523d6000602084013e6123b4565b606091505b50909250905060018261212b576121286123d661018087016101608801613518565b6123e86101c088016101a08901613518565b6101208801356123fe60a08a0160808b016137b0565b600061309e565b60005a905061241660008335611fa0565b60008030612432612309611ff961018088016101608901613518565b604051637d7a756960e01b9061233390889060240161422c565b60006114d583836040518060400160405280600481526020016329a6989960e11b8152506131be565b60006003611b84565b825460009083111561249257506000612504565b600083815260048501602052604090205460ff16156124b357506005612504565b600083815260068501602052604090205460ff16156124d457506004612504565b60008381526002850160205260409020546124f157506003612504565b42821061250057506001612504565b5060025b9392505050565b808201828110156114d8576040805162461bcd60e51b81526020600480830191909152602482015263534d344560e01b604482015290519081900360640190fd5b60004261256160608501356301e1338061250b565b109050600161257660408501602086016137ca565b600481111561258157fe5b141561265e576000816125a5576125a06101c085016101a08601613518565b6125b2565b6008546001600160a01b03165b90506125ff816125ca61018087016101608801613518565b6101208701356125e26101a089016101808a01613518565b6101408901356125f860a08b0160808c016137b0565b6001612d8a565b61261b5760405162461bcd60e51b815260040161073590613d4f565b82156126585761263c8161263760e087013560c0880135613256565b6132ab565b6126585760405162461bcd60e51b815260040161073590613dc7565b50612812565b600261267060408501602086016137ca565b600481111561267b57fe5b141561274d5760006126aa61269861018086016101608701613518565b610fb66101a087016101808801613518565b5090506000826126cb576126c66101c086016101a08701613518565b6126d8565b6008546001600160a01b03165b90506126f2828261010088013563064e6cbb60e51b612f93565b61270e5760405162461bcd60e51b815260040161073590613d4f565b83156127465761272a8161263760e088013560c0890135613256565b6127465760405162461bcd60e51b815260040161073590613dc7565b5050612812565b600361275f60408501602086016137ca565b600481111561276a57fe5b14156127d05760008161278e576127896101c085016101a08601613518565b61279b565b6008546001600160a01b03165b90506125ff6127b261018086016101608701613518565b826101208701356127c960a0890160808a016137b0565b600161309e565b60046127e260408501602086016137ca565b60048111156127ed57fe5b141561280c5760008161278e576127896101c085016101a08601613518565b5061079d565b6112f96000843561331a565b60006001600160a01b0382166128375750612710610759565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b03831614156128655750617918610759565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0383161415612893575061a410610759565b73dac17f958d2ee523a2206206994597c13d831ec76001600160a01b03831614156128c25750620101d0610759565b732260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b03831614156128f057506184d0610759565b734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b038316141561291e5750617918610759565b736b3595068778dd592e39a122f4f5a5cf09c90fe26001600160a01b038316141561294c5750617918610759565b73ae7ab96520de3a18e5e111b5eaab095312d7fe846001600160a01b038316141561297b5750620109a0610759565b737f39c581f595b53c5cb19bd0b3f8da6c935e2ca06001600160a01b03831614156129a95750617918610759565b73d33526068d116ce69f19a9ee46f0bd304f21a51f6001600160a01b03831614156129d75750617918610759565b7348c3399719b582dd63eb5aadf12a40b4c3f52fa26001600160a01b0383161415612a055750619c40610759565b735a98fcbea516cf06857215779fd812ca3bef1b326001600160a01b0383161415612a34575062024608610759565b739f8f72aa9304c8b593d555f12ef6589cc3a579a26001600160a01b0383161415612a6257506184d0610759565b731f9840a85d5af5bf1d1762f925bdaddc4201f9846001600160a01b0383161415612a905750619088610759565b73514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0383161415612abe5750617d00610759565b733c3a81e81dc49a522a592e7622a7e711c06bf3546001600160a01b0383161415612aec57506184d0610759565b5061ea60919050565b60006001611b84565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310612b7a5780518252601f199092019160209182019101612b5b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612bdc576040519150601f19603f3d011682016040523d82523d6000602084013e612be1565b606091505b5091509150818015612c0f575080511580612c0f5750808060200190516020811015612c0c57600080fd5b50515b612c49576040805162461bcd60e51b815260206004808301919091526024820152635448303560e01b604482015290519081900360640190fd5b5050505050565b6040516000906001600160a01b038516908390859084818181858888f193505050503d8060008114612c9e576040519150601f19603f3d011682016040523d82523d6000602084013e612ca3565b606091505b50509050806117b5576040805162461bcd60e51b815260206004808301919091526024820152632a2419a360e11b604482015290519081900360640190fd5b60006004611b84565b6009546001600160a01b0382811691161415612d195760405162461bcd60e51b815260040161073590613da9565b6001600160a01b038116612d3f5760405162461bcd60e51b815260040161073590613e3f565b600980546001600160a01b0319166001600160a01b0383161790556040517f99db624faf5b574db8409c17138c4894a18b552e2cd1dbe8c70b375a02748b6690611b74908390613c00565b600080803084612db057612d9d8861281e565b612da68b61281e565b01619c4001612db2565b5a5b604051633ed76f1760e01b90612dd6908e908e908e908e908e908e90602401613c51565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612e149190613be4565b60006040518083038160008787f1925050503d8060008114612e52576040519150601f19603f3d011682016040523d82523d6000602084013e612e57565b606091505b509150915081612ed857886001600160a01b03168a6001600160a01b031660008051602061430c8339815191528a84604051612e9492919061428d565b60405180910390a3866001600160a01b03168a6001600160a01b031660008051602061430c8339815191528884604051612ecf92919061428d565b60405180910390a35b5098975050505050505050565b80612ef957612ef4600061332e565b610747565b6107476000613353565b60008080612f118787613256565b9050612f246193ac610e865a889061244c565b92506000612f4982612f446000600301548761325690919063ffffffff16565b61336c565b9050612f55828261244c565b9250612f6133826132ab565b612f7d5760405162461bcd60e51b815260040161073590613dc7565b612f8785846132ab565b50505094509492505050565b600082612fa257506001613096565b600080306001600160a01b031661d6d8858989896000604051602401612fcb9493929190613c8b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516130099190613be4565b60006040518083038160008787f1925050503d8060008114613047576040519150601f19603f3d011682016040523d82523d6000602084013e61304c565b606091505b50915091508161309257866001600160a01b0316866001600160a01b031660008051602061430c833981519152878460405161308992919061428d565b60405180910390a35b5090505b949350505050565b6000836130ad575060016131b5565b60008030846130c8576130bf8961281e565b614e20016130ca565b5a5b60405163e5b1be6560e01b906130ea908c908c908c908c90602401613c8b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516131289190613be4565b60006040518083038160008787f1925050503d8060008114613166576040519150601f19603f3d011682016040523d82523d6000602084013e61316b565b606091505b5091509150816131b157876001600160a01b0316876001600160a01b031660008051602061430c83398151915288846040516131a892919061428d565b60405180910390a35b5090505b95945050505050565b818303818482111561324e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156132135781810151838201526020016131fb565b50505050905090810190601f1680156132405780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b60008115806132715750508082028282828161326e57fe5b04145b6114d8576040805162461bcd60e51b81526020600480830191909152602482015263534d324160e01b604482015290519081900360640190fd5b6000816132ba575060016114d8565b6132ce83836132c9600061281e565b613382565b9050801515836001600160a01b03167fdbef2fc26e7694e7a1c5a4801b1ad144136d149cf76f310a780689b4087f0ffe8460405161330c9190614284565b60405180910390a392915050565b600090815260029091016020526040812055565b600181810154600090815260069092016020526040909120805460ff19169091179055565b6001810154600090815260029091016020526040812055565b600081831061337b57816114d5565b5090919050565b6040516000906001600160a01b038516908390859084818181858888f193505050503d80600081146133d0576040519150601f19603f3d011682016040523d82523d6000602084013e6133d5565b606091505b509095945050505050565b60405180606001604052806133f3613407565b815260006020820181905260409091015290565b6040805161028081019091526000808252602082019081526020016000151581526020016000815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000151581526020016000815260200160008152602001600081525090565b8035610759816142f6565b8035801515811461075957600080fd5b80356005811061075957600080fd5b600061010082840312156134fe578081fd5b50919050565b803563ffffffff8116811461075957600080fd5b600060208284031215613529578081fd5b8135612504816142f6565b600060208284031215613545578081fd5b8151612504816142f6565b60008060408385031215613562578081fd5b823561356d816142f6565b9150602083013561357d816142f6565b809150509250929050565b60008060006060848603121561359c578081fd5b83356135a7816142f6565b925060208401356135b7816142f6565b929592945050506040919091013590565b60008060008060008060c087890312156135e0578182fd5b86356135eb816142f6565b955060208701356135fb816142f6565b9450604087013593506060870135613612816142f6565b92506080870135915061362760a088016134cd565b90509295509295509295565b60008060008060808587031215613648578384fd5b8435613653816142f6565b93506020850135613663816142f6565b925060408501359150613678606086016134cd565b905092959194509250565b60008060008060608587031215613698578182fd5b84356136a3816142f6565b9350602085013567ffffffffffffffff808211156136bf578384fd5b818701915087601f8301126136d2578384fd5b8135818111156136e0578485fd5b88602080830285010111156136f3578485fd5b602083019550809450505050613678604086016134cd565b6000806040838503121561371d578182fd5b8235613728816142f6565b9150613736602084016134cd565b90509250929050565b60008060208385031215613751578182fd5b823567ffffffffffffffff80821115613768578384fd5b818501915085601f83011261377b578384fd5b813581811115613789578485fd5b8660206102808302850101111561379e578485fd5b60209290920196919550909350505050565b6000602082840312156137c1578081fd5b6114d5826134cd565b6000602082840312156137db578081fd5b6114d5826134dd565b600061010082840312156137f6578081fd5b6114d583836134ec565b600061016082840312156134fe578081fd5b600061028082840312156134fe578081fd5b6000610280808385031215613837578182fd5b613840816142a6565b905082358152613852602084016134dd565b6020820152613863604084016134cd565b60408201526060830135606082015261387e608084016134cd565b608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013581830152506101408084013581830152506101606138d38185016134c2565b908201526101806138e58482016134c2565b908201526101a06138f78482016134c2565b908201526101c083810135908201526101e0808401359082015261020061391f8185016134cd565b9082015261022083810135908201526102408084013590820152610260928301359281019290925250919050565b600061012082840312156134fe578081fd5b600060208284031215613970578081fd5b5035919050565b600060208284031215613988578081fd5b5051919050565b600080604083850312156139a1578182fd5b50508035926020909101359150565b6001600160a01b03169052565b15159052565b600081518084526139db8160208601602086016142ca565b601f01601f19169290920160200192915050565b600581106139f957fe5b9052565b8035613a08816142f6565b6001600160a01b039081168352602082013590613a24826142f6565b80821660208501526040830135604085015260608301356060850152613a4c608084016134cd565b1515608085015260a08301359150613a63826142f6565b1660a083015260c08181013590830152613a7f60e08201613504565b6112f960e0840182613bda565b80358252613a9c602082016134dd565b613aa960208401826139ef565b50613ab6604082016134cd565b613ac360408401826139bd565b5060608101356060830152613ada608082016134cd565b613ae760808401826139bd565b5060a081013560a083015260c081013560c083015260e081013560e0830152610100808201358184015250610120808201358184015250610140808201358184015250610160613b388183016134c2565b613b44828501826139b0565b5050610180613b548183016134c2565b613b60828501826139b0565b50506101a0613b708183016134c2565b613b7c828501826139b0565b50506101c081810135908301526101e08082013590830152610200613ba28183016134cd565b613bae828501826139bd565b50506102208181013590830152610240808201359083015261026090810135910152565b61ffff169052565b63ffffffff169052565b60008251613bf68184602087016142ca565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b0396871681529486166020860152604085019390935293166060830152608082019290925290151560a082015260c00190565b6001600160a01b0394851681529290931660208301526040820152901515606082015260800190565b6001600160a01b039290921682521515602082015260400190565b901515815260200190565b600060608252613ced60608301866139c3565b60208301949094525060400152919050565b6020810160068310613d0d57fe5b91905290565b6020808252600490820152632a22181b60e11b604082015260600190565b6020808252600490820152635444314360e01b604082015260600190565b60208082526004908201526315110c4d60e21b604082015260600190565b6020808252600490820152635444323160e01b604082015260600190565b6020808252600490820152630544430360e41b604082015260600190565b6020808252600490820152635444303160e01b604082015260600190565b6020808252600490820152630544434360e41b604082015260600190565b6020808252600490820152634f53313760e01b604082015260600190565b6020808252600490820152632a221a9960e11b604082015260600190565b60208082526004908201526327a99b9960e11b604082015260600190565b6020808252600490820152632a22181960e11b604082015260600190565b8581526001600160a01b0385166020808301919091526080604083018190528201849052600090859060a08401835b87811015613eb657613ea682613ea1866134dd565b6139ef565b9282019290820190600101613e8c565b5080935050505082151560608301529695505050505050565b8381526101408101613ee460208301856139fd565b82610120830152949350505050565b8381526101a08101613f1060208301613f0b866134c2565b6139b0565b613f1c602085016134c2565b613f2960408401826139b0565b506040840135606083015260608401356080830152608084013560a083015260a084013560c0830152613f5e60c085016134cd565b613f6b60e08401826139bd565b50613f7860e085016134cd565b610100613f87818501836139bd565b613f928187016134c2565b915050610120613fa4818501836139b0565b6101409150808601358285015250613fbd818601613504565b9050613fcd610160840182613bda565b5082610180830152949350505050565b8281526102a081016125046020830184613a8c565b828152610140810161400a60208301613f0b856134c2565b614016602084016134c2565b61402360408401826139b0565b506040830135606083015260608301356080830152608083013560a083015261404e60a084016134cd565b61405b60c08401826139bd565b5061406860c084016134c2565b61407560e08401826139b0565b5061010060e08401358184015261408d818501613504565b905061324e610120840182613bda565b918252602082015260400190565b9485526001600160a01b0393841660208601526040850192909252606084015216608082015260a00190565b60006102e08201905083518051835260208101516140f860208501826139ef565b50604081015161410b60408501826139bd565b5060608101516060840152608081015161412860808501826139bd565b5060a081015160a084015260c081015160c084015260e081015160e08401526101008082015181850152506101208082015181850152506101408082015181850152506101608082015161417e828601826139b0565b505061018080820151614193828601826139b0565b50506101a0808201516141a8828601826139b0565b50506101c081810151908401526101e08082015190840152610200808201516141d3828601826139bd565b505061022081810151908401526102408082015190840152610260908101519083015260208401516142096102808401826139b0565b50604084015161421d6102a0840182613bd2565b50826102c08301529392505050565b61028081016114d88284613a8c565b6102e0810161424a8287613a8c565b6001600160a01b039490941661028082015261ffff929092166102a08301526102c090910152919050565b61ffff91909116815260200190565b90815260200190565b60008382526040602083015261309660408301846139c3565b60405181810167ffffffffffffffff811182821017156142c257fe5b604052919050565b60005b838110156142e55781810151838201526020016142cd565b838111156117b55750506000910152565b6001600160a01b038116811461074757600080fdfe786212e89f390a4c768f3b935b85e0ec2561a24b6f48cda3c4b48a996b211592a264697066735822122099bde760c5a3a45475e145709e72c67d165673645fd1abfea9ffbe368107fd4764736f6c63430007060033ed243800dd924a6f05da349ad56411a9154d39d02c09c49db8faafc3966306968563e1de6a8955dcbdc3719833791025efb62c4cb350b8a64bc6823168115f026b4044e33be5af8fcdb7449c49137010eede3c8c06d5d08067151a7ace17266d000000000000000000000000f4418d9fe76a788f2868a558dd216549ad2d869b0000000000000000000000003a1d749fa4a9e650fce844ff1c58c5faf7e2a9d1
Deployed Bytecode
0x60806040526004361061026b5760003560e01c80638da5cb5b11610144578063ceb0981f116100b6578063e677e6c21161007a578063e677e6c214610686578063e6a0cc9414610699578063e88e0aab146106ae578063ee859d28146106c1578063ef381b33146106e1578063fe173b97146106f657610272565b8063ceb0981f146105f1578063d14533441461061e578063e30a49931461063e578063e5b1be6514610653578063e5e7988e1461066657610272565b8063b038555311610108578063b038555314610556578063ba4d531214610583578063bf6b874e14610596578063c45a0155146105b6578063c9cd9760146105cb578063cdfd7ca9146105de57610272565b80638da5cb5b146104db578063953556e2146104f05780639718f627146105035780639d08ebb514610523578063af482b581461053657610272565b80634d847865116101dd5780635e45da23116101a15780635e45da23146104545780636a42b8f8146104695780636de3c67c1461047e57806377632ec2146104935780637d7a7569146104b35780638406c079146104c657610272565b80634d847865146103cc5780635051349a146103ec57806356e56dcc1461040c578063576b332b1461042c57806357a62a4f1461043f57610272565b80633bbac5791161022f5780633bbac579146103315780633ed76f17146103515780633fc8cef31461036457806348d8d3881461037957806348f80c16146103995780634c016016146103ac57610272565b806313af40351461027757806320a68fab146102995780632c391c7b146102cf578063342aa8b5146102ef57806337b1b9581461030f57610272565b3661027257005b600080fd5b34801561028357600080fd5b50610297610292366004613518565b61070b565b005b3480156102a557600080fd5b506102b96102b4366004613518565b61074a565b6040516102c69190613ccf565b60405180910390f35b3480156102db57600080fd5b506102b96102ea366004613518565b61075e565b3480156102fb57600080fd5b5061029761030a36600461370b565b610769565b34801561031b57600080fd5b506103246107a1565b6040516102c69190613c00565b34801561033d57600080fd5b506102b961034c366004613518565b6107b0565b61029761035f3660046135c8565b6107c5565b34801561037057600080fd5b506103246107e5565b34801561038557600080fd5b50610324610394366004613550565b6107fd565b6102976103a736600461373f565b610892565b3480156103b857600080fd5b506102b96103c7366004613518565b610c4c565b3480156103d857600080fd5b506102976103e7366004613683565b610c58565b6103ff6103fa3660046137e4565b610cf8565b6040516102c69190614284565b34801561041857600080fd5b50610297610427366004613812565b610d9b565b6103ff61043a36600461394d565b610eda565b34801561044b57600080fd5b506103ff610f3d565b34801561046057600080fd5b506103ff610f44565b34801561047557600080fd5b506103ff610f4b565b34801561048a57600080fd5b506103ff610f51565b34801561049f57600080fd5b506102b96104ae36600461395f565b610f59565b6102976104c1366004613812565b610f6e565b3480156104d257600080fd5b506103246110c4565b3480156104e757600080fd5b506103246110dc565b6103ff6104fe3660046137e4565b6110eb565b34801561050f57600080fd5b506103ff61051e366004613518565b611182565b6103ff610531366004613800565b61118d565b34801561054257600080fd5b506102b9610551366004613518565b6111f3565b34801561056257600080fd5b50610576610571366004613518565b6111ff565b6040516102c69190614275565b6103ff6105913660046137e4565b611236565b3480156105a257600080fd5b506103ff6105b1366004613518565b61129c565b3480156105c257600080fd5b506103246112b7565b6102976105d9366004613588565b6112cf565b6102976105ec366004613812565b6112fe565b3480156105fd57600080fd5b5061061161060c36600461398f565b6114c8565b6040516102c69190613cff565b34801561062a57600080fd5b50610297610639366004613812565b6114de565b34801561064a57600080fd5b506103ff6115ab565b610297610661366004613633565b6115b1565b34801561067257600080fd5b506102b9610681366004613518565b6117bb565b610297610694366004613812565b6117c7565b3480156106a557600080fd5b506103ff611974565b6102976106bc366004613812565b61197a565b3480156106cd57600080fd5b506102976106dc366004613518565b611a84565b3480156106ed57600080fd5b50610324611ab7565b34801561070257600080fd5b506103ff611acf565b6008546001600160a01b0316331461073e5760405162461bcd60e51b815260040161073590613d8b565b60405180910390fd5b61074781611ad5565b50565b60006107568183611b7f565b90505b919050565b600061075682611bb3565b6008546001600160a01b031633146107935760405162461bcd60e51b815260040161073590613d8b565b61079d8282611e2b565b5050565b6009546001600160a01b031681565b600a6020526000908152604090205460ff1681565b6107d1858786846115b1565b6107dd838784846115b1565b505050505050565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b6009546000906001600160a01b0316331461082a5760405162461bcd60e51b815260040161073590613d8b565b6108348383611ecc565b5080915050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561087457600080fd5b505af1158015610888573d6000803e3d6000fd5b5050505092915050565b600b546001146108b45760405162461bcd60e51b815260040161073590613d13565b6002600b558060005a336000908152600a602052604081205491925090819060ff168061090b575060008052600a6020527f13da86008ba1c6922daee3e07db95305ef49ebced9f5467a0b8613fcc6b343e35460ff165b905060005b84811015610bc35760015487878381811061092757fe5b90506102800201600001351161093c57610bbb565b6004600088888481811061094c57fe5b61028002919091013582525060208101919091526040016000205460ff16156109955761099087878381811061097e57fe5b60009261028090910201359050611fa0565b610bbb565b73465e0b6518603e0d75b4737dac052845cf855925632e548b5b60008989858181106109bd57fe5b905061028002016040518363ffffffff1660e01b81526004016109e1929190613fdd565b60006040518083038186803b1580156109f957600080fd5b505af4158015610a0d573d6000803e3d6000fd5b505050506000878783818110610a1f57fe5b90506102800201606001359050428110610a395750610bc3565b8280610a4957506104b081014210155b610a655760405162461bcd60e51b815260040161073590613d8b565b6001935083888884818110610a7657fe5b905061028002016020016020810190610a8f91906137ca565b6004811115610a9a57fe5b1415610ac057610abb888884818110610aaf57fe5b90506102800201611fcc565b610bb9565b6002888884818110610ace57fe5b905061028002016020016020810190610ae791906137ca565b6004811115610af257fe5b1415610b1357610abb888884818110610b0757fe5b905061028002016121ad565b6003888884818110610b2157fe5b905061028002016020016020810190610b3a91906137ca565b6004811115610b4557fe5b1415610b6657610abb888884818110610b5a57fe5b905061028002016122dc565b6004888884818110610b7457fe5b905061028002016020016020810190610b8d91906137ca565b6004811115610b9857fe5b1415610bb957610bb9888884818110610bad57fe5b90506102800201612405565b505b600101610910565b508115610c3f5773465e0b6518603e0d75b4737dac052845cf855925639db74df16000610bf15a879061244c565b6040518363ffffffff1660e01b8152600401610c0e92919061409d565b60006040518083038186803b158015610c2657600080fd5b505af4158015610c3a573d6000803e3d6000fd5b505050505b50506001600b5550505050565b60006107568183612475565b6008546001600160a01b03163314610c825760405162461bcd60e51b815260040161073590613d8b565b604051638a6ade6360e01b815273465e0b6518603e0d75b4737dac052845cf85592590638a6ade6390610cc2906000908890889088908890600401613e5d565b60006040518083038186803b158015610cda57600080fd5b505af4158015610cee573d6000803e3d6000fd5b5050505050505050565b6000600b54600114610d1c5760405162461bcd60e51b815260040161073590613d13565b6002600b5560405162c44ff160e31b815273465e0b6518603e0d75b4737dac052845cf855925906306227f8890610d5d906000908690600790600401613ecf565b60006040518083038186803b158015610d7557600080fd5b505af4158015610d89573d6000803e3d6000fd5b50506000546001600b55949350505050565b600b54600114610dbd5760405162461bcd60e51b815260040161073590613d13565b6002600b55604051632e548b5b60e01b815273465e0b6518603e0d75b4737dac052845cf85592590632e548b5b90610dfc906000908590600401613fdd565b60006040518083038186803b158015610e1457600080fd5b505af4158015610e28573d6000803e3d6000fd5b5060029250610e35915050565b610e4660008335606085013561247e565b6005811115610e5157fe5b14610e6e5760405162461bcd60e51b815260040161073590613e03565b42610e8c62015180610e86606085013561070861244c565b9061250b565b10610ea95760405162461bcd60e51b815260040161073590613d31565b80356000908152600460205260409020805460ff19166001908117909155610ed290829061254c565b506001600b55565b6000600b54600114610efe5760405162461bcd60e51b815260040161073590613d13565b6002600b55604051636587992160e01b815273465e0b6518603e0d75b4737dac052845cf85592590636587992190610d5d906000908690600401613ff2565b620f424090565b624c4b4090565b61070890565b6301312d0090565b60009081526004602052604090205460ff1690565b333014610f8d5760405162461bcd60e51b815260040161073590613d8b565b6000610fbb610fa461018084016101608501613518565b610fb66101a085016101808601613518565b611ecc565b509050610fc66133e0565b610fd536849003840184613824565b81526001600160a01b0382166020820152610fef826111ff565b816040019061ffff16908161ffff1681525050816001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561103d57600080fd5b505af1158015611051573d6000803e3d6000fd5b50506040516383dc420b60e01b8152734a1dbc839b4ebad8db9058e856e90cb41dffce1f92506383dc420b915061108f9084906007906004016140d7565b60006040518083038186803b1580156110a757600080fd5b505af41580156110bb573d6000803e3d6000fd5b50505050505050565b73d17b3c9784510e33cd5b87b490e79253bcd81e2e90565b6008546001600160a01b031681565b6000600b5460011461110f5760405162461bcd60e51b815260040161073590613d13565b6002600b553373d17b3c9784510e33cd5b87b490e79253bcd81e2e146111475760405162461bcd60e51b815260040161073590613d8b565b604051621dd40d60e01b815273465e0b6518603e0d75b4737dac052845cf85592590621dd40d90610d5d906000908690600790600401613ecf565b60006107568261281e565b6000600b546001146111b15760405162461bcd60e51b815260040161073590613d13565b6002600b55604051638f0e6bef60e01b815273465e0b6518603e0d75b4737dac052845cf85592590638f0e6bef90610d5d906000908690600790600401613ef3565b60006107568183612af5565b600073d4d2140ed70dcf8794a986f0cfd07560ee738c716001600160a01b038316141561122e57506004610759565b506000919050565b6000600b5460011461125a5760405162461bcd60e51b815260040161073590613d13565b6002600b5560405163758e99b360e01b815273465e0b6518603e0d75b4737dac052845cf8559259063758e99b390610d5d906000908690600790600401613ecf565b6001600160a01b031660009081526007602052604090205490565b73c480b33ee5229de3fbdfad1d2dcd3f3bad0c56c690565b3330146112ee5760405162461bcd60e51b815260040161073590613d8b565b6112f9838383612afe565b505050565b33301461131d5760405162461bcd60e51b815260040161073590613d8b565b6000611334610fa461018084016101608501613518565b509050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561137257600080fd5b505af1158015611386573d6000803e3d6000fd5b50506009546001600160a01b03169150638a34ffa290506113af61018085016101608601613518565b6113c16101a086016101808701613518565b846040518463ffffffff1660e01b81526004016113e093929190613c2e565b600060405180830381600087803b1580156113fa57600080fd5b505af115801561140e573d6000803e3d6000fd5b50505050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561144d57600080fd5b505af1158015611461573d6000803e3d6000fd5b5050604051636491033560e11b8152734a1dbc839b4ebad8db9058e856e90cb41dffce1f925063c922066a915061149c90859060040161422c565b60006040518083038186803b1580156114b457600080fd5b505af41580156107dd573d6000803e3d6000fd5b60006114d581848461247e565b90505b92915050565b600b546001146115005760405162461bcd60e51b815260040161073590613d13565b6002600b55604051632e548b5b60e01b815273465e0b6518603e0d75b4737dac052845cf85592590632e548b5b9061153f906000908590600401613fdd565b60006040518083038186803b15801561155757600080fd5b505af415801561156b573d6000803e3d6000fd5b505050813560009081526006602052604090205460ff1690506115a05760405162461bcd60e51b815260040161073590613d6d565b610ed281600061254c565b60005490565b3330146115d05760405162461bcd60e51b815260040161073590613d8b565b6001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21480156115f95750805b1561171757604051632a359a6d60e21b815260009073e92b1734fc37f8acc950d0d13a414753729587309063a8d669b490611641906007908990889087908b906004016140ab565b60206040518083038186803b15801561165957600080fd5b505af415801561166d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116919190613977565b604051632e1a7d4d60e01b815290915073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d906116cb908490600401614284565b600060405180830381600087803b1580156116e557600080fd5b505af11580156116f9573d6000803e3d6000fd5b50505050611711848261170c600061281e565b612c50565b506117b5565b604051632a359a6d60e21b81526117b5908590859073e92b1734fc37f8acc950d0d13a414753729587309063a8d669b4906117609060079086908a9060009088906004016140ab565b60206040518083038186803b15801561177857600080fd5b505af415801561178c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b09190613977565b612afe565b50505050565b60006107568183612ce2565b3330146117e65760405162461bcd60e51b815260040161073590613d8b565b60006117fd610fa461018084016101608501613518565b509050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561183b57600080fd5b505af115801561184f573d6000803e3d6000fd5b50506009546001600160a01b03169150638a34ffa2905061187861018085016101608601613518565b61188a6101a086016101808701613518565b846040518463ffffffff1660e01b81526004016118a993929190613c2e565b600060405180830381600087803b1580156118c357600080fd5b505af11580156118d7573d6000803e3d6000fd5b50505050806001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561191657600080fd5b505af115801561192a573d6000803e3d6000fd5b50505050734a1dbc839b4ebad8db9058e856e90cb41dffce1f632c9745af8383611953856111ff565b60076040518563ffffffff1660e01b815260040161149c949392919061423b565b60015490565b3330146119995760405162461bcd60e51b815260040161073590613d8b565b60006119b0610fa461018084016101608501613518565b5090506119bb6133e0565b6119ca36849003840184613824565b81526001600160a01b03821660208201526119e4826111ff565b816040019061ffff16908161ffff1681525050816001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611a3257600080fd5b505af1158015611a46573d6000803e3d6000fd5b5050604051630287b3a760e31b8152734a1dbc839b4ebad8db9058e856e90cb41dffce1f925063143d9d38915061108f9084906007906004016140d7565b6008546001600160a01b03163314611aae5760405162461bcd60e51b815260040161073590613d8b565b61074781612ceb565b73d17b3c9784510e33cd5b87b490e79253bcd81e2e81565b60035490565b6008546001600160a01b0382811691161415611b035760405162461bcd60e51b815260040161073590613da9565b6001600160a01b038116611b295760405162461bcd60e51b815260040161073590613e3f565b600880546001600160a01b0319166001600160a01b0383161790556040517f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe290611b74908390613c00565b60405180910390a150565b600060025b6001600160a01b0383166000908152600585016020526040902054600160ff9283161b16161515905092915050565b600073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0383161415611be257506001610759565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0383161415611c0f57506001610759565b73dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0383161415611c3c57506001610759565b732260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b0383161415611c6957506001610759565b734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b0383161415611c9657506001610759565b736b3595068778dd592e39a122f4f5a5cf09c90fe26001600160a01b0383161415611cc357506001610759565b737f39c581f595b53c5cb19bd0b3f8da6c935e2ca06001600160a01b0383161415611cf057506001610759565b73d33526068d116ce69f19a9ee46f0bd304f21a51f6001600160a01b0383161415611d1d57506001610759565b7348c3399719b582dd63eb5aadf12a40b4c3f52fa26001600160a01b0383161415611d4a57506001610759565b735a98fcbea516cf06857215779fd812ca3bef1b326001600160a01b0383161415611d7757506001610759565b739f8f72aa9304c8b593d555f12ef6589cc3a579a26001600160a01b0383161415611da457506001610759565b731f9840a85d5af5bf1d1762f925bdaddc4201f9846001600160a01b0383161415611dd157506001610759565b73514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0383161415611dfe57506001610759565b733c3a81e81dc49a522a592e7622a7e711c06bf3546001600160a01b038316141561122e57506001610759565b6001600160a01b0382166000908152600a602052604090205460ff1615158115151415611e6a5760405162461bcd60e51b815260040161073590613da9565b6001600160a01b0382166000908152600a602052604090819020805460ff1916831515179055517f70af441dbb427737e6a5ef2cf5b664321011765ce1d19ce4a69cd024e69d4f2f90611ec09084908490613cb4565b60405180910390a15050565b60405163e6a4390560e01b8152600090819073c480b33ee5229de3fbdfad1d2dcd3f3bad0c56c69063e6a4390590611f0a9087908790600401613c14565b60206040518083038186803b158015611f2257600080fd5b505afa158015611f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5a9190613534565b91506001600160a01b038216611f825760405162461bcd60e51b815260040161073590613de5565b826001600160a01b0316846001600160a01b03161190509250929050565b6001808301805490910190819055811461079d5760405162461bcd60e51b815260040161073590613e21565b60005a9050611fdd60008335611fa0565b60008030612024611ffe611ff96101a088016101808901613518565b61281e565b612013611ff961018089016101608a01613518565b60c088013591016201a51c0161244c565b60405163733bf36160e11b9061203e90889060240161422c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161207c9190613be4565b60006040518083038160008787f1925050503d80600081146120ba576040519150601f19603f3d011682016040523d82523d6000602084013e6120bf565b606091505b50909250905060018261212b576121286120e16101c087016101a08801613518565b6120f361018088016101608901613518565b61012088013561210b6101a08a016101808b01613518565b6101408a013561212160a08c0160808d016137b0565b6000612d8a565b90505b61213481612ee5565b60008061215c60c088013560e0890135886121576101c08c016101a08d01613518565b612f03565b915091508415156000600101547ff0cc99aeb224e65869630a14e23683d20b9c535c00427b50024ce8b6b21d35c386858560405161219c93929190613cda565b60405180910390a350505050505050565b60005a90506121be60008335611fa0565b600080306121d360c08601356201dfb461244c565b60405163cdfd7ca960e01b906121ed90889060240161422c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161222b9190613be4565b60006040518083038160008787f1925050503d8060008114612269576040519150601f19603f3d011682016040523d82523d6000602084013e61226e565b606091505b50909250905060018261212b5760006122a461229261018088016101608901613518565b610fb66101a089016101808a01613518565b5090506122d0816122bd6101c089016101a08a01613518565b61010089013563064e6cbb60e51b612f93565b91505061213481612ee5565b60005a90506122ed60008335611fa0565b60008030612319612309611ff961018088016101608901613518565b60c087013590620156fc0161244c565b60405163e88e0aab60e01b9061233390889060240161422c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516123719190613be4565b60006040518083038160008787f1925050503d80600081146123af576040519150601f19603f3d011682016040523d82523d6000602084013e6123b4565b606091505b50909250905060018261212b576121286123d661018087016101608801613518565b6123e86101c088016101a08901613518565b6101208801356123fe60a08a0160808b016137b0565b600061309e565b60005a905061241660008335611fa0565b60008030612432612309611ff961018088016101608901613518565b604051637d7a756960e01b9061233390889060240161422c565b60006114d583836040518060400160405280600481526020016329a6989960e11b8152506131be565b60006003611b84565b825460009083111561249257506000612504565b600083815260048501602052604090205460ff16156124b357506005612504565b600083815260068501602052604090205460ff16156124d457506004612504565b60008381526002850160205260409020546124f157506003612504565b42821061250057506001612504565b5060025b9392505050565b808201828110156114d8576040805162461bcd60e51b81526020600480830191909152602482015263534d344560e01b604482015290519081900360640190fd5b60004261256160608501356301e1338061250b565b109050600161257660408501602086016137ca565b600481111561258157fe5b141561265e576000816125a5576125a06101c085016101a08601613518565b6125b2565b6008546001600160a01b03165b90506125ff816125ca61018087016101608801613518565b6101208701356125e26101a089016101808a01613518565b6101408901356125f860a08b0160808c016137b0565b6001612d8a565b61261b5760405162461bcd60e51b815260040161073590613d4f565b82156126585761263c8161263760e087013560c0880135613256565b6132ab565b6126585760405162461bcd60e51b815260040161073590613dc7565b50612812565b600261267060408501602086016137ca565b600481111561267b57fe5b141561274d5760006126aa61269861018086016101608701613518565b610fb66101a087016101808801613518565b5090506000826126cb576126c66101c086016101a08701613518565b6126d8565b6008546001600160a01b03165b90506126f2828261010088013563064e6cbb60e51b612f93565b61270e5760405162461bcd60e51b815260040161073590613d4f565b83156127465761272a8161263760e088013560c0890135613256565b6127465760405162461bcd60e51b815260040161073590613dc7565b5050612812565b600361275f60408501602086016137ca565b600481111561276a57fe5b14156127d05760008161278e576127896101c085016101a08601613518565b61279b565b6008546001600160a01b03165b90506125ff6127b261018086016101608701613518565b826101208701356127c960a0890160808a016137b0565b600161309e565b60046127e260408501602086016137ca565b60048111156127ed57fe5b141561280c5760008161278e576127896101c085016101a08601613518565b5061079d565b6112f96000843561331a565b60006001600160a01b0382166128375750612710610759565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b03831614156128655750617918610759565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0383161415612893575061a410610759565b73dac17f958d2ee523a2206206994597c13d831ec76001600160a01b03831614156128c25750620101d0610759565b732260fac5e5542a773aa44fbcfedf7c193bc2c5996001600160a01b03831614156128f057506184d0610759565b734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b038316141561291e5750617918610759565b736b3595068778dd592e39a122f4f5a5cf09c90fe26001600160a01b038316141561294c5750617918610759565b73ae7ab96520de3a18e5e111b5eaab095312d7fe846001600160a01b038316141561297b5750620109a0610759565b737f39c581f595b53c5cb19bd0b3f8da6c935e2ca06001600160a01b03831614156129a95750617918610759565b73d33526068d116ce69f19a9ee46f0bd304f21a51f6001600160a01b03831614156129d75750617918610759565b7348c3399719b582dd63eb5aadf12a40b4c3f52fa26001600160a01b0383161415612a055750619c40610759565b735a98fcbea516cf06857215779fd812ca3bef1b326001600160a01b0383161415612a34575062024608610759565b739f8f72aa9304c8b593d555f12ef6589cc3a579a26001600160a01b0383161415612a6257506184d0610759565b731f9840a85d5af5bf1d1762f925bdaddc4201f9846001600160a01b0383161415612a905750619088610759565b73514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0383161415612abe5750617d00610759565b733c3a81e81dc49a522a592e7622a7e711c06bf3546001600160a01b0383161415612aec57506184d0610759565b5061ea60919050565b60006001611b84565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310612b7a5780518252601f199092019160209182019101612b5b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612bdc576040519150601f19603f3d011682016040523d82523d6000602084013e612be1565b606091505b5091509150818015612c0f575080511580612c0f5750808060200190516020811015612c0c57600080fd5b50515b612c49576040805162461bcd60e51b815260206004808301919091526024820152635448303560e01b604482015290519081900360640190fd5b5050505050565b6040516000906001600160a01b038516908390859084818181858888f193505050503d8060008114612c9e576040519150601f19603f3d011682016040523d82523d6000602084013e612ca3565b606091505b50509050806117b5576040805162461bcd60e51b815260206004808301919091526024820152632a2419a360e11b604482015290519081900360640190fd5b60006004611b84565b6009546001600160a01b0382811691161415612d195760405162461bcd60e51b815260040161073590613da9565b6001600160a01b038116612d3f5760405162461bcd60e51b815260040161073590613e3f565b600980546001600160a01b0319166001600160a01b0383161790556040517f99db624faf5b574db8409c17138c4894a18b552e2cd1dbe8c70b375a02748b6690611b74908390613c00565b600080803084612db057612d9d8861281e565b612da68b61281e565b01619c4001612db2565b5a5b604051633ed76f1760e01b90612dd6908e908e908e908e908e908e90602401613c51565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612e149190613be4565b60006040518083038160008787f1925050503d8060008114612e52576040519150601f19603f3d011682016040523d82523d6000602084013e612e57565b606091505b509150915081612ed857886001600160a01b03168a6001600160a01b031660008051602061430c8339815191528a84604051612e9492919061428d565b60405180910390a3866001600160a01b03168a6001600160a01b031660008051602061430c8339815191528884604051612ecf92919061428d565b60405180910390a35b5098975050505050505050565b80612ef957612ef4600061332e565b610747565b6107476000613353565b60008080612f118787613256565b9050612f246193ac610e865a889061244c565b92506000612f4982612f446000600301548761325690919063ffffffff16565b61336c565b9050612f55828261244c565b9250612f6133826132ab565b612f7d5760405162461bcd60e51b815260040161073590613dc7565b612f8785846132ab565b50505094509492505050565b600082612fa257506001613096565b600080306001600160a01b031661d6d8858989896000604051602401612fcb9493929190613c8b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516130099190613be4565b60006040518083038160008787f1925050503d8060008114613047576040519150601f19603f3d011682016040523d82523d6000602084013e61304c565b606091505b50915091508161309257866001600160a01b0316866001600160a01b031660008051602061430c833981519152878460405161308992919061428d565b60405180910390a35b5090505b949350505050565b6000836130ad575060016131b5565b60008030846130c8576130bf8961281e565b614e20016130ca565b5a5b60405163e5b1be6560e01b906130ea908c908c908c908c90602401613c8b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516131289190613be4565b60006040518083038160008787f1925050503d8060008114613166576040519150601f19603f3d011682016040523d82523d6000602084013e61316b565b606091505b5091509150816131b157876001600160a01b0316876001600160a01b031660008051602061430c83398151915288846040516131a892919061428d565b60405180910390a35b5090505b95945050505050565b818303818482111561324e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156132135781810151838201526020016131fb565b50505050905090810190601f1680156132405780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b60008115806132715750508082028282828161326e57fe5b04145b6114d8576040805162461bcd60e51b81526020600480830191909152602482015263534d324160e01b604482015290519081900360640190fd5b6000816132ba575060016114d8565b6132ce83836132c9600061281e565b613382565b9050801515836001600160a01b03167fdbef2fc26e7694e7a1c5a4801b1ad144136d149cf76f310a780689b4087f0ffe8460405161330c9190614284565b60405180910390a392915050565b600090815260029091016020526040812055565b600181810154600090815260069092016020526040909120805460ff19169091179055565b6001810154600090815260029091016020526040812055565b600081831061337b57816114d5565b5090919050565b6040516000906001600160a01b038516908390859084818181858888f193505050503d80600081146133d0576040519150601f19603f3d011682016040523d82523d6000602084013e6133d5565b606091505b509095945050505050565b60405180606001604052806133f3613407565b815260006020820181905260409091015290565b6040805161028081019091526000808252602082019081526020016000151581526020016000815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000151581526020016000815260200160008152602001600081525090565b8035610759816142f6565b8035801515811461075957600080fd5b80356005811061075957600080fd5b600061010082840312156134fe578081fd5b50919050565b803563ffffffff8116811461075957600080fd5b600060208284031215613529578081fd5b8135612504816142f6565b600060208284031215613545578081fd5b8151612504816142f6565b60008060408385031215613562578081fd5b823561356d816142f6565b9150602083013561357d816142f6565b809150509250929050565b60008060006060848603121561359c578081fd5b83356135a7816142f6565b925060208401356135b7816142f6565b929592945050506040919091013590565b60008060008060008060c087890312156135e0578182fd5b86356135eb816142f6565b955060208701356135fb816142f6565b9450604087013593506060870135613612816142f6565b92506080870135915061362760a088016134cd565b90509295509295509295565b60008060008060808587031215613648578384fd5b8435613653816142f6565b93506020850135613663816142f6565b925060408501359150613678606086016134cd565b905092959194509250565b60008060008060608587031215613698578182fd5b84356136a3816142f6565b9350602085013567ffffffffffffffff808211156136bf578384fd5b818701915087601f8301126136d2578384fd5b8135818111156136e0578485fd5b88602080830285010111156136f3578485fd5b602083019550809450505050613678604086016134cd565b6000806040838503121561371d578182fd5b8235613728816142f6565b9150613736602084016134cd565b90509250929050565b60008060208385031215613751578182fd5b823567ffffffffffffffff80821115613768578384fd5b818501915085601f83011261377b578384fd5b813581811115613789578485fd5b8660206102808302850101111561379e578485fd5b60209290920196919550909350505050565b6000602082840312156137c1578081fd5b6114d5826134cd565b6000602082840312156137db578081fd5b6114d5826134dd565b600061010082840312156137f6578081fd5b6114d583836134ec565b600061016082840312156134fe578081fd5b600061028082840312156134fe578081fd5b6000610280808385031215613837578182fd5b613840816142a6565b905082358152613852602084016134dd565b6020820152613863604084016134cd565b60408201526060830135606082015261387e608084016134cd565b608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013581830152506101408084013581830152506101606138d38185016134c2565b908201526101806138e58482016134c2565b908201526101a06138f78482016134c2565b908201526101c083810135908201526101e0808401359082015261020061391f8185016134cd565b9082015261022083810135908201526102408084013590820152610260928301359281019290925250919050565b600061012082840312156134fe578081fd5b600060208284031215613970578081fd5b5035919050565b600060208284031215613988578081fd5b5051919050565b600080604083850312156139a1578182fd5b50508035926020909101359150565b6001600160a01b03169052565b15159052565b600081518084526139db8160208601602086016142ca565b601f01601f19169290920160200192915050565b600581106139f957fe5b9052565b8035613a08816142f6565b6001600160a01b039081168352602082013590613a24826142f6565b80821660208501526040830135604085015260608301356060850152613a4c608084016134cd565b1515608085015260a08301359150613a63826142f6565b1660a083015260c08181013590830152613a7f60e08201613504565b6112f960e0840182613bda565b80358252613a9c602082016134dd565b613aa960208401826139ef565b50613ab6604082016134cd565b613ac360408401826139bd565b5060608101356060830152613ada608082016134cd565b613ae760808401826139bd565b5060a081013560a083015260c081013560c083015260e081013560e0830152610100808201358184015250610120808201358184015250610140808201358184015250610160613b388183016134c2565b613b44828501826139b0565b5050610180613b548183016134c2565b613b60828501826139b0565b50506101a0613b708183016134c2565b613b7c828501826139b0565b50506101c081810135908301526101e08082013590830152610200613ba28183016134cd565b613bae828501826139bd565b50506102208181013590830152610240808201359083015261026090810135910152565b61ffff169052565b63ffffffff169052565b60008251613bf68184602087016142ca565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b0396871681529486166020860152604085019390935293166060830152608082019290925290151560a082015260c00190565b6001600160a01b0394851681529290931660208301526040820152901515606082015260800190565b6001600160a01b039290921682521515602082015260400190565b901515815260200190565b600060608252613ced60608301866139c3565b60208301949094525060400152919050565b6020810160068310613d0d57fe5b91905290565b6020808252600490820152632a22181b60e11b604082015260600190565b6020808252600490820152635444314360e01b604082015260600190565b60208082526004908201526315110c4d60e21b604082015260600190565b6020808252600490820152635444323160e01b604082015260600190565b6020808252600490820152630544430360e41b604082015260600190565b6020808252600490820152635444303160e01b604082015260600190565b6020808252600490820152630544434360e41b604082015260600190565b6020808252600490820152634f53313760e01b604082015260600190565b6020808252600490820152632a221a9960e11b604082015260600190565b60208082526004908201526327a99b9960e11b604082015260600190565b6020808252600490820152632a22181960e11b604082015260600190565b8581526001600160a01b0385166020808301919091526080604083018190528201849052600090859060a08401835b87811015613eb657613ea682613ea1866134dd565b6139ef565b9282019290820190600101613e8c565b5080935050505082151560608301529695505050505050565b8381526101408101613ee460208301856139fd565b82610120830152949350505050565b8381526101a08101613f1060208301613f0b866134c2565b6139b0565b613f1c602085016134c2565b613f2960408401826139b0565b506040840135606083015260608401356080830152608084013560a083015260a084013560c0830152613f5e60c085016134cd565b613f6b60e08401826139bd565b50613f7860e085016134cd565b610100613f87818501836139bd565b613f928187016134c2565b915050610120613fa4818501836139b0565b6101409150808601358285015250613fbd818601613504565b9050613fcd610160840182613bda565b5082610180830152949350505050565b8281526102a081016125046020830184613a8c565b828152610140810161400a60208301613f0b856134c2565b614016602084016134c2565b61402360408401826139b0565b506040830135606083015260608301356080830152608083013560a083015261404e60a084016134cd565b61405b60c08401826139bd565b5061406860c084016134c2565b61407560e08401826139b0565b5061010060e08401358184015261408d818501613504565b905061324e610120840182613bda565b918252602082015260400190565b9485526001600160a01b0393841660208601526040850192909252606084015216608082015260a00190565b60006102e08201905083518051835260208101516140f860208501826139ef565b50604081015161410b60408501826139bd565b5060608101516060840152608081015161412860808501826139bd565b5060a081015160a084015260c081015160c084015260e081015160e08401526101008082015181850152506101208082015181850152506101408082015181850152506101608082015161417e828601826139b0565b505061018080820151614193828601826139b0565b50506101a0808201516141a8828601826139b0565b50506101c081810151908401526101e08082015190840152610200808201516141d3828601826139bd565b505061022081810151908401526102408082015190840152610260908101519083015260208401516142096102808401826139b0565b50604084015161421d6102a0840182613bd2565b50826102c08301529392505050565b61028081016114d88284613a8c565b6102e0810161424a8287613a8c565b6001600160a01b039490941661028082015261ffff929092166102a08301526102c090910152919050565b61ffff91909116815260200190565b90815260200190565b60008382526040602083015261309660408301846139c3565b60405181810167ffffffffffffffff811182821017156142c257fe5b604052919050565b60005b838110156142e55781810151838201526020016142cd565b838111156117b55750506000910152565b6001600160a01b038116811461074757600080fdfe786212e89f390a4c768f3b935b85e0ec2561a24b6f48cda3c4b48a996b211592a264697066735822122099bde760c5a3a45475e145709e72c67d165673645fd1abfea9ffbe368107fd4764736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f4418d9fe76a788f2868a558dd216549ad2d869b0000000000000000000000003a1d749fa4a9e650fce844ff1c58c5faf7e2a9d1
-----Decoded View---------------
Arg [0] : _factoryGovernor (address): 0xF4418d9fe76A788F2868a558dD216549aD2d869B
Arg [1] : _bot (address): 0x3a1D749fa4a9E650FCe844fF1C58C5faf7e2a9D1
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000f4418d9fe76a788f2868a558dd216549ad2d869b
Arg [1] : 0000000000000000000000003a1d749fa4a9e650fce844ff1c58c5faf7e2a9d1
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.