More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 536 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Order Disabl... | 12431620 | 1439 days ago | IN | 0 ETH | 0.00602999 | ||||
Set Order Disabl... | 12431616 | 1439 days ago | IN | 0 ETH | 0.00602491 | ||||
Set Order Disabl... | 12431612 | 1439 days ago | IN | 0 ETH | 0.00601846 | ||||
Set Order Disabl... | 12431602 | 1439 days ago | IN | 0 ETH | 0.00601201 | ||||
Set Order Disabl... | 12431597 | 1439 days ago | IN | 0 ETH | 0.00611704 | ||||
Set Order Disabl... | 12431588 | 1439 days ago | IN | 0 ETH | 0.00620748 | ||||
Set Order Disabl... | 12431586 | 1439 days ago | IN | 0 ETH | 0.00626269 | ||||
Set Order Disabl... | 12431580 | 1439 days ago | IN | 0 ETH | 0.00620748 | ||||
Set Order Disabl... | 12431576 | 1439 days ago | IN | 0 ETH | 0.00627468 | ||||
Set Order Disabl... | 12431573 | 1439 days ago | IN | 0 ETH | 0.0064638 | ||||
Set Order Disabl... | 12431570 | 1439 days ago | IN | 0 ETH | 0.00655398 | ||||
Set Order Disabl... | 12431565 | 1439 days ago | IN | 0 ETH | 0.00630448 | ||||
Set Order Disabl... | 12431558 | 1439 days ago | IN | 0 ETH | 0.00655398 | ||||
Set Order Disabl... | 12431548 | 1439 days ago | IN | 0 ETH | 0.01066912 | ||||
Execute | 12431168 | 1439 days ago | IN | 0 ETH | 0.0248843 | ||||
Withdraw | 12431140 | 1439 days ago | IN | 0.06978428 ETH | 0.01989446 | ||||
Execute | 12431100 | 1439 days ago | IN | 0 ETH | 0.02631352 | ||||
Withdraw | 12431072 | 1439 days ago | IN | 0.07020058 ETH | 0.02059996 | ||||
Execute | 12431060 | 1439 days ago | IN | 0 ETH | 0.02468062 | ||||
Withdraw | 12431036 | 1439 days ago | IN | 0.07053089 ETH | 0.02652744 | ||||
Execute | 12430785 | 1439 days ago | IN | 0 ETH | 0.02757116 | ||||
Withdraw | 12430771 | 1439 days ago | IN | 0.07080387 ETH | 0.03218745 | ||||
Execute | 12430594 | 1439 days ago | IN | 0 ETH | 0.03636622 | ||||
Deposit | 12430578 | 1439 days ago | IN | 0.73846526 ETH | 0.0255188 | ||||
Execute | 12430524 | 1439 days ago | IN | 0 ETH | 0.01978671 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
- | 12431168 | 1439 days ago | 0.02331475 ETH | ||||
- | 12431168 | 1439 days ago | 0.04314646 ETH | ||||
- | 12431140 | 1439 days ago | 0.00332306 ETH | ||||
- | 12431100 | 1439 days ago | 0.02079831 ETH | ||||
- | 12431100 | 1439 days ago | 0.04605938 ETH | ||||
- | 12431072 | 1439 days ago | 0.00334288 ETH | ||||
- | 12431060 | 1439 days ago | 0.02629906 ETH | ||||
- | 12431060 | 1439 days ago | 0.04087321 ETH | ||||
- | 12431036 | 1439 days ago | 0.00335861 ETH | ||||
- | 12430785 | 1439 days ago | 0.02577341 ETH | ||||
- | 12430785 | 1439 days ago | 0.04165884 ETH | ||||
- | 12430771 | 1439 days ago | 0.00337161 ETH | ||||
- | 12430594 | 1439 days ago | 0.0643718 ETH | ||||
- | 12430594 | 1439 days ago | 0.04335347 ETH | ||||
- | 12430578 | 1439 days ago | 0.62535372 ETH | ||||
- | 12430578 | 1439 days ago | 0.00538626 ETH | ||||
- | 12430524 | 1439 days ago | 0.02928554 ETH | ||||
- | 12430524 | 1439 days ago | 0.03862971 ETH | ||||
- | 12430496 | 1439 days ago | 0.00339576 ETH | ||||
- | 12430419 | 1439 days ago | 0.02667377 ETH | ||||
- | 12430419 | 1439 days ago | 0.04163418 ETH | ||||
- | 12430395 | 1439 days ago | 0.00341539 ETH | ||||
- | 12430159 | 1439 days ago | 0.02398271 ETH | ||||
- | 12430159 | 1439 days ago | 0.0445827 ETH | ||||
- | 12430136 | 1439 days ago | 0.00342827 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:
IntegralDelay
Compiler Version
v0.7.5+commit.eb77ed08
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import 'IIntegralPair.sol'; import 'IIntegralDelay.sol'; import 'IIntegralOracle.sol'; import 'IWETH.sol'; import 'SafeMath.sol'; import 'Normalizer.sol'; import 'Orders.sol'; import 'TokenShares.sol'; import 'AddLiquidity.sol'; import 'BuyHelper.sol'; contract IntegralDelay is IIntegralDelay { using SafeMath for uint256; using Normalizer for uint256; using Orders for Orders.Data; using TokenShares for TokenShares.Data; Orders.Data internal orders; TokenShares.Data internal tokenShares; uint256 public constant ORDER_CANCEL_TIME = 24 hours; uint256 private constant ORDER_EXECUTED_COST = 3700; address public override owner; mapping(address => bool) public override isBot; uint256 public override botExecuteTime; constructor( address _factory, address _weth, address _bot ) { orders.factory = _factory; owner = msg.sender; isBot[_bot] = true; orders.gasPrice = tx.gasprice - (tx.gasprice % 1e6); tokenShares.setWeth(_weth); orders.delay = 5 minutes; botExecuteTime = 4 * orders.delay; orders.maxGasLimit = 5000000; orders.gasPriceInertia = 20000000; orders.maxGasPriceImpact = 1000000; } function getTransferGasCost(address token) public view override returns (uint256 gasCost) { return orders.transferGasCosts[token]; } function getDepositOrder(uint256 orderId) public view override returns (Orders.DepositOrder memory order) { return orders.getDepositOrder(orderId); } function getWithdrawOrder(uint256 orderId) public view override returns (Orders.WithdrawOrder memory order) { return orders.getWithdrawOrder(orderId); } function getSellOrder(uint256 orderId) public view override returns (Orders.SellOrder memory order) { return orders.getSellOrder(orderId); } function getBuyOrder(uint256 orderId) public view override returns (Orders.BuyOrder memory order) { return orders.getBuyOrder(orderId); } function getDepositDisabled(address pair) public view override returns (bool) { return orders.depositDisabled[pair]; } function getWithdrawDisabled(address pair) public view override returns (bool) { return orders.withdrawDisabled[pair]; } function getBuyDisabled(address pair) public view override returns (bool) { return orders.buyDisabled[pair]; } function getSellDisabled(address pair) public view override returns (bool) { return orders.sellDisabled[pair]; } function getOrderStatus(uint256 orderId) public view override returns (Orders.OrderStatus) { return orders.getOrderStatus(orderId); } uint256 private unlocked = 1; modifier lock() { require(unlocked == 1, 'ID_LOCKED'); unlocked = 0; _; unlocked = 1; } function factory() public view override returns (address) { return orders.factory; } function totalShares(address token) public view override returns (uint256) { return tokenShares.totalShares[token]; } function weth() public view override returns (address) { return tokenShares.weth; } function delay() public view override returns (uint256) { return orders.delay; } function lastProcessedOrderId() public view returns (uint256) { return orders.lastProcessedOrderId; } function newestOrderId() public view returns (uint256) { return orders.newestOrderId; } function getOrder(uint256 orderId) public view returns (Orders.OrderType orderType, uint256 validAfterTimestamp) { return orders.getOrder(orderId); } function isOrderCanceled(uint256 orderId) public view returns (bool) { return orders.canceled[orderId]; } function maxGasLimit() public view override returns (uint256) { return orders.maxGasLimit; } function maxGasPriceImpact() public view override returns (uint256) { return orders.maxGasPriceImpact; } function gasPriceInertia() public view override returns (uint256) { return orders.gasPriceInertia; } function gasPrice() public view override returns (uint256) { return orders.gasPrice; } function setOrderDisabled( address pair, Orders.OrderType orderType, bool disabled ) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); require(orderType != Orders.OrderType.Empty, 'ID_INVALID_ORDER_TYPE'); if (orderType == Orders.OrderType.Deposit) { orders.depositDisabled[pair] = disabled; } else if (orderType == Orders.OrderType.Withdraw) { orders.withdrawDisabled[pair] = disabled; } else if (orderType == Orders.OrderType.Sell) { orders.sellDisabled[pair] = disabled; } else if (orderType == Orders.OrderType.Buy) { orders.buyDisabled[pair] = disabled; } emit OrderDisabled(pair, orderType, disabled); } function setOwner(address _owner) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); owner = _owner; emit OwnerSet(owner); } function setBot(address _bot, bool _isBot) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); isBot[_bot] = _isBot; emit BotSet(_bot, _isBot); } function setMaxGasLimit(uint256 _maxGasLimit) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); orders.setMaxGasLimit(_maxGasLimit); } function setDelay(uint256 _delay) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); orders.delay = _delay; botExecuteTime = 4 * _delay; emit DelaySet(_delay); } function setGasPriceInertia(uint256 _gasPriceInertia) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); orders.setGasPriceInertia(_gasPriceInertia); } function setMaxGasPriceImpact(uint256 _maxGasPriceImpact) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); orders.setMaxGasPriceImpact(_maxGasPriceImpact); } function setTransferGasCost(address token, uint256 gasCost) public override { require(msg.sender == owner, 'ID_FORBIDDEN'); orders.setTransferGasCost(token, gasCost); } 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 buy(Orders.BuyParams calldata buyParams) external payable override lock returns (uint256 orderId) { orders.buy(buyParams, tokenShares); return orders.newestOrderId; } function execute(uint256 n) public override lock { emit Execute(msg.sender, n); uint256 gasBefore = gasleft(); bool orderExecuted = false; for (uint256 i = 0; i < n; i++) { if (isOrderCanceled(orders.lastProcessedOrderId + 1)) { orders.dequeueCanceledOrder(); continue; } (Orders.OrderType orderType, uint256 validAfterTimestamp) = orders.getNextOrder(); if (orderType == Orders.OrderType.Empty || validAfterTimestamp >= block.timestamp) { break; } require( block.timestamp >= validAfterTimestamp + botExecuteTime || isBot[msg.sender] || isBot[address(0)], 'ID_FORBIDDEN' ); orderExecuted = true; if (orderType == Orders.OrderType.Deposit) { executeDeposit(); } else if (orderType == Orders.OrderType.Withdraw) { executeWithdraw(); } else if (orderType == Orders.OrderType.Sell) { executeSell(); } else if (orderType == Orders.OrderType.Buy) { executeBuy(); } } if (orderExecuted) { orders.updateGasPrice(gasBefore.sub(gasleft())); } } function executeDeposit() internal { uint256 gasStart = gasleft(); Orders.DepositOrder memory depositOrder = orders.dequeueDepositOrder(); (, address token0, address token1) = orders.getPairInfo(depositOrder.pairId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: depositOrder.gasLimit.sub( Orders.ORDER_BASE_COST.add(orders.transferGasCosts[token0]).add(orders.transferGasCosts[token1]) ) }(abi.encodeWithSelector(this._executeDeposit.selector, depositOrder)); bool refundSuccess = true; if (!executionSuccess) { refundSuccess = refundTokens( depositOrder.to, token0, depositOrder.share0, token1, depositOrder.share1, depositOrder.unwrap ); } if (!refundSuccess) { orders.markRefundFailed(); } else { orders.forgetLastProcessedOrder(); } (uint256 gasUsed, uint256 ethRefund) = refund( depositOrder.gasLimit, depositOrder.gasPrice, gasStart, depositOrder.to ); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } function executeWithdraw() internal { uint256 gasStart = gasleft(); Orders.WithdrawOrder memory withdrawOrder = orders.dequeueWithdrawOrder(); (address pair, , ) = orders.getPairInfo(withdrawOrder.pairId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: withdrawOrder.gasLimit.sub(Orders.ORDER_BASE_COST.add(Orders.PAIR_TRANSFER_COST)) }(abi.encodeWithSelector(this._executeWithdraw.selector, withdrawOrder)); bool refundSuccess = true; if (!executionSuccess) { refundSuccess = refundLiquidity(pair, withdrawOrder.to, withdrawOrder.liquidity); } if (!refundSuccess) { orders.markRefundFailed(); } else { orders.forgetLastProcessedOrder(); } (uint256 gasUsed, uint256 ethRefund) = refund( withdrawOrder.gasLimit, withdrawOrder.gasPrice, gasStart, withdrawOrder.to ); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } function executeSell() internal { uint256 gasStart = gasleft(); Orders.SellOrder memory sellOrder = orders.dequeueSellOrder(); (, address token0, address token1) = orders.getPairInfo(sellOrder.pairId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: sellOrder.gasLimit.sub( Orders.ORDER_BASE_COST.add(orders.transferGasCosts[sellOrder.inverse ? token1 : token0]) ) }(abi.encodeWithSelector(this._executeSell.selector, sellOrder)); bool refundSuccess = true; if (!executionSuccess) { refundSuccess = refundToken( sellOrder.inverse ? token1 : token0, sellOrder.to, sellOrder.shareIn, sellOrder.unwrap ); } if (!refundSuccess) { orders.markRefundFailed(); } else { orders.forgetLastProcessedOrder(); } (uint256 gasUsed, uint256 ethRefund) = refund(sellOrder.gasLimit, sellOrder.gasPrice, gasStart, sellOrder.to); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } function executeBuy() internal { uint256 gasStart = gasleft(); Orders.BuyOrder memory buyOrder = orders.dequeueBuyOrder(); (, address token0, address token1) = orders.getPairInfo(buyOrder.pairId); (bool executionSuccess, bytes memory data) = address(this).call{ gas: buyOrder.gasLimit.sub( Orders.ORDER_BASE_COST.add(orders.transferGasCosts[buyOrder.inverse ? token1 : token0]) ) }(abi.encodeWithSelector(this._executeBuy.selector, buyOrder)); bool refundSuccess = true; if (!executionSuccess) { refundSuccess = refundToken( buyOrder.inverse ? token1 : token0, buyOrder.to, buyOrder.shareInMax, buyOrder.unwrap ); } if (!refundSuccess) { orders.markRefundFailed(); } else { orders.forgetLastProcessedOrder(); } (uint256 gasUsed, uint256 ethRefund) = refund(buyOrder.gasLimit, buyOrder.gasPrice, gasStart, buyOrder.to); emit OrderExecuted(orders.lastProcessedOrderId, executionSuccess, data, gasUsed, ethRefund); } 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_END_COST).add(ORDER_EXECUTED_COST); uint256 actualRefund = Math.min(feeCollected, gasUsed.mul(orders.gasPrice)); leftOver = feeCollected.sub(actualRefund); require(refundEth(msg.sender, actualRefund), 'ID_ETH_REFUND_FAILED'); refundEth(payable(to), leftOver); } function refundEth(address payable to, uint256 value) internal returns (bool success) { if (value == 0) { return true; } success = to.send(value); emit EthRefund(to, success, value); } function refundToken( address token, address to, uint256 share, bool unwrap ) private returns (bool) { if (share == 0) { return true; } (bool success, bytes memory data) = address(this).call{ gas: orders.transferGasCosts[token] }( abi.encodeWithSelector(this._refundToken.selector, token, to, share, unwrap) ); if (!success) { emit RefundFailed(to, token, share, data); } return success; } function refundTokens( address to, address token0, uint256 share0, address token1, uint256 share1, bool unwrap ) private returns (bool) { (bool success, bytes memory data) = address(this).call{ gas: orders.transferGasCosts[token0].add(orders.transferGasCosts[token1]) }(abi.encodeWithSelector(this._refundTokens.selector, to, token0, share0, token1, share1, unwrap)); if (!success) { emit RefundFailed(to, token0, share0, data); emit RefundFailed(to, token1, share1, data); } return success; } function _refundTokens( address to, address token0, uint256 share0, address token1, uint256 share1, bool unwrap ) external { // 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 { require(msg.sender == address(this), 'ID_FORBIDDEN'); if (token == tokenShares.weth && unwrap) { uint256 amount = tokenShares.sharesToAmount(token, share); IWETH(tokenShares.weth).withdraw(amount); payable(to).transfer(amount); } else { return TransferHelper.safeTransfer(token, to, tokenShares.sharesToAmount(token, share)); } } function refundLiquidity( address pair, address to, uint256 liquidity ) private returns (bool) { if (liquidity == 0) { return true; } (bool success, bytes memory data) = address(this).call{ gas: Orders.PAIR_TRANSFER_COST }( abi.encodeWithSelector(this._refundLiquidity.selector, pair, to, liquidity, false) ); if (!success) { emit RefundFailed(to, pair, liquidity, data); } return success; } function _refundLiquidity( address pair, address to, uint256 liquidity ) public { require(msg.sender == address(this), 'ID_FORBIDDEN'); return TransferHelper.safeTransfer(pair, to, liquidity); } function _executeDeposit(Orders.DepositOrder memory depositOrder) public { require(msg.sender == address(this), 'ID_FORBIDDEN'); require(depositOrder.deadline >= block.timestamp, 'ID_EXPIRED'); (address pair, address token0, address token1, uint256 amount0Left, uint256 amount1Left) = _initialDeposit( depositOrder ); if ( (amount0Left != 0 || amount1Left != 0) && AddLiquidity.canSwap( depositOrder.initialRatio, depositOrder.minRatioChangeToSwap, orders.pairs[depositOrder.pairId].pair ) ) { if (amount0Left != 0) { (amount0Left, amount1Left) = AddLiquidity.swapDeposit0( pair, token0, amount0Left, depositOrder.minSwapPrice ); } else if (amount1Left != 0) { (amount0Left, amount1Left) = AddLiquidity.swapDeposit1( pair, token1, amount1Left, depositOrder.maxSwapPrice ); } } if (amount0Left != 0 && amount1Left != 0) { (amount0Left, amount1Left) = _addLiquidityAndMint( pair, depositOrder.to, token0, token1, amount0Left, amount1Left ); } _refundDeposit(depositOrder.to, token0, token1, amount0Left, amount1Left); } function _initialDeposit(Orders.DepositOrder memory depositOrder) private returns ( address pair, address token0, address token1, uint256 amount0Left, uint256 amount1Left ) { (pair, token0, token1) = orders.getPairInfo(depositOrder.pairId); uint256 amount0Desired = tokenShares.sharesToAmount(token0, depositOrder.share0); uint256 amount1Desired = tokenShares.sharesToAmount(token1, depositOrder.share1); IIntegralPair(pair).fullSync(); (amount0Left, amount1Left) = _addLiquidityAndMint( pair, depositOrder.to, token0, token1, amount0Desired, amount1Desired ); } function _addLiquidityAndMint( address pair, address to, address token0, address token1, uint256 amount0Desired, uint256 amount1Desired ) private returns (uint256 amount0Left, uint256 amount1Left) { (uint256 amount0, uint256 amount1) = AddLiquidity.addLiquidity(pair, amount0Desired, amount1Desired); if (amount0 == 0 || amount1 == 0) { return (amount0Desired, amount1Desired); } TransferHelper.safeTransfer(token0, pair, amount0); TransferHelper.safeTransfer(token1, pair, amount1); IIntegralPair(pair).mint(to); amount0Left = amount0Desired.sub(amount0); amount1Left = amount1Desired.sub(amount1); } function _refundDeposit( address to, address token0, address token1, uint256 amount0, uint256 amount1 ) private { if (amount0 > 0) { TransferHelper.safeTransfer(token0, to, amount0); } if (amount1 > 0) { TransferHelper.safeTransfer(token1, to, amount1); } } function _executeWithdraw(Orders.WithdrawOrder memory withdrawOrder) public { require(msg.sender == address(this), 'ID_FORBIDDEN'); require(withdrawOrder.deadline >= block.timestamp, 'ID_EXPIRED'); (address pair, , ) = orders.getPairInfo(withdrawOrder.pairId); IIntegralPair(pair).fullSync(); TransferHelper.safeTransfer(pair, pair, withdrawOrder.liquidity); (uint256 amount0, uint256 amount1) = IIntegralPair(pair).burn(withdrawOrder.to); require(amount0 >= withdrawOrder.amount0Min && amount1 >= withdrawOrder.amount1Min, 'ID_INSUFFICIENT_AMOUNT'); } function _executeBuy(Orders.BuyOrder memory buyOrder) public { require(msg.sender == address(this), 'ID_FORBIDDEN'); require(buyOrder.deadline >= block.timestamp, 'ID_EXPIRED'); (address pairAddress, address token0, address token1) = orders.getPairInfo(buyOrder.pairId); (address tokenIn, address tokenOut) = buyOrder.inverse ? (token1, token0) : (token0, token1); uint256 amountInMax = tokenShares.sharesToAmount(tokenIn, buyOrder.shareInMax); IIntegralPair pair = IIntegralPair(pairAddress); pair.fullSync(); uint256 amountIn = buyOrder.inverse ? BuyHelper.getSwapAmount1In(pairAddress, buyOrder.amountOut) : BuyHelper.getSwapAmount0In(pairAddress, buyOrder.amountOut); require(amountInMax >= amountIn, 'ID_INSUFFICIENT_INPUT_AMOUNT'); (uint256 amount0Out, uint256 amount1Out) = buyOrder.inverse ? (buyOrder.amountOut, uint256(0)) : (uint256(0), buyOrder.amountOut); TransferHelper.safeTransfer(tokenIn, pairAddress, amountIn); if (tokenOut == tokenShares.weth && buyOrder.unwrap) { pair.swap(amount0Out, amount1Out, address(this)); IWETH(tokenShares.weth).withdraw(buyOrder.amountOut); (bool success, ) = buyOrder.to.call{ value: buyOrder.amountOut, gas: Orders.ETHER_TRANSFER_CALL_COST }(''); if (!success) { tokenShares.onUnwrapFailed(buyOrder.to, buyOrder.amountOut); } } else { pair.swap(amount0Out, amount1Out, buyOrder.to); } } function _executeSell(Orders.SellOrder memory sellOrder) public { require(msg.sender == address(this), 'ID_FORBIDDEN'); require(sellOrder.deadline >= block.timestamp, 'ID_EXPIRED'); (address pairAddress, address token0, address token1) = orders.getPairInfo(sellOrder.pairId); (address tokenIn, address tokenOut) = sellOrder.inverse ? (token1, token0) : (token0, token1); uint256 amountIn = tokenShares.sharesToAmount(tokenIn, sellOrder.shareIn); IIntegralPair pair = IIntegralPair(pairAddress); pair.fullSync(); TransferHelper.safeTransfer(tokenIn, pairAddress, amountIn); uint256 amountOut = sellOrder.inverse ? pair.getSwapAmount0Out(amountIn) : pair.getSwapAmount1Out(amountIn); require(amountOut >= sellOrder.amountOutMin, 'ID_INSUFFICIENT_OUTPUT_AMOUNT'); (uint256 amount0Out, uint256 amount1Out) = sellOrder.inverse ? (amountOut, uint256(0)) : (uint256(0), amountOut); if (tokenOut == tokenShares.weth && sellOrder.unwrap) { pair.swap(amount0Out, amount1Out, address(this)); IWETH(tokenShares.weth).withdraw(amountOut); (bool success, ) = sellOrder.to.call{ value: amountOut, gas: Orders.ETHER_TRANSFER_CALL_COST }(''); if (!success) { tokenShares.onUnwrapFailed(sellOrder.to, amountOut); } } else { pair.swap(amount0Out, amount1Out, sellOrder.to); } } function performRefund( Orders.OrderType orderType, uint256 validAfterTimestamp, uint256 orderId, bool shouldRefundEth ) internal { bool canOwnerRefund = validAfterTimestamp.add(365 days) < block.timestamp; if (orderType == Orders.OrderType.Deposit) { Orders.DepositOrder memory depositOrder = orders.getDepositOrder(orderId); (, address token0, address token1) = orders.getPairInfo(depositOrder.pairId); address to = canOwnerRefund ? owner : depositOrder.to; require( refundTokens(to, token0, depositOrder.share0, token1, depositOrder.share1, depositOrder.unwrap), 'ID_REFUND_FAILED' ); if (shouldRefundEth) { uint256 value = depositOrder.gasPrice.mul(depositOrder.gasLimit); require(refundEth(payable(to), value), 'ID_ETH_REFUND_FAILED'); } } else if (orderType == Orders.OrderType.Withdraw) { Orders.WithdrawOrder memory withdrawOrder = orders.getWithdrawOrder(orderId); (address pair, , ) = orders.getPairInfo(withdrawOrder.pairId); address to = canOwnerRefund ? owner : withdrawOrder.to; require(refundLiquidity(pair, to, withdrawOrder.liquidity), 'ID_REFUND_FAILED'); if (shouldRefundEth) { uint256 value = withdrawOrder.gasPrice.mul(withdrawOrder.gasLimit); require(refundEth(payable(to), value), 'ID_ETH_REFUND_FAILED'); } } else if (orderType == Orders.OrderType.Sell) { Orders.SellOrder memory sellOrder = orders.getSellOrder(orderId); (, address token0, address token1) = orders.getPairInfo(sellOrder.pairId); address to = canOwnerRefund ? owner : sellOrder.to; require( refundToken(sellOrder.inverse ? token1 : token0, to, sellOrder.shareIn, sellOrder.unwrap), 'ID_REFUND_FAILED' ); if (shouldRefundEth) { uint256 value = sellOrder.gasPrice.mul(sellOrder.gasLimit); require(refundEth(payable(to), value), 'ID_ETH_REFUND_FAILED'); } } else if (orderType == Orders.OrderType.Buy) { Orders.BuyOrder memory buyOrder = orders.getBuyOrder(orderId); (, address token0, address token1) = orders.getPairInfo(buyOrder.pairId); address to = canOwnerRefund ? owner : buyOrder.to; require( refundToken(buyOrder.inverse ? token1 : token0, to, buyOrder.shareInMax, buyOrder.unwrap), 'ID_REFUND_FAILED' ); if (shouldRefundEth) { uint256 value = buyOrder.gasPrice.mul(buyOrder.gasLimit); require(refundEth(payable(to), value), 'ID_ETH_REFUND_FAILED'); } } orders.forgetOrder(orderId); } function retryRefund(uint256 orderId) public lock { (Orders.OrderType orderType, uint256 validAfterTimestamp) = orders.getFailedOrderType(orderId); performRefund(orderType, validAfterTimestamp, orderId, false); } function cancelOrder(uint256 orderId) public lock { (Orders.OrderType orderType, uint256 validAfterTimestamp) = orders.getOrder(orderId); require(validAfterTimestamp.sub(delay()).add(ORDER_CANCEL_TIME) < block.timestamp, 'ID_ORDER_NOT_EXCEEDED'); performRefund(orderType, validAfterTimestamp, orderId, true); orders.canceled[orderId] = true; } receive() external payable {} }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; 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); }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; import 'IERC20.sol'; interface IIntegralERC20 is IERC20 { function DOMAIN_SEPARATOR() external view returns (bytes32); 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); }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; interface IReserves { event Sync(uint112 reserve0, uint112 reserve1); event Fees(uint256 fee0, uint256 fee1); function getReserves() external view returns ( uint112 reserve0, uint112 reserve1, uint32 lastTimestamp ); function getReferences() external view returns ( uint112 reference0, uint112 reference1, uint32 epoch ); function getFees() external view returns (uint256 fee0, uint256 fee1); }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; import 'IIntegralERC20.sol'; import 'IReserves.sol'; interface IIntegralPair is IIntegralERC20, IReserves { event Mint(address indexed sender, address indexed to); event Burn(address indexed sender, address indexed to); event Swap(address indexed sender, address indexed to); event SetMintFee(uint256 fee); event SetBurnFee(uint256 fee); event SetSwapFee(uint256 fee); event SetOracle(address account); event SetTrader(address trader); event SetToken0AbsoluteLimit(uint256 limit); event SetToken1AbsoluteLimit(uint256 limit); event SetToken0RelativeLimit(uint256 limit); event SetToken1RelativeLimit(uint256 limit); event SetPriceDeviationLimit(uint256 limit); 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 token0AbsoluteLimit() external view returns (uint256); function setToken0AbsoluteLimit(uint256 limit) external; function token1AbsoluteLimit() external view returns (uint256); function setToken1AbsoluteLimit(uint256 limit) external; function token0RelativeLimit() external view returns (uint256); function setToken0RelativeLimit(uint256 limit) external; function token1RelativeLimit() external view returns (uint256); function setToken1RelativeLimit(uint256 limit) external; function priceDeviationLimit() external view returns (uint256); function setPriceDeviationLimit(uint256 limit) external; function collect(address to) external; function swap( uint256 amount0Out, uint256 amount1Out, address to ) external; function sync() external; function initialize( address _token0, address _token1, address _oracle, address _trader ) external; function syncWithOracle() external; function fullSync() external; function getSpotPrice() external view returns (uint256 spotPrice); function getSwapAmount0In(uint256 amount1Out) external view returns (uint256 swapAmount0In); function getSwapAmount1In(uint256 amount0Out) external view returns (uint256 swapAmount1In); function getSwapAmount0Out(uint256 amount1In) external view returns (uint256 swapAmount0Out); function getSwapAmount1Out(uint256 amount0In) external view returns (uint256 swapAmount1Out); function getDepositAmount0In(uint256 amount0) external view returns (uint256 depositAmount0In); function getDepositAmount1In(uint256 amount1) external view returns (uint256 depositAmount1In); }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) library SafeMath { function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x, 'SM_ADD_OVERFLOW'); } function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { z = sub(x, y, 'SM_SUB_UNDERFLOW'); } 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, 'SM_MUL_OVERFLOW'); } function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, 'SM_DIV_BY_ZERO'); uint256 c = a / b; return c; } function ceil_div(uint256 a, uint256 b) internal pure returns (uint256 c) { c = div(a, b); if (c == mul(a, b)) { return c; } else { return add(c, 1); } } }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; // 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; } } }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; interface IIntegralFactory { 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; }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity =0.7.5; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; // 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))), 'TH_APPROVE_FAILED'); } 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))), 'TH_TRANSFER_FAILED'); } 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))), 'TH_TRANSFER_FROM_FAILED'); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{ value: value }(new bytes(0)); require(success, 'TH_ETH_TRANSFER_FAILED'); } }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; import 'IERC20.sol'; import 'IWETH.sol'; import 'SafeMath.sol'; import 'TransferHelper.sol'; library TokenShares { using SafeMath for uint256; using TransferHelper for address; event UnwrapFailed(address to, uint256 amount); struct Data { mapping(address => uint256) totalShares; address weth; } function setWeth(Data storage data, address _weth) internal { data.weth = _weth; } function sharesToAmount( Data storage data, address token, uint256 share ) external returns (uint256) { if (share == 0) { return 0; } if (token == data.weth) { return share; } require(data.totalShares[token] >= share, 'TS_INSUFFICIENT_BALANCE'); uint256 balance = IERC20(token).balanceOf(address(this)); uint256 value = balance.mul(share).div(data.totalShares[token]); data.totalShares[token] = data.totalShares[token].sub(share); return value; } function amountToShares( Data storage data, address token, uint256 amount, bool wrap ) external returns (uint256) { if (amount == 0) { return 0; } if (token == data.weth) { if (wrap) { require(msg.value >= amount, 'TS_INSUFFICIENT_AMOUNT'); IWETH(token).deposit{ value: amount }(); } else { token.safeTransferFrom(msg.sender, address(this), amount); } return amount; } else { uint256 balanceBefore = IERC20(token).balanceOf(address(this)); require(balanceBefore > 0 || data.totalShares[token] == 0, 'TS_INVALID_SHARES'); if (data.totalShares[token] == 0) { data.totalShares[token] = balanceBefore; } token.safeTransferFrom(msg.sender, address(this), amount); uint256 balanceAfter = IERC20(token).balanceOf(address(this)); require(balanceAfter > balanceBefore, 'TS_INVALID_TRANSFER'); if (balanceBefore > 0) { uint256 lastShares = data.totalShares[token]; data.totalShares[token] = lastShares.mul(balanceAfter).div(balanceBefore); return data.totalShares[token] - lastShares; } else { data.totalShares[token] = balanceAfter; data.totalShares[token] = balanceAfter; return balanceAfter; } } } function onUnwrapFailed( Data storage data, address to, uint256 amount ) external { emit UnwrapFailed(to, amount); IWETH(data.weth).deposit{ value: amount }(); TransferHelper.safeTransfer(data.weth, to, amount); } }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import 'SafeMath.sol'; import 'Math.sol'; import 'IIntegralFactory.sol'; import 'IIntegralPair.sol'; import '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 MaxGasLimitSet(uint256 maxGasLimit); event GasPriceInertiaSet(uint256 gasPriceInertia); event MaxGasPriceImpactSet(uint256 maxGasPriceImpact); event TransferGasCostSet(address token, uint256 gasCost); event DepositEnqueued(uint256 indexed orderId, uint128 validAfterTimestamp, uint256 gasPrice); event WithdrawEnqueued(uint256 indexed orderId, uint128 validAfterTimestamp, uint256 gasPrice); event SellEnqueued(uint256 indexed orderId, uint128 validAfterTimestamp, uint256 gasPrice); event BuyEnqueued(uint256 indexed orderId, uint128 validAfterTimestamp, uint256 gasPrice); uint8 private constant DEPOSIT_TYPE = 1; uint8 private constant WITHDRAW_TYPE = 2; uint8 private constant BUY_TYPE = 3; uint8 private constant BUY_INVERTED_TYPE = 4; uint8 private constant SELL_TYPE = 5; uint8 private constant SELL_INVERTED_TYPE = 6; uint8 private constant UNWRAP_NOT_FAILED = 0; uint8 private constant KEEP_NOT_FAILED = 1; uint8 private constant UNWRAP_FAILED = 2; uint8 private constant KEEP_FAILED = 3; uint256 private constant ETHER_TRANSFER_COST = 2300; uint256 private constant BUFFER_COST = 10000; uint256 private constant EXECUTE_PREPARATION_COST = 55000; // dequeue + getPair in execute uint256 public constant ETHER_TRANSFER_CALL_COST = 10000; uint256 public constant PAIR_TRANSFER_COST = 55000; uint256 public constant REFUND_END_COST = 2 * ETHER_TRANSFER_COST + BUFFER_COST; uint256 public constant ORDER_BASE_COST = EXECUTE_PREPARATION_COST + REFUND_END_COST; uint256 private constant TIMESTAMP_OFFSET = 1609455600; // 2021 Jan 1 struct PairInfo { address pair; address token0; address token1; } struct Data { uint256 delay; uint256 newestOrderId; uint256 lastProcessedOrderId; mapping(uint256 => StoredOrder) orderQueue; address factory; uint256 maxGasLimit; uint256 gasPrice; uint256 gasPriceInertia; uint256 maxGasPriceImpact; mapping(uint32 => PairInfo) pairs; mapping(address => uint256) transferGasCosts; mapping(uint256 => bool) canceled; mapping(address => bool) depositDisabled; mapping(address => bool) withdrawDisabled; mapping(address => bool) buyDisabled; mapping(address => bool) sellDisabled; } struct StoredOrder { // slot 1 uint8 orderType; uint32 validAfterTimestamp; uint8 unwrapAndFailure; uint32 deadline; uint32 gasLimit; uint32 gasPrice; uint112 liquidityOrRatio; // slot 1 uint112 value0; uint112 value1; uint32 pairId; // slot2 address to; uint32 minRatioChangeToSwap; uint32 minSwapPrice; uint32 maxSwapPrice; } struct DepositOrder { uint32 pairId; uint256 share0; uint256 share1; uint256 initialRatio; uint256 minRatioChangeToSwap; uint256 minSwapPrice; uint256 maxSwapPrice; bool unwrap; address to; uint256 gasPrice; uint256 gasLimit; uint256 deadline; } struct WithdrawOrder { uint32 pairId; uint256 liquidity; uint256 amount0Min; uint256 amount1Min; bool unwrap; address to; uint256 gasPrice; uint256 gasLimit; uint256 deadline; } struct SellOrder { uint32 pairId; bool inverse; uint256 shareIn; uint256 amountOutMin; bool unwrap; address to; uint256 gasPrice; uint256 gasLimit; uint256 deadline; } struct BuyOrder { uint32 pairId; bool inverse; uint256 shareInMax; uint256 amountOut; bool unwrap; address to; uint256 gasPrice; uint256 gasLimit; uint256 deadline; } function decodeType(uint256 internalType) internal pure returns (OrderType orderType) { if (internalType == DEPOSIT_TYPE) { orderType = OrderType.Deposit; } else if (internalType == WITHDRAW_TYPE) { orderType = OrderType.Withdraw; } else if (internalType == BUY_TYPE) { orderType = OrderType.Buy; } else if (internalType == BUY_INVERTED_TYPE) { orderType = OrderType.Buy; } else if (internalType == SELL_TYPE) { orderType = OrderType.Sell; } else if (internalType == SELL_INVERTED_TYPE) { orderType = OrderType.Sell; } else { orderType = OrderType.Empty; } } function getOrder(Data storage data, uint256 orderId) public view returns (OrderType orderType, uint256 validAfterTimestamp) { StoredOrder storage order = data.orderQueue[orderId]; uint8 internalType = order.orderType; validAfterTimestamp = uint32ToTimestamp(order.validAfterTimestamp); orderType = decodeType(internalType); } function getOrderStatus(Data storage data, uint256 orderId) external view returns (OrderStatus orderStatus) { if (orderId > data.newestOrderId) { return OrderStatus.NonExistent; } if (data.canceled[orderId]) { return OrderStatus.Canceled; } if (isRefundFailed(data, orderId)) { return OrderStatus.ExecutedFailed; } (OrderType orderType, uint256 validAfterTimestamp) = getOrder(data, orderId); if (orderType == OrderType.Empty) { return OrderStatus.ExecutedSucceeded; } if (validAfterTimestamp >= block.timestamp) { return OrderStatus.EnqueuedWaiting; } return OrderStatus.EnqueuedReady; } function getPair( Data storage data, address tokenA, address tokenB ) internal returns ( address pair, uint32 pairId, bool inverted ) { inverted = tokenA > tokenB; (address token0, address token1) = inverted ? (tokenB, tokenA) : (tokenA, tokenB); pair = IIntegralFactory(data.factory).getPair(token0, token1); pairId = uint32(bytes4(keccak256(abi.encodePacked((pair))))); require(pair != address(0), 'OS_PAIR_NONEXISTENT'); if (data.pairs[pairId].pair == address(0)) { data.pairs[pairId] = PairInfo(pair, token0, token1); } } function getPairInfo(Data storage data, uint32 pairId) external view returns ( address pair, address token0, address token1 ) { PairInfo storage info = data.pairs[pairId]; pair = info.pair; token0 = info.token0; token1 = info.token1; } function getDepositOrder(Data storage data, uint256 index) public view returns (DepositOrder memory order) { StoredOrder memory stored = data.orderQueue[index]; require(stored.orderType == DEPOSIT_TYPE, 'OS_INVALID_ORDER_TYPE'); order.pairId = stored.pairId; order.share0 = stored.value0; order.share1 = stored.value1; order.initialRatio = stored.liquidityOrRatio; order.minRatioChangeToSwap = stored.minRatioChangeToSwap; order.minSwapPrice = float32ToUint(stored.minSwapPrice); order.maxSwapPrice = float32ToUint(stored.maxSwapPrice); order.unwrap = getUnwrap(stored.unwrapAndFailure); order.to = stored.to; order.gasPrice = uint32ToGasPrice(stored.gasPrice); order.gasLimit = stored.gasLimit; order.deadline = uint32ToTimestamp(stored.deadline); } function getWithdrawOrder(Data storage data, uint256 index) public view returns (WithdrawOrder memory order) { StoredOrder memory stored = data.orderQueue[index]; require(stored.orderType == WITHDRAW_TYPE, 'OS_INVALID_ORDER_TYPE'); order.pairId = stored.pairId; order.liquidity = stored.liquidityOrRatio; order.amount0Min = stored.value0; order.amount1Min = stored.value1; order.unwrap = getUnwrap(stored.unwrapAndFailure); order.to = stored.to; order.gasPrice = uint32ToGasPrice(stored.gasPrice); order.gasLimit = stored.gasLimit; order.deadline = uint32ToTimestamp(stored.deadline); } function getSellOrder(Data storage data, uint256 index) public view returns (SellOrder memory order) { StoredOrder memory stored = data.orderQueue[index]; require(stored.orderType == SELL_TYPE || stored.orderType == SELL_INVERTED_TYPE, 'OS_INVALID_ORDER_TYPE'); order.pairId = stored.pairId; order.inverse = stored.orderType == SELL_INVERTED_TYPE; order.shareIn = stored.value0; order.amountOutMin = stored.value1; order.unwrap = getUnwrap(stored.unwrapAndFailure); order.to = stored.to; order.gasPrice = uint32ToGasPrice(stored.gasPrice); order.gasLimit = stored.gasLimit; order.deadline = uint32ToTimestamp(stored.deadline); } function getBuyOrder(Data storage data, uint256 index) public view returns (BuyOrder memory order) { StoredOrder memory stored = data.orderQueue[index]; require(stored.orderType == BUY_TYPE || stored.orderType == BUY_INVERTED_TYPE, 'OS_INVALID_ORDER_TYPE'); order.pairId = stored.pairId; order.inverse = stored.orderType == BUY_INVERTED_TYPE; order.shareInMax = stored.value0; order.amountOut = stored.value1; order.unwrap = getUnwrap(stored.unwrapAndFailure); order.to = stored.to; order.gasPrice = uint32ToGasPrice(stored.gasPrice); order.gasLimit = stored.gasLimit; order.deadline = uint32ToTimestamp(stored.deadline); } function getFailedOrderType(Data storage data, uint256 orderId) external view returns (OrderType orderType, uint256 validAfterTimestamp) { require(isRefundFailed(data, orderId), 'OS_NO_POSSIBLE_REFUND'); (orderType, validAfterTimestamp) = getOrder(data, orderId); } function getUnwrap(uint8 unwrapAndFailure) private pure returns (bool) { return unwrapAndFailure == UNWRAP_FAILED || unwrapAndFailure == UNWRAP_NOT_FAILED; } function getUnwrapAndFailure(bool unwrap) private pure returns (uint8) { return unwrap ? UNWRAP_NOT_FAILED : KEEP_NOT_FAILED; } function timestampToUint32(uint256 timestamp) private pure returns (uint32 timestamp32) { if (timestamp == uint256(-1)) { return uint32(-1); } timestamp32 = uintToUint32(timestamp.sub(TIMESTAMP_OFFSET)); } function uint32ToTimestamp(uint32 timestamp32) private pure returns (uint256 timestamp) { if (timestamp32 == uint32(-1)) { return uint256(-1); } if (timestamp32 == 0) { return 0; } timestamp = uint256(timestamp32) + TIMESTAMP_OFFSET; } function gasPriceToUint32(uint256 gasPrice) private pure returns (uint32 gasPrice32) { require((gasPrice / 1e6) * 1e6 == gasPrice, 'OS_GAS_PRICE_PRECISION'); gasPrice32 = uintToUint32(gasPrice / 1e6); } function uint32ToGasPrice(uint32 gasPrice32) public pure returns (uint256 gasPrice) { gasPrice = uint256(gasPrice32) * 1e6; } function uintToUint32(uint256 number) private pure returns (uint32 number32) { number32 = uint32(number); require(uint256(number32) == number, 'OS_OVERFLOW_32'); } function uintToUint112(uint256 number) private pure returns (uint112 number112) { number112 = uint112(number); require(uint256(number112) == number, 'OS_OVERFLOW_112'); } function uintToFloat32(uint256 number) internal pure returns (uint32 float32) { // Number is encoded on 4 bytes. 3 bytes for mantissa and 1 for exponent. // If the number fits in the mantissa we set the exponent to zero and return. if (number < 2 << 24) { return uint32(number << 8); } // We find the exponent by counting the number of trailing zeroes. // Simultaneously we remove those zeroes from the number. uint32 exponent; for (exponent = 0; exponent < 256 - 24; exponent++) { // Last bit is one. if (number & 1 == 1) { break; } number = number >> 1; } // The number must fit in the mantissa. require(number < 2 << 24, 'OS_OVERFLOW_FLOAT_ENCODE'); // Set the first three bytes to the number and the fourth to the exponent. float32 = uint32(number << 8) | exponent; } function float32ToUint(uint32 float32) internal pure returns (uint256 number) { // Number is encoded on 4 bytes. 3 bytes for mantissa and 1 for exponent. // We get the exponent by extracting the last byte. uint256 exponent = float32 & 0xFF; // Sanity check. Only triggered for values not encoded with uintToFloat32. require(exponent <= 256 - 24, 'OS_OVERFLOW_FLOAT_DECODE'); // We get the mantissa by extracting the first three bytes and removing the fourth. uint256 mantissa = (float32 & 0xFFFFFF00) >> 8; // We add exponent number zeroes after the mantissa. number = mantissa << exponent; } function enqueueDepositOrder(Data storage data, DepositOrder memory depositOrder) internal { data.newestOrderId++; uint128 validAfterTimestamp = uint128(block.timestamp + data.delay); emit DepositEnqueued(data.newestOrderId, validAfterTimestamp, depositOrder.gasPrice); data.orderQueue[data.newestOrderId] = StoredOrder( DEPOSIT_TYPE, timestampToUint32(validAfterTimestamp), getUnwrapAndFailure(depositOrder.unwrap), timestampToUint32(depositOrder.deadline), uintToUint32(depositOrder.gasLimit), gasPriceToUint32(depositOrder.gasPrice), uintToUint112(depositOrder.initialRatio), uintToUint112(depositOrder.share0), uintToUint112(depositOrder.share1), depositOrder.pairId, depositOrder.to, uint32(depositOrder.minRatioChangeToSwap), uintToFloat32(depositOrder.minSwapPrice), uintToFloat32(depositOrder.maxSwapPrice) ); } function enqueueWithdrawOrder(Data storage data, WithdrawOrder memory withdrawOrder) internal { data.newestOrderId++; uint128 validAfterTimestamp = uint128(block.timestamp + data.delay); emit WithdrawEnqueued(data.newestOrderId, validAfterTimestamp, withdrawOrder.gasPrice); data.orderQueue[data.newestOrderId] = StoredOrder( WITHDRAW_TYPE, timestampToUint32(validAfterTimestamp), getUnwrapAndFailure(withdrawOrder.unwrap), timestampToUint32(withdrawOrder.deadline), uintToUint32(withdrawOrder.gasLimit), gasPriceToUint32(withdrawOrder.gasPrice), uintToUint112(withdrawOrder.liquidity), uintToUint112(withdrawOrder.amount0Min), uintToUint112(withdrawOrder.amount1Min), withdrawOrder.pairId, withdrawOrder.to, 0, // maxRatioChange 0, // minSwapPrice 0 // maxSwapPrice ); } function enqueueSellOrder(Data storage data, SellOrder memory sellOrder) internal { data.newestOrderId++; uint128 validAfterTimestamp = uint128(block.timestamp + data.delay); emit SellEnqueued(data.newestOrderId, validAfterTimestamp, sellOrder.gasPrice); data.orderQueue[data.newestOrderId] = StoredOrder( sellOrder.inverse ? SELL_INVERTED_TYPE : SELL_TYPE, timestampToUint32(validAfterTimestamp), getUnwrapAndFailure(sellOrder.unwrap), timestampToUint32(sellOrder.deadline), uintToUint32(sellOrder.gasLimit), gasPriceToUint32(sellOrder.gasPrice), 0, // liquidityOrRatio uintToUint112(sellOrder.shareIn), uintToUint112(sellOrder.amountOutMin), sellOrder.pairId, sellOrder.to, 0, // maxRatioChange 0, // minSwapPrice 0 // maxSwapPrice ); } function enqueueBuyOrder(Data storage data, BuyOrder memory buyOrder) internal { data.newestOrderId++; uint128 validAfterTimestamp = uint128(block.timestamp + data.delay); emit BuyEnqueued(data.newestOrderId, validAfterTimestamp, buyOrder.gasPrice); data.orderQueue[data.newestOrderId] = StoredOrder( buyOrder.inverse ? BUY_INVERTED_TYPE : BUY_TYPE, timestampToUint32(validAfterTimestamp), getUnwrapAndFailure(buyOrder.unwrap), timestampToUint32(buyOrder.deadline), uintToUint32(buyOrder.gasLimit), gasPriceToUint32(buyOrder.gasPrice), 0, // liquidityOrRatio uintToUint112(buyOrder.shareInMax), uintToUint112(buyOrder.amountOut), buyOrder.pairId, buyOrder.to, 0, // maxRatioChange 0, // minSwapPrice 0 // maxSwapPrice ); } function isRefundFailed(Data storage data, uint256 index) internal view returns (bool) { uint8 unwrapAndFailure = data.orderQueue[index].unwrapAndFailure; return unwrapAndFailure == UNWRAP_FAILED || unwrapAndFailure == KEEP_FAILED; } function markRefundFailed(Data storage data) internal { StoredOrder storage stored = data.orderQueue[data.lastProcessedOrderId]; stored.unwrapAndFailure = stored.unwrapAndFailure == UNWRAP_NOT_FAILED ? UNWRAP_FAILED : KEEP_FAILED; } function getNextOrder(Data storage data) internal view returns (OrderType orderType, uint256 validAfterTimestamp) { return getOrder(data, data.lastProcessedOrderId + 1); } function dequeueCanceledOrder(Data storage data) external { data.lastProcessedOrderId++; } function dequeueDepositOrder(Data storage data) external returns (DepositOrder memory order) { data.lastProcessedOrderId++; order = getDepositOrder(data, data.lastProcessedOrderId); } function dequeueWithdrawOrder(Data storage data) external returns (WithdrawOrder memory order) { data.lastProcessedOrderId++; order = getWithdrawOrder(data, data.lastProcessedOrderId); } function dequeueSellOrder(Data storage data) external returns (SellOrder memory order) { data.lastProcessedOrderId++; order = getSellOrder(data, data.lastProcessedOrderId); } function dequeueBuyOrder(Data storage data) external returns (BuyOrder memory order) { data.lastProcessedOrderId++; order = getBuyOrder(data, data.lastProcessedOrderId); } function forgetOrder(Data storage data, uint256 orderId) internal { delete data.orderQueue[orderId]; } function forgetLastProcessedOrder(Data storage data) internal { delete data.orderQueue[data.lastProcessedOrderId]; } struct DepositParams { address token0; address token1; uint256 amount0; uint256 amount1; uint256 initialRatio; uint256 minRatioChangeToSwap; uint256 minSwapPrice; uint256 maxSwapPrice; bool wrap; address to; uint256 gasLimit; uint256 submitDeadline; uint256 executionDeadline; } function deposit( Data storage data, DepositParams calldata depositParams, TokenShares.Data storage tokenShares ) external { require( data.transferGasCosts[depositParams.token0] != 0 && data.transferGasCosts[depositParams.token1] != 0, 'OS_TOKEN_TRANSFER_GAS_COST_UNSET' ); checkOrderParams( data, depositParams.to, depositParams.gasLimit, depositParams.submitDeadline, depositParams.executionDeadline, ORDER_BASE_COST.add(data.transferGasCosts[depositParams.token0]).add( data.transferGasCosts[depositParams.token1] ) ); require(depositParams.amount0 != 0 || depositParams.amount1 != 0, 'OS_NO_AMOUNT'); (address pair, uint32 pairId, bool inverted) = getPair(data, depositParams.token0, depositParams.token1); require(!data.depositDisabled[pair], 'OS_DEPOSIT_DISABLED'); uint256 value = msg.value; // allocate gas refund if (depositParams.token0 == tokenShares.weth && depositParams.wrap) { value = value.sub(depositParams.amount0, 'OS_NOT_ENOUGH_FUNDS'); } else if (depositParams.token1 == tokenShares.weth && depositParams.wrap) { value = value.sub(depositParams.amount1, 'OS_NOT_ENOUGH_FUNDS'); } allocateGasRefund(data, value, depositParams.gasLimit); uint256 shares0 = tokenShares.amountToShares(depositParams.token0, depositParams.amount0, depositParams.wrap); uint256 shares1 = tokenShares.amountToShares(depositParams.token1, depositParams.amount1, depositParams.wrap); IIntegralPair(pair).syncWithOracle(); enqueueDepositOrder( data, DepositOrder( pairId, inverted ? shares1 : shares0, inverted ? shares0 : shares1, depositParams.initialRatio, depositParams.minRatioChangeToSwap, depositParams.minSwapPrice, depositParams.maxSwapPrice, depositParams.wrap, depositParams.to, data.gasPrice, depositParams.gasLimit, depositParams.executionDeadline ) ); } struct WithdrawParams { address token0; address token1; uint256 liquidity; uint256 amount0Min; uint256 amount1Min; bool unwrap; address to; uint256 gasLimit; uint256 submitDeadline; uint256 executionDeadline; } function withdraw(Data storage data, WithdrawParams calldata withdrawParams) external { (address pair, uint32 pairId, bool inverted) = getPair(data, withdrawParams.token0, withdrawParams.token1); require(!data.withdrawDisabled[pair], 'OS_WITHDRAW_DISABLED'); checkOrderParams( data, withdrawParams.to, withdrawParams.gasLimit, withdrawParams.submitDeadline, withdrawParams.executionDeadline, ORDER_BASE_COST.add(PAIR_TRANSFER_COST) ); require(withdrawParams.liquidity != 0, 'OS_NO_LIQUIDITY'); allocateGasRefund(data, msg.value, withdrawParams.gasLimit); pair.safeTransferFrom(msg.sender, address(this), withdrawParams.liquidity); IIntegralPair(pair).syncWithOracle(); enqueueWithdrawOrder( data, WithdrawOrder( pairId, withdrawParams.liquidity, inverted ? withdrawParams.amount1Min : withdrawParams.amount0Min, inverted ? withdrawParams.amount0Min : withdrawParams.amount1Min, withdrawParams.unwrap, withdrawParams.to, data.gasPrice, withdrawParams.gasLimit, withdrawParams.executionDeadline ) ); } struct SellParams { address tokenIn; address tokenOut; uint256 amountIn; uint256 amountOutMin; bool wrapUnwrap; address to; uint256 gasLimit; uint256 submitDeadline; uint256 executionDeadline; } function sell( Data storage data, SellParams calldata sellParams, TokenShares.Data storage tokenShares ) external { require(data.transferGasCosts[sellParams.tokenIn] != 0, 'OS_TOKEN_TRANSFER_GAS_COST_UNSET'); checkOrderParams( data, sellParams.to, sellParams.gasLimit, sellParams.submitDeadline, sellParams.executionDeadline, ORDER_BASE_COST.add(data.transferGasCosts[sellParams.tokenIn]) ); require(sellParams.amountIn != 0, 'OS_NO_AMOUNT_IN'); (address pair, uint32 pairId, bool inverted) = getPair(data, sellParams.tokenIn, sellParams.tokenOut); require(!data.sellDisabled[pair], 'OS_SELL_DISABLED'); uint256 value = msg.value; // allocate gas refund if (sellParams.tokenIn == tokenShares.weth && sellParams.wrapUnwrap) { value = value.sub(sellParams.amountIn, 'OS_NOT_ENOUGH_FUNDS'); } allocateGasRefund(data, value, sellParams.gasLimit); uint256 shares = tokenShares.amountToShares(sellParams.tokenIn, sellParams.amountIn, sellParams.wrapUnwrap); IIntegralPair(pair).syncWithOracle(); enqueueSellOrder( data, SellOrder( pairId, inverted, shares, sellParams.amountOutMin, sellParams.wrapUnwrap, sellParams.to, data.gasPrice, sellParams.gasLimit, sellParams.executionDeadline ) ); } struct BuyParams { address tokenIn; address tokenOut; uint256 amountInMax; uint256 amountOut; bool wrapUnwrap; address to; uint256 gasLimit; uint256 submitDeadline; uint256 executionDeadline; } function buy( Data storage data, BuyParams calldata buyParams, TokenShares.Data storage tokenShares ) external { require(data.transferGasCosts[buyParams.tokenIn] != 0, 'OS_TOKEN_TRANSFER_GAS_COST_UNSET'); checkOrderParams( data, buyParams.to, buyParams.gasLimit, buyParams.submitDeadline, buyParams.executionDeadline, ORDER_BASE_COST.add(data.transferGasCosts[buyParams.tokenIn]) ); require(buyParams.amountOut != 0, 'OS_NO_AMOUNT_OUT'); (address pair, uint32 pairId, bool inverted) = getPair(data, buyParams.tokenIn, buyParams.tokenOut); require(!data.buyDisabled[pair], 'OS_BUY_DISABLED'); uint256 value = msg.value; // allocate gas refund if (buyParams.tokenIn == tokenShares.weth && buyParams.wrapUnwrap) { value = value.sub(buyParams.amountInMax, 'OS_NOT_ENOUGH_FUNDS'); } allocateGasRefund(data, value, buyParams.gasLimit); uint256 shares = tokenShares.amountToShares(buyParams.tokenIn, buyParams.amountInMax, buyParams.wrapUnwrap); IIntegralPair(pair).syncWithOracle(); enqueueBuyOrder( data, BuyOrder( pairId, inverted, shares, buyParams.amountOut, buyParams.wrapUnwrap, buyParams.to, data.gasPrice, buyParams.gasLimit, buyParams.executionDeadline ) ); } function checkOrderParams( Data storage data, address to, uint256 gasLimit, uint256 submitDeadline, uint256 executionDeadline, uint256 minGasLimit ) private view { require(submitDeadline >= block.timestamp, 'OS_EXPIRED'); require(executionDeadline > block.timestamp.add(data.delay), 'OS_INVALID_DEADLINE'); require(gasLimit <= data.maxGasLimit, 'OS_GAS_LIMIT_TOO_HIGH'); require(gasLimit >= minGasLimit, 'OS_GAS_LIMIT_TOO_LOW'); require(to != address(0), 'OS_NO_ADDRESS'); } function allocateGasRefund( Data storage data, uint256 value, uint256 gasLimit ) private returns (uint256 futureFee) { futureFee = data.gasPrice.mul(gasLimit); require(value >= futureFee, 'OS_NOT_ENOUGH_FUNDS'); if (value > futureFee) { msg.sender.transfer(value.sub(futureFee)); } } function updateGasPrice(Data storage data, uint256 gasUsed) external { uint256 scale = Math.min(gasUsed, data.maxGasPriceImpact); uint256 updated = data.gasPrice.mul(data.gasPriceInertia.sub(scale)).add(tx.gasprice.mul(scale)).div( data.gasPriceInertia ); // we lower the precision for gas savings in order queue data.gasPrice = updated - (updated % 1e6); } function setMaxGasLimit(Data storage data, uint256 _maxGasLimit) external { require(_maxGasLimit <= 10000000, 'OS_MAX_GAS_LIMIT_TOO_HIGH'); data.maxGasLimit = _maxGasLimit; emit MaxGasLimitSet(_maxGasLimit); } function setGasPriceInertia(Data storage data, uint256 _gasPriceInertia) external { require(_gasPriceInertia >= 1, 'OS_INVALID_INERTIA'); data.gasPriceInertia = _gasPriceInertia; emit GasPriceInertiaSet(_gasPriceInertia); } function setMaxGasPriceImpact(Data storage data, uint256 _maxGasPriceImpact) external { require(_maxGasPriceImpact <= data.gasPriceInertia, 'OS_INVALID_MAX_GAS_PRICE_IMPACT'); data.maxGasPriceImpact = _maxGasPriceImpact; emit MaxGasPriceImpactSet(_maxGasPriceImpact); } function setTransferGasCost( Data storage data, address token, uint256 gasCost ) external { data.transferGasCosts[token] = gasCost; emit TransferGasCostSet(token, gasCost); } }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; pragma experimental ABIEncoderV2; import 'Orders.sol'; interface IIntegralDelay { event OrderExecuted(uint256 indexed id, bool indexed success, bytes data, uint256 gasSpent, uint256 ethRefunded); event RefundFailed(address indexed to, address indexed token, uint256 amount, bytes data); event EthRefund(address indexed to, bool indexed success, uint256 value); event OwnerSet(address owner); event BotSet(address bot, bool isBot); event DelaySet(uint256 delay); event MaxGasLimitSet(uint256 maxGasLimit); event GasPriceInertiaSet(uint256 gasPriceInertia); event MaxGasPriceImpactSet(uint256 maxGasPriceImpact); event TransferGasCostSet(address token, uint256 gasCost); event OrderDisabled(address pair, Orders.OrderType orderType, bool disabled); event UnwrapFailed(address to, uint256 amount); event Execute(address sender, uint256 n); function factory() external returns (address); function owner() external returns (address); function isBot(address bot) external returns (bool); function botExecuteTime() external returns (uint256); function gasPriceInertia() external returns (uint256); function gasPrice() external returns (uint256); function maxGasPriceImpact() external returns (uint256); function maxGasLimit() external returns (uint256); function delay() external returns (uint256); function totalShares(address token) external returns (uint256); function weth() external returns (address); function getTransferGasCost(address token) external returns (uint256); function getDepositOrder(uint256 orderId) external returns (Orders.DepositOrder memory order); function getWithdrawOrder(uint256 orderId) external returns (Orders.WithdrawOrder memory order); function getSellOrder(uint256 orderId) external returns (Orders.SellOrder memory order); function getBuyOrder(uint256 orderId) external returns (Orders.BuyOrder memory order); function getDepositDisabled(address pair) external returns (bool); function getWithdrawDisabled(address pair) external returns (bool); function getBuyDisabled(address pair) external returns (bool); function getSellDisabled(address pair) external returns (bool); function getOrderStatus(uint256 orderId) external returns (Orders.OrderStatus); function setOrderDisabled( address pair, Orders.OrderType orderType, bool disabled ) external; function setOwner(address _owner) external; function setBot(address _bot, bool _isBot) external; function setMaxGasLimit(uint256 _maxGasLimit) external; function setDelay(uint256 _delay) external; function setGasPriceInertia(uint256 _gasPriceInertia) external; function setMaxGasPriceImpact(uint256 _maxGasPriceImpact) external; function setTransferGasCost(address token, uint256 gasCost) 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 buy(Orders.BuyParams memory buyParams) external payable returns (uint256 orderId); function execute(uint256 n) external; }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; interface IIntegralOracle { event OwnerSet(address owner); event UniswapPairSet(address uniswapPair); event PriceUpdateIntervalSet(uint32 interval); event ParametersSet(uint32 epoch, int256[] bidExponents, int256[] bidQs, int256[] askExponents, int256[] askQs); function owner() external view returns (address); function setOwner(address) external; function epoch() external view returns (uint32); function xDecimals() external view returns (uint8); function yDecimals() external view returns (uint8); function getParameters() external view returns ( int256[] memory bidExponents, int256[] memory bidQs, int256[] memory askExponents, int256[] memory askQs ); function setParameters( int256[] calldata bidExponents, int256[] calldata bidQs, int256[] calldata askExponents, int256[] calldata askQs ) external; function price() external view returns (int256); function priceUpdateInterval() external view returns (uint32); function updatePrice() external returns (uint32 _epoch); function setPriceUpdateInterval(uint32 interval) external; function price0CumulativeLast() external view returns (uint256); function blockTimestampLast() external view returns (uint32); function tradeX( uint256 xAfter, uint256 xBefore, uint256 yBefore ) external view returns (uint256 yAfter); function tradeY( uint256 yAfter, uint256 xBefore, uint256 yBefore ) external view returns (uint256 xAfter); function getSpotPrice(uint256 xCurrent, uint256 xBefore) external view returns (uint256 spotPrice); }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; import 'SafeMath.sol'; library Normalizer { using SafeMath for uint256; function normalize(uint256 amount, uint8 decimals) internal pure returns (uint256) { if (decimals == 18) { return amount; } else if (decimals > 18) { return amount.div(10**(decimals - 18)); } else { return amount.mul(10**(18 - decimals)); } } function denormalize(uint256 amount, uint8 decimals) internal pure returns (uint256) { if (decimals == 18) { return amount; } else if (decimals > 18) { return amount.mul(10**(decimals - 18)); } else { return amount.div(10**(18 - decimals)); } } }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; import 'TransferHelper.sol'; import 'SafeMath.sol'; import 'Math.sol'; import 'IIntegralPair.sol'; library AddLiquidity { using SafeMath for uint256; function _quote( uint256 amount0, uint256 reserve0, uint256 reserve1 ) private pure returns (uint256 amountB) { require(amount0 > 0, 'AL_INSUFFICIENT_AMOUNT'); require(reserve0 > 0 && reserve1 > 0, 'AL_INSUFFICIENT_LIQUIDITY'); amountB = amount0.mul(reserve1) / reserve0; } function addLiquidity( address pair, uint256 amount0Desired, uint256 amount1Desired ) external view returns (uint256 amount0, uint256 amount1) { if (amount0Desired == 0 || amount1Desired == 0) { return (0, 0); } (uint256 reserve0, uint256 reserve1, ) = IIntegralPair(pair).getReserves(); if (reserve0 == 0 && reserve1 == 0) { (amount0, amount1) = (amount0Desired, amount1Desired); } else { uint256 amount1Optimal = _quote(amount0Desired, reserve0, reserve1); if (amount1Optimal <= amount1Desired) { (amount0, amount1) = (amount0Desired, amount1Optimal); } else { uint256 amount0Optimal = _quote(amount1Desired, reserve1, reserve0); assert(amount0Optimal <= amount0Desired); (amount0, amount1) = (amount0Optimal, amount1Desired); } } } function swapDeposit0( address pair, address token0, uint256 amount0, uint256 minSwapPrice ) external returns (uint256 amount0Left, uint256 amount1Left) { uint256 amount0In = IIntegralPair(pair).getDepositAmount0In(amount0); amount1Left = IIntegralPair(pair).getSwapAmount1Out(amount0In); if (amount1Left == 0) { return (amount0, amount1Left); } uint256 price = amount1Left.mul(1e18).div(amount0In); require(minSwapPrice == 0 || price >= minSwapPrice, 'AL_PRICE_TOO_LOW'); TransferHelper.safeTransfer(token0, pair, amount0In); IIntegralPair(pair).swap(0, amount1Left, address(this)); amount0Left = amount0.sub(amount0In); } function swapDeposit1( address pair, address token1, uint256 amount1, uint256 maxSwapPrice ) external returns (uint256 amount0Left, uint256 amount1Left) { uint256 amount1In = IIntegralPair(pair).getDepositAmount1In(amount1); amount0Left = IIntegralPair(pair).getSwapAmount0Out(amount1In); if (amount0Left == 0) { return (amount0Left, amount1); } uint256 price = amount1In.mul(1e18).div(amount0Left); require(maxSwapPrice == 0 || price <= maxSwapPrice, 'AL_PRICE_TOO_HIGH'); TransferHelper.safeTransfer(token1, pair, amount1In); IIntegralPair(pair).swap(amount0Left, 0, address(this)); amount1Left = amount1.sub(amount1In); } function canSwap( uint256 initialRatio, // setting it to 0 disables swap uint256 minRatioChangeToSwap, address pairAddress ) external view returns (bool) { (uint256 reserve0, uint256 reserve1, ) = IIntegralPair(pairAddress).getReserves(); if (reserve0 == 0 || reserve1 == 0 || initialRatio == 0) { return false; } uint256 ratio = reserve0.mul(1e18).div(reserve1); // ratioChange(before, after) = MAX(before, after) / MIN(before, after) - 1 uint256 change = Math.max(initialRatio, ratio).mul(1e3).div(Math.min(initialRatio, ratio)).sub(1e3); return change >= minRatioChangeToSwap; } }
// SPDX-License-Identifier: GPL-3.0-or-later // Deployed with donations via Gitcoin GR9 pragma solidity 0.7.5; // pragma abicoder v2; import 'IIntegralOracle.sol'; import 'IIntegralPair.sol'; import 'SafeMath.sol'; library BuyHelper { using SafeMath for uint256; uint256 public constant PRECISION = 10**18; function getSwapAmount0In(address pair, uint256 amount1Out) external view returns (uint256 swapAmount0In) { (uint112 reserve0, uint112 reserve1, ) = IIntegralPair(pair).getReserves(); (uint112 reference0, uint112 reference1, ) = IIntegralPair(pair).getReferences(); uint256 balance1After = uint256(reserve1).sub(amount1Out); uint256 balance0After = IIntegralOracle(IIntegralPair(pair).oracle()).tradeY( balance1After, reference0, reference1 ); uint256 swapFee = IIntegralPair(pair).swapFee(); return balance0After.sub(uint256(reserve0)).mul(PRECISION).ceil_div(PRECISION.sub(swapFee)).add(1); } function getSwapAmount1In(address pair, uint256 amount0Out) external view returns (uint256 swapAmount1In) { (uint112 reserve0, uint112 reserve1, ) = IIntegralPair(pair).getReserves(); (uint112 reference0, uint112 reference1, ) = IIntegralPair(pair).getReferences(); uint256 balance0After = uint256(reserve0).sub(amount0Out); uint256 balance1After = IIntegralOracle(IIntegralPair(pair).oracle()).tradeX( balance0After, reference0, reference1 ); uint256 swapFee = IIntegralPair(pair).swapFee(); return balance1After.sub(uint256(reserve1)).mul(PRECISION).ceil_div(PRECISION.sub(swapFee)).add(1); } }
{ "libraries": { "IERC20.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IIntegralERC20.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IReserves.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IIntegralPair.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "SafeMath.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "Math.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IIntegralFactory.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IWETH.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "TransferHelper.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "TokenShares.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "Orders.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IIntegralDelay.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IIntegralOracle.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "Normalizer.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "AddLiquidity.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "BuyHelper.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" }, "IntegralDelay.sol": { "TokenShares": "0xc82938b53e0e190459ba4e3502bf26f194760183", "Orders": "0x7218D567b671E36c4e6B3257b8919196CF68ff5E", "AddLiquidity": "0x3A09FA6c7Cb82FC94c377087cF59eC9529094e61", "BuyHelper": "0x5d0434d41C77E4D9a858000f3939c0c4A05B0e26" } }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_weth","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":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"n","type":"uint256"}],"name":"Execute","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":"pair","type":"address"},{"indexed":false,"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"indexed":false,"internalType":"bool","name":"disabled","type":"bool"}],"name":"OrderDisabled","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":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"RefundFailed","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnwrapFailed","type":"event"},{"inputs":[],"name":"ORDER_CANCEL_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"internalType":"bool","name":"inverse","type":"bool"},{"internalType":"uint256","name":"shareInMax","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.BuyOrder","name":"buyOrder","type":"tuple"}],"name":"_executeBuy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"internalType":"uint256","name":"share0","type":"uint256"},{"internalType":"uint256","name":"share1","type":"uint256"},{"internalType":"uint256","name":"initialRatio","type":"uint256"},{"internalType":"uint256","name":"minRatioChangeToSwap","type":"uint256"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.DepositOrder","name":"depositOrder","type":"tuple"}],"name":"_executeDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"internalType":"bool","name":"inverse","type":"bool"},{"internalType":"uint256","name":"shareIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.SellOrder","name":"sellOrder","type":"tuple"}],"name":"_executeSell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"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":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.WithdrawOrder","name":"withdrawOrder","type":"tuple"}],"name":"_executeWithdraw","outputs":[],"stateMutability":"nonpayable","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":"nonpayable","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":"nonpayable","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":"nonpayable","type":"function"},{"inputs":[],"name":"botExecuteTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"uint256","name":"submitDeadline","type":"uint256"},{"internalType":"uint256","name":"executionDeadline","type":"uint256"}],"internalType":"struct Orders.BuyParams","name":"buyParams","type":"tuple"}],"name":"buy","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"cancelOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"initialRatio","type":"uint256"},{"internalType":"uint256","name":"minRatioChangeToSwap","type":"uint256"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"wrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"submitDeadline","type":"uint256"},{"internalType":"uint256","name":"executionDeadline","type":"uint256"}],"internalType":"struct Orders.DepositParams","name":"depositParams","type":"tuple"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"n","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","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":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"getBuyDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"getBuyOrder","outputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"internalType":"bool","name":"inverse","type":"bool"},{"internalType":"uint256","name":"shareInMax","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.BuyOrder","name":"order","type":"tuple"}],"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"}],"name":"getDepositOrder","outputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"internalType":"uint256","name":"share0","type":"uint256"},{"internalType":"uint256","name":"share1","type":"uint256"},{"internalType":"uint256","name":"initialRatio","type":"uint256"},{"internalType":"uint256","name":"minRatioChangeToSwap","type":"uint256"},{"internalType":"uint256","name":"minSwapPrice","type":"uint256"},{"internalType":"uint256","name":"maxSwapPrice","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.DepositOrder","name":"order","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"getOrder","outputs":[{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"validAfterTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","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":"uint256","name":"orderId","type":"uint256"}],"name":"getSellOrder","outputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"internalType":"bool","name":"inverse","type":"bool"},{"internalType":"uint256","name":"shareIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"unwrap","type":"bool"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.SellOrder","name":"order","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTransferGasCost","outputs":[{"internalType":"uint256","name":"gasCost","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"getWithdrawDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"getWithdrawOrder","outputs":[{"components":[{"internalType":"uint32","name":"pairId","type":"uint32"},{"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":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct Orders.WithdrawOrder","name":"order","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"view","type":"function"},{"inputs":[],"name":"maxGasPriceImpact","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"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":"uint256","name":"submitDeadline","type":"uint256"},{"internalType":"uint256","name":"executionDeadline","type":"uint256"}],"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":"uint256","name":"_delay","type":"uint256"}],"name":"setDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasPriceInertia","type":"uint256"}],"name":"setGasPriceInertia","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxGasLimit","type":"uint256"}],"name":"setMaxGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxGasPriceImpact","type":"uint256"}],"name":"setMaxGasPriceImpact","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"enum Orders.OrderType","name":"orderType","type":"uint8"},{"internalType":"bool","name":"disabled","type":"bool"}],"name":"setOrderDisabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"gasCost","type":"uint256"}],"name":"setTransferGasCost","outputs":[],"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":"view","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":"uint256","name":"submitDeadline","type":"uint256"},{"internalType":"uint256","name":"executionDeadline","type":"uint256"}],"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
608060405260016015553480156200001657600080fd5b5060405162005a9d38038062005a9d83398101604081905262000039916200010f565b600480546001600160a01b038086166001600160a01b031992831617909255601280549091163317905581166000908152601360205260409020805460ff19166001179055620f42403a063a03600655620000a2601083620000cd602090811b6200298f17901c565b505061012c600055506104b0601455624c4b406005556301312d00600755620f424060085562000158565b60019190910180546001600160a01b0319166001600160a01b03909216919091179055565b80516001600160a01b03811681146200010a57600080fd5b919050565b60008060006060848603121562000124578283fd5b6200012f84620000f2565b92506200013f60208501620000f2565b91506200014f60408501620000f2565b90509250925092565b61593580620001686000396000f3fe6080604052600436106102975760003560e01c8063945317131161015a578063d09ef241116100c1578063e5e7988e1161007a578063e5e7988e146107c0578063e6a0cc94146107e0578063f0aa61a3146107f5578063f968bc2a1461080a578063fe0d94c11461082a578063fe173b971461084a5761029e565b8063d09ef2411461070a578063d22e924214610738578063e085272f14610758578063e177246e1461076b578063e30a49931461078b578063e5b1be65146107a05761029e565b8063b800522611610113578063b800522614610660578063be58130414610675578063bf6b874e14610695578063c35930c3146106b5578063c45a0155146106d5578063c9cd9760146106ea5761029e565b806394531713146105a05780639718f627146105c0578063af482b58146105e0578063b1af1bda14610600578063b32ac93614610620578063b3756220146106405761029e565b806345fa8aae116101fe5780636a42b8f8116101b75780636a42b8f8146105015780636de3c67c1461051657806377632ec21461052b5780637f6a1caf1461054b578063814494701461056b5780638da5cb5b1461058b5761029e565b806345fa8aae1461043d5780634c0160161461046a578063514fcac71461048a57806354df6d74146104aa57806357a62a4f146104d75780635e45da23146104ec5761029e565b8063342aa8b511610250578063342aa8b51461037b578063390ce0d31461039b5780633bbac579146103c85780633ed76f17146103e85780633fc8cef31461040857806343133c4b1461042a5761029e565b806307ddd3bc146102a357806313af4035146102cc5780631776834a146102ee57806317818a5c1461030e57806320a68fab1461033b5780632da7cbfd146103685761029e565b3661029e57005b600080fd5b6102b66102b1366004614fc8565b61085f565b6040516102c391906154fe565b60405180910390f35b3480156102d857600080fd5b506102ec6102e7366004614a65565b61090a565b005b3480156102fa57600080fd5b506102ec610309366004614fda565b610990565b34801561031a57600080fd5b5061032e610329366004614fda565b610a27565b6040516102c3919061579c565b34801561034757600080fd5b5061035b610356366004614a65565b610ac2565b6040516102c391906152cf565b6102b6610376366004614e90565b610ae0565b34801561038757600080fd5b506102ec610396366004614bce565b610b46565b3480156103a757600080fd5b506103bb6103b6366004614fda565b610bd2565b6040516102c391906154ef565b3480156103d457600080fd5b5061035b6103e3366004614a65565b610c65565b3480156103f457600080fd5b506102ec610403366004614b0d565b610c7a565b34801561041457600080fd5b5061041d610c9a565b6040516102c391906151ad565b6102b6610438366004614d10565b610ca9565b34801561044957600080fd5b5061045d610458366004614fda565b610d0f565b6040516102c391906152ff565b34801561047657600080fd5b5061035b610485366004614a65565b610d9b565b34801561049657600080fd5b506102ec6104a5366004614fda565b610db9565b3480156104b657600080fd5b506104ca6104c5366004614fda565b610edd565b6040516102c391906156fc565b3480156104e357600080fd5b506102b6610f70565b3480156104f857600080fd5b506102b6610f76565b34801561050d57600080fd5b506102b6610f7c565b34801561052257600080fd5b506102b6610f82565b34801561053757600080fd5b5061035b610546366004614fda565b610f88565b34801561055757600080fd5b506102ec610566366004614c06565b610f9d565b34801561057757600080fd5b506102ec610586366004614d2c565b611123565b34801561059757600080fd5b5061041d6113ca565b3480156105ac57600080fd5b506102ec6105bb366004614fda565b6113d9565b3480156105cc57600080fd5b506102b66105db366004614a65565b61143d565b3480156105ec57600080fd5b5061035b6105fb366004614a65565b611458565b34801561060c57600080fd5b506103bb61061b366004614fda565b611476565b34801561062c57600080fd5b506102ec61063b366004614fda565b6114b8565b34801561064c57600080fd5b506102ec61065b366004614ea2565b61151c565b34801561066c57600080fd5b506102b6611715565b34801561068157600080fd5b506102ec610690366004614fda565b61171c565b3480156106a157600080fd5b506102b66106b0366004614a65565b6117ea565b3480156106c157600080fd5b506102ec6106d0366004614cd8565b611805565b3480156106e157600080fd5b5061041d611dab565b3480156106f657600080fd5b506102ec610705366004614acd565b611dba565b34801561071657600080fd5b5061072a610725366004614fda565b611de9565b6040516102c3929190615313565b34801561074457600080fd5b506102ec610753366004614c45565b611e7f565b6102b6610766366004614d10565b611f11565b34801561077757600080fd5b506102ec610786366004614fda565b611f76565b34801561079757600080fd5b506102b6611fdc565b3480156107ac57600080fd5b506102ec6107bb366004614b7c565b611fe2565b3480156107cc57600080fd5b5061035b6107db366004614a65565b6121ed565b3480156107ec57600080fd5b506102b661220b565b34801561080157600080fd5b506102b6612211565b34801561081657600080fd5b506102ec610825366004614cd8565b612217565b34801561083657600080fd5b506102ec610845366004614fda565b6126e3565b34801561085657600080fd5b506102b6612989565b600060155460011461088c5760405162461bcd60e51b81526004016108839061532e565b60405180910390fd5b60006015819055604051636587992160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e916365879921916108cb9190869060040161562c565b60006040518083038186803b1580156108e357600080fd5b505af41580156108f7573d6000803e3d6000fd5b5050600154925050506001601555919050565b6012546001600160a01b031633146109345760405162461bcd60e51b815260040161088390615434565b601280546001600160a01b0319166001600160a01b0383811691909117918290556040517f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe2926109859216906151ad565b60405180910390a150565b6012546001600160a01b031633146109ba5760405162461bcd60e51b815260040161088390615434565b604051636702eca360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e90636702eca3906109f49060009085906004016156da565b60006040518083038186803b158015610a0c57600080fd5b505af4158015610a20573d6000803e3d6000fd5b5050505050565b610a2f6147af565b604051634ce4436960e11b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906399c886d290610a699060009086906004016156da565b6101206040518083038186803b158015610a8257600080fd5b505af4158015610a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614f35565b90505b919050565b6001600160a01b03166000908152600d602052604090205460ff1690565b6000601554600114610b045760405162461bcd60e51b81526004016108839061532e565b60006015819055604051638f0e6bef60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e91638f0e6bef916108cb9190869060109060040161554a565b6012546001600160a01b03163314610b705760405162461bcd60e51b815260040161088390615434565b6001600160a01b03821660009081526013602052604090819020805460ff1916831515179055517f70af441dbb427737e6a5ef2cf5b664321011765ce1d19ce4a69cd024e69d4f2f90610bc69084908490615266565b60405180910390a15050565b610bda61480c565b60405163ac1ecdb360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063ac1ecdb390610c149060009086906004016156da565b6101206040518083038186803b158015610c2d57600080fd5b505af4158015610c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614cf4565b60136020526000908152604090205460ff1681565b610c8685878684611fe2565b610c9283878484611fe2565b505050505050565b6011546001600160a01b031690565b6000601554600114610ccd5760405162461bcd60e51b81526004016108839061532e565b6000601581905560405163758e99b360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9163758e99b3916108cb91908690601090600401615526565b604051634dc1ffe760e11b8152600090737218d567b671e36c4e6b3257b8919196cf68ff5e90639b83ffce90610d4b90849086906004016156da565b60206040518083038186803b158015610d6357600080fd5b505af4158015610d77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614c8c565b6001600160a01b03166000908152600f602052604090205460ff1690565b601554600114610ddb5760405162461bcd60e51b81526004016108839061532e565b6000601581905560405163317e626f60e21b81528190737218d567b671e36c4e6b3257b8919196cf68ff5e9063c5f989bc90610e1d90849087906004016156da565b604080518083038186803b158015610e3457600080fd5b505af4158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190614cab565b9150915042610e9062015180610e8a610e83610f7c565b85906129b4565b906129f0565b10610ead5760405162461bcd60e51b815260040161088390615388565b610eba8282856001612a40565b50506000908152600b60205260409020805460ff19166001908117909155601555565b610ee561486b565b60405163117d7ab160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063117d7ab190610f1f9060009086906004016156da565b6101806040518083038186803b158015610f3857600080fd5b505af4158015610f4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614dde565b60085490565b60055490565b60005490565b60075490565b6000908152600b602052604090205460ff1690565b6012546001600160a01b03163314610fc75760405162461bcd60e51b815260040161088390615434565b6000826004811115610fd557fe5b1415610ff35760405162461bcd60e51b8152600401610883906153b7565b600182600481111561100157fe5b1415611030576001600160a01b0383166000908152600c60205260409020805460ff19168215151790556110e3565b600282600481111561103e57fe5b141561106d576001600160a01b0383166000908152600d60205260409020805460ff19168215151790556110e3565b600382600481111561107b57fe5b14156110aa576001600160a01b0383166000908152600f60205260409020805460ff19168215151790556110e3565b60048260048111156110b857fe5b14156110e3576001600160a01b0383166000908152600e60205260409020805460ff19168215151790555b7f3d5726ff7c14d1fb7a71ac46100040a8b7a9edb7624e96b8abde4a15649fdf4983838360405161111693929190615281565b60405180910390a1505050565b3330146111425760405162461bcd60e51b815260040161088390615434565b4281610160015110156111675760405162461bcd60e51b8152600401610883906153e6565b6000806000806000611178866131c3565b9450945094509450945081600014158061119157508015155b801561124d575060608601516080870151875163ffffffff1660009081526009602052604090819020549051635c1941c160e11b8152733a09fa6c7cb82fc94c377087cf59ec9529094e619363b8328382936111fd93919290916001600160a01b03169060040161582b565b60206040518083038186803b15801561121557600080fd5b505af4158015611229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124d9190614c70565b1561138c5781156112f15760a0860151604051634f57f14d60e11b8152733a09fa6c7cb82fc94c377087cf59ec9529094e6191639eafe29a916112989189918991889160040161523d565b604080518083038186803b1580156112af57600080fd5b505af41580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e7919061500a565b909250905061138c565b801561138c5760c086015160405163aceb17df60e01b8152733a09fa6c7cb82fc94c377087cf59ec9529094e619163aceb17df916113379189918891879160040161523d565b604080518083038186803b15801561134e57600080fd5b505af4158015611362573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611386919061500a565b90925090505b811580159061139a57508015155b156113b8576113b28587610100015186868686613401565b90925090505b610c928661010001518585858561356f565b6012546001600160a01b031681565b6012546001600160a01b031633146114035760405162461bcd60e51b815260040161088390615434565b604051630fd1437d60e11b8152737218d567b671e36c4e6b3257b8919196cf68ff5e90631fa286fa906109f49060009085906004016156da565b6001600160a01b03166000908152600a602052604090205490565b6001600160a01b03166000908152600c602052604090205460ff1690565b61147e61480c565b6040516311c8197f60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906311c8197f90610c149060009086906004016156da565b6012546001600160a01b031633146114e25760405162461bcd60e51b815260040161088390615434565b60405163153cc2fd60e31b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063a9e617e8906109f49060009085906004016156da565b33301461153b5760405162461bcd60e51b815260040161088390615434565b4281610100015110156115605760405162461bcd60e51b8152600401610883906153e6565b8051604051630270f5c360e51b8152600091737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb8609161159d918591906004016156e8565b60606040518083038186803b1580156115b557600080fd5b505af41580156115c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ed9190614a81565b50509050806001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561162c57600080fd5b505af1158015611640573d6000803e3d6000fd5b505050506116538182846020015161358d565b600080826001600160a01b03166389afcb448560a001516040518263ffffffff1660e01b815260040161168691906151ad565b6040805180830381600087803b15801561169f57600080fd5b505af11580156116b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d7919061500a565b91509150836040015182101580156116f3575083606001518110155b61170f5760405162461bcd60e51b81526004016108839061545a565b50505050565b6201518081565b60155460011461173e5760405162461bcd60e51b81526004016108839061532e565b60006015819055604051631ae4f06f60e01b81528190737218d567b671e36c4e6b3257b8919196cf68ff5e90631ae4f06f9061178090849087906004016156da565b604080518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cf9190614cab565b915091506117e08282856000612a40565b5050600160155550565b6001600160a01b031660009081526010602052604090205490565b3330146118245760405162461bcd60e51b815260040161088390615434565b4281610100015110156118495760405162461bcd60e51b8152600401610883906153e6565b8051604051630270f5c360e51b815260009182918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb8609161188a918591906004016156e8565b60606040518083038186803b1580156118a257600080fd5b505af41580156118b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118da9190614a81565b92509250925060008085602001516118f35783836118f6565b82845b915091506000601073c82938b53e0e190459ba4e3502bf26f194760183636c5d9cf09091858a604001516040518463ffffffff1660e01b815260040161193e93929190615507565b60206040518083038186803b15801561195657600080fd5b505af415801561196a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198e9190614ff2565b90506000869050806001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156119d057600080fd5b505af11580156119e4573d6000803e3d6000fd5b5050505060008860200151611a8457606089015160405163049c271760e41b8152735d0434d41c77e4d9a858000f3939c0c4a05b0e26916349c2717091611a2f918c916004016151c1565b60206040518083038186803b158015611a4757600080fd5b505af4158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f9190614ff2565b611b10565b6060890151604051635ee8722f60e01b8152735d0434d41c77e4d9a858000f3939c0c4a05b0e2691635ee8722f91611ac0918c916004016151c1565b60206040518083038186803b158015611ad857600080fd5b505af4158015611aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b109190614ff2565b905080831015611b325760405162461bcd60e51b8152600401610883906154b8565b6000808a60200151611b4a5760008b60600151611b52565b8a6060015160005b91509150611b61878b8561358d565b6011546001600160a01b038781169116148015611b7f57508a608001515b15611d37576040516336cd320560e11b81526001600160a01b03851690636d9a640a90611bb49085908590309060040161582b565b600060405180830381600087803b158015611bce57600080fd5b505af1158015611be2573d6000803e3d6000fd5b505060115460608e0151604051632e1a7d4d60e01b81526001600160a01b039092169350632e1a7d4d9250611c19916004016154fe565b600060405180830381600087803b158015611c3357600080fd5b505af1158015611c47573d6000803e3d6000fd5b5050505060008b60a001516001600160a01b03168c6060015161271090604051611c70906151aa565b600060405180830381858888f193505050503d8060008114611cae576040519150601f19603f3d011682016040523d82523d6000602084013e611cb3565b606091505b5050905080611d315760a08c015160608d015160405163032b310f60e51b815273c82938b53e0e190459ba4e3502bf26f1947601839263656621e092611d00926010929190600401615507565b60006040518083038186803b158015611d1857600080fd5b505af4158015611d2c573d6000803e3d6000fd5b505050505b50611d9e565b60a08b01516040516336cd320560e11b81526001600160a01b03861691636d9a640a91611d6b91869186919060040161582b565b600060405180830381600087803b158015611d8557600080fd5b505af1158015611d99573d6000803e3d6000fd5b505050505b5050505050505050505050565b6004546001600160a01b031690565b333014611dd95760405162461bcd60e51b815260040161088390615434565b611de483838361358d565b505050565b60405163317e626f60e21b81526000908190737218d567b671e36c4e6b3257b8919196cf68ff5e9063c5f989bc90611e2790849087906004016156da565b604080518083038186803b158015611e3e57600080fd5b505af4158015611e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e769190614cab565b91509150915091565b6012546001600160a01b03163314611ea95760405162461bcd60e51b815260040161088390615434565b60405163b2456a0760e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063b2456a0790611ee59060009086908690600401615507565b60006040518083038186803b158015611efd57600080fd5b505af4158015610c92573d6000803e3d6000fd5b6000601554600114611f355760405162461bcd60e51b81526004016108839061532e565b6000601581905560405162c44ff160e31b8152737218d567b671e36c4e6b3257b8919196cf68ff5e916306227f88916108cb91908690601090600401615526565b6012546001600160a01b03163314611fa05760405162461bcd60e51b815260040161088390615434565b6000819055600481026014556040517f63e09f16584208fba1fc7ff64c62b00f07bec177c0d97ca6689891b1e77a35c7906109859083906154fe565b60015490565b3330146120015760405162461bcd60e51b815260040161088390615434565b6011546001600160a01b03858116911614801561201b5750805b1561214f576040516306c5d9cf60e41b815260009073c82938b53e0e190459ba4e3502bf26f19476018390636c5d9cf09061205f9060109089908890600401615507565b60206040518083038186803b15801561207757600080fd5b505af415801561208b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120af9190614ff2565b601154604051632e1a7d4d60e01b81529192506001600160a01b031690632e1a7d4d906120e09084906004016154fe565b600060405180830381600087803b1580156120fa57600080fd5b505af115801561210e573d6000803e3d6000fd5b50506040516001600160a01b038716925083156108fc02915083906000818181858888f19350505050158015612148573d6000803e3d6000fd5b505061170f565b6040516306c5d9cf60e41b81526121e8908590859073c82938b53e0e190459ba4e3502bf26f19476018390636c5d9cf0906121939060109086908a90600401615507565b60206040518083038186803b1580156121ab57600080fd5b505af41580156121bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e39190614ff2565b61358d565b61170f565b6001600160a01b03166000908152600e602052604090205460ff1690565b60025490565b60145481565b3330146122365760405162461bcd60e51b815260040161088390615434565b42816101000151101561225b5760405162461bcd60e51b8152600401610883906153e6565b8051604051630270f5c360e51b815260009182918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb8609161229c918591906004016156e8565b60606040518083038186803b1580156122b457600080fd5b505af41580156122c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ec9190614a81565b9250925092506000808560200151612305578383612308565b82845b915091506000601073c82938b53e0e190459ba4e3502bf26f194760183636c5d9cf09091858a604001516040518463ffffffff1660e01b815260040161235093929190615507565b60206040518083038186803b15801561236857600080fd5b505af415801561237c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a09190614ff2565b90506000869050806001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156123e257600080fd5b505af11580156123f6573d6000803e3d6000fd5b5050505061240584888461358d565b60008860200151612491576040516357db007f60e11b81526001600160a01b0383169063afb600fe9061243c9086906004016154fe565b60206040518083038186803b15801561245457600080fd5b505afa158015612468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248c9190614ff2565b61250d565b604051632e34fcc760e21b81526001600160a01b0383169063b8d3f31c906124bd9086906004016154fe565b60206040518083038186803b1580156124d557600080fd5b505afa1580156124e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250d9190614ff2565b905088606001518110156125335760405162461bcd60e51b815260040161088390615351565b6000808a602001516125475760008361254b565b8260005b60115491935091506001600160a01b03878116911614801561256e57508a608001515b15611d37576040516336cd320560e11b81526001600160a01b03851690636d9a640a906125a39085908590309060040161582b565b600060405180830381600087803b1580156125bd57600080fd5b505af11580156125d1573d6000803e3d6000fd5b5050601154604051632e1a7d4d60e01b81526001600160a01b039091169250632e1a7d4d91506126059086906004016154fe565b600060405180830381600087803b15801561261f57600080fd5b505af1158015612633573d6000803e3d6000fd5b5050505060008b60a001516001600160a01b03168461271090604051612658906151aa565b600060405180830381858888f193505050503d8060008114612696576040519150601f19603f3d011682016040523d82523d6000602084013e61269b565b606091505b5050905080611d315760a08c015160405163032b310f60e51b815273c82938b53e0e190459ba4e3502bf26f1947601839163656621e091611d00916010918990600401615507565b6015546001146127055760405162461bcd60e51b81526004016108839061532e565b60006015556040517f892cd8f5b436bd5fb7dac1f11aafb73345d892ba3e9fe09cd94d95ba84928e739061273c90339084906151c1565b60405180910390a160005a90506000805b838110156129045760025461276490600101610f88565b156127d6576040516305d4bd1160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906305d4bd11906127a1906000906004016154fe565b60006040518083038186803b1580156127b957600080fd5b505af41580156127cd573d6000803e3d6000fd5b505050506128fc565b6000806127e360006136e5565b909250905060008260048111156127f657fe5b14806128025750428110155b1561280e575050612904565b60145481014210158061283057503360009081526013602052604090205460ff165b8061286557506000805260136020527f8fa6efc3be94b5b348b21fea823fe8d100408cee9b7f90524494500445d8ff6c5460ff165b6128815760405162461bcd60e51b815260040161088390615434565b600193508382600481111561289257fe5b14156128a5576128a06136f9565b6128f9565b60028260048111156128b357fe5b14156128c1576128a06139ce565b60038260048111156128cf57fe5b14156128dd576128a0613c64565b60048260048111156128eb57fe5b14156128f9576128f9613ef8565b50505b60010161274d565b5080156117e057737218d567b671e36c4e6b3257b8919196cf68ff5e639db74df160006129325a86906129b4565b6040518363ffffffff1660e01b815260040161294f9291906156da565b60006040518083038186803b15801561296757600080fd5b505af415801561297b573d6000803e3d6000fd5b505050505050600160155550565b60065490565b60019190910180546001600160a01b0319166001600160a01b03909216919091179055565b60006129e983836040518060400160405280601081526020016f534d5f5355425f554e444552464c4f5760801b815250614069565b9392505050565b80820182811015612a3a576040805162461bcd60e51b815260206004820152600f60248201526e534d5f4144445f4f564552464c4f5760881b604482015290519081900360640190fd5b92915050565b600042612a51856301e133806129f0565b1090506001856004811115612a6257fe5b1415612c4157612a7061486b565b60405163117d7ab160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063117d7ab190612aaa9060009088906004016156da565b6101806040518083038186803b158015612ac357600080fd5b505af4158015612ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612afb9190614dde565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091612b3d918591906004016156e8565b60606040518083038186803b158015612b5557600080fd5b505af4158015612b69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8d9190614a81565b9250925050600084612ba457836101000151612bb1565b6012546001600160a01b03165b9050612bcd818486602001518588604001518960e00151614101565b612be95760405162461bcd60e51b81526004016108839061540a565b8515612c38576000612c0e85610140015186610120015161426890919063ffffffff16565b9050612c1a82826142c6565b612c365760405162461bcd60e51b81526004016108839061548a565b505b505050506131b8565b6002856004811115612c4f57fe5b1415612e1957612c5d6147af565b604051634ce4436960e11b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906399c886d290612c979060009088906004016156da565b6101206040518083038186803b158015612cb057600080fd5b505af4158015612cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce89190614f35565b8051604051630270f5c360e51b8152919250600091737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091612d279185916004016156e8565b60606040518083038186803b158015612d3f57600080fd5b505af4158015612d53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d779190614a81565b50509050600083612d8c578260a00151612d99565b6012546001600160a01b03165b9050612daa82828560200151614346565b612dc65760405162461bcd60e51b81526004016108839061540a565b8415612e11576000612de98460e001518560c0015161426890919063ffffffff16565b9050612df582826142c6565b612c385760405162461bcd60e51b81526004016108839061548a565b5050506131b8565b6003856004811115612e2757fe5b1415612fda57612e3561480c565b60405163ac1ecdb360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063ac1ecdb390612e6f9060009088906004016156da565b6101206040518083038186803b158015612e8857600080fd5b505af4158015612e9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ec09190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091612f02918591906004016156e8565b60606040518083038186803b158015612f1a57600080fd5b505af4158015612f2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f529190614a81565b9250925050600084612f68578360a00151612f75565b6012546001600160a01b03165b9050612f9b8460200151612f895783612f8b565b825b8286604001518760800151614456565b612fb75760405162461bcd60e51b81526004016108839061540a565b8515612c38576000612c0e8560e001518660c0015161426890919063ffffffff16565b6004856004811115612fe857fe5b14156131b857612ff661480c565b6040516311c8197f60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906311c8197f906130309060009088906004016156da565b6101206040518083038186803b15801561304957600080fd5b505af415801561305d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130819190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb860916130c3918591906004016156e8565b60606040518083038186803b1580156130db57600080fd5b505af41580156130ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131139190614a81565b9250925050600084613129578360a00151613136565b6012546001600160a01b03165b905061314a8460200151612f895783612f8b565b6131665760405162461bcd60e51b81526004016108839061540a565b85156131b35760006131898560e001518660c0015161426890919063ffffffff16565b905061319582826142c6565b6131b15760405162461bcd60e51b81526004016108839061548a565b505b505050505b610a20600084614576565b8051604051630270f5c360e51b81526000918291829182918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613208918591906004016156e8565b60606040518083038186803b15801561322057600080fd5b505af4158015613234573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132589190614a81565b60208901516040516306c5d9cf60e41b8152939850919650945060009173c82938b53e0e190459ba4e3502bf26f19476018391636c5d9cf0916132a3916010918a9190600401615507565b60206040518083038186803b1580156132bb57600080fd5b505af41580156132cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132f39190614ff2565b60408089015190516306c5d9cf60e41b815291925060009173c82938b53e0e190459ba4e3502bf26f19476018391636c5d9cf091613339916010918a9190600401615507565b60206040518083038186803b15801561335157600080fd5b505af4158015613365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133899190614ff2565b9050866001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156133c657600080fd5b505af11580156133da573d6000803e3d6000fd5b505050506133f18789610100015188888686613401565b9799969850949694959350505050565b600080600080733a09fa6c7cb82fc94c377087cf59ec9529094e616355776b778b88886040518463ffffffff1660e01b8152600401613442939291906152ae565b604080518083038186803b15801561345957600080fd5b505af415801561346d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613491919061500a565b9150915081600014806134a2575080155b156134b4578585935093505050613564565b6134bf888b8461358d565b6134ca878b8361358d565b6040516335313c2160e11b81526001600160a01b038b1690636a627842906134f6908c906004016151ad565b602060405180830381600087803b15801561351057600080fd5b505af1158015613524573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135489190614ff2565b5061355386836129b4565b935061355f85826129b4565b925050505b965096945050505050565b81156135805761358084868461358d565b8015610a2057610a208386835b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b178152925182516000946060949389169392918291908083835b6020831061360a5780518252601f1990920191602091820191016135eb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461366c576040519150601f19603f3d011682016040523d82523d6000602084013e613671565b606091505b509150915081801561369f57508051158061369f575080806020019051602081101561369c57600080fd5b50515b610a20576040805162461bcd60e51b8152602060048201526012602482015271151217d514905394d1915497d1905253115160721b604482015290519081900360640190fd5b600080611e76838460020154600101614597565b60005a905061370661486b565b60405163a81df10f60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063a81df10f9061373e906000906004016154fe565b6101806040518083038186803b15801561375757600080fd5b505af415801561376b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061378f9190614dde565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb860916137d1918591906004016156e8565b60606040518083038186803b1580156137e957600080fd5b505af41580156137fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138219190614a81565b6001600160a01b038082166000908152600a60205260408082205492851682528120549396509194509092506060913091613875916138699190610e8a9062010fe0906129f0565b610140880151906129b4565b604051630814494760e41b9061388f9089906024016156fc565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516138cd919061518e565b60006040518083038160008787f1925050503d806000811461390b576040519150601f19603f3d011682016040523d82523d6000602084013e613910565b606091505b50909250905060018261393f5761393c866101000151868860200151878a604001518b60e00151614101565b90505b806139535761394e60006145de565b61395d565b61395d6000614631565b60008061397b8861014001518961012001518b8b6101000151614656565b915091508415156000600201547ff0cc99aeb224e65869630a14e23683d20b9c535c00427b50024ce8b6b21d35c38685856040516139bb939291906152da565b60405180910390a3505050505050505050565b60005a90506139db6147af565b6040516313ed2f6160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906313ed2f6190613a13906000906004016154fe565b6101206040518083038186803b158015613a2c57600080fd5b505af4158015613a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a649190614f35565b8051604051630270f5c360e51b8152919250600091737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613aa39185916004016156e8565b60606040518083038186803b158015613abb57600080fd5b505af4158015613acf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af39190614a81565b5090915060009050606030613b1b613b1062010fe061d6d86129f0565b60e0870151906129b4565b60405163059bab1160e51b90613b3590889060240161579c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613b73919061518e565b60006040518083038160008787f1925050503d8060008114613bb1576040519150601f19603f3d011682016040523d82523d6000602084013e613bb6565b606091505b509092509050600182613bd957613bd6848660a001518760200151614346565b90505b80613bed57613be860006145de565b613bf7565b613bf76000614631565b600080613c128760e001518860c001518a8a60a00151614656565b915091508415156000600201547ff0cc99aeb224e65869630a14e23683d20b9c535c00427b50024ce8b6b21d35c3868585604051613c52939291906152da565b60405180910390a35050505050505050565b60005a9050613c7161480c565b604051632e9d30e160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e90632e9d30e190613ca9906000906004016154fe565b6101206040518083038186803b158015613cc257600080fd5b505af4158015613cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfa9190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613d3c918591906004016156e8565b60606040518083038186803b158015613d5457600080fd5b505af4158015613d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d8c9190614a81565b925092505060006060306001600160a01b0316613dec613de16000600a0160008960200151613dbb5788613dbd565b875b6001600160a01b0316815260208101919091526040016000205462010fe0906129f0565b60e0880151906129b4565b604051637cb45e1560e11b90613e069089906024016154ef565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613e44919061518e565b60006040518083038160008787f1925050503d8060008114613e82576040519150601f19603f3d011682016040523d82523d6000602084013e613e87565b606091505b509092509050600182613ebf57613ebc8660200151613ea65785613ea8565b845b8760a0015188604001518960800151614456565b90505b80613ed357613ece60006145de565b613edd565b613edd6000614631565b60008061397b8860e001518960c001518b8b60a00151614656565b60005a9050613f0561480c565b60405163a1ba139560e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063a1ba139590613f3d906000906004016154fe565b6101206040518083038186803b158015613f5657600080fd5b505af4158015613f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f8e9190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613fd0918591906004016156e8565b60606040518083038186803b158015613fe857600080fd5b505af4158015613ffc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140209190614a81565b925092505060006060306001600160a01b031661404f613de16000600a0160008960200151613dbb5788613dbd565b60405163c35930c360e01b90613e069089906024016154ef565b81830381848211156140f95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156140be5781810151838201526020016140a6565b50505050905090810190601f1680156140eb5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b6001600160a01b038381166000908152600a6020526040808220549288168252812054909182916060913091614136916129f0565b604051633ed76f1760e01b9061415a908d908d908d908d908d908d906024016151da565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051614198919061518e565b60006040518083038160008787f1925050503d80600081146141d6576040519150601f19603f3d011682016040523d82523d6000602084013e6141db565b606091505b50915091508161425c57876001600160a01b0316896001600160a01b03166000805160206158e08339815191528984604051614218929190615812565b60405180910390a3856001600160a01b0316896001600160a01b03166000805160206158e08339815191528784604051614253929190615812565b60405180910390a35b50979650505050505050565b60008115806142835750508082028282828161428057fe5b04145b612a3a576040805162461bcd60e51b815260206004820152600f60248201526e534d5f4d554c5f4f564552464c4f5760881b604482015290519081900360640190fd5b6000816142d557506001612a3a565b6040516001600160a01b0384169083156108fc029084906000818181858888f193505050509050801515836001600160a01b03167fdbef2fc26e7694e7a1c5a4801b1ad144136d149cf76f310a780689b4087f0ffe8460405161433891906154fe565b60405180910390a392915050565b600081614355575060016129e9565b60006060306001600160a01b031661d6d863c9cd976060e01b88888860006040516024016143869493929190615214565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516143c4919061518e565b60006040518083038160008787f1925050503d8060008114614402576040519150601f19603f3d011682016040523d82523d6000602084013e614407565b606091505b50915091508161444d57856001600160a01b0316856001600160a01b03166000805160206158e08339815191528684604051614444929190615812565b60405180910390a35b50949350505050565b6000826144655750600161456e565b6001600160a01b0385166000908152600a6020526040808220549051606091309163e5b1be6560e01b906144a3908b908b908b908b90602401615214565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516144e1919061518e565b60006040518083038160008787f1925050503d806000811461451f576040519150601f19603f3d011682016040523d82523d6000602084013e614524565b606091505b50915091508161456a57866001600160a01b0316866001600160a01b03166000805160206158e08339815191528784604051614561929190615812565b60405180910390a35b5090505b949350505050565b60009081526003909101602052604081208181556001810182905560020155565b60008181526003830160205260408120805482919060ff8116906145c590610100900463ffffffff166146ea565b92506145d38160ff16614729565b935050509250929050565b600281015460009081526003820160205260409020805465010000000000900460ff161561460d576003614610565b60025b815460ff91909116650100000000000265ff00000000001990911617905550565b6002808201546000908152600390920160205260408220828155600181018390550155565b600080806146648787614268565b905061467b610e74610e8a613908815a8a906129b4565b925060006146a08261469b6000600601548761426890919063ffffffff16565b614799565b90506146ac82826129b4565b92506146b833826142c6565b6146d45760405162461bcd60e51b81526004016108839061548a565b6146de85846142c6565b50505094509492505050565b600063ffffffff82811614156147035750600019610abd565b63ffffffff821661471657506000610abd565b5063ffffffff8116635fee57f001919050565b6000600182141561473c57506001610abd565b600282141561474d57506002610abd565b600382141561475e57506004610abd565b600482141561476f57506004610abd565b600582141561478057506003610abd565b600682141561479157506003610abd565b506000919050565b60008183106147a857816129e9565b5090919050565b604051806101200160405280600063ffffffff16815260200160008152602001600081526020016000815260200160001515815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b604051806101200160405280600063ffffffff168152602001600015158152602001600081526020016000815260200160001515815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b604051806101800160405280600063ffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160001515815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b8035610abd8161589a565b8051610abd8161589a565b8035610abd816158b2565b8051610abd816158b2565b600061012080838503121561491c578182fd5b6149258161584a565b91505061493182614a4f565b815261493f602083016148f3565b60208201526040820135604082015260608201356060820152614964608083016148f3565b608082015261497560a083016148dd565b60a082015260c082013560c082015260e082013560e082015261010080830135818301525092915050565b60006101208083850312156149b3578182fd5b6149bc8161584a565b9150506149c882614a5a565b81526149d6602083016148fe565b602082015260408201516040820152606082015160608201526149fb608083016148fe565b6080820152614a0c60a083016148e8565b60a082015260c082015160c082015260e082015160e082015261010080830151818301525092915050565b60006101208284031215614a49578081fd5b50919050565b8035610abd816158cd565b8051610abd816158cd565b600060208284031215614a76578081fd5b81356129e98161589a565b600080600060608486031215614a95578182fd5b8351614aa08161589a565b6020850151909350614ab18161589a565b6040850151909250614ac28161589a565b809150509250925092565b600080600060608486031215614ae1578081fd5b8335614aec8161589a565b92506020840135614afc8161589a565b929592945050506040919091013590565b60008060008060008060c08789031215614b25578384fd5b8635614b308161589a565b95506020870135614b408161589a565b9450604087013593506060870135614b578161589a565b92506080870135915060a0870135614b6e816158b2565b809150509295509295509295565b60008060008060808587031215614b91578182fd5b8435614b9c8161589a565b93506020850135614bac8161589a565b9250604085013591506060850135614bc3816158b2565b939692955090935050565b60008060408385031215614be0578182fd5b8235614beb8161589a565b91506020830135614bfb816158b2565b809150509250929050565b600080600060608486031215614c1a578081fd5b8335614c258161589a565b92506020840135614c35816158c0565b91506040840135614ac2816158b2565b60008060408385031215614c57578182fd5b8235614c628161589a565b946020939093013593505050565b600060208284031215614c81578081fd5b81516129e9816158b2565b600060208284031215614c9d578081fd5b8151600681106129e9578182fd5b60008060408385031215614cbd578182fd5b8251614cc8816158c0565b6020939093015192949293505050565b60006101208284031215614cea578081fd5b6129e98383614909565b60006101208284031215614d06578081fd5b6129e983836149a0565b60006101208284031215614d22578081fd5b6129e98383614a37565b6000610180808385031215614d3f578182fd5b614d488161584a565b9050614d5383614a4f565b81526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c0820152614d9d60e084016148f3565b60e0820152610100614db08185016148dd565b9082015261012083810135908201526101408084013590820152610160928301359281019290925250919050565b6000610180808385031215614df1578182fd5b614dfa8161584a565b9050614e0583614a5a565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152614e4f60e084016148fe565b60e0820152610100614e628185016148e8565b9082015261012083810151908201526101408084015190820152610160928301519281019290925250919050565b60006101a08284031215614a49578081fd5b6000610120808385031215614eb5578182fd5b614ebe8161584a565b9050614ec983614a4f565b8152602083013560208201526040830135604082015260608301356060820152614ef5608084016148f3565b6080820152614f0660a084016148dd565b60a082015260c083013560c082015260e083013560e08201526101008084013581830152508091505092915050565b6000610120808385031215614f48578182fd5b614f518161584a565b9050614f5c83614a5a565b8152602083015160208201526040830151604082015260608301516060820152614f88608084016148fe565b6080820152614f9960a084016148e8565b60a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b60006101408284031215614a49578081fd5b600060208284031215614feb578081fd5b5035919050565b600060208284031215615003578081fd5b5051919050565b6000806040838503121561501c578182fd5b505080516020909101519092909150565b6001600160a01b03169052565b15159052565b6000815180845261505881602086016020860161586e565b601f01601f19169290920160200192915050565b6005811061507657fe5b9052565b63ffffffff8151168252602081015115156020830152604081015160408301526060810151606083015260808101516150b6608084018261503a565b5060a08101516150c960a084018261502d565b5060c0818101519083015260e0808201519083015261010090810151910152565b80356150f58161589a565b6001600160a01b03168252602081013561510e8161589a565b61511b602084018261502d565b50604081013560408301526060810135606083015261513c608082016148f3565b615149608084018261503a565b5061515660a082016148dd565b61516360a084018261502d565b5060c0818101359083015260e0808201359083015261010090810135910152565b63ffffffff169052565b600082516151a081846020870161586e565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396871681529486166020860152604085019390935293166060830152608082019290925290151560a082015260c00190565b6001600160a01b0394851681529290931660208301526040820152901515606082015260800190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03841681526060810161529e602083018561506c565b8215156040830152949350505050565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b6000606082526152ed6060830186615040565b60208301949094525060400152919050565b602081016006831061530d57fe5b91905290565b60408101615321828561506c565b8260208301529392505050565b602080825260099082015268125117d313d0d2d15160ba1b604082015260600190565b6020808252601d908201527f49445f494e53554646494349454e545f4f55545055545f414d4f554e54000000604082015260600190565b602080825260159082015274125117d3d491115497d393d517d15610d151511151605a1b604082015260600190565b60208082526015908201527449445f494e56414c49445f4f524445525f5459504560581b604082015260600190565b6020808252600a9082015269125117d156141254915160b21b604082015260600190565b60208082526010908201526f125117d4915195539117d1905253115160821b604082015260600190565b6020808252600c908201526b24a22fa327a92124a22222a760a11b604082015260600190565b602080825260169082015275125117d25394d551919250d251539517d05353d5539560521b604082015260600190565b602080825260149082015273125117d1551217d4915195539117d1905253115160621b604082015260600190565b6020808252601c908201527f49445f494e53554646494349454e545f494e5055545f414d4f554e5400000000604082015260600190565b6101208101612a3a828461507a565b90815260200190565b9283526001600160a01b03919091166020830152604082015260600190565b838152610160810161553b60208301856150ea565b82610140830152949350505050565b8381526101e0810161556760208301615562866148dd565b61502d565b615573602085016148dd565b615580604084018261502d565b506040840135606083015260608401356080830152608084013560a083015260a084013560c083015260c084013560e083015261010060e0850135818401526155ca8186016148f3565b90506101206155db8185018361503a565b6155e68187016148dd565b9150506101406155f88185018361502d565b61016091508086013582850152506101808186013581850152808601356101a08501525050826101c0830152949350505050565b828152610160810161564460208301615562856148dd565b615650602084016148dd565b61565d604084018261502d565b506040830135606083015260608301356080830152608083013560a083015261568860a084016148f3565b61569560c084018261503a565b506156a260c084016148dd565b6156af60e084018261502d565b5061010060e08401358184015261012081850135818501528085013561014085015250509392505050565b918252602082015260400190565b91825263ffffffff16602082015260400190565b600061018082019050615710828451615184565b6020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015161575e60e084018261503a565b50610100808401516157728285018261502d565b50506101208381015190830152610140808401519083015261016092830151929091019190915290565b60006101208201905063ffffffff835116825260208301516020830152604083015160408301526060830151606083015260808301511515608083015260a08301516157eb60a084018261502d565b5060c083015160c083015260e083015160e083015261010080840151818401525092915050565b60008382526040602083015261456e6040830184615040565b92835260208301919091526001600160a01b0316604082015260600190565b60405181810167ffffffffffffffff8111828210171561586657fe5b604052919050565b60005b83811015615889578181015183820152602001615871565b8381111561170f5750506000910152565b6001600160a01b03811681146158af57600080fd5b50565b80151581146158af57600080fd5b600581106158af57600080fd5b63ffffffff811681146158af57600080fdfe786212e89f390a4c768f3b935b85e0ec2561a24b6f48cda3c4b48a996b211592a264697066735822122050c5be39f6e719197a07033de942e62df6a5b8c83eeee1e0ed943ade09a5d8b764736f6c63430007050033000000000000000000000000673662e97b05e001816c380ba5a628d2e29f55d1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000008971dc0105a22e54d81593af02167fc82af935e3
Deployed Bytecode
0x6080604052600436106102975760003560e01c8063945317131161015a578063d09ef241116100c1578063e5e7988e1161007a578063e5e7988e146107c0578063e6a0cc94146107e0578063f0aa61a3146107f5578063f968bc2a1461080a578063fe0d94c11461082a578063fe173b971461084a5761029e565b8063d09ef2411461070a578063d22e924214610738578063e085272f14610758578063e177246e1461076b578063e30a49931461078b578063e5b1be65146107a05761029e565b8063b800522611610113578063b800522614610660578063be58130414610675578063bf6b874e14610695578063c35930c3146106b5578063c45a0155146106d5578063c9cd9760146106ea5761029e565b806394531713146105a05780639718f627146105c0578063af482b58146105e0578063b1af1bda14610600578063b32ac93614610620578063b3756220146106405761029e565b806345fa8aae116101fe5780636a42b8f8116101b75780636a42b8f8146105015780636de3c67c1461051657806377632ec21461052b5780637f6a1caf1461054b578063814494701461056b5780638da5cb5b1461058b5761029e565b806345fa8aae1461043d5780634c0160161461046a578063514fcac71461048a57806354df6d74146104aa57806357a62a4f146104d75780635e45da23146104ec5761029e565b8063342aa8b511610250578063342aa8b51461037b578063390ce0d31461039b5780633bbac579146103c85780633ed76f17146103e85780633fc8cef31461040857806343133c4b1461042a5761029e565b806307ddd3bc146102a357806313af4035146102cc5780631776834a146102ee57806317818a5c1461030e57806320a68fab1461033b5780632da7cbfd146103685761029e565b3661029e57005b600080fd5b6102b66102b1366004614fc8565b61085f565b6040516102c391906154fe565b60405180910390f35b3480156102d857600080fd5b506102ec6102e7366004614a65565b61090a565b005b3480156102fa57600080fd5b506102ec610309366004614fda565b610990565b34801561031a57600080fd5b5061032e610329366004614fda565b610a27565b6040516102c3919061579c565b34801561034757600080fd5b5061035b610356366004614a65565b610ac2565b6040516102c391906152cf565b6102b6610376366004614e90565b610ae0565b34801561038757600080fd5b506102ec610396366004614bce565b610b46565b3480156103a757600080fd5b506103bb6103b6366004614fda565b610bd2565b6040516102c391906154ef565b3480156103d457600080fd5b5061035b6103e3366004614a65565b610c65565b3480156103f457600080fd5b506102ec610403366004614b0d565b610c7a565b34801561041457600080fd5b5061041d610c9a565b6040516102c391906151ad565b6102b6610438366004614d10565b610ca9565b34801561044957600080fd5b5061045d610458366004614fda565b610d0f565b6040516102c391906152ff565b34801561047657600080fd5b5061035b610485366004614a65565b610d9b565b34801561049657600080fd5b506102ec6104a5366004614fda565b610db9565b3480156104b657600080fd5b506104ca6104c5366004614fda565b610edd565b6040516102c391906156fc565b3480156104e357600080fd5b506102b6610f70565b3480156104f857600080fd5b506102b6610f76565b34801561050d57600080fd5b506102b6610f7c565b34801561052257600080fd5b506102b6610f82565b34801561053757600080fd5b5061035b610546366004614fda565b610f88565b34801561055757600080fd5b506102ec610566366004614c06565b610f9d565b34801561057757600080fd5b506102ec610586366004614d2c565b611123565b34801561059757600080fd5b5061041d6113ca565b3480156105ac57600080fd5b506102ec6105bb366004614fda565b6113d9565b3480156105cc57600080fd5b506102b66105db366004614a65565b61143d565b3480156105ec57600080fd5b5061035b6105fb366004614a65565b611458565b34801561060c57600080fd5b506103bb61061b366004614fda565b611476565b34801561062c57600080fd5b506102ec61063b366004614fda565b6114b8565b34801561064c57600080fd5b506102ec61065b366004614ea2565b61151c565b34801561066c57600080fd5b506102b6611715565b34801561068157600080fd5b506102ec610690366004614fda565b61171c565b3480156106a157600080fd5b506102b66106b0366004614a65565b6117ea565b3480156106c157600080fd5b506102ec6106d0366004614cd8565b611805565b3480156106e157600080fd5b5061041d611dab565b3480156106f657600080fd5b506102ec610705366004614acd565b611dba565b34801561071657600080fd5b5061072a610725366004614fda565b611de9565b6040516102c3929190615313565b34801561074457600080fd5b506102ec610753366004614c45565b611e7f565b6102b6610766366004614d10565b611f11565b34801561077757600080fd5b506102ec610786366004614fda565b611f76565b34801561079757600080fd5b506102b6611fdc565b3480156107ac57600080fd5b506102ec6107bb366004614b7c565b611fe2565b3480156107cc57600080fd5b5061035b6107db366004614a65565b6121ed565b3480156107ec57600080fd5b506102b661220b565b34801561080157600080fd5b506102b6612211565b34801561081657600080fd5b506102ec610825366004614cd8565b612217565b34801561083657600080fd5b506102ec610845366004614fda565b6126e3565b34801561085657600080fd5b506102b6612989565b600060155460011461088c5760405162461bcd60e51b81526004016108839061532e565b60405180910390fd5b60006015819055604051636587992160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e916365879921916108cb9190869060040161562c565b60006040518083038186803b1580156108e357600080fd5b505af41580156108f7573d6000803e3d6000fd5b5050600154925050506001601555919050565b6012546001600160a01b031633146109345760405162461bcd60e51b815260040161088390615434565b601280546001600160a01b0319166001600160a01b0383811691909117918290556040517f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe2926109859216906151ad565b60405180910390a150565b6012546001600160a01b031633146109ba5760405162461bcd60e51b815260040161088390615434565b604051636702eca360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e90636702eca3906109f49060009085906004016156da565b60006040518083038186803b158015610a0c57600080fd5b505af4158015610a20573d6000803e3d6000fd5b5050505050565b610a2f6147af565b604051634ce4436960e11b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906399c886d290610a699060009086906004016156da565b6101206040518083038186803b158015610a8257600080fd5b505af4158015610a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614f35565b90505b919050565b6001600160a01b03166000908152600d602052604090205460ff1690565b6000601554600114610b045760405162461bcd60e51b81526004016108839061532e565b60006015819055604051638f0e6bef60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e91638f0e6bef916108cb9190869060109060040161554a565b6012546001600160a01b03163314610b705760405162461bcd60e51b815260040161088390615434565b6001600160a01b03821660009081526013602052604090819020805460ff1916831515179055517f70af441dbb427737e6a5ef2cf5b664321011765ce1d19ce4a69cd024e69d4f2f90610bc69084908490615266565b60405180910390a15050565b610bda61480c565b60405163ac1ecdb360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063ac1ecdb390610c149060009086906004016156da565b6101206040518083038186803b158015610c2d57600080fd5b505af4158015610c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614cf4565b60136020526000908152604090205460ff1681565b610c8685878684611fe2565b610c9283878484611fe2565b505050505050565b6011546001600160a01b031690565b6000601554600114610ccd5760405162461bcd60e51b81526004016108839061532e565b6000601581905560405163758e99b360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9163758e99b3916108cb91908690601090600401615526565b604051634dc1ffe760e11b8152600090737218d567b671e36c4e6b3257b8919196cf68ff5e90639b83ffce90610d4b90849086906004016156da565b60206040518083038186803b158015610d6357600080fd5b505af4158015610d77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614c8c565b6001600160a01b03166000908152600f602052604090205460ff1690565b601554600114610ddb5760405162461bcd60e51b81526004016108839061532e565b6000601581905560405163317e626f60e21b81528190737218d567b671e36c4e6b3257b8919196cf68ff5e9063c5f989bc90610e1d90849087906004016156da565b604080518083038186803b158015610e3457600080fd5b505af4158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190614cab565b9150915042610e9062015180610e8a610e83610f7c565b85906129b4565b906129f0565b10610ead5760405162461bcd60e51b815260040161088390615388565b610eba8282856001612a40565b50506000908152600b60205260409020805460ff19166001908117909155601555565b610ee561486b565b60405163117d7ab160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063117d7ab190610f1f9060009086906004016156da565b6101806040518083038186803b158015610f3857600080fd5b505af4158015610f4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba9190614dde565b60085490565b60055490565b60005490565b60075490565b6000908152600b602052604090205460ff1690565b6012546001600160a01b03163314610fc75760405162461bcd60e51b815260040161088390615434565b6000826004811115610fd557fe5b1415610ff35760405162461bcd60e51b8152600401610883906153b7565b600182600481111561100157fe5b1415611030576001600160a01b0383166000908152600c60205260409020805460ff19168215151790556110e3565b600282600481111561103e57fe5b141561106d576001600160a01b0383166000908152600d60205260409020805460ff19168215151790556110e3565b600382600481111561107b57fe5b14156110aa576001600160a01b0383166000908152600f60205260409020805460ff19168215151790556110e3565b60048260048111156110b857fe5b14156110e3576001600160a01b0383166000908152600e60205260409020805460ff19168215151790555b7f3d5726ff7c14d1fb7a71ac46100040a8b7a9edb7624e96b8abde4a15649fdf4983838360405161111693929190615281565b60405180910390a1505050565b3330146111425760405162461bcd60e51b815260040161088390615434565b4281610160015110156111675760405162461bcd60e51b8152600401610883906153e6565b6000806000806000611178866131c3565b9450945094509450945081600014158061119157508015155b801561124d575060608601516080870151875163ffffffff1660009081526009602052604090819020549051635c1941c160e11b8152733a09fa6c7cb82fc94c377087cf59ec9529094e619363b8328382936111fd93919290916001600160a01b03169060040161582b565b60206040518083038186803b15801561121557600080fd5b505af4158015611229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124d9190614c70565b1561138c5781156112f15760a0860151604051634f57f14d60e11b8152733a09fa6c7cb82fc94c377087cf59ec9529094e6191639eafe29a916112989189918991889160040161523d565b604080518083038186803b1580156112af57600080fd5b505af41580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e7919061500a565b909250905061138c565b801561138c5760c086015160405163aceb17df60e01b8152733a09fa6c7cb82fc94c377087cf59ec9529094e619163aceb17df916113379189918891879160040161523d565b604080518083038186803b15801561134e57600080fd5b505af4158015611362573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611386919061500a565b90925090505b811580159061139a57508015155b156113b8576113b28587610100015186868686613401565b90925090505b610c928661010001518585858561356f565b6012546001600160a01b031681565b6012546001600160a01b031633146114035760405162461bcd60e51b815260040161088390615434565b604051630fd1437d60e11b8152737218d567b671e36c4e6b3257b8919196cf68ff5e90631fa286fa906109f49060009085906004016156da565b6001600160a01b03166000908152600a602052604090205490565b6001600160a01b03166000908152600c602052604090205460ff1690565b61147e61480c565b6040516311c8197f60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906311c8197f90610c149060009086906004016156da565b6012546001600160a01b031633146114e25760405162461bcd60e51b815260040161088390615434565b60405163153cc2fd60e31b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063a9e617e8906109f49060009085906004016156da565b33301461153b5760405162461bcd60e51b815260040161088390615434565b4281610100015110156115605760405162461bcd60e51b8152600401610883906153e6565b8051604051630270f5c360e51b8152600091737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb8609161159d918591906004016156e8565b60606040518083038186803b1580156115b557600080fd5b505af41580156115c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ed9190614a81565b50509050806001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561162c57600080fd5b505af1158015611640573d6000803e3d6000fd5b505050506116538182846020015161358d565b600080826001600160a01b03166389afcb448560a001516040518263ffffffff1660e01b815260040161168691906151ad565b6040805180830381600087803b15801561169f57600080fd5b505af11580156116b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d7919061500a565b91509150836040015182101580156116f3575083606001518110155b61170f5760405162461bcd60e51b81526004016108839061545a565b50505050565b6201518081565b60155460011461173e5760405162461bcd60e51b81526004016108839061532e565b60006015819055604051631ae4f06f60e01b81528190737218d567b671e36c4e6b3257b8919196cf68ff5e90631ae4f06f9061178090849087906004016156da565b604080518083038186803b15801561179757600080fd5b505af41580156117ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117cf9190614cab565b915091506117e08282856000612a40565b5050600160155550565b6001600160a01b031660009081526010602052604090205490565b3330146118245760405162461bcd60e51b815260040161088390615434565b4281610100015110156118495760405162461bcd60e51b8152600401610883906153e6565b8051604051630270f5c360e51b815260009182918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb8609161188a918591906004016156e8565b60606040518083038186803b1580156118a257600080fd5b505af41580156118b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118da9190614a81565b92509250925060008085602001516118f35783836118f6565b82845b915091506000601073c82938b53e0e190459ba4e3502bf26f194760183636c5d9cf09091858a604001516040518463ffffffff1660e01b815260040161193e93929190615507565b60206040518083038186803b15801561195657600080fd5b505af415801561196a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198e9190614ff2565b90506000869050806001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156119d057600080fd5b505af11580156119e4573d6000803e3d6000fd5b5050505060008860200151611a8457606089015160405163049c271760e41b8152735d0434d41c77e4d9a858000f3939c0c4a05b0e26916349c2717091611a2f918c916004016151c1565b60206040518083038186803b158015611a4757600080fd5b505af4158015611a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7f9190614ff2565b611b10565b6060890151604051635ee8722f60e01b8152735d0434d41c77e4d9a858000f3939c0c4a05b0e2691635ee8722f91611ac0918c916004016151c1565b60206040518083038186803b158015611ad857600080fd5b505af4158015611aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b109190614ff2565b905080831015611b325760405162461bcd60e51b8152600401610883906154b8565b6000808a60200151611b4a5760008b60600151611b52565b8a6060015160005b91509150611b61878b8561358d565b6011546001600160a01b038781169116148015611b7f57508a608001515b15611d37576040516336cd320560e11b81526001600160a01b03851690636d9a640a90611bb49085908590309060040161582b565b600060405180830381600087803b158015611bce57600080fd5b505af1158015611be2573d6000803e3d6000fd5b505060115460608e0151604051632e1a7d4d60e01b81526001600160a01b039092169350632e1a7d4d9250611c19916004016154fe565b600060405180830381600087803b158015611c3357600080fd5b505af1158015611c47573d6000803e3d6000fd5b5050505060008b60a001516001600160a01b03168c6060015161271090604051611c70906151aa565b600060405180830381858888f193505050503d8060008114611cae576040519150601f19603f3d011682016040523d82523d6000602084013e611cb3565b606091505b5050905080611d315760a08c015160608d015160405163032b310f60e51b815273c82938b53e0e190459ba4e3502bf26f1947601839263656621e092611d00926010929190600401615507565b60006040518083038186803b158015611d1857600080fd5b505af4158015611d2c573d6000803e3d6000fd5b505050505b50611d9e565b60a08b01516040516336cd320560e11b81526001600160a01b03861691636d9a640a91611d6b91869186919060040161582b565b600060405180830381600087803b158015611d8557600080fd5b505af1158015611d99573d6000803e3d6000fd5b505050505b5050505050505050505050565b6004546001600160a01b031690565b333014611dd95760405162461bcd60e51b815260040161088390615434565b611de483838361358d565b505050565b60405163317e626f60e21b81526000908190737218d567b671e36c4e6b3257b8919196cf68ff5e9063c5f989bc90611e2790849087906004016156da565b604080518083038186803b158015611e3e57600080fd5b505af4158015611e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e769190614cab565b91509150915091565b6012546001600160a01b03163314611ea95760405162461bcd60e51b815260040161088390615434565b60405163b2456a0760e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063b2456a0790611ee59060009086908690600401615507565b60006040518083038186803b158015611efd57600080fd5b505af4158015610c92573d6000803e3d6000fd5b6000601554600114611f355760405162461bcd60e51b81526004016108839061532e565b6000601581905560405162c44ff160e31b8152737218d567b671e36c4e6b3257b8919196cf68ff5e916306227f88916108cb91908690601090600401615526565b6012546001600160a01b03163314611fa05760405162461bcd60e51b815260040161088390615434565b6000819055600481026014556040517f63e09f16584208fba1fc7ff64c62b00f07bec177c0d97ca6689891b1e77a35c7906109859083906154fe565b60015490565b3330146120015760405162461bcd60e51b815260040161088390615434565b6011546001600160a01b03858116911614801561201b5750805b1561214f576040516306c5d9cf60e41b815260009073c82938b53e0e190459ba4e3502bf26f19476018390636c5d9cf09061205f9060109089908890600401615507565b60206040518083038186803b15801561207757600080fd5b505af415801561208b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120af9190614ff2565b601154604051632e1a7d4d60e01b81529192506001600160a01b031690632e1a7d4d906120e09084906004016154fe565b600060405180830381600087803b1580156120fa57600080fd5b505af115801561210e573d6000803e3d6000fd5b50506040516001600160a01b038716925083156108fc02915083906000818181858888f19350505050158015612148573d6000803e3d6000fd5b505061170f565b6040516306c5d9cf60e41b81526121e8908590859073c82938b53e0e190459ba4e3502bf26f19476018390636c5d9cf0906121939060109086908a90600401615507565b60206040518083038186803b1580156121ab57600080fd5b505af41580156121bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e39190614ff2565b61358d565b61170f565b6001600160a01b03166000908152600e602052604090205460ff1690565b60025490565b60145481565b3330146122365760405162461bcd60e51b815260040161088390615434565b42816101000151101561225b5760405162461bcd60e51b8152600401610883906153e6565b8051604051630270f5c360e51b815260009182918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb8609161229c918591906004016156e8565b60606040518083038186803b1580156122b457600080fd5b505af41580156122c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ec9190614a81565b9250925092506000808560200151612305578383612308565b82845b915091506000601073c82938b53e0e190459ba4e3502bf26f194760183636c5d9cf09091858a604001516040518463ffffffff1660e01b815260040161235093929190615507565b60206040518083038186803b15801561236857600080fd5b505af415801561237c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a09190614ff2565b90506000869050806001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156123e257600080fd5b505af11580156123f6573d6000803e3d6000fd5b5050505061240584888461358d565b60008860200151612491576040516357db007f60e11b81526001600160a01b0383169063afb600fe9061243c9086906004016154fe565b60206040518083038186803b15801561245457600080fd5b505afa158015612468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248c9190614ff2565b61250d565b604051632e34fcc760e21b81526001600160a01b0383169063b8d3f31c906124bd9086906004016154fe565b60206040518083038186803b1580156124d557600080fd5b505afa1580156124e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250d9190614ff2565b905088606001518110156125335760405162461bcd60e51b815260040161088390615351565b6000808a602001516125475760008361254b565b8260005b60115491935091506001600160a01b03878116911614801561256e57508a608001515b15611d37576040516336cd320560e11b81526001600160a01b03851690636d9a640a906125a39085908590309060040161582b565b600060405180830381600087803b1580156125bd57600080fd5b505af11580156125d1573d6000803e3d6000fd5b5050601154604051632e1a7d4d60e01b81526001600160a01b039091169250632e1a7d4d91506126059086906004016154fe565b600060405180830381600087803b15801561261f57600080fd5b505af1158015612633573d6000803e3d6000fd5b5050505060008b60a001516001600160a01b03168461271090604051612658906151aa565b600060405180830381858888f193505050503d8060008114612696576040519150601f19603f3d011682016040523d82523d6000602084013e61269b565b606091505b5050905080611d315760a08c015160405163032b310f60e51b815273c82938b53e0e190459ba4e3502bf26f1947601839163656621e091611d00916010918990600401615507565b6015546001146127055760405162461bcd60e51b81526004016108839061532e565b60006015556040517f892cd8f5b436bd5fb7dac1f11aafb73345d892ba3e9fe09cd94d95ba84928e739061273c90339084906151c1565b60405180910390a160005a90506000805b838110156129045760025461276490600101610f88565b156127d6576040516305d4bd1160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906305d4bd11906127a1906000906004016154fe565b60006040518083038186803b1580156127b957600080fd5b505af41580156127cd573d6000803e3d6000fd5b505050506128fc565b6000806127e360006136e5565b909250905060008260048111156127f657fe5b14806128025750428110155b1561280e575050612904565b60145481014210158061283057503360009081526013602052604090205460ff165b8061286557506000805260136020527f8fa6efc3be94b5b348b21fea823fe8d100408cee9b7f90524494500445d8ff6c5460ff165b6128815760405162461bcd60e51b815260040161088390615434565b600193508382600481111561289257fe5b14156128a5576128a06136f9565b6128f9565b60028260048111156128b357fe5b14156128c1576128a06139ce565b60038260048111156128cf57fe5b14156128dd576128a0613c64565b60048260048111156128eb57fe5b14156128f9576128f9613ef8565b50505b60010161274d565b5080156117e057737218d567b671e36c4e6b3257b8919196cf68ff5e639db74df160006129325a86906129b4565b6040518363ffffffff1660e01b815260040161294f9291906156da565b60006040518083038186803b15801561296757600080fd5b505af415801561297b573d6000803e3d6000fd5b505050505050600160155550565b60065490565b60019190910180546001600160a01b0319166001600160a01b03909216919091179055565b60006129e983836040518060400160405280601081526020016f534d5f5355425f554e444552464c4f5760801b815250614069565b9392505050565b80820182811015612a3a576040805162461bcd60e51b815260206004820152600f60248201526e534d5f4144445f4f564552464c4f5760881b604482015290519081900360640190fd5b92915050565b600042612a51856301e133806129f0565b1090506001856004811115612a6257fe5b1415612c4157612a7061486b565b60405163117d7ab160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063117d7ab190612aaa9060009088906004016156da565b6101806040518083038186803b158015612ac357600080fd5b505af4158015612ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612afb9190614dde565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091612b3d918591906004016156e8565b60606040518083038186803b158015612b5557600080fd5b505af4158015612b69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8d9190614a81565b9250925050600084612ba457836101000151612bb1565b6012546001600160a01b03165b9050612bcd818486602001518588604001518960e00151614101565b612be95760405162461bcd60e51b81526004016108839061540a565b8515612c38576000612c0e85610140015186610120015161426890919063ffffffff16565b9050612c1a82826142c6565b612c365760405162461bcd60e51b81526004016108839061548a565b505b505050506131b8565b6002856004811115612c4f57fe5b1415612e1957612c5d6147af565b604051634ce4436960e11b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906399c886d290612c979060009088906004016156da565b6101206040518083038186803b158015612cb057600080fd5b505af4158015612cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce89190614f35565b8051604051630270f5c360e51b8152919250600091737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091612d279185916004016156e8565b60606040518083038186803b158015612d3f57600080fd5b505af4158015612d53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d779190614a81565b50509050600083612d8c578260a00151612d99565b6012546001600160a01b03165b9050612daa82828560200151614346565b612dc65760405162461bcd60e51b81526004016108839061540a565b8415612e11576000612de98460e001518560c0015161426890919063ffffffff16565b9050612df582826142c6565b612c385760405162461bcd60e51b81526004016108839061548a565b5050506131b8565b6003856004811115612e2757fe5b1415612fda57612e3561480c565b60405163ac1ecdb360e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063ac1ecdb390612e6f9060009088906004016156da565b6101206040518083038186803b158015612e8857600080fd5b505af4158015612e9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ec09190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091612f02918591906004016156e8565b60606040518083038186803b158015612f1a57600080fd5b505af4158015612f2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f529190614a81565b9250925050600084612f68578360a00151612f75565b6012546001600160a01b03165b9050612f9b8460200151612f895783612f8b565b825b8286604001518760800151614456565b612fb75760405162461bcd60e51b81526004016108839061540a565b8515612c38576000612c0e8560e001518660c0015161426890919063ffffffff16565b6004856004811115612fe857fe5b14156131b857612ff661480c565b6040516311c8197f60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906311c8197f906130309060009088906004016156da565b6101206040518083038186803b15801561304957600080fd5b505af415801561305d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130819190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb860916130c3918591906004016156e8565b60606040518083038186803b1580156130db57600080fd5b505af41580156130ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131139190614a81565b9250925050600084613129578360a00151613136565b6012546001600160a01b03165b905061314a8460200151612f895783612f8b565b6131665760405162461bcd60e51b81526004016108839061540a565b85156131b35760006131898560e001518660c0015161426890919063ffffffff16565b905061319582826142c6565b6131b15760405162461bcd60e51b81526004016108839061548a565b505b505050505b610a20600084614576565b8051604051630270f5c360e51b81526000918291829182918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613208918591906004016156e8565b60606040518083038186803b15801561322057600080fd5b505af4158015613234573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132589190614a81565b60208901516040516306c5d9cf60e41b8152939850919650945060009173c82938b53e0e190459ba4e3502bf26f19476018391636c5d9cf0916132a3916010918a9190600401615507565b60206040518083038186803b1580156132bb57600080fd5b505af41580156132cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132f39190614ff2565b60408089015190516306c5d9cf60e41b815291925060009173c82938b53e0e190459ba4e3502bf26f19476018391636c5d9cf091613339916010918a9190600401615507565b60206040518083038186803b15801561335157600080fd5b505af4158015613365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133899190614ff2565b9050866001600160a01b031663caeba2176040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156133c657600080fd5b505af11580156133da573d6000803e3d6000fd5b505050506133f18789610100015188888686613401565b9799969850949694959350505050565b600080600080733a09fa6c7cb82fc94c377087cf59ec9529094e616355776b778b88886040518463ffffffff1660e01b8152600401613442939291906152ae565b604080518083038186803b15801561345957600080fd5b505af415801561346d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613491919061500a565b9150915081600014806134a2575080155b156134b4578585935093505050613564565b6134bf888b8461358d565b6134ca878b8361358d565b6040516335313c2160e11b81526001600160a01b038b1690636a627842906134f6908c906004016151ad565b602060405180830381600087803b15801561351057600080fd5b505af1158015613524573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135489190614ff2565b5061355386836129b4565b935061355f85826129b4565b925050505b965096945050505050565b81156135805761358084868461358d565b8015610a2057610a208386835b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b178152925182516000946060949389169392918291908083835b6020831061360a5780518252601f1990920191602091820191016135eb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461366c576040519150601f19603f3d011682016040523d82523d6000602084013e613671565b606091505b509150915081801561369f57508051158061369f575080806020019051602081101561369c57600080fd5b50515b610a20576040805162461bcd60e51b8152602060048201526012602482015271151217d514905394d1915497d1905253115160721b604482015290519081900360640190fd5b600080611e76838460020154600101614597565b60005a905061370661486b565b60405163a81df10f60e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063a81df10f9061373e906000906004016154fe565b6101806040518083038186803b15801561375757600080fd5b505af415801561376b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061378f9190614dde565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb860916137d1918591906004016156e8565b60606040518083038186803b1580156137e957600080fd5b505af41580156137fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138219190614a81565b6001600160a01b038082166000908152600a60205260408082205492851682528120549396509194509092506060913091613875916138699190610e8a9062010fe0906129f0565b610140880151906129b4565b604051630814494760e41b9061388f9089906024016156fc565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516138cd919061518e565b60006040518083038160008787f1925050503d806000811461390b576040519150601f19603f3d011682016040523d82523d6000602084013e613910565b606091505b50909250905060018261393f5761393c866101000151868860200151878a604001518b60e00151614101565b90505b806139535761394e60006145de565b61395d565b61395d6000614631565b60008061397b8861014001518961012001518b8b6101000151614656565b915091508415156000600201547ff0cc99aeb224e65869630a14e23683d20b9c535c00427b50024ce8b6b21d35c38685856040516139bb939291906152da565b60405180910390a3505050505050505050565b60005a90506139db6147af565b6040516313ed2f6160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e906313ed2f6190613a13906000906004016154fe565b6101206040518083038186803b158015613a2c57600080fd5b505af4158015613a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a649190614f35565b8051604051630270f5c360e51b8152919250600091737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613aa39185916004016156e8565b60606040518083038186803b158015613abb57600080fd5b505af4158015613acf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af39190614a81565b5090915060009050606030613b1b613b1062010fe061d6d86129f0565b60e0870151906129b4565b60405163059bab1160e51b90613b3590889060240161579c565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613b73919061518e565b60006040518083038160008787f1925050503d8060008114613bb1576040519150601f19603f3d011682016040523d82523d6000602084013e613bb6565b606091505b509092509050600182613bd957613bd6848660a001518760200151614346565b90505b80613bed57613be860006145de565b613bf7565b613bf76000614631565b600080613c128760e001518860c001518a8a60a00151614656565b915091508415156000600201547ff0cc99aeb224e65869630a14e23683d20b9c535c00427b50024ce8b6b21d35c3868585604051613c52939291906152da565b60405180910390a35050505050505050565b60005a9050613c7161480c565b604051632e9d30e160e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e90632e9d30e190613ca9906000906004016154fe565b6101206040518083038186803b158015613cc257600080fd5b505af4158015613cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfa9190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613d3c918591906004016156e8565b60606040518083038186803b158015613d5457600080fd5b505af4158015613d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d8c9190614a81565b925092505060006060306001600160a01b0316613dec613de16000600a0160008960200151613dbb5788613dbd565b875b6001600160a01b0316815260208101919091526040016000205462010fe0906129f0565b60e0880151906129b4565b604051637cb45e1560e11b90613e069089906024016154ef565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613e44919061518e565b60006040518083038160008787f1925050503d8060008114613e82576040519150601f19603f3d011682016040523d82523d6000602084013e613e87565b606091505b509092509050600182613ebf57613ebc8660200151613ea65785613ea8565b845b8760a0015188604001518960800151614456565b90505b80613ed357613ece60006145de565b613edd565b613edd6000614631565b60008061397b8860e001518960c001518b8b60a00151614656565b60005a9050613f0561480c565b60405163a1ba139560e01b8152737218d567b671e36c4e6b3257b8919196cf68ff5e9063a1ba139590613f3d906000906004016154fe565b6101206040518083038186803b158015613f5657600080fd5b505af4158015613f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f8e9190614cf4565b8051604051630270f5c360e51b81529192506000918291737218d567b671e36c4e6b3257b8919196cf68ff5e91634e1eb86091613fd0918591906004016156e8565b60606040518083038186803b158015613fe857600080fd5b505af4158015613ffc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140209190614a81565b925092505060006060306001600160a01b031661404f613de16000600a0160008960200151613dbb5788613dbd565b60405163c35930c360e01b90613e069089906024016154ef565b81830381848211156140f95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156140be5781810151838201526020016140a6565b50505050905090810190601f1680156140eb5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b509392505050565b6001600160a01b038381166000908152600a6020526040808220549288168252812054909182916060913091614136916129f0565b604051633ed76f1760e01b9061415a908d908d908d908d908d908d906024016151da565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051614198919061518e565b60006040518083038160008787f1925050503d80600081146141d6576040519150601f19603f3d011682016040523d82523d6000602084013e6141db565b606091505b50915091508161425c57876001600160a01b0316896001600160a01b03166000805160206158e08339815191528984604051614218929190615812565b60405180910390a3856001600160a01b0316896001600160a01b03166000805160206158e08339815191528784604051614253929190615812565b60405180910390a35b50979650505050505050565b60008115806142835750508082028282828161428057fe5b04145b612a3a576040805162461bcd60e51b815260206004820152600f60248201526e534d5f4d554c5f4f564552464c4f5760881b604482015290519081900360640190fd5b6000816142d557506001612a3a565b6040516001600160a01b0384169083156108fc029084906000818181858888f193505050509050801515836001600160a01b03167fdbef2fc26e7694e7a1c5a4801b1ad144136d149cf76f310a780689b4087f0ffe8460405161433891906154fe565b60405180910390a392915050565b600081614355575060016129e9565b60006060306001600160a01b031661d6d863c9cd976060e01b88888860006040516024016143869493929190615214565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516143c4919061518e565b60006040518083038160008787f1925050503d8060008114614402576040519150601f19603f3d011682016040523d82523d6000602084013e614407565b606091505b50915091508161444d57856001600160a01b0316856001600160a01b03166000805160206158e08339815191528684604051614444929190615812565b60405180910390a35b50949350505050565b6000826144655750600161456e565b6001600160a01b0385166000908152600a6020526040808220549051606091309163e5b1be6560e01b906144a3908b908b908b908b90602401615214565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516144e1919061518e565b60006040518083038160008787f1925050503d806000811461451f576040519150601f19603f3d011682016040523d82523d6000602084013e614524565b606091505b50915091508161456a57866001600160a01b0316866001600160a01b03166000805160206158e08339815191528784604051614561929190615812565b60405180910390a35b5090505b949350505050565b60009081526003909101602052604081208181556001810182905560020155565b60008181526003830160205260408120805482919060ff8116906145c590610100900463ffffffff166146ea565b92506145d38160ff16614729565b935050509250929050565b600281015460009081526003820160205260409020805465010000000000900460ff161561460d576003614610565b60025b815460ff91909116650100000000000265ff00000000001990911617905550565b6002808201546000908152600390920160205260408220828155600181018390550155565b600080806146648787614268565b905061467b610e74610e8a613908815a8a906129b4565b925060006146a08261469b6000600601548761426890919063ffffffff16565b614799565b90506146ac82826129b4565b92506146b833826142c6565b6146d45760405162461bcd60e51b81526004016108839061548a565b6146de85846142c6565b50505094509492505050565b600063ffffffff82811614156147035750600019610abd565b63ffffffff821661471657506000610abd565b5063ffffffff8116635fee57f001919050565b6000600182141561473c57506001610abd565b600282141561474d57506002610abd565b600382141561475e57506004610abd565b600482141561476f57506004610abd565b600582141561478057506003610abd565b600682141561479157506003610abd565b506000919050565b60008183106147a857816129e9565b5090919050565b604051806101200160405280600063ffffffff16815260200160008152602001600081526020016000815260200160001515815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b604051806101200160405280600063ffffffff168152602001600015158152602001600081526020016000815260200160001515815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b604051806101800160405280600063ffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160001515815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b8035610abd8161589a565b8051610abd8161589a565b8035610abd816158b2565b8051610abd816158b2565b600061012080838503121561491c578182fd5b6149258161584a565b91505061493182614a4f565b815261493f602083016148f3565b60208201526040820135604082015260608201356060820152614964608083016148f3565b608082015261497560a083016148dd565b60a082015260c082013560c082015260e082013560e082015261010080830135818301525092915050565b60006101208083850312156149b3578182fd5b6149bc8161584a565b9150506149c882614a5a565b81526149d6602083016148fe565b602082015260408201516040820152606082015160608201526149fb608083016148fe565b6080820152614a0c60a083016148e8565b60a082015260c082015160c082015260e082015160e082015261010080830151818301525092915050565b60006101208284031215614a49578081fd5b50919050565b8035610abd816158cd565b8051610abd816158cd565b600060208284031215614a76578081fd5b81356129e98161589a565b600080600060608486031215614a95578182fd5b8351614aa08161589a565b6020850151909350614ab18161589a565b6040850151909250614ac28161589a565b809150509250925092565b600080600060608486031215614ae1578081fd5b8335614aec8161589a565b92506020840135614afc8161589a565b929592945050506040919091013590565b60008060008060008060c08789031215614b25578384fd5b8635614b308161589a565b95506020870135614b408161589a565b9450604087013593506060870135614b578161589a565b92506080870135915060a0870135614b6e816158b2565b809150509295509295509295565b60008060008060808587031215614b91578182fd5b8435614b9c8161589a565b93506020850135614bac8161589a565b9250604085013591506060850135614bc3816158b2565b939692955090935050565b60008060408385031215614be0578182fd5b8235614beb8161589a565b91506020830135614bfb816158b2565b809150509250929050565b600080600060608486031215614c1a578081fd5b8335614c258161589a565b92506020840135614c35816158c0565b91506040840135614ac2816158b2565b60008060408385031215614c57578182fd5b8235614c628161589a565b946020939093013593505050565b600060208284031215614c81578081fd5b81516129e9816158b2565b600060208284031215614c9d578081fd5b8151600681106129e9578182fd5b60008060408385031215614cbd578182fd5b8251614cc8816158c0565b6020939093015192949293505050565b60006101208284031215614cea578081fd5b6129e98383614909565b60006101208284031215614d06578081fd5b6129e983836149a0565b60006101208284031215614d22578081fd5b6129e98383614a37565b6000610180808385031215614d3f578182fd5b614d488161584a565b9050614d5383614a4f565b81526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c0820152614d9d60e084016148f3565b60e0820152610100614db08185016148dd565b9082015261012083810135908201526101408084013590820152610160928301359281019290925250919050565b6000610180808385031215614df1578182fd5b614dfa8161584a565b9050614e0583614a5a565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152614e4f60e084016148fe565b60e0820152610100614e628185016148e8565b9082015261012083810151908201526101408084015190820152610160928301519281019290925250919050565b60006101a08284031215614a49578081fd5b6000610120808385031215614eb5578182fd5b614ebe8161584a565b9050614ec983614a4f565b8152602083013560208201526040830135604082015260608301356060820152614ef5608084016148f3565b6080820152614f0660a084016148dd565b60a082015260c083013560c082015260e083013560e08201526101008084013581830152508091505092915050565b6000610120808385031215614f48578182fd5b614f518161584a565b9050614f5c83614a5a565b8152602083015160208201526040830151604082015260608301516060820152614f88608084016148fe565b6080820152614f9960a084016148e8565b60a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b60006101408284031215614a49578081fd5b600060208284031215614feb578081fd5b5035919050565b600060208284031215615003578081fd5b5051919050565b6000806040838503121561501c578182fd5b505080516020909101519092909150565b6001600160a01b03169052565b15159052565b6000815180845261505881602086016020860161586e565b601f01601f19169290920160200192915050565b6005811061507657fe5b9052565b63ffffffff8151168252602081015115156020830152604081015160408301526060810151606083015260808101516150b6608084018261503a565b5060a08101516150c960a084018261502d565b5060c0818101519083015260e0808201519083015261010090810151910152565b80356150f58161589a565b6001600160a01b03168252602081013561510e8161589a565b61511b602084018261502d565b50604081013560408301526060810135606083015261513c608082016148f3565b615149608084018261503a565b5061515660a082016148dd565b61516360a084018261502d565b5060c0818101359083015260e0808201359083015261010090810135910152565b63ffffffff169052565b600082516151a081846020870161586e565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0396871681529486166020860152604085019390935293166060830152608082019290925290151560a082015260c00190565b6001600160a01b0394851681529290931660208301526040820152901515606082015260800190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03841681526060810161529e602083018561506c565b8215156040830152949350505050565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b6000606082526152ed6060830186615040565b60208301949094525060400152919050565b602081016006831061530d57fe5b91905290565b60408101615321828561506c565b8260208301529392505050565b602080825260099082015268125117d313d0d2d15160ba1b604082015260600190565b6020808252601d908201527f49445f494e53554646494349454e545f4f55545055545f414d4f554e54000000604082015260600190565b602080825260159082015274125117d3d491115497d393d517d15610d151511151605a1b604082015260600190565b60208082526015908201527449445f494e56414c49445f4f524445525f5459504560581b604082015260600190565b6020808252600a9082015269125117d156141254915160b21b604082015260600190565b60208082526010908201526f125117d4915195539117d1905253115160821b604082015260600190565b6020808252600c908201526b24a22fa327a92124a22222a760a11b604082015260600190565b602080825260169082015275125117d25394d551919250d251539517d05353d5539560521b604082015260600190565b602080825260149082015273125117d1551217d4915195539117d1905253115160621b604082015260600190565b6020808252601c908201527f49445f494e53554646494349454e545f494e5055545f414d4f554e5400000000604082015260600190565b6101208101612a3a828461507a565b90815260200190565b9283526001600160a01b03919091166020830152604082015260600190565b838152610160810161553b60208301856150ea565b82610140830152949350505050565b8381526101e0810161556760208301615562866148dd565b61502d565b615573602085016148dd565b615580604084018261502d565b506040840135606083015260608401356080830152608084013560a083015260a084013560c083015260c084013560e083015261010060e0850135818401526155ca8186016148f3565b90506101206155db8185018361503a565b6155e68187016148dd565b9150506101406155f88185018361502d565b61016091508086013582850152506101808186013581850152808601356101a08501525050826101c0830152949350505050565b828152610160810161564460208301615562856148dd565b615650602084016148dd565b61565d604084018261502d565b506040830135606083015260608301356080830152608083013560a083015261568860a084016148f3565b61569560c084018261503a565b506156a260c084016148dd565b6156af60e084018261502d565b5061010060e08401358184015261012081850135818501528085013561014085015250509392505050565b918252602082015260400190565b91825263ffffffff16602082015260400190565b600061018082019050615710828451615184565b6020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015161575e60e084018261503a565b50610100808401516157728285018261502d565b50506101208381015190830152610140808401519083015261016092830151929091019190915290565b60006101208201905063ffffffff835116825260208301516020830152604083015160408301526060830151606083015260808301511515608083015260a08301516157eb60a084018261502d565b5060c083015160c083015260e083015160e083015261010080840151818401525092915050565b60008382526040602083015261456e6040830184615040565b92835260208301919091526001600160a01b0316604082015260600190565b60405181810167ffffffffffffffff8111828210171561586657fe5b604052919050565b60005b83811015615889578181015183820152602001615871565b8381111561170f5750506000910152565b6001600160a01b03811681146158af57600080fd5b50565b80151581146158af57600080fd5b600581106158af57600080fd5b63ffffffff811681146158af57600080fdfe786212e89f390a4c768f3b935b85e0ec2561a24b6f48cda3c4b48a996b211592a264697066735822122050c5be39f6e719197a07033de942e62df6a5b8c83eeee1e0ed943ade09a5d8b764736f6c63430007050033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000673662e97b05e001816c380ba5a628d2e29f55d1000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000008971dc0105a22e54d81593af02167fc82af935e3
-----Decoded View---------------
Arg [0] : _factory (address): 0x673662e97B05e001816c380bA5a628D2E29f55D1
Arg [1] : _weth (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [2] : _bot (address): 0x8971Dc0105a22e54D81593AF02167FC82AF935E3
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000673662e97b05e001816c380ba5a628d2e29f55d1
Arg [1] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [2] : 0000000000000000000000008971dc0105a22e54d81593af02167fc82af935e3
Libraries Used
TokenShares : 0xc82938b53e0e190459ba4e3502bf26f194760183AddLiquidity : 0x3a09fa6c7cb82fc94c377087cf59ec9529094e61BuyHelper : 0x5d0434d41c77e4d9a858000f3939c0c4a05b0e26
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $1,742.01 | 0.0126 | $21.93 |
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.