Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 684 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Deposit USDC | 20169025 | 8 days ago | IN | 0 ETH | 0.00136542 | ||||
Queue Crab For W... | 20139790 | 12 days ago | IN | 0 ETH | 0.00096715 | ||||
Deposit USDC | 20135588 | 12 days ago | IN | 0 ETH | 0.00116456 | ||||
Deposit USDC | 20089876 | 19 days ago | IN | 0 ETH | 0.00133362 | ||||
Deposit USDC | 20078418 | 20 days ago | IN | 0 ETH | 0.00259339 | ||||
Deposit USDC | 20078061 | 20 days ago | IN | 0 ETH | 0.00370882 | ||||
Queue Crab For W... | 20064468 | 22 days ago | IN | 0 ETH | 0.00194146 | ||||
Deposit USDC | 20061473 | 23 days ago | IN | 0 ETH | 0.00131244 | ||||
Queue Crab For W... | 19992307 | 32 days ago | IN | 0 ETH | 0.00150223 | ||||
Queue Crab For W... | 19946158 | 39 days ago | IN | 0 ETH | 0.00068918 | ||||
Queue Crab For W... | 19923833 | 42 days ago | IN | 0 ETH | 0.00133074 | ||||
Queue Crab For W... | 19915976 | 43 days ago | IN | 0 ETH | 0.00154754 | ||||
Withdraw USDC | 19915197 | 43 days ago | IN | 0 ETH | 0.00088791 | ||||
Withdraw USDC | 19913340 | 44 days ago | IN | 0 ETH | 0.00935906 | ||||
Deposit USDC | 19909588 | 44 days ago | IN | 0 ETH | 0.00052359 | ||||
Deposit USDC | 19890004 | 47 days ago | IN | 0 ETH | 0.00140136 | ||||
Deposit USDC | 19854487 | 52 days ago | IN | 0 ETH | 0.00117216 | ||||
Queue Crab For W... | 19840906 | 54 days ago | IN | 0 ETH | 0.00019795 | ||||
Queue Crab For W... | 19840903 | 54 days ago | IN | 0 ETH | 0.00018295 | ||||
Queue Crab For W... | 19840900 | 54 days ago | IN | 0 ETH | 0.00019294 | ||||
Queue Crab For W... | 19837769 | 54 days ago | IN | 0 ETH | 0.00087962 | ||||
Withdraw USDC | 19831555 | 55 days ago | IN | 0 ETH | 0.00042361 | ||||
Queue Crab For W... | 19830284 | 55 days ago | IN | 0 ETH | 0.0008719 | ||||
Deposit USDC | 19823999 | 56 days ago | IN | 0 ETH | 0.00106398 | ||||
Deposit USDC | 19822522 | 56 days ago | IN | 0 ETH | 0.00111966 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
20169957 | 8 days ago | 1.69251296 ETH | ||||
20169957 | 8 days ago | 1.69251296 ETH | ||||
20119896 | 15 days ago | 0.01597584 ETH | ||||
20119896 | 15 days ago | 10.62373864 ETH | ||||
20119896 | 15 days ago | 10.63971449 ETH | ||||
20069960 | 22 days ago | 11.42143778 ETH | ||||
20069960 | 22 days ago | 11.42143778 ETH | ||||
20019859 | 29 days ago | 3.01637135 ETH | ||||
20019859 | 29 days ago | 3.01637135 ETH | ||||
19969642 | 36 days ago | 168.23481991 ETH | ||||
19969642 | 36 days ago | 168.23481991 ETH | ||||
19919534 | 43 days ago | 6.30582675 ETH | ||||
19919534 | 43 days ago | 6.30582675 ETH | ||||
19869486 | 50 days ago | 0.01416946 ETH | ||||
19869486 | 50 days ago | 5.17927946 ETH | ||||
19869486 | 50 days ago | 5.19344892 ETH | ||||
19819464 | 57 days ago | 0.68167211 ETH | ||||
19819464 | 57 days ago | 308.96757038 ETH | ||||
19819464 | 57 days ago | 309.64924249 ETH | ||||
19769390 | 64 days ago | 0.00863087 ETH | ||||
19769390 | 64 days ago | 0.00863087 ETH | ||||
19769390 | 64 days ago | 0.0210513 ETH | ||||
19769390 | 64 days ago | 6.41177982 ETH | ||||
19769390 | 64 days ago | 6.43283113 ETH | ||||
19719352 | 71 days ago | 0.00075407 ETH |
Loading...
Loading
Contract Name:
CrabNetting
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.13; // interface import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IWETH} from "../src/interfaces/IWETH.sol"; import {IOracle} from "../src/interfaces/IOracle.sol"; import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import {ICrabStrategyV2} from "../src/interfaces/ICrabStrategyV2.sol"; import {IController} from "../src/interfaces/IController.sol"; // contract import {Ownable} from "openzeppelin/access/Ownable.sol"; import {EIP712} from "openzeppelin/utils/cryptography/draft-EIP712.sol"; import {ECDSA} from "openzeppelin/utils/cryptography/ECDSA.sol"; /// @dev order struct for a signed order from market maker struct Order { uint256 bidId; address trader; uint256 quantity; uint256 price; bool isBuying; uint256 expiry; uint256 nonce; uint8 v; bytes32 r; bytes32 s; } /// @dev struct to store proportional amounts of erc20s (received or to send) struct Portion { uint256 crab; uint256 eth; uint256 sqth; } /// @dev params for deposit auction struct DepositAuctionParams { /// @dev USDC to deposit uint256 depositsQueued; /// @dev minETH equivalent to get from uniswap of the USDC to deposit uint256 minEth; /// @dev total ETH to deposit after selling the minted SQTH uint256 totalDeposit; /// @dev orders to buy sqth Order[] orders; /// @dev price from the auction to sell sqth uint256 clearingPrice; /// @dev remaining ETH to flashDeposit uint256 ethToFlashDeposit; /// @dev fee to pay uniswap for ethUSD swap uint24 ethUSDFee; /// @dev fee to pay uniswap for sqthETH swap uint24 flashDepositFee; } /// @dev params for withdraw auction struct WithdrawAuctionParams { /// @dev amont of crab to queue for withdrawal uint256 crabToWithdraw; /// @dev orders that sell sqth to the auction Order[] orders; /// @dev price that the auction pays for the purchased sqth uint256 clearingPrice; /// @dev minUSDC to receive from swapping the ETH obtained by withdrawing uint256 minUSDC; /// @dev uniswap fee for swapping eth to USD; uint24 ethUSDFee; } /// @dev receipt used to store deposits and withdraws struct Receipt { /// @dev address of the depositor or withdrawer address sender; /// @dev usdc amount to queue for deposit or crab amount to queue for withdrawal uint256 amount; /// @dev time of deposit uint256 timestamp; } /** * Crab netting error codes * N1: deposit amount smaller than minimum OTC amount * N2: auction is live * N3: remaining amount smaller than minimum, consider removing full balance * N4: force withdraw after 1 week from deposit * N5: withdraw amount smaller than minimum OTC amount * N6: remaining amount smaller than minimum, consider removing full balance * N7: Not enough deposits to net * N8: Not enough withdrawals to net * N9: signature incorrect * N10: order expired * N11: Min ETH out too low * N12: auction order not buying sqth * N13: buy order price less than clearing * N14: not enough buy orders for sqth * N15: auction order is not selling * N16: sell order price greater than clearing * N17: min USDC out too low * N18: twap period cannot be less than 180 * N19: Price tolerance has to be less than 20% * N20: Nonce already used * N21: Price too high relative to Uniswap twap. * N22: Price too low relative to Uniswap twap. * N23: Crab Price too high * N24: Crab Price too low * N25: only weth and crab can send me monies */ /** * @dev CrabNetting contract * @notice Contract for Netting Deposits and Withdrawals * @author Opyn team */ contract CrabNetting is Ownable, EIP712 { /// @dev typehash for signed orders bytes32 private constant _CRAB_NETTING_TYPEHASH = keccak256( "Order(uint256 bidId,address trader,uint256 quantity,uint256 price,bool isBuying,uint256 expiry,uint256 nonce)" ); /// @dev owner sets to true when starting auction bool public isAuctionLive; /// @dev sqth twap period uint32 public immutable sqthTwapPeriod; /// @dev twap period to use for auction calculations uint32 public auctionTwapPeriod = 420 seconds; /// @dev min USDC amounts to withdraw or deposit via netting uint256 public minUSDCAmount; /// @dev min CRAB amounts to withdraw or deposit via netting uint256 public minCrabAmount; // @dev OTC price must be within this distance of the uniswap twap price uint256 public otcPriceTolerance = 5e16; // 5% // @dev OTC price tolerance cannot exceed 20% uint256 public constant MAX_OTC_PRICE_TOLERANCE = 2e17; // 20% /// @dev address for ERC20 tokens address public immutable usdc; address public immutable crab; address public immutable weth; address public immutable sqth; /// @dev address for uniswap router ISwapRouter public immutable swapRouter; /// @dev address for uniswap oracle address public immutable oracle; /// @dev address for sqth eth pool address public immutable ethSqueethPool; /// @dev address for usdc eth pool address public immutable ethUsdcPool; /// @dev address for sqth controller address public immutable sqthController; /// @dev array index of last processed deposits uint256 public depositsIndex; /// @dev array index of last processed withdraws uint256 public withdrawsIndex; /// @dev array of deposit receipts Receipt[] public deposits; /// @dev array of withdrawal receipts Receipt[] public withdraws; /// @dev usd amount to deposit for an address mapping(address => uint256) public usdBalance; /// @dev crab amount to withdraw for an address mapping(address => uint256) public crabBalance; /// @dev indexes of deposit receipts of an address mapping(address => uint256[]) public userDepositsIndex; /// @dev indexes of withdraw receipts of an address mapping(address => uint256[]) public userWithdrawsIndex; /// @dev store the used flag for a nonce for each address mapping(address => mapping(uint256 => bool)) public nonces; event USDCQueued( address indexed depositor, uint256 amount, uint256 depositorsBalance, uint256 indexed receiptIndex ); event USDCDeQueued(address indexed depositor, uint256 amount, uint256 depositorsBalance); event CrabQueued( address indexed withdrawer, uint256 amount, uint256 withdrawersBalance, uint256 indexed receiptIndex ); event CrabDeQueued(address indexed withdrawer, uint256 amount, uint256 withdrawersBalance); event USDCDeposited( address indexed depositor, uint256 usdcAmount, uint256 crabAmount, uint256 indexed receiptIndex, uint256 refundedETH ); event CrabWithdrawn( address indexed withdrawer, uint256 crabAmount, uint256 usdcAmount, uint256 indexed receiptIndex ); event WithdrawRejected(address indexed withdrawer, uint256 crabAmount, uint256 index); event BidTraded(uint256 indexed bidId, address indexed trader, uint256 quantity, uint256 price, bool isBuying); event SetAuctionTwapPeriod(uint32 previousTwap, uint32 newTwap); event SetOTCPriceTolerance(uint256 previousTolerance, uint256 newOtcPriceTolerance); event SetMinCrab(uint256 amount); event SetMinUSDC(uint256 amount); event SetDepositsIndex(uint256 newDepositsIndex); event SetWithdrawsIndex(uint256 newWithdrawsIndex); event NonceTrue(address sender, uint256 nonce); event ToggledAuctionLive(bool isAuctionLive); /** * @notice netting contract constructor * @dev initializes the erc20 address, uniswap router and approves them * @param _crab address of crab contract token * @param _swapRouter address of uniswap swap router */ constructor(address _crab, address _swapRouter) EIP712("CRABNetting", "1") { crab = _crab; swapRouter = ISwapRouter(_swapRouter); sqthController = ICrabStrategyV2(_crab).powerTokenController(); usdc = IController(sqthController).quoteCurrency(); weth = ICrabStrategyV2(_crab).weth(); sqth = ICrabStrategyV2(_crab).wPowerPerp(); oracle = ICrabStrategyV2(_crab).oracle(); ethSqueethPool = ICrabStrategyV2(_crab).ethWSqueethPool(); ethUsdcPool = IController(sqthController).ethQuoteCurrencyPool(); sqthTwapPeriod = IController(sqthController).TWAP_PERIOD(); // approve crab and sqth so withdraw can happen IERC20(sqth).approve(crab, type(uint256).max); IERC20(weth).approve(address(swapRouter), type(uint256).max); IERC20(usdc).approve(address(swapRouter), type(uint256).max); } /** * @dev view function to get the domain seperator used in signing */ function DOMAIN_SEPARATOR() external view returns (bytes32) { return _domainSeparatorV4(); } /** * @dev toggles the value of isAuctionLive */ function toggleAuctionLive() external onlyOwner { isAuctionLive = !isAuctionLive; emit ToggledAuctionLive(isAuctionLive); } /** * @notice set nonce to true * @param _nonce the number to be set true */ function setNonceTrue(uint256 _nonce) external { nonces[msg.sender][_nonce] = true; emit NonceTrue(msg.sender, _nonce); } /** * @notice set minUSDCAmount * @param _amount the number to be set as minUSDC */ function setMinUSDC(uint256 _amount) external onlyOwner { minUSDCAmount = _amount; emit SetMinUSDC(_amount); } /** * @notice set minCrabAmount * @param _amount the number to be set as minCrab */ function setMinCrab(uint256 _amount) external onlyOwner { minCrabAmount = _amount; emit SetMinCrab(_amount); } /** * @notice set the depositIndex so that we want to skip processing some deposits * @param _newDepositsIndex the new deposits index */ function setDepositsIndex(uint256 _newDepositsIndex) external onlyOwner { depositsIndex = _newDepositsIndex; emit SetDepositsIndex(_newDepositsIndex); } /** * @notice set the withdraw index so that we want to skip processing some withdraws * @param _newWithdrawsIndex the new withdraw index */ function setWithdrawsIndex(uint256 _newWithdrawsIndex) external onlyOwner { withdrawsIndex = _newWithdrawsIndex; emit SetWithdrawsIndex(_newWithdrawsIndex); } /** * @notice queue USDC for deposit into crab strategy * @param _amount USDC amount to deposit */ function depositUSDC(uint256 _amount) external { require(_amount >= minUSDCAmount, "N1"); IERC20(usdc).transferFrom(msg.sender, address(this), _amount); // update usd balance of user, add their receipt, and receipt index to user deposits index usdBalance[msg.sender] = usdBalance[msg.sender] + _amount; deposits.push(Receipt(msg.sender, _amount, block.timestamp)); userDepositsIndex[msg.sender].push(deposits.length - 1); emit USDCQueued(msg.sender, _amount, usdBalance[msg.sender], deposits.length - 1); } /** * @notice withdraw USDC from queue * @param _amount USDC amount to dequeue * @param _force forceWithdraw if deposited more than a week ago */ function withdrawUSDC(uint256 _amount, bool _force) external { require(!isAuctionLive || _force, "N2"); usdBalance[msg.sender] = usdBalance[msg.sender] - _amount; require(usdBalance[msg.sender] >= minUSDCAmount || usdBalance[msg.sender] == 0, "N3"); // start withdrawing from the users last deposit uint256 toRemove = _amount; uint256 lastIndexP1 = userDepositsIndex[msg.sender].length; for (uint256 i = lastIndexP1; i > 0; i--) { Receipt storage r = deposits[userDepositsIndex[msg.sender][i - 1]]; if (_force) { require(block.timestamp > r.timestamp + 1 weeks, "N4"); } if (r.amount > toRemove) { r.amount -= toRemove; toRemove = 0; break; } else { toRemove -= r.amount; delete deposits[userDepositsIndex[msg.sender][i - 1]]; userDepositsIndex[msg.sender].pop(); } } IERC20(usdc).transfer(msg.sender, _amount); emit USDCDeQueued(msg.sender, _amount, usdBalance[msg.sender]); } /** * @notice queue Crab for withdraw from crab strategy * @param _amount crab amount to withdraw */ function queueCrabForWithdrawal(uint256 _amount) external { require(_amount >= minCrabAmount, "N5"); IERC20(crab).transferFrom(msg.sender, address(this), _amount); crabBalance[msg.sender] = crabBalance[msg.sender] + _amount; withdraws.push(Receipt(msg.sender, _amount, block.timestamp)); userWithdrawsIndex[msg.sender].push(withdraws.length - 1); emit CrabQueued(msg.sender, _amount, crabBalance[msg.sender], withdraws.length - 1); } /** * @notice withdraw Crab from queue * @param _amount Crab amount to dequeue * @param _force forceWithdraw if deposited more than a week ago */ function dequeueCrab(uint256 _amount, bool _force) external { require(!isAuctionLive || _force, "N2"); crabBalance[msg.sender] = crabBalance[msg.sender] - _amount; require(crabBalance[msg.sender] >= minCrabAmount || crabBalance[msg.sender] == 0, "N6"); // deQueue crab from the last, last in first out uint256 toRemove = _amount; uint256 lastIndexP1 = userWithdrawsIndex[msg.sender].length; for (uint256 i = lastIndexP1; i > 0; i--) { Receipt storage r = withdraws[userWithdrawsIndex[msg.sender][i - 1]]; if (_force) { require(block.timestamp > r.timestamp + 1 weeks, "N4"); } if (r.amount > toRemove) { r.amount -= toRemove; toRemove = 0; break; } else { toRemove -= r.amount; delete withdraws[userWithdrawsIndex[msg.sender][i - 1]]; userWithdrawsIndex[msg.sender].pop(); } } IERC20(crab).transfer(msg.sender, _amount); emit CrabDeQueued(msg.sender, _amount, crabBalance[msg.sender]); } /** * @dev swaps _quantity amount of usdc for crab at _price * @param _price price of crab in usdc * @param _quantity amount of USDC to net */ function netAtPrice(uint256 _price, uint256 _quantity) external onlyOwner { _checkCrabPrice(_price); uint256 crabQuantity = (_quantity * 1e18) / _price; require(_quantity <= IERC20(usdc).balanceOf(address(this)), "N7"); require(crabQuantity <= IERC20(crab).balanceOf(address(this)), "N8"); // process deposits and send crab uint256 i = depositsIndex; uint256 amountToSend; while (_quantity > 0) { Receipt memory deposit = deposits[i]; if (deposit.amount == 0) { i++; continue; } if (deposit.amount <= _quantity) { // deposit amount is lesser than quantity use it fully _quantity = _quantity - deposit.amount; usdBalance[deposit.sender] -= deposit.amount; amountToSend = (deposit.amount * 1e18) / _price; IERC20(crab).transfer(deposit.sender, amountToSend); emit USDCDeposited(deposit.sender, deposit.amount, amountToSend, i, 0); delete deposits[i]; i++; } else { // deposit amount is greater than quantity; use it partially deposits[i].amount = deposit.amount - _quantity; usdBalance[deposit.sender] -= _quantity; amountToSend = (_quantity * 1e18) / _price; IERC20(crab).transfer(deposit.sender, amountToSend); emit USDCDeposited(deposit.sender, _quantity, amountToSend, i, 0); _quantity = 0; } } depositsIndex = i; // process withdraws and send usdc i = withdrawsIndex; while (crabQuantity > 0) { Receipt memory withdraw = withdraws[i]; if (withdraw.amount == 0) { i++; continue; } if (withdraw.amount <= crabQuantity) { crabQuantity = crabQuantity - withdraw.amount; crabBalance[withdraw.sender] -= withdraw.amount; amountToSend = (withdraw.amount * _price) / 1e18; IERC20(usdc).transfer(withdraw.sender, amountToSend); emit CrabWithdrawn(withdraw.sender, withdraw.amount, amountToSend, i); delete withdraws[i]; i++; } else { withdraws[i].amount = withdraw.amount - crabQuantity; crabBalance[withdraw.sender] -= crabQuantity; amountToSend = (crabQuantity * _price) / 1e18; IERC20(usdc).transfer(withdraw.sender, amountToSend); emit CrabWithdrawn(withdraw.sender, withdraw.amount, amountToSend, i); crabQuantity = 0; } } withdrawsIndex = i; } /** * @return sum usdc amount in queue */ function depositsQueued() external view returns (uint256) { uint256 j = depositsIndex; uint256 sum; while (j < deposits.length) { sum = sum + deposits[j].amount; j++; } return sum; } /** * @return sum crab amount in queue */ function withdrawsQueued() external view returns (uint256) { uint256 j = withdrawsIndex; uint256 sum; while (j < withdraws.length) { sum = sum + withdraws[j].amount; j++; } return sum; } function checkOrder(Order memory _order) external view { return _checkOrder(_order); } /** * @dev checks the expiry nonce and signer of an order * @param _order is the Order struct */ function _checkOrder(Order memory _order) internal view { bytes32 structHash = keccak256( abi.encode( _CRAB_NETTING_TYPEHASH, _order.bidId, _order.trader, _order.quantity, _order.price, _order.isBuying, _order.expiry, _order.nonce ) ); bytes32 hash = _hashTypedDataV4(structHash); address offerSigner = ECDSA.recover(hash, _order.v, _order.r, _order.s); require(offerSigner == _order.trader, "N9"); require(_order.expiry >= block.timestamp, "N10"); } /** * @dev calculates wSqueeth minted when amount is deposited * @param _amount to deposit into crab */ function _debtToMint(uint256 _amount) internal view returns (uint256) { uint256 feeAdjustment = _calcFeeAdjustment(); (,, uint256 collateral, uint256 debt) = ICrabStrategyV2(crab).getVaultDetails(); uint256 wSqueethToMint = (_amount * debt) / (collateral + (debt * feeAdjustment) / 1e18); return wSqueethToMint; } /** * @dev takes in orders from mm's to buy sqth and deposits the usd amount from the depositQueue into crab along with the eth from selling sqth * @param _p DepositAuction Params that contain orders, usdToDeposit, uniswap min amount and fee */ function depositAuction(DepositAuctionParams calldata _p) external onlyOwner { _checkOTCPrice(_p.clearingPrice, false); uint256 ethUSDCPrice = IOracle(oracle).getTwap(ethUsdcPool, weth, usdc, auctionTwapPeriod, true); require((_p.depositsQueued * (1e18 - otcPriceTolerance) * 1e12 / ethUSDCPrice) < _p.minEth, "N11"); /** * step 1: get eth from mm * step 2: get eth from deposit usdc * step 3: crab deposit * step 4: flash deposit * step 5: send sqth to mms * step 6: send crab to depositors */ uint256 initCrabBalance = IERC20(crab).balanceOf(address(this)); uint256 initEthBalance = address(this).balance; uint256 sqthToSell = _debtToMint(_p.totalDeposit); // step 1 get all the eth in uint256 remainingToSell = sqthToSell; for (uint256 i = 0; i < _p.orders.length; i++) { require(_p.orders[i].isBuying, "N12"); require(_p.orders[i].price >= _p.clearingPrice, "N13"); _checkOrder(_p.orders[i]); _useNonce(_p.orders[i].trader, _p.orders[i].nonce); if (_p.orders[i].quantity >= remainingToSell) { IWETH(weth).transferFrom( _p.orders[i].trader, address(this), (remainingToSell * _p.clearingPrice) / 1e18 ); remainingToSell = 0; break; } else { IWETH(weth).transferFrom( _p.orders[i].trader, address(this), (_p.orders[i].quantity * _p.clearingPrice) / 1e18 ); remainingToSell -= _p.orders[i].quantity; } } require(remainingToSell == 0, "N14"); // step 2 ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: usdc, tokenOut: weth, fee: _p.ethUSDFee, recipient: address(this), deadline: block.timestamp, amountIn: _p.depositsQueued, amountOutMinimum: _p.minEth, sqrtPriceLimitX96: 0 }); swapRouter.exactInputSingle(params); // step 3 IWETH(weth).withdraw(IWETH(weth).balanceOf(address(this))); ICrabStrategyV2(crab).deposit{value: _p.totalDeposit}(); // step 4 Portion memory to_send; to_send.eth = address(this).balance - initEthBalance; if (to_send.eth > 0 && _p.ethToFlashDeposit > 0) { if (to_send.eth <= _p.ethToFlashDeposit) { // we cant send more than the flashDeposit ICrabStrategyV2(crab).flashDeposit{value: to_send.eth}(_p.ethToFlashDeposit, _p.flashDepositFee); } } // step 5 to_send.sqth = IERC20(sqth).balanceOf(address(this)); remainingToSell = to_send.sqth; for (uint256 j = 0; j < _p.orders.length; j++) { if (_p.orders[j].quantity < remainingToSell) { IERC20(sqth).transfer(_p.orders[j].trader, _p.orders[j].quantity); remainingToSell -= _p.orders[j].quantity; emit BidTraded(_p.orders[j].bidId, _p.orders[j].trader, _p.orders[j].quantity, _p.clearingPrice, true); } else { IERC20(sqth).transfer(_p.orders[j].trader, remainingToSell); emit BidTraded(_p.orders[j].bidId, _p.orders[j].trader, remainingToSell, _p.clearingPrice, true); break; } } // step 6 send crab to depositors uint256 remainingDeposits = _p.depositsQueued; uint256 k = depositsIndex; to_send.crab = IERC20(crab).balanceOf(address(this)) - initCrabBalance; // get the balance between start and now to_send.eth = address(this).balance - initEthBalance; IWETH(weth).deposit{value: to_send.eth}(); while (remainingDeposits > 0) { uint256 queuedAmount = deposits[k].amount; Portion memory portion; if (queuedAmount == 0) { k++; continue; } if (queuedAmount <= remainingDeposits) { remainingDeposits = remainingDeposits - queuedAmount; usdBalance[deposits[k].sender] -= queuedAmount; portion.crab = queuedAmount * to_send.crab / _p.depositsQueued; IERC20(crab).transfer(deposits[k].sender, portion.crab); portion.eth = queuedAmount * to_send.eth / _p.depositsQueued; if (portion.eth > 1e12) { IWETH(weth).transfer(deposits[k].sender, portion.eth); } else { portion.eth = 0; } emit USDCDeposited(deposits[k].sender, queuedAmount, portion.crab, k, portion.eth); delete deposits[k]; k++; } else { usdBalance[deposits[k].sender] -= remainingDeposits; portion.crab = remainingDeposits * to_send.crab / _p.depositsQueued; IERC20(crab).transfer(deposits[k].sender, portion.crab); portion.eth = remainingDeposits * to_send.eth / _p.depositsQueued; if (portion.eth > 1e12) { IWETH(weth).transfer(deposits[k].sender, portion.eth); } else { portion.eth = 0; } emit USDCDeposited(deposits[k].sender, remainingDeposits, portion.crab, k, portion.eth); deposits[k].amount -= remainingDeposits; remainingDeposits = 0; } } depositsIndex = k; isAuctionLive = false; } /** * @dev takes in orders from mm's to sell sqth and withdraws the crab amount in q * @param _p Withdraw Params that contain orders, crabToWithdraw, uniswap min amount and fee */ function withdrawAuction(WithdrawAuctionParams calldata _p) public onlyOwner { _checkOTCPrice(_p.clearingPrice, true); uint256 initWethBalance = IERC20(weth).balanceOf(address(this)); uint256 initEthBalance = address(this).balance; /** * step 1: get sqth from mms * step 2: withdraw from crab * step 3: send eth to mms * step 4: convert eth to usdc * step 5: send usdc to withdrawers */ // step 1 get sqth from mms uint256 sqthRequired = ICrabStrategyV2(crab).getWsqueethFromCrabAmount(_p.crabToWithdraw); uint256 toPull = sqthRequired; for (uint256 i = 0; i < _p.orders.length && toPull > 0; i++) { _checkOrder(_p.orders[i]); _useNonce(_p.orders[i].trader, _p.orders[i].nonce); require(!_p.orders[i].isBuying, "N15"); require(_p.orders[i].price <= _p.clearingPrice, "N16"); if (_p.orders[i].quantity < toPull) { toPull -= _p.orders[i].quantity; IERC20(sqth).transferFrom(_p.orders[i].trader, address(this), _p.orders[i].quantity); } else { IERC20(sqth).transferFrom(_p.orders[i].trader, address(this), toPull); toPull = 0; } } // step 2 withdraw from crab ICrabStrategyV2(crab).withdraw(_p.crabToWithdraw); // step 3 pay all mms IWETH(weth).deposit{value: address(this).balance - initEthBalance}(); toPull = sqthRequired; uint256 sqthQuantity; for (uint256 i = 0; i < _p.orders.length && toPull > 0; i++) { if (_p.orders[i].quantity < toPull) { sqthQuantity = _p.orders[i].quantity; } else { sqthQuantity = toPull; } IERC20(weth).transfer(_p.orders[i].trader, (sqthQuantity * _p.clearingPrice) / 1e18); toPull -= sqthQuantity; emit BidTraded(_p.orders[i].bidId, _p.orders[i].trader, sqthQuantity, _p.clearingPrice, false); } // step 4 convert to USDC uint256 ethUSDCPrice = IOracle(oracle).getTwap(ethUsdcPool, weth, usdc, auctionTwapPeriod, true); uint256 amountIn = (IERC20(weth).balanceOf(address(this)) - initWethBalance); require((amountIn * ethUSDCPrice * (1e18 - otcPriceTolerance) / 1e36 / 1e12) < _p.minUSDC, "N17"); ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: address(weth), tokenOut: address(usdc), fee: _p.ethUSDFee, recipient: address(this), deadline: block.timestamp, amountIn: amountIn, amountOutMinimum: _p.minUSDC, sqrtPriceLimitX96: 0 }); uint256 usdcReceived = swapRouter.exactInputSingle(params); // step 5 pay all withdrawers and mark their withdraws as done uint256 remainingWithdraws = _p.crabToWithdraw; uint256 j = withdrawsIndex; uint256 usdcAmount; while (remainingWithdraws > 0) { Receipt memory withdraw = withdraws[j]; if (withdraw.amount == 0) { j++; continue; } if (withdraw.amount <= remainingWithdraws) { // full usage remainingWithdraws -= withdraw.amount; crabBalance[withdraw.sender] -= withdraw.amount; // send proportional usdc usdcAmount = withdraw.amount * usdcReceived / _p.crabToWithdraw; IERC20(usdc).transfer(withdraw.sender, usdcAmount); emit CrabWithdrawn(withdraw.sender, withdraw.amount, usdcAmount, j); delete withdraws[j]; j++; } else { withdraws[j].amount -= remainingWithdraws; crabBalance[withdraw.sender] -= remainingWithdraws; // send proportional usdc usdcAmount = remainingWithdraws * usdcReceived / _p.crabToWithdraw; IERC20(usdc).transfer(withdraw.sender, usdcAmount); emit CrabWithdrawn(withdraw.sender, remainingWithdraws, usdcAmount, j); remainingWithdraws = 0; } } withdrawsIndex = j; isAuctionLive = false; } /** * @dev owner rejects the withdraw at index i thereby sending the withdrawer their crab back * @param i index of the Withdraw receipt to reject */ function rejectWithdraw(uint256 i) external onlyOwner { Receipt memory withdraw = withdraws[i]; crabBalance[withdraw.sender] -= withdraw.amount; ICrabStrategyV2(crab).transfer(withdraw.sender, withdraw.amount); delete withdraws[i]; emit WithdrawRejected(withdraw.sender, withdraw.amount, i); } /** * @notice owner can set the twap period in seconds that is used for obtaining TWAP prices * @param _auctionTwapPeriod the twap period, in seconds */ function setAuctionTwapPeriod(uint32 _auctionTwapPeriod) external onlyOwner { require(_auctionTwapPeriod >= 180, "N18"); uint32 previousTwap = auctionTwapPeriod; auctionTwapPeriod = _auctionTwapPeriod; emit SetAuctionTwapPeriod(previousTwap, _auctionTwapPeriod); } /** * @notice owner can set a threshold, scaled by 1e18 that determines the maximum discount of a clearing sale price to the current uniswap twap price * @param _otcPriceTolerance the OTC price tolerance, in percent, scaled by 1e18 */ function setOTCPriceTolerance(uint256 _otcPriceTolerance) external onlyOwner { // Tolerance cannot be more than 20% require(_otcPriceTolerance <= MAX_OTC_PRICE_TOLERANCE, "N19"); uint256 previousOtcTolerance = otcPriceTolerance; otcPriceTolerance = _otcPriceTolerance; emit SetOTCPriceTolerance(previousOtcTolerance, _otcPriceTolerance); } /** * @dev set nonce flag of the trader to true * @param _trader address of the signer * @param _nonce number that is to be traded only once */ function _useNonce(address _trader, uint256 _nonce) internal { require(!nonces[_trader][_nonce], "N20"); nonces[_trader][_nonce] = true; } /** * @notice check that the proposed sale price is within a tolerance of the current Uniswap twap * @param _price clearing price provided by manager * @param _isAuctionBuying is crab buying or selling oSQTH */ function _checkOTCPrice(uint256 _price, bool _isAuctionBuying) internal view { // Get twap uint256 squeethEthPrice = IOracle(oracle).getTwap(ethSqueethPool, sqth, weth, auctionTwapPeriod, true); if (_isAuctionBuying) { require(_price <= (squeethEthPrice * (1e18 + otcPriceTolerance)) / 1e18, "N21"); } else { require(_price >= (squeethEthPrice * (1e18 - otcPriceTolerance)) / 1e18, "N22"); } } function _checkCrabPrice(uint256 _price) internal view { // Get twap uint256 squeethEthPrice = IOracle(oracle).getTwap(ethSqueethPool, sqth, weth, auctionTwapPeriod, true); uint256 usdcEthPrice = IOracle(oracle).getTwap(ethUsdcPool, weth, usdc, auctionTwapPeriod, true); (,, uint256 collateral, uint256 debt) = ICrabStrategyV2(crab).getVaultDetails(); uint256 crabFairPrice = ((collateral - ((debt * squeethEthPrice) / 1e18)) * usdcEthPrice) / ICrabStrategyV2(crab).totalSupply(); crabFairPrice = crabFairPrice / 1e12; //converting from units of 18 to 6 require(_price <= (crabFairPrice * (1e18 + otcPriceTolerance)) / 1e18, "N23"); require(_price >= (crabFairPrice * (1e18 - otcPriceTolerance)) / 1e18, "N24"); } function _calcFeeAdjustment() internal view returns (uint256) { uint256 feeRate = IController(sqthController).feeRate(); if (feeRate == 0) return 0; uint256 squeethEthPrice = IOracle(oracle).getTwap(ethSqueethPool, sqth, weth, sqthTwapPeriod, true); return (squeethEthPrice * feeRate) / 10000; } receive() external payable { require(msg.sender == weth || msg.sender == crab, "N25"); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // EIP-712 is Final as of 2022-08-11. This file is deprecated. import "./EIP712.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.17; interface IController { function feeRate() external view returns (uint256); function TWAP_PERIOD() external view returns (uint32); function quoteCurrency() external view returns (address); function ethQuoteCurrencyPool() external view returns (address); function setFeeRate(uint256 _newFeeRate) external; function setFeeRecipient(address _newFeeRecipient) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; import {IERC20} from "openzeppelin/interfaces/IERC20.sol"; interface ICrabStrategyV2 is IERC20 { function getVaultDetails() external view returns (address, uint256, uint256, uint256); function deposit() external payable; function withdraw(uint256 _crabAmount) external; function flashDeposit(uint256 _ethToDeposit, uint24 _poolFee) external payable; function getWsqueethFromCrabAmount(uint256 _crabAmount) external view returns (uint256); function powerTokenController() external view returns (address); function weth() external view returns (address); function wPowerPerp() external view returns (address); function oracle() external view returns (address); function ethWSqueethPool() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; interface IOracle { function getTwap(address _pool, address _base, address _quote, uint32 _period, bool _checkPeriod) external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; import {IERC20} from "openzeppelin/interfaces/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 wad) external; }
{ "remappings": [ "@uniswap/v3-core/=lib/v3-core/", "@uniswap/v3-periphery/=lib/v3-periphery/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "squeeth-monorepo/=lib/squeeth-monorepo/packages/hardhat/contracts/", "v3-core/=lib/v3-core/", "v3-periphery/=lib/v3-periphery/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_crab","type":"address"},{"internalType":"address","name":"_swapRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"bidId","type":"uint256"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isBuying","type":"bool"}],"name":"BidTraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawersBalance","type":"uint256"}],"name":"CrabDeQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawersBalance","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"receiptIndex","type":"uint256"}],"name":"CrabQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":false,"internalType":"uint256","name":"crabAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdcAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"receiptIndex","type":"uint256"}],"name":"CrabWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"NonceTrue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousTwap","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newTwap","type":"uint32"}],"name":"SetAuctionTwapPeriod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDepositsIndex","type":"uint256"}],"name":"SetDepositsIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetMinCrab","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SetMinUSDC","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousTolerance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newOtcPriceTolerance","type":"uint256"}],"name":"SetOTCPriceTolerance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newWithdrawsIndex","type":"uint256"}],"name":"SetWithdrawsIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isAuctionLive","type":"bool"}],"name":"ToggledAuctionLive","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositorsBalance","type":"uint256"}],"name":"USDCDeQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"usdcAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"crabAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"receiptIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"refundedETH","type":"uint256"}],"name":"USDCDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositorsBalance","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"receiptIndex","type":"uint256"}],"name":"USDCQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":false,"internalType":"uint256","name":"crabAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"WithdrawRejected","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OTC_PRICE_TOLERANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionTwapPeriod","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"bidId","type":"uint256"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isBuying","type":"bool"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Order","name":"_order","type":"tuple"}],"name":"checkOrder","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crab","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"crabBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"depositsQueued","type":"uint256"},{"internalType":"uint256","name":"minEth","type":"uint256"},{"internalType":"uint256","name":"totalDeposit","type":"uint256"},{"components":[{"internalType":"uint256","name":"bidId","type":"uint256"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isBuying","type":"bool"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Order[]","name":"orders","type":"tuple[]"},{"internalType":"uint256","name":"clearingPrice","type":"uint256"},{"internalType":"uint256","name":"ethToFlashDeposit","type":"uint256"},{"internalType":"uint24","name":"ethUSDFee","type":"uint24"},{"internalType":"uint24","name":"flashDepositFee","type":"uint24"}],"internalType":"struct DepositAuctionParams","name":"_p","type":"tuple"}],"name":"depositAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"deposits","outputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositsIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositsQueued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_force","type":"bool"}],"name":"dequeueCrab","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethSqueethPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ethUsdcPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isAuctionLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minCrabAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minUSDCAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"netAtPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonces","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"otcPriceTolerance","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":"_amount","type":"uint256"}],"name":"queueCrabForWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"rejectWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_auctionTwapPeriod","type":"uint32"}],"name":"setAuctionTwapPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newDepositsIndex","type":"uint256"}],"name":"setDepositsIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMinCrab","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMinUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"setNonceTrue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_otcPriceTolerance","type":"uint256"}],"name":"setOTCPriceTolerance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newWithdrawsIndex","type":"uint256"}],"name":"setWithdrawsIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sqth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sqthController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sqthTwapPeriod","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleAuctionLive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usdBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdc","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userDepositsIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userWithdrawsIndex","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":"uint256","name":"crabToWithdraw","type":"uint256"},{"components":[{"internalType":"uint256","name":"bidId","type":"uint256"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isBuying","type":"bool"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Order[]","name":"orders","type":"tuple[]"},{"internalType":"uint256","name":"clearingPrice","type":"uint256"},{"internalType":"uint256","name":"minUSDC","type":"uint256"},{"internalType":"uint24","name":"ethUSDFee","type":"uint24"}],"internalType":"struct WithdrawAuctionParams","name":"_p","type":"tuple"}],"name":"withdrawAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_force","type":"bool"}],"name":"withdrawUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdraws","outputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawsIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawsQueued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6102806040526000805463ffffffff60a81b1916606960aa1b17905566b1a2bc2ec500006003553480156200003357600080fd5b50604051620068f4380380620068f4833981016040819052620000569162000728565b6040518060400160405280600b81526020016a435241424e657474696e6760a81b815250604051806040016040528060018152602001603160f81b815250620000ae620000a8620006b760201b60201c565b620006bb565b815160209283012081519183019190912060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818801819052818301969096526060810194909452608080850193909352308483018190528151808603909301835260c0808601808452845194890194909420909452909252610120939093526001600160a01b038681166101808190529086166101e052633dcb0c5d60e01b909352519192633dcb0c5d9260c4808401938290030181865afa1580156200018e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b4919062000760565b6001600160a01b03166102608190526040805163412b25e560e11b815290516382564bca916004808201926020929091908290030181865afa158015620001ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000225919062000760565b6001600160a01b0316610160816001600160a01b031681525050816001600160a01b0316633fc8cef36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200027e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002a4919062000760565b6001600160a01b03166101a0816001600160a01b031681525050816001600160a01b0316637f07b1306040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000323919062000760565b6001600160a01b03166101c0816001600160a01b031681525050816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200037c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a2919062000760565b6001600160a01b0316610200816001600160a01b031681525050816001600160a01b0316634d76e6fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000421919062000760565b6001600160a01b0316610220816001600160a01b031681525050610260516001600160a01b0316634468c0226040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200047d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004a3919062000760565b6001600160a01b0316610240816001600160a01b031681525050610260516001600160a01b0316637ca251846040518163ffffffff1660e01b8152600401602060405180830381865afa158015620004ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000525919062000785565b63ffffffff16610140526101c0516101805160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af115801562000588573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005ae9190620007ad565b506101a0516101e05160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af115801562000608573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200062e9190620007ad565b50610160516101e05160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af115801562000688573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006ae9190620007ad565b505050620007d1565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200072357600080fd5b919050565b600080604083850312156200073c57600080fd5b62000747836200070b565b915062000757602084016200070b565b90509250929050565b6000602082840312156200077357600080fd5b6200077e826200070b565b9392505050565b6000602082840312156200079857600080fd5b815163ffffffff811681146200077e57600080fd5b600060208284031215620007c057600080fd5b815180151581146200077e57600080fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051615e6662000a8e600039600081816103c101526154d10152600081816108c30152818161159f01528181613c29015261514701526000818161078901528181614d040152818161505301526155aa01526000818161064c0152818161156a01528181613bf401528181614ccf0152818161501e01528181615118015261557d01526000818161087301528181611c5e0152613ec701526000818161097001528181611f5c0152818161202a01528181612229015281816136dd015281816137d201528181614d260152818161507501526155cc0152600081816102a7015281816104a4015281816115c10152818161192f01528181611a2101528181611bdf01528181611d010152818161245f015281816126c1015281816129ad015281816134230152818161392501528181613a3901528181613c4b01528181613d0d01528181613e2501528181614d48015281816150970152818161516801526155ee0152600081816102d9015281816104d801528181610add01528181610eb0015281816116eb01528181611dce01528181611eae015281816123cb015281816125d7015281816128c301528181612c4701528181612e0401528181612fae015281816134b4015281816138bf015281816145d901528181614eb20152818161522501526152af01526000818161047001528181611476015281816115e301528181611bba01528181612b8b0152818161318b0152818161332d01528181613c6d01528181613e4a0152818161406a015281816142030152818161479a01526151890152600081816106c0015261561001526000614a6901526000614ab801526000614a93015260006149ec01526000614a1601526000614a400152615e666000f3fe6080604052600436106102975760003560e01c80638da5cb5b1161015a578063d359e09e116100c1578063e9c3cb4f1161007a578063e9c3cb4f14610992578063ec13a775146109a8578063f0890dd5146109be578063f2fde38b146109d4578063f688bcfb146109f4578063f752549c14610a1457600080fd5b8063d359e09e146108b1578063d7fde229146108e5578063dc076e00146108fa578063dccb35c31461091e578063e28df0f81461093e578063e71716d21461095e57600080fd5b8063b15d566d11610113578063b15d566d146107e1578063ba53e9f214610801578063bb358d0114610821578063be20dc5614610841578063c31c9c0714610861578063cfa70b181461089557600080fd5b80638da5cb5b146107245780639e54bd94146107425780639ff69a5114610757578063a80a144514610777578063ab9f7c7f146107ab578063b02c43d0146107c157600080fd5b806355466c37116101fe578063771b4f7e116101b7578063771b4f7e1461061a5780637dc0d1d01461063a57806383cb98181461066e57806385fd0b601461068e5780638d1bbd9a146106ae5780638d86f60e146106f757600080fd5b806355466c371461054b5780635d35c81514610590578063616721a2146105b05780636b577714146105d05780636ec68625146105f0578063715018a61461060557600080fd5b80633d65fdac116102505780633d65fdac1461043e5780633e413bee1461045e5780633fc8cef3146104925780634285512d146104c65780634b277b22146104fa578063502e1a161461051057600080fd5b80631be19f4b146103395780632ad5314f1461036f57806330be6ca61461038f57806333fd7da7146103af578063351b7979146103fb5780633644e5151461041b57600080fd5b3661033457336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806102fb5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6103325760405162461bcd60e51b81526020600482015260036024820152624e323560e81b60448201526064015b60405180910390fd5b005b600080fd5b34801561034557600080fd5b5060005461035a90600160a01b900460ff1681565b60405190151581526020015b60405180910390f35b34801561037b57600080fd5b5061033261038a3660046158aa565b610a41565b34801561039b57600080fd5b506103326103aa3660046158aa565b610be4565b3480156103bb57600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610366565b34801561040757600080fd5b506103326104163660046158c3565b610c28565b34801561042757600080fd5b50610430610cd7565b604051908152602001610366565b34801561044a57600080fd5b506103326104593660046158aa565b610ce6565b34801561046a57600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b34801561049e57600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d257600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b34801561050657600080fd5b5061043060025481565b34801561051c57600080fd5b5061035a61052b366004615915565b600c60209081526000928352604080842090915290825290205460ff1681565b34801561055757600080fd5b5061056b6105663660046158aa565b610d3b565b604080516001600160a01b039094168452602084019290925290820152606001610366565b34801561059c57600080fd5b506104306105ab366004615915565b610d78565b3480156105bc57600080fd5b506103326105cb3660046158aa565b610da9565b3480156105dc57600080fd5b506103326105eb3660046159a3565b610de6565b3480156105fc57600080fd5b50610430610df2565b34801561061157600080fd5b50610332610e4e565b34801561062657600080fd5b506103326106353660046158aa565b610e62565b34801561064657600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b34801561067a57600080fd5b50610430610689366004615915565b6110a2565b34801561069a57600080fd5b506103326106a93660046158aa565b6110be565b3480156106ba57600080fd5b506106e27f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610366565b34801561070357600080fd5b50610430610712366004615a3c565b60096020526000908152604090205481565b34801561073057600080fd5b506000546001600160a01b03166103e3565b34801561074e57600080fd5b506104306110fb565b34801561076357600080fd5b506103326107723660046158aa565b611151565b34801561078357600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156107b757600080fd5b5061043060045481565b3480156107cd57600080fd5b5061056b6107dc3660046158aa565b6111d5565b3480156107ed57600080fd5b506103326107fc366004615a59565b6111e5565b34801561080d57600080fd5b5061033261081c366004615a89565b611540565b34801561082d57600080fd5b5061033261083c366004615ac5565b612b43565b34801561084d57600080fd5b5061033261085c366004615ae7565b6133f4565b34801561086d57600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156108a157600080fd5b506104306702c68af0bb14000081565b3480156108bd57600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156108f157600080fd5b506103326142da565b34801561090657600080fd5b506000546106e290600160a81b900463ffffffff1681565b34801561092a57600080fd5b50610332610939366004615a59565b614348565b34801561094a57600080fd5b506103326109593660046158aa565b614699565b34801561096a57600080fd5b506103e37f000000000000000000000000000000000000000000000000000000000000000081565b34801561099e57600080fd5b5061043060035481565b3480156109b457600080fd5b5061043060055481565b3480156109ca57600080fd5b5061043060015481565b3480156109e057600080fd5b506103326109ef366004615a3c565b6146d6565b348015610a0057600080fd5b50610332610a0f3660046158aa565b61474c565b348015610a2057600080fd5b50610430610a2f366004615a3c565b60086020526000908152604090205481565b610a49614985565b600060078281548110610a5e57610a5e615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b0316808552600182015485850181905260029092015485840152855260099092528320805492945090929091610aba908490615b4e565b90915550508051602082015160405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263a9059cbb92610b1092600401615b61565b6020604051808303816000875af1158015610b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b539190615b7a565b5060078281548110610b6757610b67615b22565b6000918252602080832060039290920290910180546001600160a01b03191681556001810183905560020191909155815182820151604080519182529281018590526001600160a01b03909116917f33bb4dad7b0e24e5b68b61b81e08d26918ca45368d5e884dbca27a0492b25ca1910160405180910390a25050565b610bec614985565b60028190556040518181527f9cd4637c18a5aa90dc4d6494990c2c947b3ac1b1fb3e501859b07dc837647f28906020015b60405180910390a150565b610c30614985565b60b48163ffffffff161015610c6d5760405162461bcd60e51b815260206004820152600360248201526209c62760eb1b6044820152606401610329565b6000805463ffffffff838116600160a81b81810263ffffffff60a81b1985161790945560408051949093049091168084526020840191909152917f0c822eb813f3e206482238798fc18dac04c64d5d1f7aa04902764a561fb49dec91015b60405180910390a15050565b6000610ce16149df565b905090565b336000818152600c6020908152604080832085845290915290819020805460ff19166001179055517fb08bc192d897ee2c202636edceef256b6c873aab9cb3dbac5d02f143180806e091610c1d918490615b61565b60078181548110610d4b57600080fd5b60009182526020909120600390910201805460018201546002909201546001600160a01b03909116925083565b600b6020528160005260406000208181548110610d9457600080fd5b90600052602060002001600091509150505481565b610db1614985565b60048190556040518181527fedd711fc4c4d0010fe15757bd2c5cb3e0e739d37a662f9e691c1c1129187162690602001610c1d565b610def81614b06565b50565b600554600090815b600754821015610e485760078281548110610e1757610e17615b22565b90600052602060002090600302016001015481610e349190615b97565b905081610e4081615baa565b925050610dfa565b92915050565b610e56614985565b610e606000614c6c565b565b600254811015610e995760405162461bcd60e51b81526020600482015260026024820152614e3560f01b6044820152606401610329565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd90610ee990339030908690600401615bc3565b6020604051808303816000875af1158015610f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2c9190615b7a565b5033600090815260096020526040902054610f48908290615b97565b33600081815260096020908152604080832094909455835160608101855283815280820186815242828701908152600780546001808201835582885294517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390920291820180546001600160a01b0319166001600160a01b0390921691909117905592517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68984015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a90920191909155938352600b9091529290209054909161103491615b4e565b8154600181810184556000938452602090932001556007546110569190615b4e565b33600081815260096020908152604091829020548251868152918201527fa0b20c5744bd90bfa023d069a8d9eb19eb0c126373e9d4b2197265d902da387f91015b60405180910390a350565b600a6020528160005260406000208181548110610d9457600080fd5b6110c6614985565b60058190556040518181527f7e92dd6744ac55122826169c9cc551bffc2f89dfeab43add7a384ae3a2c260d290602001610c1d565b600454600090815b600654821015610e48576006828154811061112057611120615b22565b9060005260206000209060030201600101548161113d9190615b97565b90508161114981615baa565b925050611103565b611159614985565b6702c68af0bb1400008111156111975760405162461bcd60e51b81526020600482015260036024820152624e313960e81b6044820152606401610329565b600380549082905560408051828152602081018490527fdc2bec2c9994acf58f0642c15c46b46d91d42495bd1c2fb789b56277f5e6ba899101610ccb565b60068181548110610d4b57600080fd5b600054600160a01b900460ff1615806111fb5750805b61122c5760405162461bcd60e51b8152602060048201526002602482015261271960f11b6044820152606401610329565b33600090815260086020526040902054611247908390615b4e565b336000908152600860205260409020819055600154111580611276575033600090815260086020526040902054155b6112a75760405162461bcd60e51b81526020600482015260026024820152614e3360f01b6044820152606401610329565b336000908152600a60205260409020548290805b801561145e57336000908152600a602052604081206006906112de600185615b4e565b815481106112ee576112ee615b22565b90600052602060002001548154811061130957611309615b22565b9060005260206000209060030201905084156113645760028101546113319062093a80615b97565b42116113645760405162461bcd60e51b8152602060048201526002602482015261138d60f21b6044820152606401610329565b838160010154111561139457838160010160008282546113849190615b4e565b909155506000945061145e915050565b60018101546113a39085615b4e565b336000908152600a602052604090209094506006906113c3600185615b4e565b815481106113d3576113d3615b22565b9060005260206000200154815481106113ee576113ee615b22565b60009182526020808320600390920290910180546001600160a01b031916815560018101839055600201829055338252600a90526040902080548061143557611435615be7565b60019003818190600052602060002001600090559055508061145681615bfd565b9150506112bb565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906114ad9033908890600401615b61565b6020604051808303816000875af11580156114cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f09190615b7a565b5033600081815260086020908152604091829020548251888152918201527f01cc9a8d1d62713e2bad4a1df8670605f491c86ab26bbe23f72dd6609d3f7ba491015b60405180910390a250505050565b611548614985565b61155781608001356000614cbc565b6000805460405163cce79bd560e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163cce79bd59161161d917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa15801561163a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165e9190615c4d565b9050816020013581600354670de0b6b3a764000061167c9190615b4e565b611687908535615c66565b6116969064e8d4a51000615c66565b6116a09190615c7d565b106116d35760405162461bcd60e51b81526020600482015260036024820152624e313160e81b6044820152606401610329565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561173a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175e9190615c4d565b90504760006117706040860135614ea0565b90508060005b6117836060880188615c9f565b9050811015611b70576117996060880188615c9f565b828181106117a9576117a9615b22565b9050610140020160800160208101906117c29190615cf0565b6117f45760405162461bcd60e51b815260206004820152600360248201526227189960e91b6044820152606401610329565b60808701356118066060890189615c9f565b8381811061181657611816615b22565b905061014002016060013510156118555760405162461bcd60e51b81526020600482015260036024820152624e313360e81b6044820152606401610329565b6118916118656060890189615c9f565b8381811061187557611875615b22565b9050610140020180360381019061188c91906159a3565b614b06565b6118f76118a16060890189615c9f565b838181106118b1576118b1615b22565b9050610140020160200160208101906118ca9190615a3c565b6118d760608a018a615c9f565b848181106118e7576118e7615b22565b9050610140020160c00135614f81565b816119056060890189615c9f565b8381811061191557611915615b22565b905061014002016040013510611a17576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd61196160608a018a615c9f565b8481811061197157611971615b22565b90506101400201602001602081019061198a9190615a3c565b30670de0b6b3a76400006119a260808d013588615c66565b6119ac9190615c7d565b6040518463ffffffff1660e01b81526004016119ca93929190615bc3565b6020604051808303816000875af11580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d9190615b7a565b5060009150611b70565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd611a5360608a018a615c9f565b84818110611a6357611a63615b22565b905061014002016020016020810190611a7c9190615a3c565b30670de0b6b3a764000060808c0135611a9860608e018e615c9f565b88818110611aa857611aa8615b22565b9050610140020160400135611abd9190615c66565b611ac79190615c7d565b6040518463ffffffff1660e01b8152600401611ae593929190615bc3565b6020604051808303816000875af1158015611b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b289190615b7a565b50611b366060880188615c9f565b82818110611b4657611b46615b22565b905061014002016040013582611b5c9190615b4e565b915080611b6881615baa565b915050611776565b508015611ba55760405162461bcd60e51b8152602060048201526003602482015262138c4d60ea1b6044820152606401610329565b60408051610100810182526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f00000000000000000000000000000000000000000000000000000000000000001660208201526000918101611c1960e08a0160c08b01615d0d565b62ffffff168152602001306001600160a01b03168152602001428152602001886000013581526020018860200135815260200160006001600160a01b031681525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663414bf389826040518263ffffffff1660e01b8152600401611ca89190615d32565b6020604051808303816000875af1158015611cc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ceb9190615c4d565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d9082906370a0823190602401602060405180830381865afa158015611d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7c9190615c4d565b6040518263ffffffff1660e01b8152600401611d9a91815260200190565b600060405180830381600087803b158015611db457600080fd5b505af1158015611dc8573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db088604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e2b57600080fd5b505af1158015611e3f573d6000803e3d6000fd5b5050505050611e6860405180606001604052806000815260200160008152602001600081525090565b611e728547615b4e565b6020820181905215801590611e8b575060008860a00135115b15611f47578760a00135816020015111611f475760208101516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fc5b73ff9060a08b0135611eeb6101008d0160e08e01615d0d565b6040516001600160e01b031960e086901b168152600481019290925262ffffff1660248201526044016000604051808303818588803b158015611f2d57600080fd5b505af1158015611f41573d6000803e3d6000fd5b50505050505b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf9190615c4d565b60408201819052925060005b611fe860608a018a615c9f565b90508110156123aa5783611fff60608b018b615c9f565b8381811061200f5761200f615b22565b9050610140020160400135101561221f576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb61205c60608c018c615c9f565b8481811061206c5761206c615b22565b9050610140020160200160208101906120859190615a3c565b61209260608d018d615c9f565b858181106120a2576120a2615b22565b90506101400201604001356040518363ffffffff1660e01b81526004016120ca929190615b61565b6020604051808303816000875af11580156120e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210d9190615b7a565b5061211b60608a018a615c9f565b8281811061212b5761212b615b22565b9050610140020160400135846121419190615b4e565b935061215060608a018a615c9f565b8281811061216057612160615b22565b9050610140020160200160208101906121799190615a3c565b6001600160a01b031661218f60608b018b615c9f565b8381811061219f5761219f615b22565b61014002919091013590507fd1d072f838d64d5c63545bc6cf88a03b39fd711611b7df5b0c0822f745044fcc6121d860608d018d615c9f565b858181106121e8576121e8615b22565b6040805161014090920293909301830135815260808f013560208201526001928101929092525060600160405180910390a3612398565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb61225b60608c018c615c9f565b8481811061226b5761226b615b22565b9050610140020160200160208101906122849190615a3c565b866040518363ffffffff1660e01b81526004016122a2929190615b61565b6020604051808303816000875af11580156122c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e59190615b7a565b506122f360608a018a615c9f565b8281811061230357612303615b22565b90506101400201602001602081019061231c9190615a3c565b6001600160a01b031661233260608b018b615c9f565b8381811061234257612342615b22565b6040805189815260808f013560208201526001818301529051610140929092029390930135927fd1d072f838d64d5c63545bc6cf88a03b39fd711611b7df5b0c0822f745044fcc925081900360600190a36123aa565b806123a281615baa565b915050611fdb565b50600480546040516370a0823160e01b8152309281019290925289359188907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561241a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243e9190615c4d565b6124489190615b4e565b83526124548747615b4e565b8360200181815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db084602001516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156124bc57600080fd5b505af11580156124d0573d6000803e3d6000fd5b50505050505b8115612b28576000600682815481106124f1576124f1615b22565b906000526020600020906003020160010154905061252960405180606001604052806000815260200160008152602001600081525090565b81600003612545578261253b81615baa565b93505050506124d6565b838211612844576125568285615b4e565b935081600860006006868154811061257057612570615b22565b600091825260208083206003909202909101546001600160a01b03168352820192909252604001812080549091906125a9908490615b4e565b909155505084518c35906125bd9084615c66565b6125c79190615c7d565b8152600680546001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb918690811061260e5761260e615b22565b600091825260209091206003909102015483516040516001600160e01b031960e085901b16815261264c926001600160a01b03169190600401615b61565b6020604051808303816000875af115801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190615b7a565b5060208501518c35906126a29084615c66565b6126ac9190615c7d565b6020820181905264e8d4a51000101561278b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb6006858154811061270157612701615b22565b600091825260209182902060039091020154908401516040516001600160e01b031960e085901b168152612742926001600160a01b03169190600401615b61565b6020604051808303816000875af1158015612761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127859190615b7a565b50612793565b600060208201525b82600684815481106127a7576127a7615b22565b600091825260209182902060039190910201548351848301516040805188815294850192909252908301526001600160a01b031690600080516020615df18339815191529060600160405180910390a36006838154811061280a5761280a615b22565b60009182526020822060039091020180546001600160a01b031916815560018101829055600201558261283c81615baa565b935050612b21565b83600860006006868154811061285c5761285c615b22565b600091825260208083206003909202909101546001600160a01b0316835282019290925260400181208054909190612895908490615b4e565b909155505084518c35906128a99086615c66565b6128b39190615c7d565b8152600680546001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91869081106128fa576128fa615b22565b600091825260209091206003909102015483516040516001600160e01b031960e085901b168152612938926001600160a01b03169190600401615b61565b6020604051808303816000875af1158015612957573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297b9190615b7a565b5060208501518c359061298e9086615c66565b6129989190615c7d565b6020820181905264e8d4a510001015612a77577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb600685815481106129ed576129ed615b22565b600091825260209182902060039091020154908401516040516001600160e01b031960e085901b168152612a2e926001600160a01b03169190600401615b61565b6020604051808303816000875af1158015612a4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a719190615b7a565b50612a7f565b600060208201525b8260068481548110612a9357612a93615b22565b60009182526020918290206003919091020154835184830151604080518a815294850192909252908301526001600160a01b031690600080516020615df18339815191529060600160405180910390a38360068481548110612af757612af7615b22565b90600052602060002090600302016001016000828254612b179190615b4e565b9091555060009450505b50506124d6565b60045550506000805460ff60a01b1916905550505050505050565b612b4b614985565b612b548261500b565b600082612b6983670de0b6b3a7640000615c66565b612b739190615c7d565b6040516370a0823160e01b81523060048201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612bda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bfe9190615c4d565b821115612c325760405162461bcd60e51b81526020600482015260026024820152614e3760f01b6044820152606401610329565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612c96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cba9190615c4d565b811115612cee5760405162461bcd60e51b815260206004820152600260248201526109c760f31b6044820152606401610329565b60045460005b831561306f57600060068381548110612d0f57612d0f615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b03168452600181015492840183905260020154908301529092509003612d675782612d5e81615baa565b93505050612cf4565b84816020015111612f0c576020810151612d819086615b4e565b945080602001516008600083600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254612dc09190615b4e565b909155505060208101518690612dde90670de0b6b3a7640000615c66565b612de89190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91612e39918690600401615b61565b6020604051808303816000875af1158015612e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e7c9190615b7a565b50805160208083015160408051918252918101859052600081830152905185926001600160a01b031691600080516020615df1833981519152919081900360600190a360068381548110612ed257612ed2615b22565b60009182526020822060039091020180546001600160a01b0319168155600181018290556002015582612f0481615baa565b935050613069565b848160200151612f1c9190615b4e565b60068481548110612f2f57612f2f615b22565b600091825260208083206001600390930201919091019290925582516001600160a01b031681526008909152604081208054879290612f6f908490615b4e565b90915550869050612f8886670de0b6b3a7640000615c66565b612f929190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91612fe3918690600401615b61565b6020604051808303816000875af1158015613002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130269190615b7a565b5080516040805187815260208101859052600081830152905185926001600160a01b031691600080516020615df1833981519152919081900360600190a3600094505b50612cf4565b600491909155600554905b82156133eb5760006007838154811061309557613095615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b031684526001810154928401839052600201549083015290925090036130ed57826130e481615baa565b9350505061307a565b8381602001511161328b5760208101516131079085615b4e565b935080602001516009600083600001516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546131469190615b4e565b90915550506020810151670de0b6b3a764000090613165908890615c66565b61316f9190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb916131c0918690600401615b61565b6020604051808303816000875af11580156131df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132039190615b7a565b5080516020808301516040805191825291810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a36007838154811061325157613251615b22565b60009182526020822060039091020180546001600160a01b031916815560018101829055600201558261328381615baa565b9350506133e5565b83816020015161329b9190615b4e565b600784815481106132ae576132ae615b22565b600091825260208083206001600390930201919091019290925582516001600160a01b0316815260099091526040812080548692906132ee908490615b4e565b90915550670de0b6b3a764000090506133078786615c66565b6133119190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91613362918690600401615b61565b6020604051808303816000875af1158015613381573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a59190615b7a565b5080516020808301516040805191825291810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a3600093505b5061307a565b50600555505050565b6133fc614985565b61340b81604001356001614cbc565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613472573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134969190615c4d565b60405163f73e19c360e01b81528335600482015290915047906000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f73e19c390602401602060405180830381865afa158015613503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135279190615c4d565b90508060005b61353a6020870187615c9f565b90508110801561354a5750600082115b156138a85761355f6118656020880188615c9f565b6135a561356f6020880188615c9f565b8381811061357f5761357f615b22565b9050610140020160200160208101906135989190615a3c565b6118d76020890189615c9f565b6135b26020870187615c9f565b828181106135c2576135c2615b22565b9050610140020160800160208101906135db9190615cf0565b1561360e5760405162461bcd60e51b81526020600482015260036024820152624e313560e81b6044820152606401610329565b60408601356136206020880188615c9f565b8381811061363057613630615b22565b9050610140020160600135111561366f5760405162461bcd60e51b815260206004820152600360248201526227189b60e91b6044820152606401610329565b8161367d6020880188615c9f565b8381811061368d5761368d615b22565b905061014002016040013510156137c8576136ab6020870187615c9f565b828181106136bb576136bb615b22565b9050610140020160400135826136d19190615b4e565b91506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd61370f6020890189615c9f565b8481811061371f5761371f615b22565b9050610140020160200160208101906137389190615a3c565b3061374660208b018b615c9f565b8681811061375657613756615b22565b90506101400201604001356040518463ffffffff1660e01b815260040161377f93929190615bc3565b6020604051808303816000875af115801561379e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c29190615b7a565b50613896565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd6138046020890189615c9f565b8481811061381457613814615b22565b90506101400201602001602081019061382d9190615a3c565b30856040518463ffffffff1660e01b815260040161384d93929190615bc3565b6020604051808303816000875af115801561386c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138909190615b7a565b50600091505b806138a081615baa565b91505061352d565b50604051632e1a7d4d60e01b8152853560048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561390b57600080fd5b505af115801561391f573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0844761395e9190615b4e565b6040518263ffffffff1660e01b81526004016000604051808303818588803b15801561398957600080fd5b505af115801561399d573d6000803e3d6000fd5b508594506000935083925050505b6139b86020880188615c9f565b9050811080156139c85750600083115b15613be057826139db6020890189615c9f565b838181106139eb576139eb615b22565b90506101400201604001351015613a2b57613a096020880188615c9f565b82818110613a1957613a19615b22565b90506101400201604001359150613a2f565b8291505b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb613a6b60208a018a615c9f565b84818110613a7b57613a7b615b22565b905061014002016020016020810190613a949190615a3c565b670de0b6b3a7640000613aab60408c013587615c66565b613ab59190615c7d565b6040518363ffffffff1660e01b8152600401613ad2929190615b61565b6020604051808303816000875af1158015613af1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b159190615b7a565b50613b208284615b4e565b9250613b2f6020880188615c9f565b82818110613b3f57613b3f615b22565b905061014002016020016020810190613b589190615a3c565b6001600160a01b0316613b6e6020890189615c9f565b83818110613b7e57613b7e615b22565b604080518781528c82013560208201526000818301529051610140929092029390930135927fd1d072f838d64d5c63545bc6cf88a03b39fd711611b7df5b0c0822f745044fcc925081900360600190a380613bd881615baa565b9150506139ab565b506000805460405163cce79bd560e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163cce79bd591613ca7917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa158015613cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ce89190615c4d565b6040516370a0823160e01b815230600482015290915060009087906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015613d54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d789190615c4d565b613d829190615b4e565b9050876060013564e8d4a510006ec097ce7bc90715b34b9f1000000000600354670de0b6b3a7640000613db59190615b4e565b613dbf8686615c66565b613dc99190615c66565b613dd39190615c7d565b613ddd9190615c7d565b10613e105760405162461bcd60e51b81526020600482015260036024820152624e313760e81b6044820152606401610329565b60408051610100810182526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f00000000000000000000000000000000000000000000000000000000000000001660208201526000918101613e8460a08c0160808d01615d0d565b62ffffff168152602001306001600160a01b031681526020014281526020018381526020018a60600135815260200160006001600160a01b0316815250905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663414bf389836040518263ffffffff1660e01b8152600401613f119190615d32565b6020604051808303816000875af1158015613f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f549190615c4d565b6005549091508a359060005b82156142bc57600060078381548110613f7b57613f7b615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b03168452600181015492840183905260020154908301529092509003613fd35782613fca81615baa565b93505050613f60565b8381602001511161416a576020810151613fed9085615b4e565b935080602001516009600083600001516001600160a01b03166001600160a01b03168152602001908152602001600020600082825461402c9190615b4e565b909155505060208101518e3590614044908790615c66565b61404e9190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb9161409f918690600401615b61565b6020604051808303816000875af11580156140be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140e29190615b7a565b5080516020808301516040805191825291810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a36007838154811061413057614130615b22565b60009182526020822060039091020180546001600160a01b031916815560018101829055600201558261416281615baa565b9350506142b6565b836007848154811061417e5761417e615b22565b9060005260206000209060030201600101600082825461419e9190615b4e565b909155505080516001600160a01b0316600090815260096020526040812080548692906141cc908490615b4e565b90915550508d356141dd8686615c66565b6141e79190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb91614238918690600401615b61565b6020604051808303816000875af1158015614257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061427b9190615b7a565b508051604080518681526020810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a3600093505b50613f60565b5060055550506000805460ff60a01b19169055505050505050505050565b6142e2614985565b6000805460ff600160a01b808304821615810260ff60a01b1990931692909217928390556040517fe6161233d7b23251971fb55c60874862ed7a143c115402afa8e1f2c07a131add9361433e9390049091161515815260200190565b60405180910390a1565b600054600160a01b900460ff16158061435e5750805b61438f5760405162461bcd60e51b8152602060048201526002602482015261271960f11b6044820152606401610329565b336000908152600960205260409020546143aa908390615b4e565b3360009081526009602052604090208190556002541115806143d9575033600090815260096020526040902054155b61440a5760405162461bcd60e51b8152602060048201526002602482015261271b60f11b6044820152606401610329565b336000908152600b60205260409020548290805b80156145c157336000908152600b60205260408120600790614441600185615b4e565b8154811061445157614451615b22565b90600052602060002001548154811061446c5761446c615b22565b9060005260206000209060030201905084156144c75760028101546144949062093a80615b97565b42116144c75760405162461bcd60e51b8152602060048201526002602482015261138d60f21b6044820152606401610329565b83816001015411156144f757838160010160008282546144e79190615b4e565b90915550600094506145c1915050565b60018101546145069085615b4e565b336000908152600b60205260409020909450600790614526600185615b4e565b8154811061453657614536615b22565b90600052602060002001548154811061455157614551615b22565b60009182526020808320600390920290910180546001600160a01b031916815560018101839055600201829055338252600b90526040902080548061459857614598615be7565b6001900381819060005260206000200160009055905550806145b981615bfd565b91505061441e565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906146109033908890600401615b61565b6020604051808303816000875af115801561462f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146539190615b7a565b5033600081815260096020908152604091829020548251888152918201527f4f4b6ab83d39fce2cc703aa2ac1d003ccd5b4781b4a561c1c586ef2e84e4d8cb9101611532565b6146a1614985565b60018190556040518181527f2217b276de774d686f6d9419505080eeee1f2a9e95ef298c5b4266f56eb6272790602001610c1d565b6146de614985565b6001600160a01b0381166147435760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610329565b610def81614c6c565b6001548110156147835760405162461bcd60e51b81526020600482015260026024820152614e3160f01b6044820152606401610329565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906147d390339030908690600401615bc3565b6020604051808303816000875af11580156147f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148169190615b7a565b5033600090815260086020526040902054614832908290615b97565b33600081815260086020908152604080832094909455835160608101855283815280820186815242828701908152600680546001808201835582885294517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f600390920291820180546001600160a01b0319166001600160a01b0390921691909117905592517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4084015590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4190920191909155938352600a9091529290209054909161491e91615b4e565b8154600181810184556000938452602090932001556006546149409190615b4e565b33600081815260086020908152604091829020548251868152918201527fcd8a16e288c9b610f6bd123e0ed3f6aa008681653a19936f37bb6b2feb17ee8f9101611097565b6000546001600160a01b03163314610e605760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610329565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015614a3857507f000000000000000000000000000000000000000000000000000000000000000046145b15614a6257507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001614b9f98979695949392919097885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b6040516020818303038152906040528051906020012090506000614bc282615456565b90506000614be0828560e001518661010001518761012001516154a4565b905083602001516001600160a01b0316816001600160a01b031614614c2c5760405162461bcd60e51b81526020600482015260026024820152614e3960f01b6044820152606401610329565b428460a001511015614c665760405162461bcd60e51b815260206004820152600360248201526204e31360ec1b6044820152606401610329565b50505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000805460405163cce79bd560e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163cce79bd591614d82917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa158015614d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614dc39190615c4d565b90508115614e3857670de0b6b3a7640000600354670de0b6b3a7640000614dea9190615b97565b614df49083615c66565b614dfe9190615c7d565b831115614e335760405162461bcd60e51b81526020600482015260036024820152624e323160e81b6044820152606401610329565b505050565b670de0b6b3a7640000600354670de0b6b3a7640000614e579190615b4e565b614e619083615c66565b614e6b9190615c7d565b831015614e335760405162461bcd60e51b815260206004820152600360248201526227191960e91b6044820152606401610329565b600080614eab6154cc565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663533092ef6040518163ffffffff1660e01b8152600401608060405180830381865afa158015614f0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f329190615d9b565b9350935050506000670de0b6b3a76400008483614f4f9190615c66565b614f599190615c7d565b614f639084615b97565b614f6d8388615c66565b614f779190615c7d565b9695505050505050565b6001600160a01b0382166000908152600c6020908152604080832084845290915290205460ff1615614fdb5760405162461bcd60e51b815260206004820152600360248201526204e32360ec1b6044820152606401610329565b6001600160a01b039091166000908152600c6020908152604080832093835292905220805460ff19166001179055565b6000805460405163cce79bd560e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163cce79bd5916150d1917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa1580156150ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151129190615c4d565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cce79bd57f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000600060159054906101000a900463ffffffff1660016040518663ffffffff1660e01b81526004016151dd959493929190615c14565b602060405180830381865afa1580156151fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061521e9190615c4d565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663533092ef6040518163ffffffff1660e01b8152600401608060405180830381865afa158015615281573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152a59190615d9b565b93509350505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561530b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061532f9190615c4d565b84670de0b6b3a76400006153438886615c66565b61534d9190615c7d565b6153579086615b4e565b6153619190615c66565b61536b9190615c7d565b905061537c64e8d4a5100082615c7d565b9050670de0b6b3a7640000600354670de0b6b3a764000061539d9190615b97565b6153a79083615c66565b6153b19190615c7d565b8611156153e65760405162461bcd60e51b81526020600482015260036024820152624e323360e81b6044820152606401610329565b670de0b6b3a7640000600354670de0b6b3a76400006154059190615b4e565b61540f9083615c66565b6154199190615c7d565b86101561544e5760405162461bcd60e51b8152602060048201526003602482015262138c8d60ea1b6044820152606401610329565b505050505050565b6000610e486154636149df565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006154b58787878761569c565b915091506154c281615760565b5095945050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663978bbdb96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561552d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906155519190615c4d565b90508060000361556357600091505090565b60405163cce79bd560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cce79bd59061563b907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090600190600401615c14565b602060405180830381865afa158015615658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061567c9190615c4d565b905061271061568b8383615c66565b6156959190615c7d565b9250505090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156156d35750600090506003615757565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015615727573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661575057600060019250925050615757565b9150600090505b94509492505050565b600081600481111561577457615774615dda565b0361577c5750565b600181600481111561579057615790615dda565b036157dd5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610329565b60028160048111156157f1576157f1615dda565b0361583e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610329565b600381600481111561585257615852615dda565b03610def5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610329565b6000602082840312156158bc57600080fd5b5035919050565b6000602082840312156158d557600080fd5b813563ffffffff811681146158e957600080fd5b9392505050565b6001600160a01b0381168114610def57600080fd5b8035615910816158f0565b919050565b6000806040838503121561592857600080fd5b8235615933816158f0565b946020939093013593505050565b604051610140810167ffffffffffffffff8111828210171561597357634e487b7160e01b600052604160045260246000fd5b60405290565b8015158114610def57600080fd5b803561591081615979565b803560ff8116811461591057600080fd5b600061014082840312156159b657600080fd5b6159be615941565b823581526159ce60208401615905565b602082015260408301356040820152606083013560608201526159f360808401615987565b608082015260a083013560a082015260c083013560c0820152615a1860e08401615992565b60e08201526101008381013590820152610120928301359281019290925250919050565b600060208284031215615a4e57600080fd5b81356158e9816158f0565b60008060408385031215615a6c57600080fd5b823591506020830135615a7e81615979565b809150509250929050565b600060208284031215615a9b57600080fd5b813567ffffffffffffffff811115615ab257600080fd5b820161010081850312156158e957600080fd5b60008060408385031215615ad857600080fd5b50508035926020909101359150565b600060208284031215615af957600080fd5b813567ffffffffffffffff811115615b1057600080fd5b820160a081850312156158e957600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610e4857610e48615b38565b6001600160a01b03929092168252602082015260400190565b600060208284031215615b8c57600080fd5b81516158e981615979565b80820180821115610e4857610e48615b38565b600060018201615bbc57615bbc615b38565b5060010190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603160045260246000fd5b600081615c0c57615c0c615b38565b506000190190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b600060208284031215615c5f57600080fd5b5051919050565b8082028115828204841417610e4857610e48615b38565b600082615c9a57634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e19843603018112615cb657600080fd5b83018035915067ffffffffffffffff821115615cd157600080fd5b602001915061014081023603821315615ce957600080fd5b9250929050565b600060208284031215615d0257600080fd5b81356158e981615979565b600060208284031215615d1f57600080fd5b813562ffffff811681146158e957600080fd5b81516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b60008060008060808587031215615db157600080fd5b8451615dbc816158f0565b60208601516040870151606090970151919890975090945092505050565b634e487b7160e01b600052602160045260246000fdfef407c5a0c99a9a3d15fe5a46a4aba5ce747e855b58bc1aec4a589fd53bda599e460140ba175e3953a9d581c92fd2fc50c428691b4220431ff4a3f08c62aa3906a2646970667358221220851c03f17b6117b7277341d79c60c79cc765d347623650558859db49b5afd68d64736f6c634300081100330000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Deployed Bytecode
0x6080604052600436106102975760003560e01c80638da5cb5b1161015a578063d359e09e116100c1578063e9c3cb4f1161007a578063e9c3cb4f14610992578063ec13a775146109a8578063f0890dd5146109be578063f2fde38b146109d4578063f688bcfb146109f4578063f752549c14610a1457600080fd5b8063d359e09e146108b1578063d7fde229146108e5578063dc076e00146108fa578063dccb35c31461091e578063e28df0f81461093e578063e71716d21461095e57600080fd5b8063b15d566d11610113578063b15d566d146107e1578063ba53e9f214610801578063bb358d0114610821578063be20dc5614610841578063c31c9c0714610861578063cfa70b181461089557600080fd5b80638da5cb5b146107245780639e54bd94146107425780639ff69a5114610757578063a80a144514610777578063ab9f7c7f146107ab578063b02c43d0146107c157600080fd5b806355466c37116101fe578063771b4f7e116101b7578063771b4f7e1461061a5780637dc0d1d01461063a57806383cb98181461066e57806385fd0b601461068e5780638d1bbd9a146106ae5780638d86f60e146106f757600080fd5b806355466c371461054b5780635d35c81514610590578063616721a2146105b05780636b577714146105d05780636ec68625146105f0578063715018a61461060557600080fd5b80633d65fdac116102505780633d65fdac1461043e5780633e413bee1461045e5780633fc8cef3146104925780634285512d146104c65780634b277b22146104fa578063502e1a161461051057600080fd5b80631be19f4b146103395780632ad5314f1461036f57806330be6ca61461038f57806333fd7da7146103af578063351b7979146103fb5780633644e5151461041b57600080fd5b3661033457336001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21614806102fb5750336001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e816145b6103325760405162461bcd60e51b81526020600482015260036024820152624e323560e81b60448201526064015b60405180910390fd5b005b600080fd5b34801561034557600080fd5b5060005461035a90600160a01b900460ff1681565b60405190151581526020015b60405180910390f35b34801561037b57600080fd5b5061033261038a3660046158aa565b610a41565b34801561039b57600080fd5b506103326103aa3660046158aa565b610be4565b3480156103bb57600080fd5b506103e37f00000000000000000000000064187ae08781b09368e6253f9e94951243a493d581565b6040516001600160a01b039091168152602001610366565b34801561040757600080fd5b506103326104163660046158c3565b610c28565b34801561042757600080fd5b50610430610cd7565b604051908152602001610366565b34801561044a57600080fd5b506103326104593660046158aa565b610ce6565b34801561046a57600080fd5b506103e37f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b34801561049e57600080fd5b506103e37f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b3480156104d257600080fd5b506103e37f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e881565b34801561050657600080fd5b5061043060025481565b34801561051c57600080fd5b5061035a61052b366004615915565b600c60209081526000928352604080842090915290825290205460ff1681565b34801561055757600080fd5b5061056b6105663660046158aa565b610d3b565b604080516001600160a01b039094168452602084019290925290820152606001610366565b34801561059c57600080fd5b506104306105ab366004615915565b610d78565b3480156105bc57600080fd5b506103326105cb3660046158aa565b610da9565b3480156105dc57600080fd5b506103326105eb3660046159a3565b610de6565b3480156105fc57600080fd5b50610430610df2565b34801561061157600080fd5b50610332610e4e565b34801561062657600080fd5b506103326106353660046158aa565b610e62565b34801561064657600080fd5b506103e37f00000000000000000000000065d66c76447ccb45daf1e8044e918fa786a483a181565b34801561067a57600080fd5b50610430610689366004615915565b6110a2565b34801561069a57600080fd5b506103326106a93660046158aa565b6110be565b3480156106ba57600080fd5b506106e27f00000000000000000000000000000000000000000000000000000000000001a481565b60405163ffffffff9091168152602001610366565b34801561070357600080fd5b50610430610712366004615a3c565b60096020526000908152604090205481565b34801561073057600080fd5b506000546001600160a01b03166103e3565b34801561074e57600080fd5b506104306110fb565b34801561076357600080fd5b506103326107723660046158aa565b611151565b34801561078357600080fd5b506103e37f00000000000000000000000082c427adfdf2d245ec51d8046b41c4ee87f0d29c81565b3480156107b757600080fd5b5061043060045481565b3480156107cd57600080fd5b5061056b6107dc3660046158aa565b6111d5565b3480156107ed57600080fd5b506103326107fc366004615a59565b6111e5565b34801561080d57600080fd5b5061033261081c366004615a89565b611540565b34801561082d57600080fd5b5061033261083c366004615ac5565b612b43565b34801561084d57600080fd5b5061033261085c366004615ae7565b6133f4565b34801561086d57600080fd5b506103e37f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b3480156108a157600080fd5b506104306702c68af0bb14000081565b3480156108bd57600080fd5b506103e37f0000000000000000000000008ad599c3a0ff1de082011efddc58f1908eb6e6d881565b3480156108f157600080fd5b506103326142da565b34801561090657600080fd5b506000546106e290600160a81b900463ffffffff1681565b34801561092a57600080fd5b50610332610939366004615a59565b614348565b34801561094a57600080fd5b506103326109593660046158aa565b614699565b34801561096a57600080fd5b506103e37f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b81565b34801561099e57600080fd5b5061043060035481565b3480156109b457600080fd5b5061043060055481565b3480156109ca57600080fd5b5061043060015481565b3480156109e057600080fd5b506103326109ef366004615a3c565b6146d6565b348015610a0057600080fd5b50610332610a0f3660046158aa565b61474c565b348015610a2057600080fd5b50610430610a2f366004615a3c565b60086020526000908152604090205481565b610a49614985565b600060078281548110610a5e57610a5e615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b0316808552600182015485850181905260029092015485840152855260099092528320805492945090929091610aba908490615b4e565b90915550508051602082015160405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8169263a9059cbb92610b1092600401615b61565b6020604051808303816000875af1158015610b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b539190615b7a565b5060078281548110610b6757610b67615b22565b6000918252602080832060039290920290910180546001600160a01b03191681556001810183905560020191909155815182820151604080519182529281018590526001600160a01b03909116917f33bb4dad7b0e24e5b68b61b81e08d26918ca45368d5e884dbca27a0492b25ca1910160405180910390a25050565b610bec614985565b60028190556040518181527f9cd4637c18a5aa90dc4d6494990c2c947b3ac1b1fb3e501859b07dc837647f28906020015b60405180910390a150565b610c30614985565b60b48163ffffffff161015610c6d5760405162461bcd60e51b815260206004820152600360248201526209c62760eb1b6044820152606401610329565b6000805463ffffffff838116600160a81b81810263ffffffff60a81b1985161790945560408051949093049091168084526020840191909152917f0c822eb813f3e206482238798fc18dac04c64d5d1f7aa04902764a561fb49dec91015b60405180910390a15050565b6000610ce16149df565b905090565b336000818152600c6020908152604080832085845290915290819020805460ff19166001179055517fb08bc192d897ee2c202636edceef256b6c873aab9cb3dbac5d02f143180806e091610c1d918490615b61565b60078181548110610d4b57600080fd5b60009182526020909120600390910201805460018201546002909201546001600160a01b03909116925083565b600b6020528160005260406000208181548110610d9457600080fd5b90600052602060002001600091509150505481565b610db1614985565b60048190556040518181527fedd711fc4c4d0010fe15757bd2c5cb3e0e739d37a662f9e691c1c1129187162690602001610c1d565b610def81614b06565b50565b600554600090815b600754821015610e485760078281548110610e1757610e17615b22565b90600052602060002090600302016001015481610e349190615b97565b905081610e4081615baa565b925050610dfa565b92915050565b610e56614985565b610e606000614c6c565b565b600254811015610e995760405162461bcd60e51b81526020600482015260026024820152614e3560f01b6044820152606401610329565b6040516323b872dd60e01b81526001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e816906323b872dd90610ee990339030908690600401615bc3565b6020604051808303816000875af1158015610f08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2c9190615b7a565b5033600090815260096020526040902054610f48908290615b97565b33600081815260096020908152604080832094909455835160608101855283815280820186815242828701908152600780546001808201835582885294517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688600390920291820180546001600160a01b0319166001600160a01b0390921691909117905592517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68984015590517fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a90920191909155938352600b9091529290209054909161103491615b4e565b8154600181810184556000938452602090932001556007546110569190615b4e565b33600081815260096020908152604091829020548251868152918201527fa0b20c5744bd90bfa023d069a8d9eb19eb0c126373e9d4b2197265d902da387f91015b60405180910390a350565b600a6020528160005260406000208181548110610d9457600080fd5b6110c6614985565b60058190556040518181527f7e92dd6744ac55122826169c9cc551bffc2f89dfeab43add7a384ae3a2c260d290602001610c1d565b600454600090815b600654821015610e48576006828154811061112057611120615b22565b9060005260206000209060030201600101548161113d9190615b97565b90508161114981615baa565b925050611103565b611159614985565b6702c68af0bb1400008111156111975760405162461bcd60e51b81526020600482015260036024820152624e313960e81b6044820152606401610329565b600380549082905560408051828152602081018490527fdc2bec2c9994acf58f0642c15c46b46d91d42495bd1c2fb789b56277f5e6ba899101610ccb565b60068181548110610d4b57600080fd5b600054600160a01b900460ff1615806111fb5750805b61122c5760405162461bcd60e51b8152602060048201526002602482015261271960f11b6044820152606401610329565b33600090815260086020526040902054611247908390615b4e565b336000908152600860205260409020819055600154111580611276575033600090815260086020526040902054155b6112a75760405162461bcd60e51b81526020600482015260026024820152614e3360f01b6044820152606401610329565b336000908152600a60205260409020548290805b801561145e57336000908152600a602052604081206006906112de600185615b4e565b815481106112ee576112ee615b22565b90600052602060002001548154811061130957611309615b22565b9060005260206000209060030201905084156113645760028101546113319062093a80615b97565b42116113645760405162461bcd60e51b8152602060048201526002602482015261138d60f21b6044820152606401610329565b838160010154111561139457838160010160008282546113849190615b4e565b909155506000945061145e915050565b60018101546113a39085615b4e565b336000908152600a602052604090209094506006906113c3600185615b4e565b815481106113d3576113d3615b22565b9060005260206000200154815481106113ee576113ee615b22565b60009182526020808320600390920290910180546001600160a01b031916815560018101839055600201829055338252600a90526040902080548061143557611435615be7565b60019003818190600052602060002001600090559055508061145681615bfd565b9150506112bb565b5060405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48169063a9059cbb906114ad9033908890600401615b61565b6020604051808303816000875af11580156114cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f09190615b7a565b5033600081815260086020908152604091829020548251888152918201527f01cc9a8d1d62713e2bad4a1df8670605f491c86ab26bbe23f72dd6609d3f7ba491015b60405180910390a250505050565b611548614985565b61155781608001356000614cbc565b6000805460405163cce79bd560e01b81527f00000000000000000000000065d66c76447ccb45daf1e8044e918fa786a483a16001600160a01b03169163cce79bd59161161d917f0000000000000000000000008ad599c3a0ff1de082011efddc58f1908eb6e6d8917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2917f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4891600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa15801561163a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165e9190615c4d565b9050816020013581600354670de0b6b3a764000061167c9190615b4e565b611687908535615c66565b6116969064e8d4a51000615c66565b6116a09190615c7d565b106116d35760405162461bcd60e51b81526020600482015260036024820152624e313160e81b6044820152606401610329565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b0316906370a0823190602401602060405180830381865afa15801561173a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175e9190615c4d565b90504760006117706040860135614ea0565b90508060005b6117836060880188615c9f565b9050811015611b70576117996060880188615c9f565b828181106117a9576117a9615b22565b9050610140020160800160208101906117c29190615cf0565b6117f45760405162461bcd60e51b815260206004820152600360248201526227189960e91b6044820152606401610329565b60808701356118066060890189615c9f565b8381811061181657611816615b22565b905061014002016060013510156118555760405162461bcd60e51b81526020600482015260036024820152624e313360e81b6044820152606401610329565b6118916118656060890189615c9f565b8381811061187557611875615b22565b9050610140020180360381019061188c91906159a3565b614b06565b6118f76118a16060890189615c9f565b838181106118b1576118b1615b22565b9050610140020160200160208101906118ca9190615a3c565b6118d760608a018a615c9f565b848181106118e7576118e7615b22565b9050610140020160c00135614f81565b816119056060890189615c9f565b8381811061191557611915615b22565b905061014002016040013510611a17576001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166323b872dd61196160608a018a615c9f565b8481811061197157611971615b22565b90506101400201602001602081019061198a9190615a3c565b30670de0b6b3a76400006119a260808d013588615c66565b6119ac9190615c7d565b6040518463ffffffff1660e01b81526004016119ca93929190615bc3565b6020604051808303816000875af11580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d9190615b7a565b5060009150611b70565b6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2166323b872dd611a5360608a018a615c9f565b84818110611a6357611a63615b22565b905061014002016020016020810190611a7c9190615a3c565b30670de0b6b3a764000060808c0135611a9860608e018e615c9f565b88818110611aa857611aa8615b22565b9050610140020160400135611abd9190615c66565b611ac79190615c7d565b6040518463ffffffff1660e01b8152600401611ae593929190615bc3565b6020604051808303816000875af1158015611b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b289190615b7a565b50611b366060880188615c9f565b82818110611b4657611b46615b22565b905061014002016040013582611b5c9190615b4e565b915080611b6881615baa565b915050611776565b508015611ba55760405162461bcd60e51b8152602060048201526003602482015262138c4d60ea1b6044820152606401610329565b60408051610100810182526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811682527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21660208201526000918101611c1960e08a0160c08b01615d0d565b62ffffff168152602001306001600160a01b03168152602001428152602001886000013581526020018860200135815260200160006001600160a01b031681525090507f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b031663414bf389826040518263ffffffff1660e01b8152600401611ca89190615d32565b6020604051808303816000875af1158015611cc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ceb9190615c4d565b506040516370a0823160e01b81523060048201527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031690632e1a7d4d9082906370a0823190602401602060405180830381865afa158015611d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7c9190615c4d565b6040518263ffffffff1660e01b8152600401611d9a91815260200190565b600060405180830381600087803b158015611db457600080fd5b505af1158015611dc8573d6000803e3d6000fd5b505050507f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b031663d0e30db088604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e2b57600080fd5b505af1158015611e3f573d6000803e3d6000fd5b5050505050611e6860405180606001604052806000815260200160008152602001600081525090565b611e728547615b4e565b6020820181905215801590611e8b575060008860a00135115b15611f47578760a00135816020015111611f475760208101516001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8169063fc5b73ff9060a08b0135611eeb6101008d0160e08e01615d0d565b6040516001600160e01b031960e086901b168152600481019290925262ffffff1660248201526044016000604051808303818588803b158015611f2d57600080fd5b505af1158015611f41573d6000803e3d6000fd5b50505050505b6040516370a0823160e01b81523060048201527f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b6001600160a01b0316906370a0823190602401602060405180830381865afa158015611fab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fcf9190615c4d565b60408201819052925060005b611fe860608a018a615c9f565b90508110156123aa5783611fff60608b018b615c9f565b8381811061200f5761200f615b22565b9050610140020160400135101561221f576001600160a01b037f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b1663a9059cbb61205c60608c018c615c9f565b8481811061206c5761206c615b22565b9050610140020160200160208101906120859190615a3c565b61209260608d018d615c9f565b858181106120a2576120a2615b22565b90506101400201604001356040518363ffffffff1660e01b81526004016120ca929190615b61565b6020604051808303816000875af11580156120e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061210d9190615b7a565b5061211b60608a018a615c9f565b8281811061212b5761212b615b22565b9050610140020160400135846121419190615b4e565b935061215060608a018a615c9f565b8281811061216057612160615b22565b9050610140020160200160208101906121799190615a3c565b6001600160a01b031661218f60608b018b615c9f565b8381811061219f5761219f615b22565b61014002919091013590507fd1d072f838d64d5c63545bc6cf88a03b39fd711611b7df5b0c0822f745044fcc6121d860608d018d615c9f565b858181106121e8576121e8615b22565b6040805161014090920293909301830135815260808f013560208201526001928101929092525060600160405180910390a3612398565b6001600160a01b037f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b1663a9059cbb61225b60608c018c615c9f565b8481811061226b5761226b615b22565b9050610140020160200160208101906122849190615a3c565b866040518363ffffffff1660e01b81526004016122a2929190615b61565b6020604051808303816000875af11580156122c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e59190615b7a565b506122f360608a018a615c9f565b8281811061230357612303615b22565b90506101400201602001602081019061231c9190615a3c565b6001600160a01b031661233260608b018b615c9f565b8381811061234257612342615b22565b6040805189815260808f013560208201526001818301529051610140929092029390930135927fd1d072f838d64d5c63545bc6cf88a03b39fd711611b7df5b0c0822f745044fcc925081900360600190a36123aa565b806123a281615baa565b915050611fdb565b50600480546040516370a0823160e01b8152309281019290925289359188907f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b0316906370a0823190602401602060405180830381865afa15801561241a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243e9190615c4d565b6124489190615b4e565b83526124548747615b4e565b8360200181815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db084602001516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156124bc57600080fd5b505af11580156124d0573d6000803e3d6000fd5b50505050505b8115612b28576000600682815481106124f1576124f1615b22565b906000526020600020906003020160010154905061252960405180606001604052806000815260200160008152602001600081525090565b81600003612545578261253b81615baa565b93505050506124d6565b838211612844576125568285615b4e565b935081600860006006868154811061257057612570615b22565b600091825260208083206003909202909101546001600160a01b03168352820192909252604001812080549091906125a9908490615b4e565b909155505084518c35906125bd9084615c66565b6125c79190615c7d565b8152600680546001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8169163a9059cbb918690811061260e5761260e615b22565b600091825260209091206003909102015483516040516001600160e01b031960e085901b16815261264c926001600160a01b03169190600401615b61565b6020604051808303816000875af115801561266b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268f9190615b7a565b5060208501518c35906126a29084615c66565b6126ac9190615c7d565b6020820181905264e8d4a51000101561278b577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663a9059cbb6006858154811061270157612701615b22565b600091825260209182902060039091020154908401516040516001600160e01b031960e085901b168152612742926001600160a01b03169190600401615b61565b6020604051808303816000875af1158015612761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127859190615b7a565b50612793565b600060208201525b82600684815481106127a7576127a7615b22565b600091825260209182902060039190910201548351848301516040805188815294850192909252908301526001600160a01b031690600080516020615df18339815191529060600160405180910390a36006838154811061280a5761280a615b22565b60009182526020822060039091020180546001600160a01b031916815560018101829055600201558261283c81615baa565b935050612b21565b83600860006006868154811061285c5761285c615b22565b600091825260208083206003909202909101546001600160a01b0316835282019290925260400181208054909190612895908490615b4e565b909155505084518c35906128a99086615c66565b6128b39190615c7d565b8152600680546001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8169163a9059cbb91869081106128fa576128fa615b22565b600091825260209091206003909102015483516040516001600160e01b031960e085901b168152612938926001600160a01b03169190600401615b61565b6020604051808303816000875af1158015612957573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061297b9190615b7a565b5060208501518c359061298e9086615c66565b6129989190615c7d565b6020820181905264e8d4a510001015612a77577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663a9059cbb600685815481106129ed576129ed615b22565b600091825260209182902060039091020154908401516040516001600160e01b031960e085901b168152612a2e926001600160a01b03169190600401615b61565b6020604051808303816000875af1158015612a4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a719190615b7a565b50612a7f565b600060208201525b8260068481548110612a9357612a93615b22565b60009182526020918290206003919091020154835184830151604080518a815294850192909252908301526001600160a01b031690600080516020615df18339815191529060600160405180910390a38360068481548110612af757612af7615b22565b90600052602060002090600302016001016000828254612b179190615b4e565b9091555060009450505b50506124d6565b60045550506000805460ff60a01b1916905550505050505050565b612b4b614985565b612b548261500b565b600082612b6983670de0b6b3a7640000615c66565b612b739190615c7d565b6040516370a0823160e01b81523060048201529091507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316906370a0823190602401602060405180830381865afa158015612bda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bfe9190615c4d565b821115612c325760405162461bcd60e51b81526020600482015260026024820152614e3760f01b6044820152606401610329565b6040516370a0823160e01b81523060048201527f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b0316906370a0823190602401602060405180830381865afa158015612c96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cba9190615c4d565b811115612cee5760405162461bcd60e51b815260206004820152600260248201526109c760f31b6044820152606401610329565b60045460005b831561306f57600060068381548110612d0f57612d0f615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b03168452600181015492840183905260020154908301529092509003612d675782612d5e81615baa565b93505050612cf4565b84816020015111612f0c576020810151612d819086615b4e565b945080602001516008600083600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254612dc09190615b4e565b909155505060208101518690612dde90670de0b6b3a7640000615c66565b612de89190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8169163a9059cbb91612e39918690600401615b61565b6020604051808303816000875af1158015612e58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e7c9190615b7a565b50805160208083015160408051918252918101859052600081830152905185926001600160a01b031691600080516020615df1833981519152919081900360600190a360068381548110612ed257612ed2615b22565b60009182526020822060039091020180546001600160a01b0319168155600181018290556002015582612f0481615baa565b935050613069565b848160200151612f1c9190615b4e565b60068481548110612f2f57612f2f615b22565b600091825260208083206001600390930201919091019290925582516001600160a01b031681526008909152604081208054879290612f6f908490615b4e565b90915550869050612f8886670de0b6b3a7640000615c66565b612f929190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8169163a9059cbb91612fe3918690600401615b61565b6020604051808303816000875af1158015613002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130269190615b7a565b5080516040805187815260208101859052600081830152905185926001600160a01b031691600080516020615df1833981519152919081900360600190a3600094505b50612cf4565b600491909155600554905b82156133eb5760006007838154811061309557613095615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b031684526001810154928401839052600201549083015290925090036130ed57826130e481615baa565b9350505061307a565b8381602001511161328b5760208101516131079085615b4e565b935080602001516009600083600001516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546131469190615b4e565b90915550506020810151670de0b6b3a764000090613165908890615c66565b61316f9190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48169163a9059cbb916131c0918690600401615b61565b6020604051808303816000875af11580156131df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132039190615b7a565b5080516020808301516040805191825291810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a36007838154811061325157613251615b22565b60009182526020822060039091020180546001600160a01b031916815560018101829055600201558261328381615baa565b9350506133e5565b83816020015161329b9190615b4e565b600784815481106132ae576132ae615b22565b600091825260208083206001600390930201919091019290925582516001600160a01b0316815260099091526040812080548692906132ee908490615b4e565b90915550670de0b6b3a764000090506133078786615c66565b6133119190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48169163a9059cbb91613362918690600401615b61565b6020604051808303816000875af1158015613381573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a59190615b7a565b5080516020808301516040805191825291810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a3600093505b5061307a565b50600555505050565b6133fc614985565b61340b81604001356001614cbc565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316906370a0823190602401602060405180830381865afa158015613472573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134969190615c4d565b60405163f73e19c360e01b81528335600482015290915047906000907f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b03169063f73e19c390602401602060405180830381865afa158015613503573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135279190615c4d565b90508060005b61353a6020870187615c9f565b90508110801561354a5750600082115b156138a85761355f6118656020880188615c9f565b6135a561356f6020880188615c9f565b8381811061357f5761357f615b22565b9050610140020160200160208101906135989190615a3c565b6118d76020890189615c9f565b6135b26020870187615c9f565b828181106135c2576135c2615b22565b9050610140020160800160208101906135db9190615cf0565b1561360e5760405162461bcd60e51b81526020600482015260036024820152624e313560e81b6044820152606401610329565b60408601356136206020880188615c9f565b8381811061363057613630615b22565b9050610140020160600135111561366f5760405162461bcd60e51b815260206004820152600360248201526227189b60e91b6044820152606401610329565b8161367d6020880188615c9f565b8381811061368d5761368d615b22565b905061014002016040013510156137c8576136ab6020870187615c9f565b828181106136bb576136bb615b22565b9050610140020160400135826136d19190615b4e565b91506001600160a01b037f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b166323b872dd61370f6020890189615c9f565b8481811061371f5761371f615b22565b9050610140020160200160208101906137389190615a3c565b3061374660208b018b615c9f565b8681811061375657613756615b22565b90506101400201604001356040518463ffffffff1660e01b815260040161377f93929190615bc3565b6020604051808303816000875af115801561379e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c29190615b7a565b50613896565b6001600160a01b037f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b166323b872dd6138046020890189615c9f565b8481811061381457613814615b22565b90506101400201602001602081019061382d9190615a3c565b30856040518463ffffffff1660e01b815260040161384d93929190615bc3565b6020604051808303816000875af115801561386c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138909190615b7a565b50600091505b806138a081615baa565b91505061352d565b50604051632e1a7d4d60e01b8152853560048201527f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561390b57600080fd5b505af115801561391f573d6000803e3d6000fd5b505050507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0844761395e9190615b4e565b6040518263ffffffff1660e01b81526004016000604051808303818588803b15801561398957600080fd5b505af115801561399d573d6000803e3d6000fd5b508594506000935083925050505b6139b86020880188615c9f565b9050811080156139c85750600083115b15613be057826139db6020890189615c9f565b838181106139eb576139eb615b22565b90506101400201604001351015613a2b57613a096020880188615c9f565b82818110613a1957613a19615b22565b90506101400201604001359150613a2f565b8291505b6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21663a9059cbb613a6b60208a018a615c9f565b84818110613a7b57613a7b615b22565b905061014002016020016020810190613a949190615a3c565b670de0b6b3a7640000613aab60408c013587615c66565b613ab59190615c7d565b6040518363ffffffff1660e01b8152600401613ad2929190615b61565b6020604051808303816000875af1158015613af1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b159190615b7a565b50613b208284615b4e565b9250613b2f6020880188615c9f565b82818110613b3f57613b3f615b22565b905061014002016020016020810190613b589190615a3c565b6001600160a01b0316613b6e6020890189615c9f565b83818110613b7e57613b7e615b22565b604080518781528c82013560208201526000818301529051610140929092029390930135927fd1d072f838d64d5c63545bc6cf88a03b39fd711611b7df5b0c0822f745044fcc925081900360600190a380613bd881615baa565b9150506139ab565b506000805460405163cce79bd560e01b81527f00000000000000000000000065d66c76447ccb45daf1e8044e918fa786a483a16001600160a01b03169163cce79bd591613ca7917f0000000000000000000000008ad599c3a0ff1de082011efddc58f1908eb6e6d8917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2917f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4891600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa158015613cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ce89190615c4d565b6040516370a0823160e01b815230600482015290915060009087906001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216906370a0823190602401602060405180830381865afa158015613d54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d789190615c4d565b613d829190615b4e565b9050876060013564e8d4a510006ec097ce7bc90715b34b9f1000000000600354670de0b6b3a7640000613db59190615b4e565b613dbf8686615c66565b613dc99190615c66565b613dd39190615c7d565b613ddd9190615c7d565b10613e105760405162461bcd60e51b81526020600482015260036024820152624e313760e81b6044820152606401610329565b60408051610100810182526001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2811682527f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481660208201526000918101613e8460a08c0160808d01615d0d565b62ffffff168152602001306001600160a01b031681526020014281526020018381526020018a60600135815260200160006001600160a01b0316815250905060007f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b031663414bf389836040518263ffffffff1660e01b8152600401613f119190615d32565b6020604051808303816000875af1158015613f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f549190615c4d565b6005549091508a359060005b82156142bc57600060078381548110613f7b57613f7b615b22565b6000918252602080832060408051606081018252600390940290910180546001600160a01b03168452600181015492840183905260020154908301529092509003613fd35782613fca81615baa565b93505050613f60565b8381602001511161416a576020810151613fed9085615b4e565b935080602001516009600083600001516001600160a01b03166001600160a01b03168152602001908152602001600020600082825461402c9190615b4e565b909155505060208101518e3590614044908790615c66565b61404e9190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48169163a9059cbb9161409f918690600401615b61565b6020604051808303816000875af11580156140be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140e29190615b7a565b5080516020808301516040805191825291810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a36007838154811061413057614130615b22565b60009182526020822060039091020180546001600160a01b031916815560018101829055600201558261416281615baa565b9350506142b6565b836007848154811061417e5761417e615b22565b9060005260206000209060030201600101600082825461419e9190615b4e565b909155505080516001600160a01b0316600090815260096020526040812080548692906141cc908490615b4e565b90915550508d356141dd8686615c66565b6141e79190615c7d565b815160405163a9059cbb60e01b81529193506001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48169163a9059cbb91614238918690600401615b61565b6020604051808303816000875af1158015614257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061427b9190615b7a565b508051604080518681526020810185905285926001600160a01b031691600080516020615e11833981519152910160405180910390a3600093505b50613f60565b5060055550506000805460ff60a01b19169055505050505050505050565b6142e2614985565b6000805460ff600160a01b808304821615810260ff60a01b1990931692909217928390556040517fe6161233d7b23251971fb55c60874862ed7a143c115402afa8e1f2c07a131add9361433e9390049091161515815260200190565b60405180910390a1565b600054600160a01b900460ff16158061435e5750805b61438f5760405162461bcd60e51b8152602060048201526002602482015261271960f11b6044820152606401610329565b336000908152600960205260409020546143aa908390615b4e565b3360009081526009602052604090208190556002541115806143d9575033600090815260096020526040902054155b61440a5760405162461bcd60e51b8152602060048201526002602482015261271b60f11b6044820152606401610329565b336000908152600b60205260409020548290805b80156145c157336000908152600b60205260408120600790614441600185615b4e565b8154811061445157614451615b22565b90600052602060002001548154811061446c5761446c615b22565b9060005260206000209060030201905084156144c75760028101546144949062093a80615b97565b42116144c75760405162461bcd60e51b8152602060048201526002602482015261138d60f21b6044820152606401610329565b83816001015411156144f757838160010160008282546144e79190615b4e565b90915550600094506145c1915050565b60018101546145069085615b4e565b336000908152600b60205260409020909450600790614526600185615b4e565b8154811061453657614536615b22565b90600052602060002001548154811061455157614551615b22565b60009182526020808320600390920290910180546001600160a01b031916815560018101839055600201829055338252600b90526040902080548061459857614598615be7565b6001900381819060005260206000200160009055905550806145b981615bfd565b91505061441e565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8169063a9059cbb906146109033908890600401615b61565b6020604051808303816000875af115801561462f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146539190615b7a565b5033600081815260096020908152604091829020548251888152918201527f4f4b6ab83d39fce2cc703aa2ac1d003ccd5b4781b4a561c1c586ef2e84e4d8cb9101611532565b6146a1614985565b60018190556040518181527f2217b276de774d686f6d9419505080eeee1f2a9e95ef298c5b4266f56eb6272790602001610c1d565b6146de614985565b6001600160a01b0381166147435760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610329565b610def81614c6c565b6001548110156147835760405162461bcd60e51b81526020600482015260026024820152614e3160f01b6044820152606401610329565b6040516323b872dd60e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816906323b872dd906147d390339030908690600401615bc3565b6020604051808303816000875af11580156147f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148169190615b7a565b5033600090815260086020526040902054614832908290615b97565b33600081815260086020908152604080832094909455835160608101855283815280820186815242828701908152600680546001808201835582885294517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f600390920291820180546001600160a01b0319166001600160a01b0390921691909117905592517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4084015590517ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d4190920191909155938352600a9091529290209054909161491e91615b4e565b8154600181810184556000938452602090932001556006546149409190615b4e565b33600081815260086020908152604091829020548251868152918201527fcd8a16e288c9b610f6bd123e0ed3f6aa008681653a19936f37bb6b2feb17ee8f9101611097565b6000546001600160a01b03163314610e605760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610329565b6000306001600160a01b037f0000000000000000000000006e536addb53d1b47d357cdca83bcf460194a395f16148015614a3857507f000000000000000000000000000000000000000000000000000000000000000146145b15614a6257507f8589b0065033d9231159bf0ba404a710a105f42c9e5ee218d87a94049027664990565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f7d14230c545a7ded527e48f74a18e6313c4a04246c59f97044ce1006170eb1d6828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60007fc8aea8e60353611f3ed5409dad2d3173390bd252431198e7300eda67fefb66b1826000015183602001518460400151856060015186608001518760a001518860c00151604051602001614b9f98979695949392919097885260208801969096526001600160a01b0394909416604087015260608601929092526080850152151560a084015260c083015260e08201526101000190565b6040516020818303038152906040528051906020012090506000614bc282615456565b90506000614be0828560e001518661010001518761012001516154a4565b905083602001516001600160a01b0316816001600160a01b031614614c2c5760405162461bcd60e51b81526020600482015260026024820152614e3960f01b6044820152606401610329565b428460a001511015614c665760405162461bcd60e51b815260206004820152600360248201526204e31360ec1b6044820152606401610329565b50505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000805460405163cce79bd560e01b81527f00000000000000000000000065d66c76447ccb45daf1e8044e918fa786a483a16001600160a01b03169163cce79bd591614d82917f00000000000000000000000082c427adfdf2d245ec51d8046b41c4ee87f0d29c917f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc291600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa158015614d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614dc39190615c4d565b90508115614e3857670de0b6b3a7640000600354670de0b6b3a7640000614dea9190615b97565b614df49083615c66565b614dfe9190615c7d565b831115614e335760405162461bcd60e51b81526020600482015260036024820152624e323160e81b6044820152606401610329565b505050565b670de0b6b3a7640000600354670de0b6b3a7640000614e579190615b4e565b614e619083615c66565b614e6b9190615c7d565b831015614e335760405162461bcd60e51b815260206004820152600360248201526227191960e91b6044820152606401610329565b600080614eab6154cc565b90506000807f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b031663533092ef6040518163ffffffff1660e01b8152600401608060405180830381865afa158015614f0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f329190615d9b565b9350935050506000670de0b6b3a76400008483614f4f9190615c66565b614f599190615c7d565b614f639084615b97565b614f6d8388615c66565b614f779190615c7d565b9695505050505050565b6001600160a01b0382166000908152600c6020908152604080832084845290915290205460ff1615614fdb5760405162461bcd60e51b815260206004820152600360248201526204e32360ec1b6044820152606401610329565b6001600160a01b039091166000908152600c6020908152604080832093835292905220805460ff19166001179055565b6000805460405163cce79bd560e01b81527f00000000000000000000000065d66c76447ccb45daf1e8044e918fa786a483a16001600160a01b03169163cce79bd5916150d1917f00000000000000000000000082c427adfdf2d245ec51d8046b41c4ee87f0d29c917f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b917f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc291600160a81b90910463ffffffff1690600190600401615c14565b602060405180830381865afa1580156150ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151129190615c4d565b905060007f00000000000000000000000065d66c76447ccb45daf1e8044e918fa786a483a16001600160a01b031663cce79bd57f0000000000000000000000008ad599c3a0ff1de082011efddc58f1908eb6e6d87f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc27f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48600060159054906101000a900463ffffffff1660016040518663ffffffff1660e01b81526004016151dd959493929190615c14565b602060405180830381865afa1580156151fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061521e9190615c4d565b90506000807f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b031663533092ef6040518163ffffffff1660e01b8152600401608060405180830381865afa158015615281573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906152a59190615d9b565b93509350505060007f0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e86001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561530b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061532f9190615c4d565b84670de0b6b3a76400006153438886615c66565b61534d9190615c7d565b6153579086615b4e565b6153619190615c66565b61536b9190615c7d565b905061537c64e8d4a5100082615c7d565b9050670de0b6b3a7640000600354670de0b6b3a764000061539d9190615b97565b6153a79083615c66565b6153b19190615c7d565b8611156153e65760405162461bcd60e51b81526020600482015260036024820152624e323360e81b6044820152606401610329565b670de0b6b3a7640000600354670de0b6b3a76400006154059190615b4e565b61540f9083615c66565b6154199190615c7d565b86101561544e5760405162461bcd60e51b8152602060048201526003602482015262138c8d60ea1b6044820152606401610329565b505050505050565b6000610e486154636149df565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006154b58787878761569c565b915091506154c281615760565b5095945050505050565b6000807f00000000000000000000000064187ae08781b09368e6253f9e94951243a493d56001600160a01b031663978bbdb96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561552d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906155519190615c4d565b90508060000361556357600091505090565b60405163cce79bd560e01b81526000906001600160a01b037f00000000000000000000000065d66c76447ccb45daf1e8044e918fa786a483a1169063cce79bd59061563b907f00000000000000000000000082c427adfdf2d245ec51d8046b41c4ee87f0d29c907f000000000000000000000000f1b99e3e573a1a9c5e6b2ce818b617f0e664e86b907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2907f00000000000000000000000000000000000000000000000000000000000001a490600190600401615c14565b602060405180830381865afa158015615658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061567c9190615c4d565b905061271061568b8383615c66565b6156959190615c7d565b9250505090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156156d35750600090506003615757565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015615727573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661575057600060019250925050615757565b9150600090505b94509492505050565b600081600481111561577457615774615dda565b0361577c5750565b600181600481111561579057615790615dda565b036157dd5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610329565b60028160048111156157f1576157f1615dda565b0361583e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610329565b600381600481111561585257615852615dda565b03610def5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610329565b6000602082840312156158bc57600080fd5b5035919050565b6000602082840312156158d557600080fd5b813563ffffffff811681146158e957600080fd5b9392505050565b6001600160a01b0381168114610def57600080fd5b8035615910816158f0565b919050565b6000806040838503121561592857600080fd5b8235615933816158f0565b946020939093013593505050565b604051610140810167ffffffffffffffff8111828210171561597357634e487b7160e01b600052604160045260246000fd5b60405290565b8015158114610def57600080fd5b803561591081615979565b803560ff8116811461591057600080fd5b600061014082840312156159b657600080fd5b6159be615941565b823581526159ce60208401615905565b602082015260408301356040820152606083013560608201526159f360808401615987565b608082015260a083013560a082015260c083013560c0820152615a1860e08401615992565b60e08201526101008381013590820152610120928301359281019290925250919050565b600060208284031215615a4e57600080fd5b81356158e9816158f0565b60008060408385031215615a6c57600080fd5b823591506020830135615a7e81615979565b809150509250929050565b600060208284031215615a9b57600080fd5b813567ffffffffffffffff811115615ab257600080fd5b820161010081850312156158e957600080fd5b60008060408385031215615ad857600080fd5b50508035926020909101359150565b600060208284031215615af957600080fd5b813567ffffffffffffffff811115615b1057600080fd5b820160a081850312156158e957600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610e4857610e48615b38565b6001600160a01b03929092168252602082015260400190565b600060208284031215615b8c57600080fd5b81516158e981615979565b80820180821115610e4857610e48615b38565b600060018201615bbc57615bbc615b38565b5060010190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603160045260246000fd5b600081615c0c57615c0c615b38565b506000190190565b6001600160a01b039586168152938516602085015291909316604083015263ffffffff9092166060820152901515608082015260a00190565b600060208284031215615c5f57600080fd5b5051919050565b8082028115828204841417610e4857610e48615b38565b600082615c9a57634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e19843603018112615cb657600080fd5b83018035915067ffffffffffffffff821115615cd157600080fd5b602001915061014081023603821315615ce957600080fd5b9250929050565b600060208284031215615d0257600080fd5b81356158e981615979565b600060208284031215615d1f57600080fd5b813562ffffff811681146158e957600080fd5b81516001600160a01b03908116825260208084015182169083015260408084015162ffffff16908301526060808401518216908301526080808401519083015260a0838101519083015260c0808401519083015260e09283015116918101919091526101000190565b60008060008060808587031215615db157600080fd5b8451615dbc816158f0565b60208601516040870151606090970151919890975090945092505050565b634e487b7160e01b600052602160045260246000fdfef407c5a0c99a9a3d15fe5a46a4aba5ce747e855b58bc1aec4a589fd53bda599e460140ba175e3953a9d581c92fd2fc50c428691b4220431ff4a3f08c62aa3906a2646970667358221220851c03f17b6117b7277341d79c60c79cc765d347623650558859db49b5afd68d64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
-----Decoded View---------------
Arg [0] : _crab (address): 0x3B960E47784150F5a63777201ee2B15253D713e8
Arg [1] : _swapRouter (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003b960e47784150f5a63777201ee2b15253d713e8
Arg [1] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.