Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 496 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Multi Swap Split | 169319792 | 467 days ago | IN | 1 wei | 0.00018013 | ||||
Multi Swap Split | 168320538 | 470 days ago | IN | 1 wei | 0.00010957 | ||||
Multi Swap Split | 168319522 | 470 days ago | IN | 1 wei | 0.00010865 | ||||
Multi Swap Split | 168319446 | 470 days ago | IN | 1 wei | 0.00009926 | ||||
Multi Swap Split | 168319414 | 470 days ago | IN | 1 wei | 0.00009929 | ||||
Multi Swap Split | 168292348 | 470 days ago | IN | 1 wei | 0.00013338 | ||||
Multi Swap Split | 168218518 | 471 days ago | IN | 1 wei | 0.00019361 | ||||
Multi Swap Split | 168215897 | 471 days ago | IN | 0 ETH | 0.00018565 | ||||
Multi Mint Range | 168214989 | 471 days ago | IN | 0 ETH | 0.00019032 | ||||
Multi Mint Limit | 168214761 | 471 days ago | IN | 0 ETH | 0.00019847 | ||||
Multi Mint Limit | 168214422 | 471 days ago | IN | 0 ETH | 0.00019596 | ||||
Multi Swap Split | 168207389 | 471 days ago | IN | 1 wei | 0.00023224 | ||||
Multi Swap Split | 168199961 | 471 days ago | IN | 1 wei | 0.00015398 | ||||
Multi Swap Split | 168191069 | 471 days ago | IN | 0.001 ETH | 0.00016651 | ||||
Multi Swap Split | 168190336 | 471 days ago | IN | 1 wei | 0.00016773 | ||||
Multi Swap Split | 168190157 | 471 days ago | IN | 0 ETH | 0.00015011 | ||||
Multi Swap Split | 168189441 | 471 days ago | IN | 0 ETH | 0.00018155 | ||||
Multi Swap Split | 168144152 | 471 days ago | IN | 1 wei | 0.00019717 | ||||
Multi Swap Split | 168118272 | 471 days ago | IN | 1 wei | 0.0001664 | ||||
Multi Swap Split | 168115782 | 471 days ago | IN | 1 wei | 0.00018454 | ||||
Multi Swap Split | 168065642 | 471 days ago | IN | 1 wei | 0.00018744 | ||||
Multi Swap Split | 168012169 | 471 days ago | IN | 1 wei | 0.00021109 | ||||
Multi Swap Split | 168001887 | 471 days ago | IN | 1 wei | 0.00019482 | ||||
Multi Swap Split | 167937804 | 471 days ago | IN | 1 wei | 0.00016731 | ||||
Multi Swap Split | 167922414 | 471 days ago | IN | 0.035 ETH | 0.00019363 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
169319792 | 467 days ago | 1 wei | ||||
169319792 | 467 days ago | 0.05774462 ETH | ||||
169319792 | 467 days ago | 0.05774462 ETH | ||||
168320538 | 470 days ago | 1 wei | ||||
168320538 | 470 days ago | 0.74772122 ETH | ||||
168320538 | 470 days ago | 0.74772122 ETH | ||||
168319522 | 470 days ago | 1 wei | ||||
168319522 | 470 days ago | 0.21574499 ETH | ||||
168319522 | 470 days ago | 0.21574499 ETH | ||||
168292348 | 470 days ago | 1 wei | ||||
168292348 | 470 days ago | 0.08669481 ETH | ||||
168292348 | 470 days ago | 0.08669481 ETH | ||||
168218518 | 471 days ago | 1 wei | ||||
168218518 | 471 days ago | 0.45914661 ETH | ||||
168218518 | 471 days ago | 0.45914661 ETH | ||||
168207389 | 471 days ago | 1 wei | ||||
168207389 | 471 days ago | 0.14507092 ETH | ||||
168207389 | 471 days ago | 0.14507092 ETH | ||||
168199961 | 471 days ago | 1 wei | ||||
168199961 | 471 days ago | 0.13167501 ETH | ||||
168199961 | 471 days ago | 0.13167501 ETH | ||||
168191069 | 471 days ago | 0.001 ETH | ||||
168190336 | 471 days ago | 1 wei | ||||
168190336 | 471 days ago | 0.00001379 ETH | ||||
168190336 | 471 days ago | 0.00001379 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PoolsharkRouter
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPLv3 pragma solidity 0.8.18; import '../interfaces/IPool.sol'; import '../interfaces/staking/IRangeStaker.sol'; import '../interfaces/IWETH9.sol'; import '../interfaces/range/IRangePool.sol'; import '../interfaces/limit/ILimitPool.sol'; import '../interfaces/limit/ILimitPoolView.sol'; import '../interfaces/cover/ICoverPool.sol'; import '../interfaces/cover/ICoverPoolFactory.sol'; import '../interfaces/limit/ILimitPoolFactory.sol'; import '../interfaces/callbacks/ILimitPoolCallback.sol'; import '../interfaces/callbacks/ICoverPoolCallback.sol'; import '../libraries/utils/SafeTransfers.sol'; import '../libraries/utils/SafeCast.sol'; import '../interfaces/structs/PoolsharkStructs.sol'; import '../external/solady/LibClone.sol'; contract PoolsharkRouter is PoolsharkStructs, ILimitPoolMintRangeCallback, ILimitPoolMintLimitCallback, ILimitPoolSwapCallback, ICoverPoolSwapCallback, ICoverPoolMintCallback { using SafeCast for uint256; using SafeCast for int256; address public constant ethAddress = address(0); address public immutable wethAddress; address public immutable limitPoolFactory; address public immutable coverPoolFactory; event RouterDeployed( address router, address limitPoolFactory, address coverPoolFactory ); struct MintRangeInputData { address staker; } struct MintRangeCallbackData { address sender; address recipient; bool wrapped; } struct MintLimitCallbackData { address sender; bool wrapped; } struct MintCoverCallbackData { address sender; bool wrapped; } struct SwapCallbackData { address sender; address recipient; bool wrapped; } constructor( address limitPoolFactory_, address coverPoolFactory_, address wethAddress_ ) { limitPoolFactory = limitPoolFactory_; coverPoolFactory = coverPoolFactory_; wethAddress = wethAddress_; emit RouterDeployed(address(this), limitPoolFactory, coverPoolFactory); } receive() external payable { if (msg.sender != wethAddress) { require(false, 'PoolsharkRouter::ReceiveInvalid()'); } } /// @inheritdoc ILimitPoolSwapCallback function limitPoolSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { PoolsharkStructs.LimitImmutables memory constants = ILimitPoolView( msg.sender ).immutables(); // validate sender is a canonical limit pool canonicalLimitPoolsOnly(constants); // decode original msg.sender SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); // transfer from swap caller if (amount0Delta < 0) { if (constants.token0 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount0Delta)); } else { SafeTransfers.transferInto( constants.token0, _data.sender, uint256(-amount0Delta) ); } } if (amount1Delta < 0) { if (constants.token1 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount1Delta)); } else { SafeTransfers.transferInto( constants.token1, _data.sender, uint256(-amount1Delta) ); } } // transfer to swap caller if (amount0Delta > 0) { if (constants.token0 == wethAddress && _data.wrapped) { // unwrap WETH and send to recipient unwrapEth(_data.recipient, uint256(amount0Delta)); } } if (amount1Delta > 0) { if (constants.token1 == wethAddress && _data.wrapped) { // unwrap WETH and send to recipient unwrapEth(_data.recipient, uint256(amount1Delta)); } } } /// @inheritdoc ICoverPoolSwapCallback function coverPoolSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { PoolsharkStructs.CoverImmutables memory constants = ICoverPool( msg.sender ).immutables(); // validate sender is a canonical cover pool canonicalCoverPoolsOnly(constants); // decode original sender SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); // transfer from swap caller if (amount0Delta < 0) { if (constants.token0 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount0Delta)); } else { SafeTransfers.transferInto( constants.token0, _data.sender, uint256(-amount0Delta) ); } } if (amount1Delta < 0) { if (constants.token1 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount1Delta)); } else { SafeTransfers.transferInto( constants.token1, _data.sender, uint256(-amount1Delta) ); } } if (amount0Delta > 0) { if (constants.token0 == wethAddress && _data.wrapped) { // unwrap WETH and send to recipient unwrapEth(_data.recipient, uint256(amount0Delta)); } } if (amount1Delta > 0) { if (constants.token1 == wethAddress && _data.wrapped) { // unwrap WETH and send to recipient unwrapEth(_data.recipient, uint256(amount1Delta)); } } } /// @inheritdoc ILimitPoolMintRangeCallback function limitPoolMintRangeCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { PoolsharkStructs.LimitImmutables memory constants = ILimitPoolView( msg.sender ).immutables(); // validate sender is a canonical limit pool canonicalLimitPoolsOnly(constants); // decode original sender MintRangeCallbackData memory _data = abi.decode( data, (MintRangeCallbackData) ); // transfer from swap caller if (amount0Delta < 0) { if (constants.token0 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount0Delta)); } else { SafeTransfers.transferInto( constants.token0, _data.sender, uint256(-amount0Delta) ); } } if (amount1Delta < 0) { if (constants.token1 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount1Delta)); } else { SafeTransfers.transferInto( constants.token1, _data.sender, uint256(-amount1Delta) ); } } } /// @inheritdoc ILimitPoolMintLimitCallback function limitPoolMintLimitCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { PoolsharkStructs.LimitImmutables memory constants = ILimitPoolView( msg.sender ).immutables(); // validate sender is a canonical limit pool canonicalLimitPoolsOnly(constants); // decode original sender MintLimitCallbackData memory _data = abi.decode( data, (MintLimitCallbackData) ); // transfer from swap caller if (amount0Delta < 0) { if (constants.token0 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount0Delta)); } else { SafeTransfers.transferInto( constants.token0, _data.sender, uint256(-amount0Delta) ); } } if (amount1Delta < 0) { if (constants.token1 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount1Delta)); } else { SafeTransfers.transferInto( constants.token1, _data.sender, uint256(-amount1Delta) ); } } } /// @inheritdoc ICoverPoolMintCallback function coverPoolMintCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { PoolsharkStructs.CoverImmutables memory constants = ICoverPool( msg.sender ).immutables(); // validate sender is a canonical cover pool canonicalCoverPoolsOnly(constants); // decode original sender MintCoverCallbackData memory _data = abi.decode( data, (MintCoverCallbackData) ); // transfer from swap caller if (amount0Delta < 0) { if (constants.token0 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount0Delta)); } else { SafeTransfers.transferInto( constants.token0, _data.sender, uint256(-amount0Delta) ); } } if (amount1Delta < 0) { if (constants.token1 == wethAddress && _data.wrapped) { wrapEth(uint256(-amount1Delta)); } else { SafeTransfers.transferInto( constants.token1, _data.sender, uint256(-amount1Delta) ); } } } function multiMintLimit( address[] memory pools, MintLimitParams[] memory params ) external payable { if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); for (uint256 i = 0; i < pools.length; ) { params[i].callbackData = abi.encode( MintLimitCallbackData({ sender: msg.sender, wrapped: msg.value > 0 }) ); ILimitPool(pools[i]).mintLimit(params[i]); unchecked { ++i; } } refundEth(); } function multiMintRange( address[] memory pools, MintRangeParams[] memory params ) external payable { if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); for (uint256 i = 0; i < pools.length; ) { address staker; { MintRangeCallbackData memory callbackData = MintRangeCallbackData({ sender: msg.sender, recipient: params[i].to, wrapped: msg.value > 0 }); staker = abi .decode(params[i].callbackData, (MintRangeInputData)) .staker; if (staker != address(0)) { params[i].to = staker; } params[i].callbackData = abi.encode(callbackData); } IRangePool(pools[i]).mintRange(params[i]); if (staker != address(0)) { IRangeStaker(staker).stakeRange( StakeRangeParams({ to: abi .decode( params[i].callbackData, (MintRangeCallbackData) ) .recipient, pool: pools[i], positionId: params[i].positionId }) ); } // call to staking contract using positionId returned from mintRange // fees and staked position will go to params.to unchecked { ++i; } } refundEth(); } function multiMintCover( address[] memory pools, PoolsharkStructs.MintCoverParams[] memory params ) external payable { if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); for (uint256 i = 0; i < pools.length; ) { params[i].callbackData = abi.encode( MintCoverCallbackData({ sender: msg.sender, wrapped: msg.value > 0 }) ); try ICoverPool(pools[i]).mint(params[i]) {} catch {} unchecked { ++i; } } refundEth(); } function multiQuote( address[] memory pools, QuoteParams[] memory params, bool sortResults ) external view returns (QuoteResults[] memory results) { if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); if (sortResults) { // if sorting results check for matching params for (uint256 i = 0; i < pools.length; ) { if (i > 0) { if (params[i].zeroForOne != params[0].zeroForOne) require(false, 'ZeroForOneParamMismatch()'); if (params[i].exactIn != params[0].exactIn) require(false, 'ExactInParamMismatch()'); /// @dev - amount and priceLimit values are allowed to be different } unchecked { ++i; } } } results = new QuoteResults[](pools.length); for (uint256 i = 0; i < pools.length; ) { results[i].pool = pools[i]; ( results[i].amountIn, results[i].amountOut, results[i].priceAfter ) = IPool(pools[i]).quote(params[i]); unchecked { ++i; } } // sort if true if (sortResults) { results = sortQuoteResults(params, results); } } function multiSwapSplit(address[] memory pools, SwapParams[] memory params) external payable { if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); for (uint256 i = 0; i < pools.length; ) { if (i > 0) { if (params[i].zeroForOne != params[0].zeroForOne) require(false, 'ZeroForOneParamMismatch()'); if (params[i].exactIn != params[0].exactIn) require(false, 'ExactInParamMismatch()'); if (params[i].amount != params[0].amount) require(false, 'AmountParamMisMatch()'); } unchecked { ++i; } } for (uint256 i = 0; i < pools.length && params[0].amount > 0; ) { // if msg.value > 0 we either need to wrap or unwrap the native gas token params[i].callbackData = abi.encode( SwapCallbackData({ sender: msg.sender, recipient: params[i].to, wrapped: msg.value > 0 }) ); if (msg.value > 0) { IPool pool = IPool(pools[i]); address tokenIn = params[i].zeroForOne ? pool.token0() : pool.token1(); address tokenOut = params[i].zeroForOne ? pool.token1() : pool.token0(); if (tokenOut == wethAddress) { // send weth to router for unwrapping params[i].to = address(this); } else if (tokenIn != wethAddress) { require(false, 'NonNativeTokenPair()'); } } (int256 amount0Delta, int256 amount1Delta) = IPool(pools[i]).swap( params[i] ); // if there is another pool to swap against if ((i + 1) < pools.length) { // calculate amount left and set for next call if (params[0].zeroForOne && params[0].exactIn) { params[0].amount -= (-amount0Delta).toUint256().toUint128(); } else if (params[0].zeroForOne && !params[0].exactIn) { params[0].amount -= (amount1Delta).toUint256().toUint128(); } else if (!params[0].zeroForOne && !params[0].exactIn) { params[0].amount -= (amount0Delta).toUint256().toUint128(); } else if (!params[0].zeroForOne && params[0].exactIn) { params[0].amount -= (-amount1Delta).toUint256().toUint128(); } params[i + 1].amount = params[0].amount; } unchecked { ++i; } } refundEth(); } function multiSnapshotLimit( address[] memory pools, SnapshotLimitParams[] memory params ) external view returns (uint128[] memory amountIns, uint128[] memory amountOuts) { amountIns = new uint128[](pools.length); amountOuts = new uint128[](pools.length); for (uint256 i = 0; i < pools.length; ) { if (pools[i] == address(0)) require(false, 'InvalidPoolAddress()'); (amountIns[i], amountOuts[i]) = ILimitPoolView(pools[i]) .snapshotLimit(params[i]); unchecked { ++i; } } } function createLimitPoolAndMint( ILimitPoolFactory.LimitPoolParams memory params, MintRangeParams[] memory mintRangeParams, MintLimitParams[] memory mintLimitParams ) external payable returns (address pool, address poolToken) { // check if pool exists (pool, poolToken) = ILimitPoolFactory(limitPoolFactory).getLimitPool( params.tokenIn, params.tokenOut, params.swapFee, params.poolTypeId ); // create if pool doesn't exist if (pool == address(0)) { (pool, poolToken) = ILimitPoolFactory(limitPoolFactory) .createLimitPool(params); } // mint initial range positions for (uint256 i = 0; i < mintRangeParams.length; ) { address staker; { mintRangeParams[i].positionId = 0; MintRangeCallbackData memory callbackData = MintRangeCallbackData({ sender: msg.sender, recipient: mintRangeParams[i].to, wrapped: msg.value > 0 }); staker = abi .decode( mintRangeParams[i].callbackData, (MintRangeInputData) ) .staker; if (staker != address(0)) { mintRangeParams[i].to = staker; } mintRangeParams[i].callbackData = abi.encode(callbackData); } try IRangePool(pool).mintRange(mintRangeParams[i]) {} catch {} if (staker != address(0)) { IRangeStaker(staker).stakeRange( StakeRangeParams({ to: abi .decode( mintRangeParams[i].callbackData, (MintRangeCallbackData) ) .recipient, pool: pool, positionId: 0 }) ); } unchecked { ++i; } } // mint initial limit positions for (uint256 i = 0; i < mintLimitParams.length; ) { mintLimitParams[i].positionId = 0; mintLimitParams[i].callbackData = abi.encode( MintLimitCallbackData({ sender: msg.sender, wrapped: msg.value > 0 }) ); ILimitPool(pool).mintLimit(mintLimitParams[i]); unchecked { ++i; } } refundEth(); } function createCoverPoolAndMint( ICoverPoolFactory.CoverPoolParams memory params, MintCoverParams[] memory mintCoverParams ) external payable returns (address pool, address poolToken) { // check if pool exists (pool, poolToken) = ICoverPoolFactory(coverPoolFactory).getCoverPool( params ); // create if pool doesn't exist if (pool == address(0)) { (pool, poolToken) = ICoverPoolFactory(coverPoolFactory) .createCoverPool(params); } // mint initial cover positions for (uint256 i = 0; i < mintCoverParams.length; ) { mintCoverParams[i].positionId = 0; mintCoverParams[i].callbackData = abi.encode( MintCoverCallbackData({ sender: msg.sender, wrapped: msg.value > 0 }) ); try ICoverPool(pool).mint(mintCoverParams[i]) {} catch {} unchecked { ++i; } } refundEth(); } struct SortQuoteResultsLocals { QuoteResults[] sortedResults; QuoteResults[] prunedResults; bool[] sortedFlags; uint256 emptyResults; int256 sortAmount; uint256 sortIndex; uint256 prunedIndex; } function sortQuoteResults( QuoteParams[] memory params, QuoteResults[] memory results ) internal pure returns (QuoteResults[] memory) { SortQuoteResultsLocals memory locals; locals.sortedResults = new QuoteResults[](results.length); locals.sortedFlags = new bool[](results.length); locals.emptyResults = 0; for (uint256 sorted = 0; sorted < results.length; ) { // if exactIn, sort by most output // if exactOut, sort by most output then least input locals.sortAmount = params[0].exactIn ? int256(0) : type(int256).max; locals.sortIndex = type(uint256).max; for (uint256 index = 0; index < results.length; ) { // check if result already sorted if (!locals.sortedFlags[index]) { if (params[0].exactIn) { if ( results[index].amountOut > 0 && results[index].amountOut >= locals.sortAmount ) { locals.sortIndex = index; locals.sortAmount = results[index].amountOut; } } else { if ( results[index].amountIn > 0 && results[index].amountIn <= locals.sortAmount ) { locals.sortIndex = index; locals.sortAmount = results[index].amountIn; } } } // continue finding nth element unchecked { ++index; } } if (locals.sortIndex != type(uint256).max) { // add the sorted result locals.sortedResults[sorted].pool = results[locals.sortIndex] .pool; locals.sortedResults[sorted].amountIn = results[ locals.sortIndex ].amountIn; locals.sortedResults[sorted].amountOut = results[ locals.sortIndex ].amountOut; locals.sortedResults[sorted].priceAfter = results[ locals.sortIndex ].priceAfter; // indicate this result was already sorted locals.sortedFlags[locals.sortIndex] = true; } else { ++locals.emptyResults; } // find next sorted element unchecked { ++sorted; } } // if any results were empty, prune them if (locals.emptyResults > 0) { locals.prunedResults = new QuoteResults[]( results.length - locals.emptyResults ); locals.prunedIndex = 0; for (uint256 sorted = 0; sorted < results.length; ) { // empty results are omitted if (locals.sortedResults[sorted].pool != address(0)) { locals.prunedResults[locals.prunedIndex] = locals .sortedResults[sorted]; unchecked { ++locals.prunedIndex; } } unchecked { ++sorted; } } } else { locals.prunedResults = locals.sortedResults; } return locals.prunedResults; } function multiCall(address[] memory pools, SwapParams[] memory params) external { if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); for (uint256 i = 0; i < pools.length; ) { params[i].callbackData = abi.encode( SwapCallbackData({ sender: msg.sender, recipient: params[i].to, wrapped: true }) ); ICoverPool(pools[i]).swap(params[i]); unchecked { ++i; } } } function canonicalLimitPoolsOnly( PoolsharkStructs.LimitImmutables memory constants ) private view { // generate key for pool bytes32 key = keccak256( abi.encode( constants.poolImpl, constants.token0, constants.token1, constants.swapFee ) ); // compute address address predictedAddress = LibClone.predictDeterministicAddress( constants.poolImpl, encodeLimit(constants), key, limitPoolFactory ); // revert on sender mismatch if (msg.sender != predictedAddress) require(false, 'InvalidCallerAddress()'); } function canonicalCoverPoolsOnly( PoolsharkStructs.CoverImmutables memory constants ) private view { // generate key for pool bytes32 key = keccak256( abi.encode( constants.token0, constants.token1, constants.source, constants.inputPool, constants.tickSpread, constants.twapLength ) ); // compute address address predictedAddress = LibClone.predictDeterministicAddress( constants.poolImpl, encodeCover(constants), key, coverPoolFactory ); // revert on sender mismatch if (msg.sender != predictedAddress) require(false, 'InvalidCallerAddress()'); } function encodeLimit(LimitImmutables memory constants) private pure returns (bytes memory) { return abi.encodePacked( constants.owner, constants.token0, constants.token1, constants.poolToken, constants.bounds.min, constants.bounds.max, constants.genesisTime, constants.tickSpacing, constants.swapFee ); } function encodeCover(CoverImmutables memory constants) private pure returns (bytes memory) { bytes memory value1 = abi.encodePacked( constants.owner, constants.token0, constants.token1, constants.source, constants.poolToken, constants.inputPool, constants.bounds.min, constants.bounds.max ); bytes memory value2 = abi.encodePacked( constants.minAmountPerAuction, constants.genesisTime, constants.minPositionWidth, constants.tickSpread, constants.twapLength, constants.auctionLength ); bytes memory value3 = abi.encodePacked( constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced ); return abi.encodePacked(value1, value2, value3); } function wrapEth(uint256 amount) private { // wrap necessary amount of WETH IWETH9 weth = IWETH9(wethAddress); if (amount > address(this).balance) require(false, 'WrapEth::LowEthBalance()'); weth.deposit{value: amount}(); // transfer weth into pool SafeTransfers.transferOut(msg.sender, wethAddress, amount); } function unwrapEth(address recipient, uint256 amount) private { IWETH9 weth = IWETH9(wethAddress); // unwrap WETH and send to recipient weth.withdraw(amount); // send balance to recipient SafeTransfers.transferOut(recipient, ethAddress, amount); } function refundEth() private { if (address(this).balance > 0) { if (address(this).balance >= msg.value) { SafeTransfers.transferOut(msg.sender, ethAddress, msg.value); } else { SafeTransfers.transferOut( msg.sender, ethAddress, address(this).balance ); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// 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: BUSL-1.1 pragma solidity 0.8.18; abstract contract LimitPoolFactoryStorage { mapping(bytes32 => address) public pools; ///@dev - map for limit pool lookup by key }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; /// @notice Minimal proxy library. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol) /// @author Minimal proxy by 0age (https://github.com/0age) /// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie /// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args) /// /// @dev Minimal proxy: /// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime, /// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern, /// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode. /// /// @dev Clones with immutable args (CWIA): /// The implementation of CWIA here implements a `receive()` method that emits the /// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata, /// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards /// composability. The minimal proxy implementation does not offer this feature. library LibClone { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unable to deploy the clone. error DeploymentFailed(); /// @dev The salt must start with either the zero address or the caller. error SaltDoesNotStartWithCaller(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MINIMAL PROXY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Deploys a deterministic clone of `implementation`, /// using immutable arguments encoded in `data`, with `salt`. function cloneDeterministic( address implementation, bytes memory data, bytes32 salt ) internal returns (address instance) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore3 := mload(sub(data, 0x60)) let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) // Write the bytecode before the data. mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the address of the implementation. mstore(sub(data, 0x0d), implementation) // Write the rest of the bytecode. mstore( sub(data, 0x21), or( shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73 ) ) // `keccak256("ReceiveETH(uint256)")` mstore( sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff ) mstore( sub(data, 0x5a), or( shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f ) ) mstore(dataEnd, shl(0xf0, extraLength)) // Create the instance. instance := create2( 0, sub(data, 0x4c), add(extraLength, 0x6c), salt ) // If `instance` is zero, revert. if iszero(instance) { // Store the function selector of `DeploymentFailed()`. mstore(0x00, 0x30116425) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) mstore(sub(data, 0x60), mBefore3) } } /// @dev Returns the initialization code hash of the clone of `implementation` /// using immutable arguments encoded in `data`. /// Used for mining vanity addresses with create2crunch. function initCodeHash(address implementation, bytes memory data) internal pure returns (bytes32 hash) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore3 := mload(sub(data, 0x60)) let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) // Write the bytecode before the data. mstore(data, 0x5af43d3d93803e606057fd5bf3) // Write the address of the implementation. mstore(sub(data, 0x0d), implementation) // Write the rest of the bytecode. mstore( sub(data, 0x21), or( shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73 ) ) // `keccak256("ReceiveETH(uint256)")` mstore( sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff ) mstore( sub(data, 0x5a), or( shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f ) ) mstore(dataEnd, shl(0xf0, extraLength)) // Compute and store the bytecode hash. hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c)) // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) mstore(sub(data, 0x60), mBefore3) } } /// @dev Returns the address of the deterministic clone of /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`. function predictDeterministicAddress( address implementation, bytes memory data, bytes32 salt, address deployer ) internal pure returns (address predicted) { bytes32 hash = initCodeHash(implementation, data); predicted = predictDeterministicAddress(hash, salt, deployer); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OTHER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the address when a contract with initialization code hash, /// `hash`, is deployed with `salt`, by `deployer`. function predictDeterministicAddress( bytes32 hash, bytes32 salt, address deployer ) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { // Compute and store the bytecode hash. mstore8(0x00, 0xff) // Write the prefix. mstore(0x35, hash) mstore(0x01, shl(96, deployer)) mstore(0x15, salt) predicted := keccak256(0x00, 0x55) // Restore the part of the free memory pointer that has been overwritten. mstore(0x35, 0) } } /// @dev Reverts if `salt` does not start with either the zero address or the caller. function checkStartsWithCaller(bytes32 salt) internal view { /// @solidity memory-safe-assembly assembly { // If the salt does not start with the zero address or the caller. if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) { // Store the function selector of `SaltDoesNotStartWithCaller()`. mstore(0x00, 0x2f634836) // Revert with (offset, size). revert(0x1c, 0x04) } } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.18; /// @title Callback for mints /// @notice Any contract that calls the `mint` function must implement this interface. interface ICoverPoolMintCallback { /// @notice Called to `msg.sender` after executing a mint. /// @param amount0Delta The amount of token0 either received by (positive) or sent from (negative) the user. /// @param amount1Delta The amount of token1 either received by (positive) or sent from (negative) the user. function coverPoolMintCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; } /// @title Callback for swaps /// @notice Any contract that calls the `swap` function must implement this interface. interface ICoverPoolSwapCallback { /// @notice Called to `msg.sender` after executing a swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 either received by (positive) or sent from (negative) the user. /// @param amount1Delta The amount of token1 either received by (positive) or sent from (negative) the user. function coverPoolSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.18; /// @title Callback for range mints /// @notice Any contract that calls the `mintRange` function must implement this interface. interface ILimitPoolMintRangeCallback { /// @notice Called to `msg.sender` after executing a mint. /// @param amount0Delta The amount of token0 either received by (positive) or sent from (negative) the user. /// @param amount1Delta The amount of token1 either received by (positive) or sent from (negative) the user. function limitPoolMintRangeCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; } /// @title Callback for limit mints /// @notice Any contract that calls the `mintLimit` function must implement this interface. interface ILimitPoolMintLimitCallback { /// @notice Called to `msg.sender` after executing a mint. /// @param amount0Delta The amount of token0 either received by (positive) or sent from (negative) the user. /// @param amount1Delta The amount of token1 either received by (positive) or sent from (negative) the user. function limitPoolMintLimitCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; } /// @title Callback for swaps /// @notice Any contract that calls the `swap` function must implement this interface. interface ILimitPoolSwapCallback { /// @notice Called to `msg.sender` after executing a swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 either received by (positive) or sent from (negative) the user. /// @param amount1Delta The amount of token1 either received by (positive) or sent from (negative) the user. function limitPoolSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.18; import '../structs/PoolsharkStructs.sol'; /** * @title ICoverPool * @author Poolshark * @notice Defines the basic interface for a Cover Pool. */ interface ICoverPool is PoolsharkStructs { function immutables() external view returns (CoverImmutables memory constants); /** * @notice Deposits `amountIn` of asset to be auctioned off each time price range is crossed further into. * - E.g. User supplies 1 WETH in the range 1500 USDC per WETH to 1400 USDC per WETH As latestTick crosses from 1500 USDC per WETH to 1400 USDC per WETH, the user's liquidity within each tick spacing is auctioned off. * @dev The position will be shrunk onto the correct side of latestTick. * @dev The position will be minted with the `to` address as the owner. * @param params The parameters for the function. See MintCoverParams. */ function mint(MintCoverParams memory params) external; /** * @notice Withdraws the input token and returns any filled and/or unfilled amounts to the 'to' address specified. * - E.g. User supplies 1 WETH in the range 1500 USDC per WETH to 1400 USDC per WETH As latestTick crosses from 1500 USDC per WETH to 1400 USDC per WETH, the user's liquidity within each tick spacing is auctioned off. * @dev The position will be shrunk based on the claim tick passed. * @dev The position amounts will be returned to the `to` address specified. * @dev The `sync` flag can be set to false so users can exit safely without syncing latestTick. * @param params The parameters for the function. See BurnCoverParams. */ function burn(BurnCoverParams memory params) external; /** * @notice Swaps `tokenIn` for `tokenOut`. `tokenIn` will be `token0` if `zeroForOne` is true. `tokenIn` will be `token1` if `zeroForOne` is false. The pool price represents token1 per token0. The pool price will decrease if `zeroForOne` is true. The pool price will increase if `zeroForOne` is false. * @param params The parameters for the function. See SwapParams above. * @return amount0Delta The amount of token0 spent (negative) or received (positive) by the user * @return amount1Delta The amount of token1 spent (negative) or received (positive) by the user */ function swap(SwapParams memory params) external returns (int256 amount0Delta, int256 amount1Delta); /** * @notice Quotes the amount of `tokenIn` for `tokenOut`. `tokenIn` will be `token0` if `zeroForOne` is true. `tokenIn` will be `token1` if `zeroForOne` is false. The pool price represents token1 per token0. The pool price will decrease if `zeroForOne` is true. The pool price will increase if `zeroForOne` is false. * @param params The parameters for the function. See SwapParams above. * @return inAmount The amount of tokenIn to be spent * @return outAmount The amount of tokenOut to be received * @return priceAfter The Q64.96 square root price after the swap */ function quote(QuoteParams memory params) external view returns ( int256 inAmount, int256 outAmount, uint256 priceAfter ); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; abstract contract ICoverPoolFactory { struct CoverPoolParams { bytes32 poolType; address tokenIn; address tokenOut; uint16 feeTier; int16 tickSpread; uint16 twapLength; } /** * @notice Creates a new CoverPool. * @param params The CoverPoolParams struct referenced above. */ function createCoverPool(CoverPoolParams memory params) external virtual returns (address pool, address poolToken); /** * @notice Fetches an existing CoverPool. * @param params The CoverPoolParams struct referenced above. */ function getCoverPool(CoverPoolParams memory params) external view virtual returns (address pool, address poolToken); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.18; import '../structs/PoolsharkStructs.sol'; interface ITwapSource { function initialize(PoolsharkStructs.CoverImmutables memory constants) external returns (uint8 initializable, int24 startingTick); function calculateAverageTick( PoolsharkStructs.CoverImmutables memory constants, int24 latestTick ) external view returns (int24 averageTick); function getPool( address tokenA, address tokenB, uint16 feeTier ) external view returns (address pool); function feeTierTickSpacing(uint16 feeTier) external view returns (int24 tickSpacing); function factory() external view returns (address); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.18; import '../interfaces/structs/PoolsharkStructs.sol'; interface IPool is PoolsharkStructs { function immutables() external view returns (LimitImmutables memory); function swap(SwapParams memory params) external returns (int256 amount0, int256 amount1); function quote(QuoteParams memory params) external view returns ( int256 inAmount, int256 outAmount, uint160 priceAfter ); function fees(FeesParams memory params) external returns (uint128 token0Fees, uint128 token1Fees); function sample(uint32[] memory secondsAgo) external view returns ( int56[] memory tickSecondsAccum, uint160[] memory secondsPerLiquidityAccum, uint160 averagePrice, uint128 averageLiquidity, int24 averageTick ); function snapshotRange(uint32 positionId) external view returns ( int56 tickSecondsAccum, uint160 secondsPerLiquidityAccum, uint128 feesOwed0, uint128 feesOwed1 ); function snapshotLimit(SnapshotLimitParams memory params) external view returns (uint128 amountIn, uint128 amountOut); function poolToken() external view returns (address poolToken); function token0() external view returns (address token0); function token1() external view returns (address token1); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.18; interface IWETH9 { /// @notice Deposits ether in return for wrapped ether function deposit() external payable; /// @notice Withdraws ether from wrapped ether balance function withdraw(uint256 wad) external; /// @notice Withdraws ether from wrapped ether balance function transfer(address dst, uint256 wad) external returns (bool); /// @notice Returns balance for address function balanceOf(address account) external returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.18; import '../structs/LimitPoolStructs.sol'; interface ILimitPool is LimitPoolStructs { function initialize(uint160 startPrice) external; function mintLimit(MintLimitParams memory params) external returns (int256, int256); function burnLimit(BurnLimitParams memory params) external returns (int256, int256); function fees(FeesParams memory params) external returns (uint128 token0Fees, uint128 token1Fees); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import '../structs/PoolsharkStructs.sol'; import '../../base/storage/LimitPoolFactoryStorage.sol'; abstract contract ILimitPoolFactory is LimitPoolFactoryStorage, PoolsharkStructs { function createLimitPool(LimitPoolParams memory params) external virtual returns (address pool, address poolToken); function getLimitPool( address tokenIn, address tokenOut, uint16 swapFee, uint16 poolTypeId ) external view virtual returns (address pool, address poolToken); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.18; import '../structs/LimitPoolStructs.sol'; interface ILimitPoolView is LimitPoolStructs { function snapshotLimit(SnapshotLimitParams memory params) external view returns (uint128, uint128); function immutables() external view returns (LimitImmutables memory); function priceBounds(int16 tickSpacing) external pure returns (uint160 minPrice, uint160 maxPrice); function sample(uint32[] memory secondsAgo) external view returns ( int56[] memory tickSecondsAccum, uint160[] memory secondsPerLiquidityAccum, uint160 averagePrice, uint128 averageLiquidity, int24 averageTick ); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.18; import '../structs/RangePoolStructs.sol'; import './IRangePoolManager.sol'; interface IRangePool is RangePoolStructs { function mintRange(MintRangeParams memory mintParams) external returns (int256, int256); function burnRange(BurnRangeParams memory burnParams) external returns (int256, int256); function swap(SwapParams memory params) external returns (int256 amount0, int256 amount1); function quote(QuoteParams memory params) external view returns ( uint256 inAmount, uint256 outAmount, uint160 priceAfter ); function snapshotRange(uint32 positionId) external view returns ( int56 tickSecondsAccum, uint160 secondsPerLiquidityAccum, uint128 feesOwed0, uint128 feesOwed1 ); function sample(uint32[] memory secondsAgo) external view returns ( int56[] memory tickSecondsAccum, uint160[] memory secondsPerLiquidityAccum, uint160 averagePrice, uint128 averageLiquidity, int24 averageTick ); function positions(uint256 positionId) external view returns ( uint256 feeGrowthInside0Last, uint256 feeGrowthInside1Last, uint128 liquidity, int24 lower, int24 upper ); function increaseSampleCount(uint16 newSampleCountMax) external; function ticks(int24) external view returns (RangeTick memory, LimitTick memory); function samples(uint256) external view returns ( uint32, int56, uint160 ); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.18; import '../structs/RangePoolStructs.sol'; interface IRangePoolManager { function owner() external view returns (address); function feeTo() external view returns (address); function protocolFees(address pool) external view returns (uint16); function feeTiers(uint16 swapFee) external view returns (int24); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import '../structs/PoolsharkStructs.sol'; interface IRangeStaker is PoolsharkStructs { function stakeRange(StakeRangeParams memory) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import './PoolsharkStructs.sol'; interface LimitPoolStructs is PoolsharkStructs { struct LimitPosition { uint128 liquidity; // expected amount to be used not actual uint32 epochLast; // epoch when this position was created at int24 lower; // lower price tick of position range int24 upper; // upper price tick of position range bool crossedInto; // whether the position was crossed into already } struct MintLimitCache { GlobalState state; LimitPosition position; LimitImmutables constants; LimitPoolState pool; SwapCache swapCache; uint256 liquidityMinted; uint256 mintSize; uint256 priceLimit; int256 amountIn; uint256 amountOut; uint256 priceLower; uint256 priceUpper; int24 tickLimit; } struct BurnLimitCache { GlobalState state; LimitPoolState pool; LimitTick claimTick; LimitPosition position; PoolsharkStructs.LimitImmutables constants; uint160 priceLower; uint160 priceClaim; uint160 priceUpper; uint128 liquidityBurned; uint128 amountIn; uint128 amountOut; int24 claim; bool removeLower; bool removeUpper; bool search; } struct InsertSingleLocals { int24 previousFullTick; int24 nextFullTick; uint256 priceNext; uint256 pricePrevious; uint256 amountInExact; uint256 amountOutExact; uint256 amountToCross; } struct GetDeltasLocals { int24 previousFullTick; uint256 pricePrevious; uint256 priceNext; } struct SearchLocals { int24[] ticksFound; int24 searchTick; int24 searchTickAhead; uint16 searchIdx; uint16 startIdx; uint16 endIdx; uint16 ticksIncluded; uint32 claimTickEpoch; uint32 claimTickAheadEpoch; } struct TickMapLocals { uint256 word; uint256 tickIndex; uint256 wordIndex; uint256 blockIndex; } }
// SPDX-License-Identifier: GPLv3 pragma solidity 0.8.18; import '../cover/ITwapSource.sol'; interface PoolsharkStructs { /** * @custom:struct LimitPoolParams */ struct LimitPoolParams { /** * @custom:field tokenIn * @notice Address for the first token in the pair */ address tokenIn; /** * @custom:field tokenOut * @notice Address for the second token in the pair */ address tokenOut; /** * @custom:field startPrice * @notice Q64.96 formatted sqrt price to start the pool at */ uint160 startPrice; /** * @custom:field swapFee * @notice The base swap fee for the pool; 1000 = 0.1% fee */ uint16 swapFee; /** * @custom:field poolTypeId * @notice The pool type id for which to clone the implementation for */ uint16 poolTypeId; } /** * @custom:struct MintRangeParams */ struct MintRangeParams { /** * @custom:field to * @notice Address for the receiver of the minted position */ address to; /** * @custom:field lower * @notice The lower price tick for the position range */ int24 lower; /** * @custom:field upper * @notice The upper price tick for the position range */ int24 upper; /** * @custom:field positionId * @notice 0 if creating a new position; id of previous if adding liquidity */ uint32 positionId; /** * @custom:field amount0 * @notice token0 amount to be deposited into the minted position */ uint128 amount0; /** * @custom:field amount1 * @notice token1 amount to be deposited into the minted position */ uint128 amount1; /** * @custom:field callbackData * @notice callback data which gets passed back to msg.sender at the end of a `mint` call */ bytes callbackData; } struct BurnRangeParams { /** * @custom:field to * @notice Address for the receiver of the burned liquidity */ address to; /** * @custom:field positionId * @notice id of previous position minted */ uint32 positionId; uint128 burnPercent; } /** * @custom:struct MintLimitParams */ struct MintLimitParams { /** * @custom:field to * @notice Address for the receiver of the minted position */ address to; /** * @custom:field amount * @notice Token amount to be deposited into the minted position */ uint128 amount; /** * @custom:field mintPercent * @notice The percent of `amount` below which a LimitPosition will not be minted * @notice 1e26 = 1% * @notice 5e25 = 0.5% */ uint96 mintPercent; /** * @custom:field positionId * @notice 0 if creating a new position; id of previous if adding liquidity */ uint32 positionId; /** * @custom:field lower * @notice The lower price tick for the position range */ int24 lower; /** * @custom:field upper * @notice The upper price tick for the position range */ int24 upper; /** * @custom:field zeroForOne * @notice True if depositing token0, the first token address in lexographical order * @notice False if depositing token1, the second token address in lexographical order */ bool zeroForOne; /** * @custom:field callbackData * @notice callback data which gets passed back to msg.sender at the end of a `mint` call */ bytes callbackData; } /** * @custom:struct BurnLimitParams */ struct BurnLimitParams { /** * @custom:field to * @notice Address for the receiver of the collected position amounts */ address to; /** * @custom:field burnPercent * @notice Percent of the remaining liquidity to be removed * @notice 1e38 represents 100% * @notice 5e37 represents 50% * @notice 1e37 represents 10% */ uint128 burnPercent; /** * @custom:field positionId * @notice 0 if creating a new position; id of previous if adding liquidity */ uint32 positionId; /** * @custom:field claim * @notice The most recent tick crossed in this range * @notice if `zeroForOne` is true, claim tick progresses from lower => upper * @notice if `zeroForOne` is false, claim tick progresses from upper => lower */ int24 claim; /** * @custom:field zeroForOne * @notice True if deposited token0, the first token address in lexographical order * @notice False if deposited token1, the second token address in lexographical order */ bool zeroForOne; } struct SwapParams { /** * @custom:field to * @notice Address for the receiver of the swap token output */ address to; /** * @custom:field priceLimit * @notice The Q64.96 formatted sqrt price to stop swapping at * @notice zeroForOne (i.e. token0 => token1 swap) moves price lower * @notice !zeroForOne (i.e. token1 => token0 swap) moves price higher */ uint160 priceLimit; /** * @custom:field amount * @notice The maximum tokenIn to be spent (exactIn) * @notice OR tokenOut amount to be received (!exactIn) */ uint128 amount; /** * @custom:field exactIn * @notice True if `amount` is in tokenIn; False if `amount` is in tokenOut */ bool exactIn; /** * @custom:field zeroForOne * @notice True if swapping token0 => token1 * @notice False if swapping token1 => token0 */ bool zeroForOne; /** * @custom:field callbackData * @notice callback data which gets passed back to msg.sender at the end of a `mint` call */ bytes callbackData; } struct QuoteParams { /** * @custom:field priceLimit * @notice The Q64.96 formatted sqrt price to stop swapping at * @notice zeroForOne (i.e. token0 => token1 swap) moves price lower * @notice !zeroForOne (i.e. token1 => token0 swap) moves price higher */ uint160 priceLimit; /** * @custom:field amount * @notice The maximum tokenIn to be spent (exactIn) * @notice OR tokenOut amount to be received (!exactIn) */ uint128 amount; /** * @custom:field exactIn * @notice True if `amount` is in tokenIn; False if `amount` is in tokenOut */ bool exactIn; /** * @custom:field zeroForOne * @notice True if swapping token0 => token1 * @notice False if swapping token1 => token0 */ bool zeroForOne; } struct SnapshotLimitParams { /** * @custom:field owner * @notice The owner address of the Limit Position */ address owner; /** * @custom:field burnPercent * @notice The % of liquidity to burn * @notice 1e38 = 100% */ uint128 burnPercent; /** * @custom:field positionId * @notice The position id for the LimitPosition */ uint32 positionId; /** * @custom:field claim * @notice The most recent tick crossed in this range * @notice if `zeroForOne` is true, claim tick progresses from lower => upper * @notice if `zeroForOne` is false, claim tick progresses from upper => lower */ int24 claim; /** * @custom:field zeroForOne * @notice True if swapping token0 => token1 * @notice False if swapping token1 => token0 */ bool zeroForOne; } struct FeesParams { /** * @custom:field protocolSwapFee0 * @notice The protocol fee taken on all token0 fees * @notice 1e4 = 100% */ uint16 protocolSwapFee0; /** * @custom:field protocolSwapFee1 * @notice The protocol fee taken on all token1 fees * @notice 1e4 = 100% */ uint16 protocolSwapFee1; /** * @custom:field protocolFillFee0 * @notice The protocol fee taken on all token0 LimitPosition fills * @notice 1e2 = 1% */ uint16 protocolFillFee0; /** * @custom:field protocolFillFee1 * @notice The protocol fee taken on all token1 LimitPosition fills * @notice 1e2 = 1% */ uint16 protocolFillFee1; /** * @custom:field setFeesFlags * @notice The flags for which protocol fees will be set * @notice - PROTOCOL_SWAP_FEE_0 = 2**0; * @notice - PROTOCOL_SWAP_FEE_1 = 2**1; * @notice - PROTOCOL_FILL_FEE_0 = 2**2; * @notice - PROTOCOL_FILL_FEE_1 = 2**3; */ uint8 setFeesFlags; } struct GlobalState { RangePoolState pool; LimitPoolState pool0; LimitPoolState pool1; uint128 liquidityGlobal; uint32 positionIdNext; uint32 epoch; uint8 unlocked; } struct LimitPoolState { uint160 price; /// @dev Starting price current uint128 liquidity; /// @dev Liquidity currently active uint128 protocolFees; uint16 protocolFillFee; int24 tickAtPrice; } struct RangePoolState { SampleState samples; uint200 feeGrowthGlobal0; uint200 feeGrowthGlobal1; uint160 secondsPerLiquidityAccum; uint160 price; /// @dev Starting price current uint128 liquidity; /// @dev Liquidity currently active int56 tickSecondsAccum; int24 tickAtPrice; uint16 protocolSwapFee0; uint16 protocolSwapFee1; } struct Tick { RangeTick range; LimitTick limit; } struct LimitTick { uint160 priceAt; int128 liquidityDelta; uint128 liquidityAbsolute; } struct RangeTick { uint200 feeGrowthOutside0; uint200 feeGrowthOutside1; uint160 secondsPerLiquidityAccumOutside; int56 tickSecondsAccumOutside; int128 liquidityDelta; uint128 liquidityAbsolute; } struct Sample { uint32 blockTimestamp; int56 tickSecondsAccum; uint160 secondsPerLiquidityAccum; } struct SampleState { uint16 index; uint16 count; uint16 countMax; } struct StakeRangeParams { address to; address pool; uint32 positionId; } struct UnstakeRangeParams { address to; address pool; uint32 positionId; } struct StakeFinParams { address to; uint128 amount; } struct QuoteResults { address pool; int256 amountIn; int256 amountOut; uint160 priceAfter; } struct LimitImmutables { address owner; address poolImpl; address factory; PriceBounds bounds; address token0; address token1; address poolToken; uint32 genesisTime; int16 tickSpacing; uint16 swapFee; } struct CoverImmutables { ITwapSource source; PriceBounds bounds; address owner; address token0; address token1; address poolImpl; address poolToken; address inputPool; uint128 minAmountPerAuction; uint32 genesisTime; int16 minPositionWidth; int16 tickSpread; uint16 twapLength; uint16 auctionLength; uint16 sampleInterval; uint8 token0Decimals; uint8 token1Decimals; bool minAmountLowerPriced; } struct PriceBounds { uint160 min; uint160 max; } struct TickMap { uint256 blocks; /// @dev - sets of words mapping(uint256 => uint256) words; /// @dev - sets to words mapping(uint256 => uint256) ticks; /// @dev - words to ticks mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) epochs0; /// @dev - ticks to epochs mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) epochs1; /// @dev - ticks to epochs } struct SwapCache { GlobalState state; LimitImmutables constants; uint256 price; uint256 liquidity; uint256 amountLeft; uint256 input; uint256 output; uint160 crossPrice; uint160 averagePrice; uint160 secondsPerLiquidityAccum; uint128 feeAmount; int56 tickSecondsAccum; int56 tickSecondsAccumBase; int24 crossTick; uint8 crossStatus; bool limitActive; bool exactIn; bool cross; } enum CrossStatus { RANGE, LIMIT, BOTH } /** * @custom:struct MintCoverParams */ struct MintCoverParams { /** * @custom:field to * @notice Address for the receiver of the minted position */ address to; /** * @custom:field amount * @notice Token amount to be deposited into the minted position */ uint128 amount; /** * @custom:field positionId * @notice 0 if creating a new position; id of previous if adding liquidity */ uint32 positionId; /** * @custom:field lower * @notice The lower price tick for the position range */ int24 lower; /** * @custom:field upper * @notice The upper price tick for the position range */ int24 upper; /** * @custom:field zeroForOne * @notice True if depositing token0, the first token address in lexographical order * @notice False if depositing token1, the second token address in lexographical order */ bool zeroForOne; /** * @custom:field callbackData * @notice callback data which gets passed back to msg.sender at the end of a `mint` call */ bytes callbackData; } /** * @custom:struct BurnCoverParams */ struct BurnCoverParams { /** * @custom:field to * @notice Address for the receiver of the collected position amounts */ address to; /** * @custom:field burnPercent * @notice Percent of the remaining liquidity to be removed * @notice 1e38 represents 100% * @notice 5e37 represents 50% * @notice 1e37 represents 10% */ uint128 burnPercent; /** * @custom:field positionId * @notice 0 if creating a new position; id of previous if adding liquidity */ uint32 positionId; /** * @custom:field claim * @notice The most recent tick crossed in this range * @notice if `zeroForOne` is true, claim tick progresses from upper => lower * @notice if `zeroForOne` is false, claim tick progresses from lower => upper */ int24 claim; /** * @custom:field zeroForOne * @notice True if deposited token0, the first token address in lexographical order * @notice False if deposited token1, the second token address in lexographical order */ bool zeroForOne; /** * @custom:field sync * @notice True will sync the pool latestTick * @notice False will skip syncing latestTick */ bool sync; } /** * @custom:struct SnapshotCoverParams */ struct SnapshotCoverParams { /** * @custom:field to * @notice Address of the position owner */ address owner; /** * @custom:field positionId * @notice id of position */ uint32 positionId; /** * @custom:field burnPercent * @notice Percent of the remaining liquidity to be removed * @notice 1e38 represents 100% * @notice 5e37 represents 50% * @notice 1e37 represents 10% */ uint128 burnPercent; /** * @custom:field claim * @notice The most recent tick crossed in this range * @notice if `zeroForOne` is true, claim tick progresses from upper => lower * @notice if `zeroForOne` is false, claim tick progresses from lower => upper */ int24 claim; /** * @custom:field zeroForOne * @notice True if deposited token0, the first token address in lexographical order * @notice False if deposited token1, the second token address in lexographical order */ bool zeroForOne; } }
// SPDX-License-Identifier: GPLv3 pragma solidity 0.8.18; import './PoolsharkStructs.sol'; interface RangePoolStructs is PoolsharkStructs { struct RangePosition { uint256 feeGrowthInside0Last; uint256 feeGrowthInside1Last; uint128 liquidity; int24 lower; int24 upper; } struct CompoundRangeParams { uint160 priceLower; uint160 priceUpper; uint128 amount0; uint128 amount1; uint32 positionId; } struct SampleParams { uint16 sampleIndex; uint16 sampleLength; uint32 time; uint32[] secondsAgo; int24 tick; uint128 liquidity; PoolsharkStructs.LimitImmutables constants; } struct UpdateParams { int24 lower; int24 upper; uint32 positionId; uint128 burnPercent; } struct MintRangeCache { GlobalState state; RangePosition position; PoolsharkStructs.LimitImmutables constants; address owner; uint256 liquidityMinted; uint160 priceLower; uint160 priceUpper; int128 amount0; int128 amount1; int128 feesAccrued0; int128 feesAccrued1; } struct BurnRangeCache { GlobalState state; RangePosition position; PoolsharkStructs.LimitImmutables constants; uint256 liquidityBurned; uint160 priceLower; uint160 priceUpper; int128 amount0; int128 amount1; } struct RangePositionCache { uint256 liquidityAmount; uint256 rangeFeeGrowth0; uint256 rangeFeeGrowth1; uint128 amountFees0; uint128 amountFees1; uint128 feesBurned0; uint128 feesBurned1; } struct SnapshotRangeCache { RangePosition position; SampleState samples; PoolsharkStructs.LimitImmutables constants; uint160 price; uint160 secondsPerLiquidityAccum; uint160 secondsPerLiquidityAccumLower; uint160 secondsPerLiquidityAccumUpper; uint128 liquidity; uint128 amount0; uint128 amount1; int56 tickSecondsAccum; int56 tickSecondsAccumLower; int56 tickSecondsAccumUpper; uint32 secondsOutsideLower; uint32 secondsOutsideUpper; uint32 blockTimestamp; int24 tick; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.18; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { /// @notice Cast a uint256 to a uint128, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint128 function toUint128(uint256 y) internal pure returns (uint128 z) { if ((z = uint128(y)) != y) require(false, 'Uint256ToUint128:Overflow()'); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint128 function toUint128(int128 y) internal pure returns (uint128 z) { if (y < 0) require(false, 'Int128ToUint128:Underflow()'); z = uint128(y); } /// @notice Cast a uint256 to a uint160, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint160(uint256 y) internal pure returns (uint160 z) { if ((z = uint160(y)) != y) require(false, 'Uint256ToUint160:Overflow()'); } /// @notice Cast a uint256 to a uint160, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint32(uint256 y) internal pure returns (uint32 z) { if ((z = uint32(y)) != y) require(false, 'Uint256ToUint32:Overflow()'); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param y The int256 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(int256 y) internal pure returns (int128 z) { if ((z = int128(y)) != y) require(false, 'Int256ToInt128:Overflow()'); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param y The int256 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(uint128 y) internal pure returns (int128 z) { if (y > uint128(type(int128).max)) require(false, 'Uint128ToInt128:Overflow()'); z = int128(y); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt256(uint256 y) internal pure returns (int256 z) { if (y > uint256(type(int256).max)) require(false, 'Uint256ToInt256:Overflow()'); z = int256(y); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint128 function toUint256(int256 y) internal pure returns (uint256 z) { if (y < 0) require(false, 'Int256ToUint256:Underflow()'); z = uint256(y); } /// @notice Cast a uint256 to a uint16, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint128 function toUint16(uint256 y) internal pure returns (uint16 z) { if ((z = uint16(y)) != y) require(false, 'Uint256ToUint16:Overflow()'); } }
//SPDX-License-Identifier: Unlicense pragma solidity 0.8.18; import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; library SafeTransfers { /** * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified * it is >= amount, this should not revert in normal conditions. * * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ // slither-disable-next-line assembly function transferOut( address to, address token, uint256 amount ) internal { bool success; if (amount == 0) return; if (token == address(0)) { (success, ) = to.call{value: amount}(''); if (!success) require(false, 'SafeTransfers::EthTransferFailed()'); return; } IERC20 erc20Token = IERC20(token); // ? We are checking the transfer, but since we are doing so in an assembly block // ? Slither does not pick up on that and results in a hit // slither-disable-next-line unchecked-transfer erc20Token.transfer(to, amount); success = false; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := 1 // set success to true } case 32 { // This is a complaint ERC-20 returndatacopy(0, 0, 32) success := mload(0) // Set `success = returndata` of external call } default { // This is an excessively non-compliant ERC-20, revert. success := 0 } } if (!success) require(false, 'TransferFailed(address(this), msg.sender'); } /** * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case. * This will revert due to insufficient balance or insufficient allowance. * This function returns the actual amount received, * which may be less than `amount` if there is a fee attached to the transfer. * * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ // slither-disable-next-line assembly function transferInto( address token, address sender, uint256 amount ) internal { if (token == address(0)) { require(false, 'SafeTransfers::CannotTransferInEth()'); } IERC20 erc20Token = IERC20(token); /// @dev - msg.sender here is the pool erc20Token.transferFrom(sender, msg.sender, amount); bool success; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := 1 // set success to true } case 32 { // This is a compliant ERC-20 returndatacopy(0, 0, 32) success := mload(0) // Set `success = returndata` of external call } default { // This is an excessively non-compliant ERC-20, revert. success := 0 } } if (!success) require(false, 'TransferFailed(msg.sender, address(this)'); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"limitPoolFactory_","type":"address"},{"internalType":"address","name":"coverPoolFactory_","type":"address"},{"internalType":"address","name":"wethAddress_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"router","type":"address"},{"indexed":false,"internalType":"address","name":"limitPoolFactory","type":"address"},{"indexed":false,"internalType":"address","name":"coverPoolFactory","type":"address"}],"name":"RouterDeployed","type":"event"},{"inputs":[],"name":"coverPoolFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"coverPoolMintCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"coverPoolSwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"poolType","type":"bytes32"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint16","name":"feeTier","type":"uint16"},{"internalType":"int16","name":"tickSpread","type":"int16"},{"internalType":"uint16","name":"twapLength","type":"uint16"}],"internalType":"struct ICoverPoolFactory.CoverPoolParams","name":"params","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"positionId","type":"uint32"},{"internalType":"int24","name":"lower","type":"int24"},{"internalType":"int24","name":"upper","type":"int24"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.MintCoverParams[]","name":"mintCoverParams","type":"tuple[]"}],"name":"createCoverPoolAndMint","outputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"poolToken","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint160","name":"startPrice","type":"uint160"},{"internalType":"uint16","name":"swapFee","type":"uint16"},{"internalType":"uint16","name":"poolTypeId","type":"uint16"}],"internalType":"struct PoolsharkStructs.LimitPoolParams","name":"params","type":"tuple"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"int24","name":"lower","type":"int24"},{"internalType":"int24","name":"upper","type":"int24"},{"internalType":"uint32","name":"positionId","type":"uint32"},{"internalType":"uint128","name":"amount0","type":"uint128"},{"internalType":"uint128","name":"amount1","type":"uint128"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.MintRangeParams[]","name":"mintRangeParams","type":"tuple[]"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint96","name":"mintPercent","type":"uint96"},{"internalType":"uint32","name":"positionId","type":"uint32"},{"internalType":"int24","name":"lower","type":"int24"},{"internalType":"int24","name":"upper","type":"int24"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.MintLimitParams[]","name":"mintLimitParams","type":"tuple[]"}],"name":"createLimitPoolAndMint","outputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"poolToken","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"ethAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitPoolFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"limitPoolMintLimitCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"limitPoolMintRangeCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"limitPoolSwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint160","name":"priceLimit","type":"uint160"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bool","name":"exactIn","type":"bool"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.SwapParams[]","name":"params","type":"tuple[]"}],"name":"multiCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"positionId","type":"uint32"},{"internalType":"int24","name":"lower","type":"int24"},{"internalType":"int24","name":"upper","type":"int24"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.MintCoverParams[]","name":"params","type":"tuple[]"}],"name":"multiMintCover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint96","name":"mintPercent","type":"uint96"},{"internalType":"uint32","name":"positionId","type":"uint32"},{"internalType":"int24","name":"lower","type":"int24"},{"internalType":"int24","name":"upper","type":"int24"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.MintLimitParams[]","name":"params","type":"tuple[]"}],"name":"multiMintLimit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"int24","name":"lower","type":"int24"},{"internalType":"int24","name":"upper","type":"int24"},{"internalType":"uint32","name":"positionId","type":"uint32"},{"internalType":"uint128","name":"amount0","type":"uint128"},{"internalType":"uint128","name":"amount1","type":"uint128"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.MintRangeParams[]","name":"params","type":"tuple[]"}],"name":"multiMintRange","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"components":[{"internalType":"uint160","name":"priceLimit","type":"uint160"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bool","name":"exactIn","type":"bool"},{"internalType":"bool","name":"zeroForOne","type":"bool"}],"internalType":"struct PoolsharkStructs.QuoteParams[]","name":"params","type":"tuple[]"},{"internalType":"bool","name":"sortResults","type":"bool"}],"name":"multiQuote","outputs":[{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"int256","name":"amountIn","type":"int256"},{"internalType":"int256","name":"amountOut","type":"int256"},{"internalType":"uint160","name":"priceAfter","type":"uint160"}],"internalType":"struct PoolsharkStructs.QuoteResults[]","name":"results","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint128","name":"burnPercent","type":"uint128"},{"internalType":"uint32","name":"positionId","type":"uint32"},{"internalType":"int24","name":"claim","type":"int24"},{"internalType":"bool","name":"zeroForOne","type":"bool"}],"internalType":"struct PoolsharkStructs.SnapshotLimitParams[]","name":"params","type":"tuple[]"}],"name":"multiSnapshotLimit","outputs":[{"internalType":"uint128[]","name":"amountIns","type":"uint128[]"},{"internalType":"uint128[]","name":"amountOuts","type":"uint128[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint160","name":"priceLimit","type":"uint160"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"bool","name":"exactIn","type":"bool"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"internalType":"struct PoolsharkStructs.SwapParams[]","name":"params","type":"tuple[]"}],"name":"multiSwapSplit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"wethAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040523480156200001157600080fd5b506040516200541c3803806200541c8339810160408190526200003491620000ba565b6001600160a01b0383811660a081905283821660c08190529183166080526040805130815260208101929092528101919091527f26e965c9a3bc0ed153de34dbe2bf3e57e4668bfa4156ac2f1d74d5a9fc9aa50b9060600160405180910390a150505062000104565b80516001600160a01b0381168114620000b557600080fd5b919050565b600080600060608486031215620000d057600080fd5b620000db846200009d565b9250620000eb602085016200009d565b9150620000fb604085016200009d565b90509250925092565b60805160a05160c051615232620001ea60003960008181610365015281816110e90152818161119d0152612e91015260008181610311015281816120e5015281816121b80152612af901526000818161011d0152818161024a015281816104a60152818161052a01528181610950015281816109ca01528181610f3701528181610fb10152818161102b0152818161108d015281816114e10152818161155b015281816115d50152818161163701528181611b4001528181611ba9015281816128e50152818161295f01528181612b7201528181612c3b015261342201526152326000f3fe60806040526004361061010d5760003560e01c80636d44b43211610095578063bd5ad2d411610064578063bd5ad2d414610387578063cd5489f11461039a578063dc6fdb86146103ba578063e3756840146103cd578063e9648aa3146103fb57600080fd5b80636d44b432146102ec5780638613ac89146102ff5780639d39786014610333578063ac434c6c1461035357600080fd5b806346d826a0116100dc57806346d826a0146102255780634f0e0ef314610238578063545970271461026c5780635cf4dc451461029957806363be21ee146102b957600080fd5b8063030c66d5146101a05780630a1e49ca146101c0578063141a36eb146101d357806341398b15146101f357600080fd5b3661019b57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101995760405162461bcd60e51b815260206004820152602160248201527f506f6f6c736861726b526f757465723a3a52656365697665496e76616c6964286044820152602960f81b60648201526084015b60405180910390fd5b005b600080fd5b3480156101ac57600080fd5b506101996101bb366004613a33565b61041b565b6101996101ce366004613ecc565b6105a1565b3480156101df57600080fd5b506101996101ee366004613a33565b6108c5565b3480156101ff57600080fd5b50610208600081565b6040516001600160a01b0390911681526020015b60405180910390f35b610199610233366004614069565b610a34565b34801561024457600080fd5b506102087f000000000000000000000000000000000000000000000000000000000000000081565b34801561027857600080fd5b5061028c6102873660046140c2565b610b47565b60405161021c91906141ea565b3480156102a557600080fd5b506101996102b4366004613a33565b610eac565b6102cc6102c736600461428f565b6110e4565b604080516001600160a01b0393841681529290911660208301520161021c565b6101996102fa366004614492565b61132b565b34801561030b57600080fd5b506102087f000000000000000000000000000000000000000000000000000000000000000081565b34801561033f57600080fd5b5061019961034e366004613a33565b611456565b34801561035f57600080fd5b506102087f000000000000000000000000000000000000000000000000000000000000000081565b6101996103953660046144eb565b61168d565b3480156103a657600080fd5b506101996103b53660046144eb565b611f2e565b6102cc6103c8366004614650565b612097565b3480156103d957600080fd5b506103ed6103e836600461472b565b612614565b60405161021c929190614884565b34801561040757600080fd5b50610199610416366004613a33565b61285a565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161016060405180830381865afa15801561045c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104809190614920565b905061048b816129b3565b600061049983850185614a22565b9050600086121561051f577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682608001516001600160a01b03161480156104ea575080602001515b15610505576105006104fb87614a54565b612b70565b61051f565b6080820151815161051f919061051a89614a54565b612c60565b6000851215610599577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168260a001516001600160a01b031614801561056e575080602001515b156105845761057f6104fb86614a54565b610599565b60a08201518151610599919061051a88614a54565b505050505050565b80518251146105c25760405162461bcd60e51b815260040161019090614a70565b60005b82518110156108b8576000806040518060600160405280336001600160a01b031681526020018585815181106105fd576105fd614aa7565b6020026020010151600001516001600160a01b03168152602001600034111515815250905083838151811061063457610634614aa7565b602002602001015160c001518060200190518101906106539190614abd565b5191506001600160a01b03821615610691578184848151811061067857610678614aa7565b60209081029190910101516001600160a01b0390911690525b806040516020016106a29190614b08565b6040516020818303038152906040528484815181106106c3576106c3614aa7565b602002602001015160c00181905250508382815181106106e5576106e5614aa7565b60200260200101516001600160a01b031663f0a20aec84848151811061070d5761070d614aa7565b60200260200101516040518263ffffffff1660e01b81526004016107319190614b89565b60408051808303816000875af115801561074f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107739190614c17565b50506001600160a01b038116156108af57806001600160a01b0316630d55b87960405180606001604052808686815181106107b0576107b0614aa7565b602002602001015160c001518060200190518101906107cf9190614c46565b602001516001600160a01b031681526020018786815181106107f3576107f3614aa7565b60200260200101516001600160a01b0316815260200186868151811061081b5761081b614aa7565b60200260200101516060015163ffffffff168152506040518263ffffffff1660e01b815260040161087c919081516001600160a01b0390811682526020808401519091169082015260409182015163ffffffff169181019190915260600190565b600060405180830381600087803b15801561089657600080fd5b505af11580156108aa573d6000803e3d6000fd5b505050505b506001016105c5565b506108c1612dd4565b5050565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161026060405180830381865afa158015610906573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092a9190614cb6565b905061093581612dfb565b600061094383850185614a22565b905060008612156109bf577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b0316148015610994575080602001515b156109aa576109a56104fb87614a54565b6109bf565b606082015181516109bf919061051a89614a54565b6000851215610599577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682608001516001600160a01b0316148015610a0e575080602001515b15610a1f5761057f6104fb86614a54565b60808201518151610599919061051a88614a54565b8051825114610a555760405162461bcd60e51b815260040161019090614a70565b60005b82518110156108b8576040805180820182523381523415156020808301919091529151610a859201614e0d565b604051602081830303815290604052828281518110610aa657610aa6614aa7565b602002602001015160c00181905250828181518110610ac757610ac7614aa7565b60200260200101516001600160a01b031663ae286976838381518110610aef57610aef614aa7565b60200260200101516040518263ffffffff1660e01b8152600401610b139190614e2f565b600060405180830381600087803b158015610b2d57600080fd5b505af1925050508015610b3e575060015b50600101610a58565b60608251845114610b6a5760405162461bcd60e51b815260040161019090614a70565b8115610c9d5760005b8451811015610c9b578015610c935783600081518110610b9557610b95614aa7565b6020026020010151606001511515848281518110610bb557610bb5614aa7565b602002602001015160600151151514610c0c5760405162461bcd60e51b81526020600482015260196024820152785a65726f466f724f6e65506172616d4d69736d61746368282960381b6044820152606401610190565b83600081518110610c1f57610c1f614aa7565b6020026020010151604001511515848281518110610c3f57610c3f614aa7565b602002602001015160400151151514610c935760405162461bcd60e51b81526020600482015260166024820152754578616374496e506172616d4d69736d61746368282960501b6044820152606401610190565b600101610b73565b505b83516001600160401b03811115610cb657610cb6613ab2565b604051908082528060200260200182016040528015610cef57816020015b610cdc6139f9565b815260200190600190039081610cd45790505b50905060005b8451811015610e9157848181518110610d1057610d10614aa7565b6020026020010151828281518110610d2a57610d2a614aa7565b60209081029190910101516001600160a01b0390911690528451859082908110610d5657610d56614aa7565b60200260200101516001600160a01b03166343865d4e858381518110610d7e57610d7e614aa7565b602090810291909101810151604080516001600160e01b031960e086901b16815282516001600160a01b03166004820152928201516001600160801b03166024840152810151151560448301526060015115156064820152608401606060405180830381865afa158015610df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1a9190614e9b565b848481518110610e2c57610e2c614aa7565b6020026020010151602001858581518110610e4957610e49614aa7565b6020026020010151604001868681518110610e6657610e66614aa7565b60209081029190910101516001600160a01b0390931660609093019290925291905252600101610cf5565b508115610ea557610ea28382612eb5565b90505b9392505050565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161026060405180830381865afa158015610eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f119190614cb6565b9050610f1c81612dfb565b6000610f2a83850185614f29565b90506000861215610fa6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b0316148015610f7b575080604001515b15610f9157610f8c6104fb87614a54565b610fa6565b60608201518151610fa6919061051a89614a54565b6000851215611020577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682608001516001600160a01b0316148015610ff5575080604001515b1561100b576110066104fb86614a54565b611020565b60808201518151611020919061051a88614a54565b6000861315611082577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b031614801561106f575080604001515b156110825761108281602001518761340c565b6000851315610599577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682608001516001600160a01b03161480156110d1575080604001515b156105995761059981602001518661340c565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166341d80eb3856040518263ffffffff1660e01b81526004016111339190614f45565b6040805180830381865afa15801561114f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111739190614fa2565b90925090506001600160a01b03821661121a5760405163211ed5b760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063211ed5b7906111d2908790600401614f45565b60408051808303816000875af11580156111f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112149190614fa2565b90925090505b60005b835181101561131b57600084828151811061123a5761123a614aa7565b60209081029190910181015163ffffffff90921660409283015281518083018352338152341515818301529151611272929101614e0d565b60405160208183030381529060405284828151811061129357611293614aa7565b602002602001015160c00181905250826001600160a01b031663ae2869768583815181106112c3576112c3614aa7565b60200260200101516040518263ffffffff1660e01b81526004016112e79190614e2f565b600060405180830381600087803b15801561130157600080fd5b505af1925050508015611312575060015b5060010161121d565b50611324612dd4565b9250929050565b805182511461134c5760405162461bcd60e51b815260040161019090614a70565b60005b82518110156108b857604080518082018252338152341515602080830191909152915161137c9201614e0d565b60405160208183030381529060405282828151811061139d5761139d614aa7565b602002602001015160e001819052508281815181106113be576113be614aa7565b60200260200101516001600160a01b031663270ffd7d8383815181106113e6576113e6614aa7565b60200260200101516040518263ffffffff1660e01b815260040161140a9190614fdc565b60408051808303816000875af1158015611428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144c9190614c17565b505060010161134f565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161016060405180830381865afa158015611497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bb9190614920565b90506114c6816129b3565b60006114d483850185614f29565b90506000861215611550577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682608001516001600160a01b0316148015611525575080604001515b1561153b576115366104fb87614a54565b611550565b60808201518151611550919061051a89614a54565b60008512156115ca577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168260a001516001600160a01b031614801561159f575080604001515b156115b5576115b06104fb86614a54565b6115ca565b60a082015181516115ca919061051a88614a54565b600086131561162c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682608001516001600160a01b0316148015611619575080604001515b1561162c5761162c81602001518761340c565b6000851315610599577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168260a001516001600160a01b03161480156110d157508060400151156105995761059981602001518661340c565b80518251146116ae5760405162461bcd60e51b815260040161019090614a70565b60005b825181101561186d57801561186557816000815181106116d3576116d3614aa7565b60200260200101516080015115158282815181106116f3576116f3614aa7565b60200260200101516080015115151461174a5760405162461bcd60e51b81526020600482015260196024820152785a65726f466f724f6e65506172616d4d69736d61746368282960381b6044820152606401610190565b8160008151811061175d5761175d614aa7565b602002602001015160600151151582828151811061177d5761177d614aa7565b6020026020010151606001511515146117d15760405162461bcd60e51b81526020600482015260166024820152754578616374496e506172616d4d69736d61746368282960501b6044820152606401610190565b816000815181106117e4576117e4614aa7565b6020026020010151604001516001600160801b031682828151811061180b5761180b614aa7565b6020026020010151604001516001600160801b0316146118655760405162461bcd60e51b8152602060048201526015602482015274416d6f756e74506172616d4d69734d61746368282960581b6044820152606401610190565b6001016116b1565b5060005b8251811080156118a8575060008260008151811061189157611891614aa7565b6020026020010151604001516001600160801b0316115b156108b8576040518060600160405280336001600160a01b031681526020018383815181106118d9576118d9614aa7565b6020026020010151600001516001600160a01b0316815260200160003411151581525060405160200161190c9190614b08565b60405160208183030381529060405282828151811061192d5761192d614aa7565b602090810291909101015160a001523415611c2357600083828151811061195657611956614aa7565b60200260200101519050600083838151811061197457611974614aa7565b6020026020010151608001516119eb57816001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e69190615084565b611a4d565b816001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4d9190615084565b90506000848481518110611a6357611a63614aa7565b602002602001015160800151611ada57826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad59190615084565b611b3c565b826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3c9190615084565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031603611ba75730858581518110611b8a57611b8a614aa7565b60209081029190910101516001600160a01b039091169052611c1f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614611c1f5760405162461bcd60e51b81526020600482015260146024820152734e6f6e4e6174697665546f6b656e50616972282960601b6044820152606401610190565b5050505b600080848381518110611c3857611c38614aa7565b60200260200101516001600160a01b031663e323eb0e858581518110611c6057611c60614aa7565b60200260200101516040518263ffffffff1660e01b8152600401611c8491906150a1565b60408051808303816000875af1158015611ca2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc69190614c17565b86519193509150611cd8846001615107565b1015611f245783600081518110611cf157611cf1614aa7565b6020026020010151608001518015611d24575083600081518110611d1757611d17614aa7565b6020026020010151606001515b15611d7e57611d42611d3d611d3884614a54565b613494565b6134ea565b84600081518110611d5557611d55614aa7565b6020026020010151604001818151611d6d919061511a565b6001600160801b0316905250611ec2565b83600081518110611d9157611d91614aa7565b6020026020010151608001518015611dc5575083600081518110611db757611db7614aa7565b602002602001015160600151155b15611dd657611d42611d3d82613494565b83600081518110611de957611de9614aa7565b602002602001015160800151158015611e1e575083600081518110611e1057611e10614aa7565b602002602001015160600151155b15611e2f57611d42611d3d83613494565b83600081518110611e4257611e42614aa7565b602002602001015160800151158015611e76575083600081518110611e6957611e69614aa7565b6020026020010151606001515b15611ec257611e8a611d3d611d3883614a54565b84600081518110611e9d57611e9d614aa7565b6020026020010151604001818151611eb5919061511a565b6001600160801b03169052505b83600081518110611ed557611ed5614aa7565b60200260200101516040015184846001611eef9190615107565b81518110611eff57611eff614aa7565b6020026020010151604001906001600160801b031690816001600160801b0316815250505b5050600101611871565b8051825114611f4f5760405162461bcd60e51b815260040161019090614a70565b60005b8251811015612092576040518060600160405280336001600160a01b03168152602001838381518110611f8757611f87614aa7565b6020026020010151600001516001600160a01b0316815260200160011515815250604051602001611fb89190614b08565b604051602081830303815290604052828281518110611fd957611fd9614aa7565b602002602001015160a00181905250828181518110611ffa57611ffa614aa7565b60200260200101516001600160a01b031663e323eb0e83838151811061202257612022614aa7565b60200260200101516040518263ffffffff1660e01b815260040161204691906150a1565b60408051808303816000875af1158015612064573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120889190614c17565b5050600101611f52565b505050565b82516020840151606085015160808601516040516305edf9d360e31b81526001600160a01b039485166004820152928416602484015261ffff918216604484015216606482015260009182917f000000000000000000000000000000000000000000000000000000000000000090911690632f6fce98906084016040805180830381865afa15801561212d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121519190614fa2565b90925090506001600160a01b03821661222c576040805163aa5c269b60e01b815286516001600160a01b0390811660048301526020880151811660248301529187015182166044820152606087015161ffff908116606483015260808801511660848201527f00000000000000000000000000000000000000000000000000000000000000009091169063aa5c269b9060a40160408051808303816000875af1158015612202573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122269190614fa2565b90925090505b60005b84518110156124e55760008086838151811061224d5761224d614aa7565b60200260200101516060019063ffffffff16908163ffffffff168152505060006040518060600160405280336001600160a01b0316815260200188858151811061229957612299614aa7565b6020026020010151600001516001600160a01b0316815260200160003411151581525090508683815181106122d0576122d0614aa7565b602002602001015160c001518060200190518101906122ef9190614abd565b5191506001600160a01b0382161561232d578187848151811061231457612314614aa7565b60209081029190910101516001600160a01b0390911690525b8060405160200161233e9190614b08565b60405160208183030381529060405287848151811061235f5761235f614aa7565b602002602001015160c0018190525050836001600160a01b031663f0a20aec87848151811061239057612390614aa7565b60200260200101516040518263ffffffff1660e01b81526004016123b49190614b89565b60408051808303816000875af19250505080156123ee575060408051601f3d908101601f191682019092526123eb91810190614c17565b60015b156123f65750505b6001600160a01b038116156124dc57806001600160a01b0316630d55b879604051806060016040528089868151811061243157612431614aa7565b602002602001015160c001518060200190518101906124509190614c46565b6020908101516001600160a01b03908116835289811683830152600060409384015282516001600160e01b031960e087901b1681528451821660048201529184015116602482015291015163ffffffff166044820152606401600060405180830381600087803b1580156124c357600080fd5b505af11580156124d7573d6000803e3d6000fd5b505050505b5060010161222f565b5060005b835181101561260357600084828151811061250657612506614aa7565b60209081029190910181015163ffffffff9092166060909201919091526040805180820182523381523415158184015290516125429201614e0d565b60405160208183030381529060405284828151811061256357612563614aa7565b602002602001015160e00181905250826001600160a01b031663270ffd7d85838151811061259357612593614aa7565b60200260200101516040518263ffffffff1660e01b81526004016125b79190614fdc565b60408051808303816000875af11580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190614c17565b50506001016124e9565b5061260c612dd4565b935093915050565b60608083516001600160401b0381111561263057612630613ab2565b604051908082528060200260200182016040528015612659578160200160208202803683370190505b50915083516001600160401b0381111561267557612675613ab2565b60405190808252806020026020018201604052801561269e578160200160208202803683370190505b50905060005b84518110156128525760006001600160a01b03168582815181106126ca576126ca614aa7565b60200260200101516001600160a01b03160361271f5760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964506f6f6c41646472657373282960601b6044820152606401610190565b84818151811061273157612731614aa7565b60200260200101516001600160a01b0316638a5ee2c385838151811061275957612759614aa7565b602090810291909101810151604080516001600160e01b031960e086901b16815282516001600160a01b03166004820152928201516001600160801b0316602484015281015163ffffffff166044830152606081015160020b6064830152608001511515608482015260a4016040805180830381865afa1580156127e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128059190615141565b84838151811061281757612817614aa7565b6020026020010184848151811061283057612830614aa7565b6001600160801b039384166020918202929092010152911690526001016126a4565b509250929050565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161016060405180830381865afa15801561289b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128bf9190614920565b90506128ca816129b3565b60006128d883850185614f29565b90506000861215612954577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682608001516001600160a01b0316148015612929575080604001515b1561293f5761293a6104fb87614a54565b612954565b60808201518151612954919061051a89614a54565b6000851215610599577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168260a001516001600160a01b031614801561056e57508060400151156105845761057f6104fb86614a54565b6000816020015182608001518360a00151846101200151604051602001612a0694939291906001600160a01b03948516815292841660208401529216604082015261ffff91909116606082015260800190565b6040516020818303038152906040528051906020012090506000612b1d8360200151612af6858051608082015160a08084015160c0850151606080870151805160209182015160e0808b01516101008c01516101208d01516040519c881b6bffffffffffffffffffffffff19908116978e01979097529a871b861660348d015297861b851660488c015295851b8416605c8b015291841b831660708a0152831b90911660848801529190911b6001600160e01b031916609886015260f091821b609c86015292901b6001600160f01b031916609e8401529091016040516020818303038152906040529050919050565b847f0000000000000000000000000000000000000000000000000000000000000000613548565b9050336001600160a01b038216146120925760405162461bcd60e51b8152602060048201526016602482015275496e76616c696443616c6c657241646472657373282960501b6044820152606401610190565b7f000000000000000000000000000000000000000000000000000000000000000047821115612be15760405162461bcd60e51b815260206004820152601860248201527f577261704574683a3a4c6f7745746842616c616e6365282900000000000000006044820152606401610190565b806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015612c1c57600080fd5b505af1158015612c30573d6000803e3d6000fd5b50505050506108c1337f000000000000000000000000000000000000000000000000000000000000000084613623565b6001600160a01b038316612cc25760405162461bcd60e51b8152602060048201526024808201527f536166655472616e73666572733a3a43616e6e6f745472616e73666572496e456044820152637468282960e01b6064820152608401610190565b6040516323b872dd60e01b81526001600160a01b038381166004830152336024830152604482018390528491908216906323b872dd906064016020604051808303816000875af1158015612d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3e9190615170565b5060003d8015612d595760208114612d625760009150612d6e565b60019150612d6e565b60206000803e60005191505b5080612dcd5760405162461bcd60e51b815260206004820152602860248201527f5472616e736665724661696c6564286d73672e73656e6465722c206164647265604482015267737328746869732960c01b6064820152608401610190565b5050505050565b4715612ded57344710612def57612ded33600034613623565b565b612ded33600047613623565b606080820151608080840151845160e080870151610160880151610180890151604080516001600160a01b03998a1660208201529689169087015293871697850197909752949094169282019290925260019390930b60a084015261ffff1660c0830152600091016040516020818303038152906040528051906020012090506000612b1d8360a00151612e8e856137fa565b847f0000000000000000000000000000000000000000000000000000000000000000613548565b6060612ef76040518060e00160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081525090565b82516001600160401b03811115612f1057612f10613ab2565b604051908082528060200260200182016040528015612f4957816020015b612f366139f9565b815260200190600190039081612f2e5790505b50815282516001600160401b03811115612f6557612f65613ab2565b604051908082528060200260200182016040528015612f8e578160200160208202803683370190505b5060408201526000606082018190525b83518110156132e55784600081518110612fba57612fba614aa7565b602002602001015160400151612fd7576001600160ff1b03612fda565b60005b608083015260001960a083015260005b845181101561314e578260400151818151811061300957613009614aa7565b6020026020010151613146578560008151811061302857613028614aa7565b602002602001015160400151156130c257600085828151811061304d5761304d614aa7565b6020026020010151604001511380156130875750826080015185828151811061307857613078614aa7565b60200260200101516040015112155b156130bd5760a0830181905284518590829081106130a7576130a7614aa7565b6020026020010151604001518360800181815250505b613146565b60008582815181106130d6576130d6614aa7565b6020026020010151602001511380156131105750826080015185828151811061310157613101614aa7565b60200260200101516020015113155b156131465760a08301819052845185908290811061313057613130614aa7565b6020026020010151602001518360800181815250505b600101612fea565b506000198260a00151146132cb57838260a001518151811061317257613172614aa7565b6020026020010151600001518260000151828151811061319457613194614aa7565b60209081029190910101516001600160a01b03909116905260a0820151845185919081106131c4576131c4614aa7565b602002602001015160200151826000015182815181106131e6576131e6614aa7565b60200260200101516020018181525050838260a001518151811061320c5761320c614aa7565b6020026020010151604001518260000151828151811061322e5761322e614aa7565b60200260200101516040018181525050838260a001518151811061325457613254614aa7565b6020026020010151606001518260000151828151811061327657613276614aa7565b6020026020010151606001906001600160a01b031690816001600160a01b031681525050600182604001518360a00151815181106132b6576132b6614aa7565b911515602092830291909101909101526132dd565b8160600180516132da9061518d565b90525b600101612f9e565b506060810151156133f7578060600151835161330191906151a6565b6001600160401b0381111561331857613318613ab2565b60405190808252806020026020018201604052801561335157816020015b61333e6139f9565b8152602001906001900390816133365790505b506020820152600060c082018190525b83518110156133f15781518051600091908390811061338257613382614aa7565b6020026020010151600001516001600160a01b0316146133e95781518051829081106133b0576133b0614aa7565b602002602001015182602001518360c00151815181106133d2576133d2614aa7565b602090810291909101015260c08201805160010190525b600101613361565b506133ff565b805160208201525b6020015190505b92915050565b604051632e1a7d4d60e01b8152600481018290527f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03821690632e1a7d4d90602401600060405180830381600087803b15801561347057600080fd5b505af1158015613484573d6000803e3d6000fd5b5050505061209283600084613623565b6000808212156134e65760405162461bcd60e51b815260206004820152601b60248201527f496e74323536546f55696e743235363a556e646572666c6f77282900000000006044820152606401610190565b5090565b806001600160801b03811681146135435760405162461bcd60e51b815260206004820152601b60248201527f55696e74323536546f55696e743132383a4f766572666c6f77282900000000006044820152606401610190565b919050565b605f1983018051603f1985018051601f19870180518851808a0160200180516c5af43d3d93803e606057fd5bf38c52600c198c018d905260028301604881901b78593da1005b363d3d373d3d3d3d610000806062363936013d73176020198e01527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff6039198e01526064840160781b716100003d81600a3d39f336602c57343d527f176059198e015260f01b8252606e8301604b198d01209152908a529152915291526000906136198185856139d7565b9695505050505050565b6000816000036136335750505050565b6001600160a01b0383166136f3576040516001600160a01b038516908390600081818185875af1925050503d806000811461368a576040519150601f19603f3d011682016040523d82523d6000602084013e61368f565b606091505b505080915050806136ed5760405162461bcd60e51b815260206004820152602260248201527f536166655472616e73666572733a3a4574685472616e736665724661696c6564604482015261282960f01b6064820152608401610190565b50505050565b60405163a9059cbb60e01b81526001600160a01b0385811660048301526024820184905284919082169063a9059cbb906044016020604051808303816000875af1158015613745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137699190615170565b50600091503d8015613786576020811461378f576000925061379b565b6001925061379b565b60206000803e60005192505b5081612dcd5760405162461bcd60e51b815260206004820152602860248201527f5472616e736665724661696c656428616464726573732874686973292c206d73604482015267339739b2b73232b960c11b6064820152608401610190565b6040818101516060808401516080850151855160c08088015160e08901516020808b01518051908201519a516bffffffffffffffffffffffff199a8a1b8b169281019290925296881b8916603482015294871b8816604886015292861b8716605c850152851b8616607084015290841b8516608483015291831b8416609882015293821b90921660ac840152916000910160408051601f19818403018152908290526101008501516101208601516101408701516101608801516101808901516101a08a0151959750600096613932969060200160809690961b6fffffffffffffffffffffffffffffffff1916865260e09490941b6001600160e01b031916601086015260f092831b601486015290821b6016850152811b6001600160f01b0319908116601885015291901b16601a820152601c0190565b60408051601f198184030181528282526101c08701516101e08801516102008901516102208a015160f09390931b6001600160f01b031916602087015260f891821b6001600160f81b0319908116602288015290821b166023860152901515901b602484015281518084036005018152602584019092529250906139be908490849084906045016151b9565b6040516020818303038152906040529350505050919050565b600060ff60005350603592835260601b60015260155260556000908120915290565b604051806080016040528060006001600160a01b03168152602001600081526020016000815260200160006001600160a01b031681525090565b60008060008060608587031215613a4957600080fd5b843593506020850135925060408501356001600160401b0380821115613a6e57600080fd5b818701915087601f830112613a8257600080fd5b813581811115613a9157600080fd5b886020828501011115613aa357600080fd5b95989497505060200194505050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715613aea57613aea613ab2565b60405290565b604051608081016001600160401b0381118282101715613aea57613aea613ab2565b60405160c081016001600160401b0381118282101715613aea57613aea613ab2565b60405161010081016001600160401b0381118282101715613aea57613aea613ab2565b60405160a081016001600160401b0381118282101715613aea57613aea613ab2565b604080519081016001600160401b0381118282101715613aea57613aea613ab2565b60405161014081016001600160401b0381118282101715613aea57613aea613ab2565b604051606081016001600160401b0381118282101715613aea57613aea613ab2565b60405161024081016001600160401b0381118282101715613aea57613aea613ab2565b604051601f8201601f191681016001600160401b0381118282101715613c2b57613c2b613ab2565b604052919050565b60006001600160401b03821115613c4c57613c4c613ab2565b5060051b60200190565b6001600160a01b0381168114613c6b57600080fd5b50565b803561354381613c56565b600082601f830112613c8a57600080fd5b81356020613c9f613c9a83613c33565b613c03565b82815260059290921b84018101918181019086841115613cbe57600080fd5b8286015b84811015613ce2578035613cd581613c56565b8352918301918301613cc2565b509695505050505050565b8035600281900b811461354357600080fd5b63ffffffff81168114613c6b57600080fd5b803561354381613cff565b6001600160801b0381168114613c6b57600080fd5b803561354381613d1c565b600082601f830112613d4d57600080fd5b81356001600160401b03811115613d6657613d66613ab2565b613d79601f8201601f1916602001613c03565b818152846020838601011115613d8e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613dbc57600080fd5b81356020613dcc613c9a83613c33565b82815260059290921b84018101918181019086841115613deb57600080fd5b8286015b84811015613ce25780356001600160401b0380821115613e0f5760008081fd5b9088019060e0828b03601f1901811315613e295760008081fd5b613e31613ac8565b613e3c888501613c6e565b81526040613e4b818601613ced565b898301526060613e5c818701613ced565b8284015260809150613e6f828701613d11565b9083015260a0613e80868201613d31565b8284015260c09150613e93828701613d31565b90830152918401359183831115613eaa5760008081fd5b613eb88d8a85880101613d3c565b908201528652505050918301918301613def565b60008060408385031215613edf57600080fd5b82356001600160401b0380821115613ef657600080fd5b613f0286838701613c79565b93506020850135915080821115613f1857600080fd5b50613f2585828601613dab565b9150509250929050565b8015158114613c6b57600080fd5b803561354381613f2f565b600082601f830112613f5957600080fd5b81356020613f69613c9a83613c33565b82815260059290921b84018101918181019086841115613f8857600080fd5b8286015b84811015613ce25780356001600160401b0380821115613fac5760008081fd5b9088019060e0828b03601f1901811315613fc65760008081fd5b613fce613ac8565b613fd9888501613c6e565b81526040613fe8818601613d31565b898301526060613ff9818701613d11565b828401526080915061400c828701613ced565b9083015260a061401d868201613ced565b8284015260c09150614030828701613f3d565b908301529184013591838311156140475760008081fd5b6140558d8a85880101613d3c565b908201528652505050918301918301613f8c565b6000806040838503121561407c57600080fd5b82356001600160401b038082111561409357600080fd5b61409f86838701613c79565b935060208501359150808211156140b557600080fd5b50613f2585828601613f48565b600080600060608085870312156140d857600080fd5b84356001600160401b03808211156140ef57600080fd5b6140fb88838901613c79565b955060209150818701358181111561411257600080fd5b87019050601f8101881361412557600080fd5b8035614133613c9a82613c33565b81815260079190911b8201830190838101908a83111561415257600080fd5b928401925b828410156141cc576080848c0312156141705760008081fd5b614178613af0565b843561418381613c56565b81528486013561419281613d1c565b818701526040858101356141a581613f2f565b90820152848701356141b681613f2f565b8188015282526080939093019290840190614157565b8097505050505050506141e160408501613f3d565b90509250925092565b602080825282518282018190526000919060409081850190868401855b8281101561424d57815180516001600160a01b03908116865287820151888701528682015187870152606091820151169085015260809093019290850190600101614207565b5091979650505050505050565b61ffff81168114613c6b57600080fd5b80356135438161425a565b8060010b8114613c6b57600080fd5b803561354381614275565b60008082840360e08112156142a357600080fd5b60c08112156142b157600080fd5b506142ba613b12565b8335815260208401356142cc81613c56565b602082015260408401356142df81613c56565b604082015260608401356142f28161425a565b606082015261430360808501614284565b608082015261431460a0850161426a565b60a0820152915060c08301356001600160401b0381111561433457600080fd5b613f2585828601613f48565b80356bffffffffffffffffffffffff8116811461354357600080fd5b600082601f83011261436d57600080fd5b8135602061437d613c9a83613c33565b82815260059290921b8401810191818101908684111561439c57600080fd5b8286015b84811015613ce25780356001600160401b03808211156143c05760008081fd5b90880190610100828b03601f19018113156143db5760008081fd5b6143e3613b34565b6143ee888501613c6e565b815260406143fd818601613d31565b89830152606061440e818701614340565b8284015260809150614421828701613d11565b9083015260a0614432868201613ced565b8284015260c09150614445828701613ced565b9083015260e0614456868201613f3d565b8383015292850135928484111561446f57600091508182fd5b61447d8e8b86890101613d3c565b908301525086525050509183019183016143a0565b600080604083850312156144a557600080fd5b82356001600160401b03808211156144bc57600080fd5b6144c886838701613c79565b935060208501359150808211156144de57600080fd5b50613f258582860161435c565b600080604083850312156144fe57600080fd5b82356001600160401b038082111561451557600080fd5b61452186838701613c79565b935060209150818501358181111561453857600080fd5b8501601f8101871361454957600080fd5b8035614557613c9a82613c33565b81815260059190911b8201840190848101908983111561457657600080fd5b8584015b8381101561463f578035868111156145925760008081fd5b850160c0818d03601f19018113156145aa5760008081fd5b6145b2613b12565b898301356145bf81613c56565b815260408301356145cf81613c56565b818b01526060838101356145e281613d1c565b604083015260806145f4858201613f3d565b8284015260a09150614607828601613f3d565b9083015291830135918983111561461e5760008081fd5b61462c8f8c85870101613d3c565b908201528552505091860191860161457a565b508096505050505050509250929050565b600080600083850360e081121561466657600080fd5b60a081121561467457600080fd5b5061467d613b57565b843561468881613c56565b8152602085013561469881613c56565b602082015260408501356146ab81613c56565b604082015260608501356146be8161425a565b606082015260808501356146d18161425a565b6080820152925060a08401356001600160401b03808211156146f257600080fd5b6146fe87838801613dab565b935060c086013591508082111561471457600080fd5b506147218682870161435c565b9150509250925092565b600080604080848603121561473f57600080fd5b83356001600160401b038082111561475657600080fd5b61476287838801613c79565b945060209150818601358181111561477957600080fd5b86019050601f8101871361478c57600080fd5b803561479a613c9a82613c33565b81815260a0918202830184019184820191908a8411156147b957600080fd5b938501935b8385101561463f5780858c0312156147d65760008081fd5b6147de613b57565b85356147e981613c56565b8152858701356147f881613d1c565b818801528588013561480981613cff565b81890152606061481a878201613ced565b9082015260808681013561482d81613f2f565b90820152835293840193918501916147be565b600081518084526020808501945080840160005b838110156148795781516001600160801b031687529582019590820190600101614854565b509495945050505050565b6040815260006148976040830185614840565b82810360208401526148a98185614840565b95945050505050565b805161354381613c56565b6000604082840312156148cf57600080fd5b6148d7613b79565b905081516148e481613c56565b815260208201516148f481613c56565b602082015292915050565b805161354381613cff565b805161354381614275565b80516135438161425a565b6000610160828403121561493357600080fd5b61493b613b9b565b614944836148b2565b8152614952602084016148b2565b6020820152614963604084016148b2565b604082015261497584606085016148bd565b606082015261498660a084016148b2565b608082015261499760c084016148b2565b60a08201526149a860e084016148b2565b60c08201526101006149bb8185016148ff565b60e08301526101206149ce81860161490a565b828401526149df6101408601614915565b90830152509392505050565b6000604082840312156149fd57600080fd5b614a05613b79565b90508135614a1281613c56565b815260208201356148f481613f2f565b600060408284031215614a3457600080fd5b610ea583836149eb565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201614a6957614a69614a3e565b5060000390565b6020808252601b908201527f496e70757441727261794c656e677468734d69736d6174636828290000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215614acf57600080fd5b604051602081018181106001600160401b0382111715614af157614af1613ab2565b6040528251614aff81613c56565b81529392505050565b81516001600160a01b0390811682526020808401519091169082015260408083015115159082015260608101613406565b60005b83811015614b54578181015183820152602001614b3c565b50506000910152565b60008151808452614b75816020860160208601614b39565b601f01601f19169290920160200192915050565b6020815260018060a01b038251166020820152602082015160020b6040820152604082015160020b606082015263ffffffff60608301511660808201526001600160801b0360808301511660a0820152600060a0830151614bf560c08401826001600160801b03169052565b5060c083015160e080840152614c0f610100840182614b5d565b949350505050565b60008060408385031215614c2a57600080fd5b505080516020909101519092909150565b805161354381613f2f565b600060608284031215614c5857600080fd5b614c60613bbe565b8251614c6b81613c56565b81526020830151614c7b81613c56565b60208201526040830151614c8e81613f2f565b60408201529392505050565b805161354381613d1c565b805160ff8116811461354357600080fd5b60006102608284031215614cc957600080fd5b614cd1613be0565b614cda836148b2565b8152614ce984602085016148bd565b6020820152614cfa606084016148b2565b6040820152614d0b608084016148b2565b6060820152614d1c60a084016148b2565b6080820152614d2d60c084016148b2565b60a0820152614d3e60e084016148b2565b60c0820152610100614d518185016148b2565b60e0830152610120614d64818601614c9a565b828401526101409150614d788286016148ff565b90830152610160614d8a85820161490a565b828401526101809150614d9e82860161490a565b908301526101a0614db0858201614915565b828401526101c09150614dc4828601614915565b908301526101e0614dd6858201614915565b828401526102009150614dea828601614ca5565b90830152610220614dfc858201614ca5565b828401526149df6102408601614c3b565b81516001600160a01b0316815260208083015115159082015260408101613406565b6020815260018060a01b0382511660208201526001600160801b03602083015116604082015263ffffffff6040830151166060820152606082015160020b608082015260006080830151614e8860a084018260020b9052565b5060a083015180151560c0840152614bf5565b600080600060608486031215614eb057600080fd5b83519250602084015191506040840151614ec981613c56565b809150509250925092565b600060608284031215614ee657600080fd5b614eee613bbe565b90508135614efb81613c56565b81526020820135614f0b81613c56565b60208201526040820135614f1e81613f2f565b604082015292915050565b600060608284031215614f3b57600080fd5b610ea58383614ed4565b815181526020808301516001600160a01b03908116918301919091526040808401519091169082015260608083015161ffff9081169183019190915260808084015160010b9083015260a092830151169181019190915260c00190565b60008060408385031215614fb557600080fd5b8251614fc081613c56565b6020840151909250614fd181613c56565b809150509250929050565b602080825282516001600160a01b0316828201528201516001600160801b03166040808301919091528201516bffffffffffffffffffffffff8116606083015260009050606083015163ffffffff8116608084015250608083015161504660a084018260020b9052565b5060a083015161505b60c084018260020b9052565b5060c083015180151560e08401525060e083015161010083810152614c0f610120840182614b5d565b60006020828403121561509657600080fd5b8151610ea581613c56565b60208152600060018060a01b03808451166020840152806020850151166040840152506001600160801b0360408401511660608301526060830151151560808301526080830151151560a083015260a083015160c080840152614c0f60e0840182614b5d565b8082018082111561340657613406614a3e565b6001600160801b0382811682821603908082111561513a5761513a614a3e565b5092915050565b6000806040838503121561515457600080fd5b825161515f81613d1c565b6020840151909250614fd181613d1c565b60006020828403121561518257600080fd5b8151610ea581613f2f565b60006001820161519f5761519f614a3e565b5060010190565b8181038181111561340657613406614a3e565b600084516151cb818460208901614b39565b8451908301906151df818360208901614b39565b84519101906151f2818360208801614b39565b019594505050505056fea26469706673582212208aa96be23bb8346e4b24e9338221c82a212d18afb7c983f81cd51d23baf36b7364736f6c63430008120033000000000000000000000000d28d620853af6837d76f1360dc65229d57ba5435000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Deployed Bytecode
0x60806040526004361061010d5760003560e01c80636d44b43211610095578063bd5ad2d411610064578063bd5ad2d414610387578063cd5489f11461039a578063dc6fdb86146103ba578063e3756840146103cd578063e9648aa3146103fb57600080fd5b80636d44b432146102ec5780638613ac89146102ff5780639d39786014610333578063ac434c6c1461035357600080fd5b806346d826a0116100dc57806346d826a0146102255780634f0e0ef314610238578063545970271461026c5780635cf4dc451461029957806363be21ee146102b957600080fd5b8063030c66d5146101a05780630a1e49ca146101c0578063141a36eb146101d357806341398b15146101f357600080fd5b3661019b57336001600160a01b037f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab116146101995760405162461bcd60e51b815260206004820152602160248201527f506f6f6c736861726b526f757465723a3a52656365697665496e76616c6964286044820152602960f81b60648201526084015b60405180910390fd5b005b600080fd5b3480156101ac57600080fd5b506101996101bb366004613a33565b61041b565b6101996101ce366004613ecc565b6105a1565b3480156101df57600080fd5b506101996101ee366004613a33565b6108c5565b3480156101ff57600080fd5b50610208600081565b6040516001600160a01b0390911681526020015b60405180910390f35b610199610233366004614069565b610a34565b34801561024457600080fd5b506102087f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab181565b34801561027857600080fd5b5061028c6102873660046140c2565b610b47565b60405161021c91906141ea565b3480156102a557600080fd5b506101996102b4366004613a33565b610eac565b6102cc6102c736600461428f565b6110e4565b604080516001600160a01b0393841681529290911660208301520161021c565b6101996102fa366004614492565b61132b565b34801561030b57600080fd5b506102087f000000000000000000000000d28d620853af6837d76f1360dc65229d57ba543581565b34801561033f57600080fd5b5061019961034e366004613a33565b611456565b34801561035f57600080fd5b506102087f000000000000000000000000000000000000000000000000000000000000000081565b6101996103953660046144eb565b61168d565b3480156103a657600080fd5b506101996103b53660046144eb565b611f2e565b6102cc6103c8366004614650565b612097565b3480156103d957600080fd5b506103ed6103e836600461472b565b612614565b60405161021c929190614884565b34801561040757600080fd5b50610199610416366004613a33565b61285a565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161016060405180830381865afa15801561045c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104809190614920565b905061048b816129b3565b600061049983850185614a22565b9050600086121561051f577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682608001516001600160a01b03161480156104ea575080602001515b15610505576105006104fb87614a54565b612b70565b61051f565b6080820151815161051f919061051a89614a54565b612c60565b6000851215610599577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b03168260a001516001600160a01b031614801561056e575080602001515b156105845761057f6104fb86614a54565b610599565b60a08201518151610599919061051a88614a54565b505050505050565b80518251146105c25760405162461bcd60e51b815260040161019090614a70565b60005b82518110156108b8576000806040518060600160405280336001600160a01b031681526020018585815181106105fd576105fd614aa7565b6020026020010151600001516001600160a01b03168152602001600034111515815250905083838151811061063457610634614aa7565b602002602001015160c001518060200190518101906106539190614abd565b5191506001600160a01b03821615610691578184848151811061067857610678614aa7565b60209081029190910101516001600160a01b0390911690525b806040516020016106a29190614b08565b6040516020818303038152906040528484815181106106c3576106c3614aa7565b602002602001015160c00181905250508382815181106106e5576106e5614aa7565b60200260200101516001600160a01b031663f0a20aec84848151811061070d5761070d614aa7565b60200260200101516040518263ffffffff1660e01b81526004016107319190614b89565b60408051808303816000875af115801561074f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107739190614c17565b50506001600160a01b038116156108af57806001600160a01b0316630d55b87960405180606001604052808686815181106107b0576107b0614aa7565b602002602001015160c001518060200190518101906107cf9190614c46565b602001516001600160a01b031681526020018786815181106107f3576107f3614aa7565b60200260200101516001600160a01b0316815260200186868151811061081b5761081b614aa7565b60200260200101516060015163ffffffff168152506040518263ffffffff1660e01b815260040161087c919081516001600160a01b0390811682526020808401519091169082015260409182015163ffffffff169181019190915260600190565b600060405180830381600087803b15801561089657600080fd5b505af11580156108aa573d6000803e3d6000fd5b505050505b506001016105c5565b506108c1612dd4565b5050565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161026060405180830381865afa158015610906573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092a9190614cb6565b905061093581612dfb565b600061094383850185614a22565b905060008612156109bf577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682606001516001600160a01b0316148015610994575080602001515b156109aa576109a56104fb87614a54565b6109bf565b606082015181516109bf919061051a89614a54565b6000851215610599577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682608001516001600160a01b0316148015610a0e575080602001515b15610a1f5761057f6104fb86614a54565b60808201518151610599919061051a88614a54565b8051825114610a555760405162461bcd60e51b815260040161019090614a70565b60005b82518110156108b8576040805180820182523381523415156020808301919091529151610a859201614e0d565b604051602081830303815290604052828281518110610aa657610aa6614aa7565b602002602001015160c00181905250828181518110610ac757610ac7614aa7565b60200260200101516001600160a01b031663ae286976838381518110610aef57610aef614aa7565b60200260200101516040518263ffffffff1660e01b8152600401610b139190614e2f565b600060405180830381600087803b158015610b2d57600080fd5b505af1925050508015610b3e575060015b50600101610a58565b60608251845114610b6a5760405162461bcd60e51b815260040161019090614a70565b8115610c9d5760005b8451811015610c9b578015610c935783600081518110610b9557610b95614aa7565b6020026020010151606001511515848281518110610bb557610bb5614aa7565b602002602001015160600151151514610c0c5760405162461bcd60e51b81526020600482015260196024820152785a65726f466f724f6e65506172616d4d69736d61746368282960381b6044820152606401610190565b83600081518110610c1f57610c1f614aa7565b6020026020010151604001511515848281518110610c3f57610c3f614aa7565b602002602001015160400151151514610c935760405162461bcd60e51b81526020600482015260166024820152754578616374496e506172616d4d69736d61746368282960501b6044820152606401610190565b600101610b73565b505b83516001600160401b03811115610cb657610cb6613ab2565b604051908082528060200260200182016040528015610cef57816020015b610cdc6139f9565b815260200190600190039081610cd45790505b50905060005b8451811015610e9157848181518110610d1057610d10614aa7565b6020026020010151828281518110610d2a57610d2a614aa7565b60209081029190910101516001600160a01b0390911690528451859082908110610d5657610d56614aa7565b60200260200101516001600160a01b03166343865d4e858381518110610d7e57610d7e614aa7565b602090810291909101810151604080516001600160e01b031960e086901b16815282516001600160a01b03166004820152928201516001600160801b03166024840152810151151560448301526060015115156064820152608401606060405180830381865afa158015610df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1a9190614e9b565b848481518110610e2c57610e2c614aa7565b6020026020010151602001858581518110610e4957610e49614aa7565b6020026020010151604001868681518110610e6657610e66614aa7565b60209081029190910101516001600160a01b0390931660609093019290925291905252600101610cf5565b508115610ea557610ea28382612eb5565b90505b9392505050565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161026060405180830381865afa158015610eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f119190614cb6565b9050610f1c81612dfb565b6000610f2a83850185614f29565b90506000861215610fa6577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682606001516001600160a01b0316148015610f7b575080604001515b15610f9157610f8c6104fb87614a54565b610fa6565b60608201518151610fa6919061051a89614a54565b6000851215611020577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682608001516001600160a01b0316148015610ff5575080604001515b1561100b576110066104fb86614a54565b611020565b60808201518151611020919061051a88614a54565b6000861315611082577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682606001516001600160a01b031614801561106f575080604001515b156110825761108281602001518761340c565b6000851315610599577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682608001516001600160a01b03161480156110d1575080604001515b156105995761059981602001518661340c565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166341d80eb3856040518263ffffffff1660e01b81526004016111339190614f45565b6040805180830381865afa15801561114f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111739190614fa2565b90925090506001600160a01b03821661121a5760405163211ed5b760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063211ed5b7906111d2908790600401614f45565b60408051808303816000875af11580156111f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112149190614fa2565b90925090505b60005b835181101561131b57600084828151811061123a5761123a614aa7565b60209081029190910181015163ffffffff90921660409283015281518083018352338152341515818301529151611272929101614e0d565b60405160208183030381529060405284828151811061129357611293614aa7565b602002602001015160c00181905250826001600160a01b031663ae2869768583815181106112c3576112c3614aa7565b60200260200101516040518263ffffffff1660e01b81526004016112e79190614e2f565b600060405180830381600087803b15801561130157600080fd5b505af1925050508015611312575060015b5060010161121d565b50611324612dd4565b9250929050565b805182511461134c5760405162461bcd60e51b815260040161019090614a70565b60005b82518110156108b857604080518082018252338152341515602080830191909152915161137c9201614e0d565b60405160208183030381529060405282828151811061139d5761139d614aa7565b602002602001015160e001819052508281815181106113be576113be614aa7565b60200260200101516001600160a01b031663270ffd7d8383815181106113e6576113e6614aa7565b60200260200101516040518263ffffffff1660e01b815260040161140a9190614fdc565b60408051808303816000875af1158015611428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144c9190614c17565b505060010161134f565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161016060405180830381865afa158015611497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bb9190614920565b90506114c6816129b3565b60006114d483850185614f29565b90506000861215611550577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682608001516001600160a01b0316148015611525575080604001515b1561153b576115366104fb87614a54565b611550565b60808201518151611550919061051a89614a54565b60008512156115ca577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b03168260a001516001600160a01b031614801561159f575080604001515b156115b5576115b06104fb86614a54565b6115ca565b60a082015181516115ca919061051a88614a54565b600086131561162c577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682608001516001600160a01b0316148015611619575080604001515b1561162c5761162c81602001518761340c565b6000851315610599577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b03168260a001516001600160a01b03161480156110d157508060400151156105995761059981602001518661340c565b80518251146116ae5760405162461bcd60e51b815260040161019090614a70565b60005b825181101561186d57801561186557816000815181106116d3576116d3614aa7565b60200260200101516080015115158282815181106116f3576116f3614aa7565b60200260200101516080015115151461174a5760405162461bcd60e51b81526020600482015260196024820152785a65726f466f724f6e65506172616d4d69736d61746368282960381b6044820152606401610190565b8160008151811061175d5761175d614aa7565b602002602001015160600151151582828151811061177d5761177d614aa7565b6020026020010151606001511515146117d15760405162461bcd60e51b81526020600482015260166024820152754578616374496e506172616d4d69736d61746368282960501b6044820152606401610190565b816000815181106117e4576117e4614aa7565b6020026020010151604001516001600160801b031682828151811061180b5761180b614aa7565b6020026020010151604001516001600160801b0316146118655760405162461bcd60e51b8152602060048201526015602482015274416d6f756e74506172616d4d69734d61746368282960581b6044820152606401610190565b6001016116b1565b5060005b8251811080156118a8575060008260008151811061189157611891614aa7565b6020026020010151604001516001600160801b0316115b156108b8576040518060600160405280336001600160a01b031681526020018383815181106118d9576118d9614aa7565b6020026020010151600001516001600160a01b0316815260200160003411151581525060405160200161190c9190614b08565b60405160208183030381529060405282828151811061192d5761192d614aa7565b602090810291909101015160a001523415611c2357600083828151811061195657611956614aa7565b60200260200101519050600083838151811061197457611974614aa7565b6020026020010151608001516119eb57816001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e69190615084565b611a4d565b816001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4d9190615084565b90506000848481518110611a6357611a63614aa7565b602002602001015160800151611ada57826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad59190615084565b611b3c565b826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3c9190615084565b90507f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b0316816001600160a01b031603611ba75730858581518110611b8a57611b8a614aa7565b60209081029190910101516001600160a01b039091169052611c1f565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b0316826001600160a01b031614611c1f5760405162461bcd60e51b81526020600482015260146024820152734e6f6e4e6174697665546f6b656e50616972282960601b6044820152606401610190565b5050505b600080848381518110611c3857611c38614aa7565b60200260200101516001600160a01b031663e323eb0e858581518110611c6057611c60614aa7565b60200260200101516040518263ffffffff1660e01b8152600401611c8491906150a1565b60408051808303816000875af1158015611ca2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc69190614c17565b86519193509150611cd8846001615107565b1015611f245783600081518110611cf157611cf1614aa7565b6020026020010151608001518015611d24575083600081518110611d1757611d17614aa7565b6020026020010151606001515b15611d7e57611d42611d3d611d3884614a54565b613494565b6134ea565b84600081518110611d5557611d55614aa7565b6020026020010151604001818151611d6d919061511a565b6001600160801b0316905250611ec2565b83600081518110611d9157611d91614aa7565b6020026020010151608001518015611dc5575083600081518110611db757611db7614aa7565b602002602001015160600151155b15611dd657611d42611d3d82613494565b83600081518110611de957611de9614aa7565b602002602001015160800151158015611e1e575083600081518110611e1057611e10614aa7565b602002602001015160600151155b15611e2f57611d42611d3d83613494565b83600081518110611e4257611e42614aa7565b602002602001015160800151158015611e76575083600081518110611e6957611e69614aa7565b6020026020010151606001515b15611ec257611e8a611d3d611d3883614a54565b84600081518110611e9d57611e9d614aa7565b6020026020010151604001818151611eb5919061511a565b6001600160801b03169052505b83600081518110611ed557611ed5614aa7565b60200260200101516040015184846001611eef9190615107565b81518110611eff57611eff614aa7565b6020026020010151604001906001600160801b031690816001600160801b0316815250505b5050600101611871565b8051825114611f4f5760405162461bcd60e51b815260040161019090614a70565b60005b8251811015612092576040518060600160405280336001600160a01b03168152602001838381518110611f8757611f87614aa7565b6020026020010151600001516001600160a01b0316815260200160011515815250604051602001611fb89190614b08565b604051602081830303815290604052828281518110611fd957611fd9614aa7565b602002602001015160a00181905250828181518110611ffa57611ffa614aa7565b60200260200101516001600160a01b031663e323eb0e83838151811061202257612022614aa7565b60200260200101516040518263ffffffff1660e01b815260040161204691906150a1565b60408051808303816000875af1158015612064573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120889190614c17565b5050600101611f52565b505050565b82516020840151606085015160808601516040516305edf9d360e31b81526001600160a01b039485166004820152928416602484015261ffff918216604484015216606482015260009182917f000000000000000000000000d28d620853af6837d76f1360dc65229d57ba543590911690632f6fce98906084016040805180830381865afa15801561212d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121519190614fa2565b90925090506001600160a01b03821661222c576040805163aa5c269b60e01b815286516001600160a01b0390811660048301526020880151811660248301529187015182166044820152606087015161ffff908116606483015260808801511660848201527f000000000000000000000000d28d620853af6837d76f1360dc65229d57ba54359091169063aa5c269b9060a40160408051808303816000875af1158015612202573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122269190614fa2565b90925090505b60005b84518110156124e55760008086838151811061224d5761224d614aa7565b60200260200101516060019063ffffffff16908163ffffffff168152505060006040518060600160405280336001600160a01b0316815260200188858151811061229957612299614aa7565b6020026020010151600001516001600160a01b0316815260200160003411151581525090508683815181106122d0576122d0614aa7565b602002602001015160c001518060200190518101906122ef9190614abd565b5191506001600160a01b0382161561232d578187848151811061231457612314614aa7565b60209081029190910101516001600160a01b0390911690525b8060405160200161233e9190614b08565b60405160208183030381529060405287848151811061235f5761235f614aa7565b602002602001015160c0018190525050836001600160a01b031663f0a20aec87848151811061239057612390614aa7565b60200260200101516040518263ffffffff1660e01b81526004016123b49190614b89565b60408051808303816000875af19250505080156123ee575060408051601f3d908101601f191682019092526123eb91810190614c17565b60015b156123f65750505b6001600160a01b038116156124dc57806001600160a01b0316630d55b879604051806060016040528089868151811061243157612431614aa7565b602002602001015160c001518060200190518101906124509190614c46565b6020908101516001600160a01b03908116835289811683830152600060409384015282516001600160e01b031960e087901b1681528451821660048201529184015116602482015291015163ffffffff166044820152606401600060405180830381600087803b1580156124c357600080fd5b505af11580156124d7573d6000803e3d6000fd5b505050505b5060010161222f565b5060005b835181101561260357600084828151811061250657612506614aa7565b60209081029190910181015163ffffffff9092166060909201919091526040805180820182523381523415158184015290516125429201614e0d565b60405160208183030381529060405284828151811061256357612563614aa7565b602002602001015160e00181905250826001600160a01b031663270ffd7d85838151811061259357612593614aa7565b60200260200101516040518263ffffffff1660e01b81526004016125b79190614fdc565b60408051808303816000875af11580156125d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f99190614c17565b50506001016124e9565b5061260c612dd4565b935093915050565b60608083516001600160401b0381111561263057612630613ab2565b604051908082528060200260200182016040528015612659578160200160208202803683370190505b50915083516001600160401b0381111561267557612675613ab2565b60405190808252806020026020018201604052801561269e578160200160208202803683370190505b50905060005b84518110156128525760006001600160a01b03168582815181106126ca576126ca614aa7565b60200260200101516001600160a01b03160361271f5760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964506f6f6c41646472657373282960601b6044820152606401610190565b84818151811061273157612731614aa7565b60200260200101516001600160a01b0316638a5ee2c385838151811061275957612759614aa7565b602090810291909101810151604080516001600160e01b031960e086901b16815282516001600160a01b03166004820152928201516001600160801b0316602484015281015163ffffffff166044830152606081015160020b6064830152608001511515608482015260a4016040805180830381865afa1580156127e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128059190615141565b84838151811061281757612817614aa7565b6020026020010184848151811061283057612830614aa7565b6001600160801b039384166020918202929092010152911690526001016126a4565b509250929050565b6000336001600160a01b031663fdf536656040518163ffffffff1660e01b815260040161016060405180830381865afa15801561289b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128bf9190614920565b90506128ca816129b3565b60006128d883850185614f29565b90506000861215612954577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031682608001516001600160a01b0316148015612929575080604001515b1561293f5761293a6104fb87614a54565b612954565b60808201518151612954919061051a89614a54565b6000851215610599577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b03168260a001516001600160a01b031614801561056e57508060400151156105845761057f6104fb86614a54565b6000816020015182608001518360a00151846101200151604051602001612a0694939291906001600160a01b03948516815292841660208401529216604082015261ffff91909116606082015260800190565b6040516020818303038152906040528051906020012090506000612b1d8360200151612af6858051608082015160a08084015160c0850151606080870151805160209182015160e0808b01516101008c01516101208d01516040519c881b6bffffffffffffffffffffffff19908116978e01979097529a871b861660348d015297861b851660488c015295851b8416605c8b015291841b831660708a0152831b90911660848801529190911b6001600160e01b031916609886015260f091821b609c86015292901b6001600160f01b031916609e8401529091016040516020818303038152906040529050919050565b847f000000000000000000000000d28d620853af6837d76f1360dc65229d57ba5435613548565b9050336001600160a01b038216146120925760405162461bcd60e51b8152602060048201526016602482015275496e76616c696443616c6c657241646472657373282960501b6044820152606401610190565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab147821115612be15760405162461bcd60e51b815260206004820152601860248201527f577261704574683a3a4c6f7745746842616c616e6365282900000000000000006044820152606401610190565b806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015612c1c57600080fd5b505af1158015612c30573d6000803e3d6000fd5b50505050506108c1337f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab184613623565b6001600160a01b038316612cc25760405162461bcd60e51b8152602060048201526024808201527f536166655472616e73666572733a3a43616e6e6f745472616e73666572496e456044820152637468282960e01b6064820152608401610190565b6040516323b872dd60e01b81526001600160a01b038381166004830152336024830152604482018390528491908216906323b872dd906064016020604051808303816000875af1158015612d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3e9190615170565b5060003d8015612d595760208114612d625760009150612d6e565b60019150612d6e565b60206000803e60005191505b5080612dcd5760405162461bcd60e51b815260206004820152602860248201527f5472616e736665724661696c6564286d73672e73656e6465722c206164647265604482015267737328746869732960c01b6064820152608401610190565b5050505050565b4715612ded57344710612def57612ded33600034613623565b565b612ded33600047613623565b606080820151608080840151845160e080870151610160880151610180890151604080516001600160a01b03998a1660208201529689169087015293871697850197909752949094169282019290925260019390930b60a084015261ffff1660c0830152600091016040516020818303038152906040528051906020012090506000612b1d8360a00151612e8e856137fa565b847f0000000000000000000000000000000000000000000000000000000000000000613548565b6060612ef76040518060e00160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081525090565b82516001600160401b03811115612f1057612f10613ab2565b604051908082528060200260200182016040528015612f4957816020015b612f366139f9565b815260200190600190039081612f2e5790505b50815282516001600160401b03811115612f6557612f65613ab2565b604051908082528060200260200182016040528015612f8e578160200160208202803683370190505b5060408201526000606082018190525b83518110156132e55784600081518110612fba57612fba614aa7565b602002602001015160400151612fd7576001600160ff1b03612fda565b60005b608083015260001960a083015260005b845181101561314e578260400151818151811061300957613009614aa7565b6020026020010151613146578560008151811061302857613028614aa7565b602002602001015160400151156130c257600085828151811061304d5761304d614aa7565b6020026020010151604001511380156130875750826080015185828151811061307857613078614aa7565b60200260200101516040015112155b156130bd5760a0830181905284518590829081106130a7576130a7614aa7565b6020026020010151604001518360800181815250505b613146565b60008582815181106130d6576130d6614aa7565b6020026020010151602001511380156131105750826080015185828151811061310157613101614aa7565b60200260200101516020015113155b156131465760a08301819052845185908290811061313057613130614aa7565b6020026020010151602001518360800181815250505b600101612fea565b506000198260a00151146132cb57838260a001518151811061317257613172614aa7565b6020026020010151600001518260000151828151811061319457613194614aa7565b60209081029190910101516001600160a01b03909116905260a0820151845185919081106131c4576131c4614aa7565b602002602001015160200151826000015182815181106131e6576131e6614aa7565b60200260200101516020018181525050838260a001518151811061320c5761320c614aa7565b6020026020010151604001518260000151828151811061322e5761322e614aa7565b60200260200101516040018181525050838260a001518151811061325457613254614aa7565b6020026020010151606001518260000151828151811061327657613276614aa7565b6020026020010151606001906001600160a01b031690816001600160a01b031681525050600182604001518360a00151815181106132b6576132b6614aa7565b911515602092830291909101909101526132dd565b8160600180516132da9061518d565b90525b600101612f9e565b506060810151156133f7578060600151835161330191906151a6565b6001600160401b0381111561331857613318613ab2565b60405190808252806020026020018201604052801561335157816020015b61333e6139f9565b8152602001906001900390816133365790505b506020820152600060c082018190525b83518110156133f15781518051600091908390811061338257613382614aa7565b6020026020010151600001516001600160a01b0316146133e95781518051829081106133b0576133b0614aa7565b602002602001015182602001518360c00151815181106133d2576133d2614aa7565b602090810291909101015260c08201805160010190525b600101613361565b506133ff565b805160208201525b6020015190505b92915050565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1906001600160a01b03821690632e1a7d4d90602401600060405180830381600087803b15801561347057600080fd5b505af1158015613484573d6000803e3d6000fd5b5050505061209283600084613623565b6000808212156134e65760405162461bcd60e51b815260206004820152601b60248201527f496e74323536546f55696e743235363a556e646572666c6f77282900000000006044820152606401610190565b5090565b806001600160801b03811681146135435760405162461bcd60e51b815260206004820152601b60248201527f55696e74323536546f55696e743132383a4f766572666c6f77282900000000006044820152606401610190565b919050565b605f1983018051603f1985018051601f19870180518851808a0160200180516c5af43d3d93803e606057fd5bf38c52600c198c018d905260028301604881901b78593da1005b363d3d373d3d3d3d610000806062363936013d73176020198e01527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff6039198e01526064840160781b716100003d81600a3d39f336602c57343d527f176059198e015260f01b8252606e8301604b198d01209152908a529152915291526000906136198185856139d7565b9695505050505050565b6000816000036136335750505050565b6001600160a01b0383166136f3576040516001600160a01b038516908390600081818185875af1925050503d806000811461368a576040519150601f19603f3d011682016040523d82523d6000602084013e61368f565b606091505b505080915050806136ed5760405162461bcd60e51b815260206004820152602260248201527f536166655472616e73666572733a3a4574685472616e736665724661696c6564604482015261282960f01b6064820152608401610190565b50505050565b60405163a9059cbb60e01b81526001600160a01b0385811660048301526024820184905284919082169063a9059cbb906044016020604051808303816000875af1158015613745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137699190615170565b50600091503d8015613786576020811461378f576000925061379b565b6001925061379b565b60206000803e60005192505b5081612dcd5760405162461bcd60e51b815260206004820152602860248201527f5472616e736665724661696c656428616464726573732874686973292c206d73604482015267339739b2b73232b960c11b6064820152608401610190565b6040818101516060808401516080850151855160c08088015160e08901516020808b01518051908201519a516bffffffffffffffffffffffff199a8a1b8b169281019290925296881b8916603482015294871b8816604886015292861b8716605c850152851b8616607084015290841b8516608483015291831b8416609882015293821b90921660ac840152916000910160408051601f19818403018152908290526101008501516101208601516101408701516101608801516101808901516101a08a0151959750600096613932969060200160809690961b6fffffffffffffffffffffffffffffffff1916865260e09490941b6001600160e01b031916601086015260f092831b601486015290821b6016850152811b6001600160f01b0319908116601885015291901b16601a820152601c0190565b60408051601f198184030181528282526101c08701516101e08801516102008901516102208a015160f09390931b6001600160f01b031916602087015260f891821b6001600160f81b0319908116602288015290821b166023860152901515901b602484015281518084036005018152602584019092529250906139be908490849084906045016151b9565b6040516020818303038152906040529350505050919050565b600060ff60005350603592835260601b60015260155260556000908120915290565b604051806080016040528060006001600160a01b03168152602001600081526020016000815260200160006001600160a01b031681525090565b60008060008060608587031215613a4957600080fd5b843593506020850135925060408501356001600160401b0380821115613a6e57600080fd5b818701915087601f830112613a8257600080fd5b813581811115613a9157600080fd5b886020828501011115613aa357600080fd5b95989497505060200194505050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715613aea57613aea613ab2565b60405290565b604051608081016001600160401b0381118282101715613aea57613aea613ab2565b60405160c081016001600160401b0381118282101715613aea57613aea613ab2565b60405161010081016001600160401b0381118282101715613aea57613aea613ab2565b60405160a081016001600160401b0381118282101715613aea57613aea613ab2565b604080519081016001600160401b0381118282101715613aea57613aea613ab2565b60405161014081016001600160401b0381118282101715613aea57613aea613ab2565b604051606081016001600160401b0381118282101715613aea57613aea613ab2565b60405161024081016001600160401b0381118282101715613aea57613aea613ab2565b604051601f8201601f191681016001600160401b0381118282101715613c2b57613c2b613ab2565b604052919050565b60006001600160401b03821115613c4c57613c4c613ab2565b5060051b60200190565b6001600160a01b0381168114613c6b57600080fd5b50565b803561354381613c56565b600082601f830112613c8a57600080fd5b81356020613c9f613c9a83613c33565b613c03565b82815260059290921b84018101918181019086841115613cbe57600080fd5b8286015b84811015613ce2578035613cd581613c56565b8352918301918301613cc2565b509695505050505050565b8035600281900b811461354357600080fd5b63ffffffff81168114613c6b57600080fd5b803561354381613cff565b6001600160801b0381168114613c6b57600080fd5b803561354381613d1c565b600082601f830112613d4d57600080fd5b81356001600160401b03811115613d6657613d66613ab2565b613d79601f8201601f1916602001613c03565b818152846020838601011115613d8e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112613dbc57600080fd5b81356020613dcc613c9a83613c33565b82815260059290921b84018101918181019086841115613deb57600080fd5b8286015b84811015613ce25780356001600160401b0380821115613e0f5760008081fd5b9088019060e0828b03601f1901811315613e295760008081fd5b613e31613ac8565b613e3c888501613c6e565b81526040613e4b818601613ced565b898301526060613e5c818701613ced565b8284015260809150613e6f828701613d11565b9083015260a0613e80868201613d31565b8284015260c09150613e93828701613d31565b90830152918401359183831115613eaa5760008081fd5b613eb88d8a85880101613d3c565b908201528652505050918301918301613def565b60008060408385031215613edf57600080fd5b82356001600160401b0380821115613ef657600080fd5b613f0286838701613c79565b93506020850135915080821115613f1857600080fd5b50613f2585828601613dab565b9150509250929050565b8015158114613c6b57600080fd5b803561354381613f2f565b600082601f830112613f5957600080fd5b81356020613f69613c9a83613c33565b82815260059290921b84018101918181019086841115613f8857600080fd5b8286015b84811015613ce25780356001600160401b0380821115613fac5760008081fd5b9088019060e0828b03601f1901811315613fc65760008081fd5b613fce613ac8565b613fd9888501613c6e565b81526040613fe8818601613d31565b898301526060613ff9818701613d11565b828401526080915061400c828701613ced565b9083015260a061401d868201613ced565b8284015260c09150614030828701613f3d565b908301529184013591838311156140475760008081fd5b6140558d8a85880101613d3c565b908201528652505050918301918301613f8c565b6000806040838503121561407c57600080fd5b82356001600160401b038082111561409357600080fd5b61409f86838701613c79565b935060208501359150808211156140b557600080fd5b50613f2585828601613f48565b600080600060608085870312156140d857600080fd5b84356001600160401b03808211156140ef57600080fd5b6140fb88838901613c79565b955060209150818701358181111561411257600080fd5b87019050601f8101881361412557600080fd5b8035614133613c9a82613c33565b81815260079190911b8201830190838101908a83111561415257600080fd5b928401925b828410156141cc576080848c0312156141705760008081fd5b614178613af0565b843561418381613c56565b81528486013561419281613d1c565b818701526040858101356141a581613f2f565b90820152848701356141b681613f2f565b8188015282526080939093019290840190614157565b8097505050505050506141e160408501613f3d565b90509250925092565b602080825282518282018190526000919060409081850190868401855b8281101561424d57815180516001600160a01b03908116865287820151888701528682015187870152606091820151169085015260809093019290850190600101614207565b5091979650505050505050565b61ffff81168114613c6b57600080fd5b80356135438161425a565b8060010b8114613c6b57600080fd5b803561354381614275565b60008082840360e08112156142a357600080fd5b60c08112156142b157600080fd5b506142ba613b12565b8335815260208401356142cc81613c56565b602082015260408401356142df81613c56565b604082015260608401356142f28161425a565b606082015261430360808501614284565b608082015261431460a0850161426a565b60a0820152915060c08301356001600160401b0381111561433457600080fd5b613f2585828601613f48565b80356bffffffffffffffffffffffff8116811461354357600080fd5b600082601f83011261436d57600080fd5b8135602061437d613c9a83613c33565b82815260059290921b8401810191818101908684111561439c57600080fd5b8286015b84811015613ce25780356001600160401b03808211156143c05760008081fd5b90880190610100828b03601f19018113156143db5760008081fd5b6143e3613b34565b6143ee888501613c6e565b815260406143fd818601613d31565b89830152606061440e818701614340565b8284015260809150614421828701613d11565b9083015260a0614432868201613ced565b8284015260c09150614445828701613ced565b9083015260e0614456868201613f3d565b8383015292850135928484111561446f57600091508182fd5b61447d8e8b86890101613d3c565b908301525086525050509183019183016143a0565b600080604083850312156144a557600080fd5b82356001600160401b03808211156144bc57600080fd5b6144c886838701613c79565b935060208501359150808211156144de57600080fd5b50613f258582860161435c565b600080604083850312156144fe57600080fd5b82356001600160401b038082111561451557600080fd5b61452186838701613c79565b935060209150818501358181111561453857600080fd5b8501601f8101871361454957600080fd5b8035614557613c9a82613c33565b81815260059190911b8201840190848101908983111561457657600080fd5b8584015b8381101561463f578035868111156145925760008081fd5b850160c0818d03601f19018113156145aa5760008081fd5b6145b2613b12565b898301356145bf81613c56565b815260408301356145cf81613c56565b818b01526060838101356145e281613d1c565b604083015260806145f4858201613f3d565b8284015260a09150614607828601613f3d565b9083015291830135918983111561461e5760008081fd5b61462c8f8c85870101613d3c565b908201528552505091860191860161457a565b508096505050505050509250929050565b600080600083850360e081121561466657600080fd5b60a081121561467457600080fd5b5061467d613b57565b843561468881613c56565b8152602085013561469881613c56565b602082015260408501356146ab81613c56565b604082015260608501356146be8161425a565b606082015260808501356146d18161425a565b6080820152925060a08401356001600160401b03808211156146f257600080fd5b6146fe87838801613dab565b935060c086013591508082111561471457600080fd5b506147218682870161435c565b9150509250925092565b600080604080848603121561473f57600080fd5b83356001600160401b038082111561475657600080fd5b61476287838801613c79565b945060209150818601358181111561477957600080fd5b86019050601f8101871361478c57600080fd5b803561479a613c9a82613c33565b81815260a0918202830184019184820191908a8411156147b957600080fd5b938501935b8385101561463f5780858c0312156147d65760008081fd5b6147de613b57565b85356147e981613c56565b8152858701356147f881613d1c565b818801528588013561480981613cff565b81890152606061481a878201613ced565b9082015260808681013561482d81613f2f565b90820152835293840193918501916147be565b600081518084526020808501945080840160005b838110156148795781516001600160801b031687529582019590820190600101614854565b509495945050505050565b6040815260006148976040830185614840565b82810360208401526148a98185614840565b95945050505050565b805161354381613c56565b6000604082840312156148cf57600080fd5b6148d7613b79565b905081516148e481613c56565b815260208201516148f481613c56565b602082015292915050565b805161354381613cff565b805161354381614275565b80516135438161425a565b6000610160828403121561493357600080fd5b61493b613b9b565b614944836148b2565b8152614952602084016148b2565b6020820152614963604084016148b2565b604082015261497584606085016148bd565b606082015261498660a084016148b2565b608082015261499760c084016148b2565b60a08201526149a860e084016148b2565b60c08201526101006149bb8185016148ff565b60e08301526101206149ce81860161490a565b828401526149df6101408601614915565b90830152509392505050565b6000604082840312156149fd57600080fd5b614a05613b79565b90508135614a1281613c56565b815260208201356148f481613f2f565b600060408284031215614a3457600080fd5b610ea583836149eb565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b8201614a6957614a69614a3e565b5060000390565b6020808252601b908201527f496e70757441727261794c656e677468734d69736d6174636828290000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215614acf57600080fd5b604051602081018181106001600160401b0382111715614af157614af1613ab2565b6040528251614aff81613c56565b81529392505050565b81516001600160a01b0390811682526020808401519091169082015260408083015115159082015260608101613406565b60005b83811015614b54578181015183820152602001614b3c565b50506000910152565b60008151808452614b75816020860160208601614b39565b601f01601f19169290920160200192915050565b6020815260018060a01b038251166020820152602082015160020b6040820152604082015160020b606082015263ffffffff60608301511660808201526001600160801b0360808301511660a0820152600060a0830151614bf560c08401826001600160801b03169052565b5060c083015160e080840152614c0f610100840182614b5d565b949350505050565b60008060408385031215614c2a57600080fd5b505080516020909101519092909150565b805161354381613f2f565b600060608284031215614c5857600080fd5b614c60613bbe565b8251614c6b81613c56565b81526020830151614c7b81613c56565b60208201526040830151614c8e81613f2f565b60408201529392505050565b805161354381613d1c565b805160ff8116811461354357600080fd5b60006102608284031215614cc957600080fd5b614cd1613be0565b614cda836148b2565b8152614ce984602085016148bd565b6020820152614cfa606084016148b2565b6040820152614d0b608084016148b2565b6060820152614d1c60a084016148b2565b6080820152614d2d60c084016148b2565b60a0820152614d3e60e084016148b2565b60c0820152610100614d518185016148b2565b60e0830152610120614d64818601614c9a565b828401526101409150614d788286016148ff565b90830152610160614d8a85820161490a565b828401526101809150614d9e82860161490a565b908301526101a0614db0858201614915565b828401526101c09150614dc4828601614915565b908301526101e0614dd6858201614915565b828401526102009150614dea828601614ca5565b90830152610220614dfc858201614ca5565b828401526149df6102408601614c3b565b81516001600160a01b0316815260208083015115159082015260408101613406565b6020815260018060a01b0382511660208201526001600160801b03602083015116604082015263ffffffff6040830151166060820152606082015160020b608082015260006080830151614e8860a084018260020b9052565b5060a083015180151560c0840152614bf5565b600080600060608486031215614eb057600080fd5b83519250602084015191506040840151614ec981613c56565b809150509250925092565b600060608284031215614ee657600080fd5b614eee613bbe565b90508135614efb81613c56565b81526020820135614f0b81613c56565b60208201526040820135614f1e81613f2f565b604082015292915050565b600060608284031215614f3b57600080fd5b610ea58383614ed4565b815181526020808301516001600160a01b03908116918301919091526040808401519091169082015260608083015161ffff9081169183019190915260808084015160010b9083015260a092830151169181019190915260c00190565b60008060408385031215614fb557600080fd5b8251614fc081613c56565b6020840151909250614fd181613c56565b809150509250929050565b602080825282516001600160a01b0316828201528201516001600160801b03166040808301919091528201516bffffffffffffffffffffffff8116606083015260009050606083015163ffffffff8116608084015250608083015161504660a084018260020b9052565b5060a083015161505b60c084018260020b9052565b5060c083015180151560e08401525060e083015161010083810152614c0f610120840182614b5d565b60006020828403121561509657600080fd5b8151610ea581613c56565b60208152600060018060a01b03808451166020840152806020850151166040840152506001600160801b0360408401511660608301526060830151151560808301526080830151151560a083015260a083015160c080840152614c0f60e0840182614b5d565b8082018082111561340657613406614a3e565b6001600160801b0382811682821603908082111561513a5761513a614a3e565b5092915050565b6000806040838503121561515457600080fd5b825161515f81613d1c565b6020840151909250614fd181613d1c565b60006020828403121561518257600080fd5b8151610ea581613f2f565b60006001820161519f5761519f614a3e565b5060010190565b8181038181111561340657613406614a3e565b600084516151cb818460208901614b39565b8451908301906151df818360208901614b39565b84519101906151f2818360208801614b39565b019594505050505056fea26469706673582212208aa96be23bb8346e4b24e9338221c82a212d18afb7c983f81cd51d23baf36b7364736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d28d620853af6837d76f1360dc65229d57ba5435000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
-----Decoded View---------------
Arg [0] : limitPoolFactory_ (address): 0xD28d620853aF6837D76F1360Dc65229D57bA5435
Arg [1] : coverPoolFactory_ (address): 0x0000000000000000000000000000000000000000
Arg [2] : wethAddress_ (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000d28d620853af6837d76f1360dc65229d57ba5435
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.