More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 45,851 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Remove Liquidity | 115952097 | 339 days ago | IN | 0 ETH | 0.00019185788 | ||||
Remove Liquidity | 115896573 | 341 days ago | IN | 0 ETH | 0.000119671068 | ||||
Remove Liquidity | 115325912 | 354 days ago | IN | 0 ETH | 0.000041566355 | ||||
Remove Liquidity | 115287666 | 355 days ago | IN | 0 ETH | 0.000112923954 | ||||
Remove Liquidity | 115287583 | 355 days ago | IN | 0 ETH | 0.000112715922 | ||||
Remove Liquidity | 114588849 | 371 days ago | IN | 0 ETH | 0.000034305308 | ||||
Remove Liquidity | 114588830 | 371 days ago | IN | 0 ETH | 0.000036572005 | ||||
Remove Liquidity | 114495066 | 373 days ago | IN | 0 ETH | 0.000045560035 | ||||
Remove Liquidity | 114312944 | 377 days ago | IN | 0 ETH | 0.000078415499 | ||||
Remove Liquidity | 113870564 | 388 days ago | IN | 0 ETH | 0.000056684339 | ||||
Remove Liquidity | 113710980 | 391 days ago | IN | 0 ETH | 0.000184145831 | ||||
Remove Liquidity | 113576480 | 394 days ago | IN | 0 ETH | 0.00012912757 | ||||
Remove Liquidity | 113576436 | 394 days ago | IN | 0 ETH | 0.000143079948 | ||||
Remove Liquidity | 113543379 | 395 days ago | IN | 0 ETH | 0.00015385017 | ||||
Remove Liquidity | 113384554 | 399 days ago | IN | 0 ETH | 0.000153147202 | ||||
Remove Liquidity | 113319116 | 400 days ago | IN | 0 ETH | 0.000077399324 | ||||
Remove Liquidity | 113317941 | 400 days ago | IN | 0 ETH | 0.000068051717 | ||||
Remove Liquidity | 113317856 | 400 days ago | IN | 0 ETH | 0.000072743081 | ||||
Withdraw | 113317698 | 400 days ago | IN | 0 ETH | 0.000074154791 | ||||
Exit | 113317677 | 400 days ago | IN | 0 ETH | 0.000077110883 | ||||
Withdraw | 113173734 | 404 days ago | IN | 0 ETH | 0.00006248998 | ||||
Exit | 113173720 | 404 days ago | IN | 0 ETH | 0.000083523919 | ||||
Exit | 113141910 | 405 days ago | IN | 0 ETH | 0.000136802103 | ||||
Remove Liquidity | 113086210 | 406 days ago | IN | 0 ETH | 0.000103897883 | ||||
Remove Liquidity | 113023275 | 407 days ago | IN | 0 ETH | 0.000085091988 |
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | ||||
---|---|---|---|---|---|---|---|
115952097 | 339 days ago | 0 ETH | |||||
115952097 | 339 days ago | 0 ETH | |||||
115952097 | 339 days ago | 0 ETH | |||||
115952097 | 339 days ago | 0 ETH | |||||
115952097 | 339 days ago | 0 ETH | |||||
115952097 | 339 days ago | 0 ETH | |||||
115952097 | 339 days ago | 0 ETH | |||||
115896573 | 341 days ago | 0 ETH | |||||
115896573 | 341 days ago | 0 ETH | |||||
115896573 | 341 days ago | 0 ETH | |||||
115896573 | 341 days ago | 0 ETH | |||||
115896573 | 341 days ago | 0 ETH | |||||
115896573 | 341 days ago | 0 ETH | |||||
115896573 | 341 days ago | 0 ETH | |||||
115325912 | 354 days ago | 0 ETH | |||||
115325912 | 354 days ago | 0 ETH | |||||
115325912 | 354 days ago | 0 ETH | |||||
115325912 | 354 days ago | 0 ETH | |||||
115325912 | 354 days ago | 0 ETH | |||||
115325912 | 354 days ago | 0 ETH | |||||
115325912 | 354 days ago | 0 ETH | |||||
115287666 | 355 days ago | 0 ETH | |||||
115287666 | 355 days ago | 0 ETH | |||||
115287666 | 355 days ago | 0 ETH | |||||
115287666 | 355 days ago | 0 ETH |
Loading...
Loading
Contract Name:
KyberSwapElasticLM
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import {KSMath} from '../libraries/KSMath.sol'; import {IKyberSwapElasticLM} from '../interfaces/liquidityMining/IKyberSwapElasticLM.sol'; import {IKSElasticLMHelper} from '../interfaces/liquidityMining/IKSElasticLMHelper.sol'; import {IBasePositionManager} from '../interfaces/liquidityMining/IBasePositionManager.sol'; import {IPoolStorage} from '../interfaces/liquidityMining/IPoolStorage.sol'; import {KSAdmin} from './base/KSAdmin.sol'; import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol'; import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import {IERC20Metadata} from '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol'; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; import {ReentrancyGuard} from '@openzeppelin/contracts/security/ReentrancyGuard.sol'; contract KyberSwapElasticLM is IKyberSwapElasticLM, ReentrancyGuard, KSAdmin { using EnumerableSet for EnumerableSet.UintSet; using SafeERC20 for IERC20Metadata; using KSMath for uint256; IERC721 public immutable nft; IKSElasticLMHelper private helper; address public immutable weth; uint256 internal constant PRECISION = 1e12; uint256 public poolLength; // pId => Pool info mapping(uint256 => LMPoolInfo) public pools; // nftId => Position info mapping(uint256 => PositionInfo) public positions; // nftId => pId => Stake info mapping(uint256 => mapping(uint256 => StakeInfo)) public stakes; // nftId => list of joined pools mapping(uint256 => EnumerableSet.UintSet) internal joinedPools; // user address => set of nft id which user already deposit into LM contract mapping(address => EnumerableSet.UintSet) private depositNFTs; mapping(uint256 => bool) public isEmergencyWithdrawnNFT; bool public emergencyEnabled; bool public specialFeatureEnabled; modifier checkLength(uint256 a, uint256 b) { require(a == b, 'invalid length'); _; } modifier isSpecialFeaturesEnabled() { require(specialFeatureEnabled, 'special feature disabled'); _; } constructor(IERC721 _nft, IKSElasticLMHelper _helper) { nft = _nft; helper = _helper; weth = IBasePositionManager(address(_nft)).WETH(); } /** * EXTERNAL FUNCTIONS ************************* */ /** * @dev receive native reward token */ receive() external payable {} /** * @dev Set emergencyEnabled flag to true */ function emergencyEnable() public isAdmin { require(!emergencyEnabled, 'Invalid value'); emergencyEnabled = true; emit EmergencyEnabled(); } /** * @dev Set specialFeatureEnabled flag to true or false */ function updateSpecialFeatureEnabled(bool enableOrDisable) public isAdmin { specialFeatureEnabled = enableOrDisable; emit UpdateSpecialFeatureEnabled(enableOrDisable); } function updateHelper(IKSElasticLMHelper _helper) external isAdmin { helper = _helper; emit LMHelperUpdated(_helper); } /// @inheritdoc IKyberSwapElasticLM function addPool( address poolAddress, uint32 startTime, uint32 endTime, address[] calldata rewardTokens, uint256[] calldata rewardAmounts, uint256 feeTarget ) external override isOperator checkLength(rewardTokens.length, rewardAmounts.length) { require(startTime >= _getBlockTime() && endTime > startTime, 'addPool: invalid times'); uint256 pId = poolLength; // save gas LMPoolInfo storage pool = pools[pId]; pool.poolAddress = poolAddress; pool.startTime = startTime; pool.endTime = endTime; pool.totalSecondsClaimed = 0; pool.feeTarget = feeTarget; for (uint256 i = 0; i < rewardTokens.length; i++) { pool.rewards.push(RewardData(rewardTokens[i], rewardAmounts[i])); } poolLength++; emit AddPool(pId, poolAddress, startTime, endTime, feeTarget); } /// @inheritdoc IKyberSwapElasticLM function renewPool( uint256 pId, uint32 startTime, uint32 endTime, uint256[] calldata rewardAmounts, uint256 feeTarget ) external override isOperator { LMPoolInfo storage pool = pools[pId]; // check if pool has not started or already ended require( pool.startTime > _getBlockTime() || pool.endTime < _getBlockTime(), 'renew: invalid pool state' ); require(pool.rewards.length == rewardAmounts.length, 'renew: invalid length'); // check input startTime and endTime require(startTime > _getBlockTime() && endTime > startTime, 'renew: invalid times'); // check pool has stakes require(pool.numStakes == 0, 'renew: pool has stakes'); pool.startTime = startTime; pool.endTime = endTime; pool.totalSecondsClaimed = 0; pool.feeTarget = feeTarget; for (uint256 i = 0; i < rewardAmounts.length; ++i) { pool.rewards[i].rewardUnclaimed = rewardAmounts[i]; } emit RenewPool(pId, startTime, endTime, feeTarget); } /// @inheritdoc IKyberSwapElasticLM function deposit(uint256[] calldata nftIds) external override nonReentrant { _depositAndJoin(0, nftIds, false); } /// @inheritdoc IKyberSwapElasticLM function depositAndJoin( uint256 pId, uint256[] calldata nftIds ) external override isSpecialFeaturesEnabled nonReentrant { _depositAndJoin(pId, nftIds, true); } /// @inheritdoc IKyberSwapElasticLM function withdraw(uint256[] calldata nftIds) external override nonReentrant { address sender = msg.sender; for (uint256 i = 0; i < nftIds.length; ++i) { require(positions[nftIds[i]].owner == sender, 'withdraw: not owner'); require(joinedPools[nftIds[i]].length() == 0, 'withdraw: not exited yet'); delete positions[nftIds[i]]; require(depositNFTs[sender].remove(nftIds[i])); nft.transferFrom(address(this), sender, nftIds[i]); emit Withdraw(sender, nftIds[i]); } } /// @inheritdoc IKyberSwapElasticLM function emergencyWithdraw(uint256[] calldata nftIds) external override nonReentrant { address sender = msg.sender; // save gas bool _emergencyEnabled = emergencyEnabled; for (uint256 i = 0; i < nftIds.length; ++i) { require(positions[nftIds[i]].owner == sender, 'withdraw: not owner'); isEmergencyWithdrawnNFT[nftIds[i]] = true; uint256[] memory values = joinedPools[nftIds[i]].values(); for (uint256 j = 0; j < values.length; ++j) { uint256 poolId = values[j]; unchecked { pools[poolId].numStakes--; } delete stakes[nftIds[i]][poolId]; } delete positions[nftIds[i]]; if (!_emergencyEnabled) { require(depositNFTs[sender].remove(nftIds[i])); for (uint256 j = 0; j < values.length; ++j) { uint256 poolId = values[j]; require(joinedPools[nftIds[i]].remove(poolId)); } } nft.transferFrom(address(this), sender, nftIds[i]); emit EmergencyWithdraw(sender, nftIds[i]); } } /// @inheritdoc IKyberSwapElasticLM function emergencyWithdrawForOwner( address[] calldata rewards, uint256[] calldata amounts ) external override isAdmin checkLength(rewards.length, amounts.length) { for (uint256 i = 0; i < rewards.length; ++i) { _transferReward(rewards[i], msg.sender, amounts[i]); emit EmergencyWithdrawForOwner(rewards[i], amounts[i]); } } /// @inheritdoc IKyberSwapElasticLM function join( uint256 pId, uint256[] calldata nftIds, uint256[] calldata liqs ) external override nonReentrant checkLength(nftIds.length, liqs.length) { require(poolLength > pId, 'Pool not exists'); LMPoolInfo storage pool = pools[pId]; require(pool.startTime <= _getBlockTime() && _getBlockTime() < pool.endTime, 'Invalid time'); for (uint256 i = 0; i < nftIds.length; ++i) { require(positions[nftIds[i]].owner == msg.sender, 'Not owner'); positions[nftIds[i]].liquidity = helper.getLiq(address(nft), nftIds[i]); StakeInfo storage stake = stakes[nftIds[i]][pId]; if (stake.liquidity == 0) { _join(nftIds[i], pId, liqs[i], pool); } else { _sync(nftIds[i], pId, liqs[i], pool); } } } /// @inheritdoc IKyberSwapElasticLM function exit( uint256 pId, uint256[] calldata nftIds, uint256[] calldata liqs ) external override nonReentrant checkLength(nftIds.length, liqs.length) { require(poolLength > pId, 'Pool not exists'); for (uint256 i = 0; i < nftIds.length; ++i) { _exit(nftIds[i], pId, liqs[i], true); } } /// @inheritdoc IKyberSwapElasticLM function harvestMultiplePools( uint256[] calldata nftIds, bytes[] calldata datas ) external override nonReentrant checkLength(nftIds.length, datas.length) { for (uint256 i; i < nftIds.length; ++i) { require(positions[nftIds[i]].owner == msg.sender, 'harvest: not owner'); HarvestData memory data = abi.decode(datas[i], (HarvestData)); for (uint256 j; j < data.pIds.length; ++j) { _harvest(nftIds[i], data.pIds[j]); } } } /// @inheritdoc IKyberSwapElasticLM function removeLiquidity( uint256 nftId, uint128 liquidity, uint256 amount0Min, uint256 amount1Min, uint256 deadline, bool isReceiveNative, bool[2] calldata claimFeeAndRewards ) external override nonReentrant isSpecialFeaturesEnabled { require(_getBlockTime() <= deadline, 'removeLiquidity: expired'); require(positions[nftId].owner == msg.sender, 'removeLiquidity: not owner'); uint256 posLiquidity = helper.getLiq(address(nft), nftId); require(liquidity > 0 && liquidity <= posLiquidity, 'removeLiquidity: invalid liquidity'); posLiquidity -= liquidity; positions[nftId].liquidity = posLiquidity; uint256[] memory poolIds = joinedPools[nftId].values(); for (uint256 i; i < poolIds.length; ) { uint256 stakedLiquidity = stakes[nftId][poolIds[i]].liquidity; uint256 deltaLiq = stakedLiquidity > posLiquidity ? stakedLiquidity - posLiquidity : 0; if (deltaLiq > 0) _exit(nftId, poolIds[i], deltaLiq, claimFeeAndRewards[1]); unchecked { ++i; } } (address token0, address token1) = helper.getPair(address(nft), nftId); _removeLiquidity(nftId, liquidity, deadline); if (claimFeeAndRewards[0]) _claimFee(nftId, deadline, false); _transferTokens(token0, token1, amount0Min, amount1Min, msg.sender, isReceiveNative); } /// @inheritdoc IKyberSwapElasticLM function claimFee( uint256[] calldata nftIds, uint256 amount0Min, uint256 amount1Min, address poolAddress, bool isReceiveNative, uint256 deadline ) external override nonReentrant isSpecialFeaturesEnabled { require(_getBlockTime() <= deadline, 'claimFee: expired'); uint256 length = nftIds.length; (address token0, address token1) = ( address(IPoolStorage(poolAddress).token0()), address(IPoolStorage(poolAddress).token1()) ); for (uint256 i; i < length; ) { require(positions[nftIds[i]].owner == msg.sender, 'claimFee: not owner'); (address nftToken0, address nftToken1) = helper.getPair(address(nft), nftIds[i]); require(nftToken0 == token0 && nftToken1 == token1, 'claimFee: token pair not match'); _claimFee(nftIds[i], deadline, true); unchecked { ++i; } } _transferTokens(token0, token1, amount0Min, amount1Min, msg.sender, isReceiveNative); } /// @inheritdoc IKyberSwapElasticLM function getJoinedPools( uint256 nftId ) external view override returns (uint256[] memory poolIds) { uint256 length = joinedPools[nftId].length(); poolIds = new uint256[](length); for (uint256 i = 0; i < length; ++i) { poolIds[i] = joinedPools[nftId].at(i); } } /// @inheritdoc IKyberSwapElasticLM function getJoinedPoolsInRange( uint256 nftId, uint256 fromIndex, uint256 toIndex ) external view returns (uint256[] memory poolIds) { require(fromIndex <= toIndex, 'fromIndex > toIndex'); require(toIndex < joinedPools[nftId].length(), 'toIndex >= length'); poolIds = new uint256[](toIndex - fromIndex + 1); for (uint256 index = fromIndex; index <= toIndex; ++index) { poolIds[index - fromIndex] = joinedPools[nftId].at(index); } } /// @inheritdoc IKyberSwapElasticLM function getUserInfo( uint256 nftId, uint256 pId ) external view override returns (uint256 liquidity, uint256[] memory rewardPending, uint256[] memory rewardLast) { LMPoolInfo storage pool = pools[pId]; StakeInfo storage stake = stakes[nftId][pId]; require(stake.liquidity > 0, 'getUserInfo: not joined yet'); rewardPending = new uint256[](pool.rewards.length); rewardLast = new uint256[](pool.rewards.length); RewardCalculationData memory data = getRewardCalculationData(nftId, pId); for (uint256 i = 0; i < pool.rewards.length; ++i) { uint256 rewardHarvest = _calculateRewardHarvest( stake.liquidity, pool.rewards[i].rewardUnclaimed, data.totalSecondsUnclaimed, data.secondsPerLiquidity ); uint256 rewardCollected = _calculateRewardCollected( stake.rewardHarvested[i] + rewardHarvest, data.vestingVolume, stake.rewardLast[i] ); rewardPending[i] = stake.rewardPending[i] + rewardCollected; rewardLast[i] = stake.rewardLast[i]; } liquidity = stake.liquidity; } /// @inheritdoc IKyberSwapElasticLM function getPoolInfo( uint256 pId ) external view override returns ( address poolAddress, uint32 startTime, uint32 endTime, uint256 totalSecondsClaimed, uint256 feeTarget, uint256 numStakes, //index reward => reward data address[] memory rewardTokens, uint256[] memory rewardUnclaimeds ) { LMPoolInfo storage pool = pools[pId]; poolAddress = pool.poolAddress; startTime = pool.startTime; endTime = pool.endTime; totalSecondsClaimed = pool.totalSecondsClaimed; feeTarget = pool.feeTarget; numStakes = pool.numStakes; uint256 length = pool.rewards.length; rewardTokens = new address[](length); rewardUnclaimeds = new uint256[](length); for (uint256 i = 0; i < length; ++i) { rewardTokens[i] = pool.rewards[i].rewardToken; rewardUnclaimeds[i] = pool.rewards[i].rewardUnclaimed; } } /// @inheritdoc IKyberSwapElasticLM function getDepositedNFTs(address user) external view returns (uint256[] memory listNFTs) { listNFTs = depositNFTs[user].values(); } /** * INTERNAL FUNCTIONS ************************* */ /** * @dev Deposit NFTs to the LM contract, and join farming pool if needed * @param pId pool id to join farm, if isJoining = true * @param nftIds list of NFT ids to deposit * @param isJoining whether to join farm with pId */ function _depositAndJoin(uint256 pId, uint256[] memory nftIds, bool isJoining) internal { require(!emergencyEnabled, 'Not allowed to deposit'); if (isJoining) { // verify if pool's state is valid require(poolLength > pId, 'Pool not exists'); uint32 _blockTime = _getBlockTime(); require( pools[pId].startTime <= _blockTime && _blockTime < pools[pId].endTime, 'Invalid time' ); } address sender = msg.sender; for (uint256 i = 0; i < nftIds.length; ) { // if the nft has used emergency withdraw before, not allow to re-deposit require(!isEmergencyWithdrawnNFT[nftIds[i]], 'Not allowed to deposit'); // and nft to the list and deposit nft to the LM contract require(depositNFTs[sender].add(nftIds[i])); nft.transferFrom(sender, address(this), nftIds[i]); emit Deposit(sender, nftIds[i]); // update position data positions[nftIds[i]].owner = sender; uint128 liquidity = helper.getLiq(address(nft), nftIds[i]); positions[nftIds[i]].liquidity = liquidity; // join full liquidity to the farm if joining is enabled if (isJoining) { _join(nftIds[i], pId, liquidity, pools[pId]); } unchecked { ++i; } } } /** * @dev join pool first time * @param nftId NFT id to join * @param pId pool id to join * @param liq liquidity amount to join * @param pool LM pool */ function _join(uint256 nftId, uint256 pId, uint256 liq, LMPoolInfo storage pool) internal { PositionInfo storage position = positions[nftId]; StakeInfo storage stake = stakes[nftId][pId]; require(helper.checkPool(pool.poolAddress, address(nft), nftId), 'join: invalid pool'); require(liq != 0 && liq <= position.liquidity, 'join: invalid liq'); stake.secondsPerLiquidityLast = helper.getActiveTime(pool.poolAddress, address(nft), nftId); stake.rewardLast = new uint256[](pool.rewards.length); stake.rewardPending = new uint256[](pool.rewards.length); stake.rewardHarvested = new uint256[](pool.rewards.length); if (pool.feeTarget != 0) { stake.feeFirst = helper.getSignedFee(address(nft), nftId); } stake.liquidity = liq; pool.numStakes++; require(joinedPools[nftId].add(pId), 'Fail to add joinedPools'); emit Join(nftId, pId, liq); } /** * @dev Increase liquidity in pool * @param nftId NFT id to sync * @param pId pool id to sync * @param liq liquidity amount to increase * @param pool LM pool */ function _sync(uint256 nftId, uint256 pId, uint256 liq, LMPoolInfo storage pool) internal { PositionInfo storage position = positions[nftId]; StakeInfo storage stake = stakes[nftId][pId]; require(liq != 0 && liq + stake.liquidity <= position.liquidity, 'sync: invalid liq'); RewardCalculationData memory data = getRewardCalculationData(nftId, pId); for (uint256 i = 0; i < pool.rewards.length; ++i) { uint256 rewardHarvest = _calculateRewardHarvest( stake.liquidity, pool.rewards[i].rewardUnclaimed, data.totalSecondsUnclaimed, data.secondsPerLiquidity ); if (rewardHarvest != 0) { stake.rewardHarvested[i] += rewardHarvest; pool.rewards[i].rewardUnclaimed -= rewardHarvest; } uint256 rewardCollected = _calculateRewardCollected( stake.rewardHarvested[i], data.vestingVolume, stake.rewardLast[i] ); if (rewardCollected != 0) { stake.rewardLast[i] += rewardCollected; stake.rewardPending[i] += rewardCollected; } } pool.totalSecondsClaimed += data.secondsClaim; stake.secondsPerLiquidityLast = data.secondsPerLiquidityNow; stake.feeFirst = _calculateFeeFirstAfterJoin( stake.feeFirst, data.feeNow, pool.feeTarget, stake.liquidity, liq, nftId ); stake.liquidity += liq; emit SyncLiq(nftId, pId, liq); } /** * @dev Exit pool * @param nftId NFT id to exit * @param pId pool id to exit * @param liq liquidity amount to exit * @param claimReward transfer reward or not */ function _exit(uint256 nftId, uint256 pId, uint256 liq, bool claimReward) internal { LMPoolInfo storage pool = pools[pId]; address pOwner = positions[nftId].owner; StakeInfo storage stake = stakes[nftId][pId]; require( pOwner == msg.sender || (_getBlockTime() > pool.endTime && operators[msg.sender]), 'exit: not owner or pool not ended' ); uint256 liquidityOld = stake.liquidity; require(liq != 0 && liq <= liquidityOld, 'exit: invalid liq'); uint256 liquidityNew = liquidityOld - liq; RewardCalculationData memory data = getRewardCalculationData(nftId, pId); pool.totalSecondsClaimed += data.secondsClaim; stake.secondsPerLiquidityLast = data.secondsPerLiquidityNow; stake.liquidity = liquidityNew; for (uint256 i = 0; i < pool.rewards.length; ++i) { uint256 rewardHarvest = _calculateRewardHarvest( liquidityOld, pool.rewards[i].rewardUnclaimed, data.totalSecondsUnclaimed, data.secondsPerLiquidity ); if (rewardHarvest != 0) { stake.rewardHarvested[i] += rewardHarvest; pool.rewards[i].rewardUnclaimed -= rewardHarvest; } uint256 rewardCollected = _calculateRewardCollected( stake.rewardHarvested[i], data.vestingVolume, stake.rewardLast[i] ); uint256 rewardPending = stake.rewardPending[i]; if (rewardCollected != 0) { stake.rewardLast[i] += rewardCollected; rewardPending += rewardCollected; } if (rewardPending != 0) { if (claimReward) { stake.rewardPending[i] = 0; _transferReward(pool.rewards[i].rewardToken, pOwner, rewardPending); emit Harvest(nftId, pOwner, pool.rewards[i].rewardToken, rewardPending); } else { stake.rewardPending[i] = rewardPending; } } } if (liquidityNew == 0) { delete stakes[nftId][pId]; pool.numStakes--; require(joinedPools[nftId].remove(pId), 'Fail to remove joinedPools'); } emit Exit(msg.sender, nftId, pId, liq); } /** * @dev Harvest reward * @param nftId NFT id to harvest * @param pId pool id to harvest */ function _harvest(uint256 nftId, uint256 pId) internal { require(poolLength > pId, 'Pool not exists'); LMPoolInfo storage pool = pools[pId]; address pOwner = positions[nftId].owner; StakeInfo storage stake = stakes[nftId][pId]; require(stake.liquidity > 0, 'harvest: not joined yet'); RewardCalculationData memory data = getRewardCalculationData(nftId, pId); pool.totalSecondsClaimed += data.secondsClaim; stake.secondsPerLiquidityLast = data.secondsPerLiquidityNow; for (uint256 i = 0; i < pool.rewards.length; ++i) { uint256 rewardHarvest = _calculateRewardHarvest( stake.liquidity, pool.rewards[i].rewardUnclaimed, data.totalSecondsUnclaimed, data.secondsPerLiquidity ); if (rewardHarvest != 0) { stake.rewardHarvested[i] += rewardHarvest; pool.rewards[i].rewardUnclaimed -= rewardHarvest; } uint256 rewardCollected = _calculateRewardCollected( stake.rewardHarvested[i], data.vestingVolume, stake.rewardLast[i] ); uint256 rewardPending = stake.rewardPending[i] + rewardCollected; if (rewardPending != 0) { if (rewardCollected != 0) { stake.rewardLast[i] += rewardCollected; } stake.rewardPending[i] = 0; _transferReward(pool.rewards[i].rewardToken, pOwner, rewardPending); emit Harvest(nftId, pOwner, pool.rewards[i].rewardToken, rewardPending); } } } /** * @dev transfer reward */ function _transferReward(address _token, address _account, uint256 _amount) internal { if (_token == address(0)) { (bool success, ) = payable(_account).call{value: _amount}(''); require(success, 'transfer reward token failed'); } else { IERC20Metadata(_token).safeTransfer(_account, _amount); } } /// @dev remove liquidiy of nft from posManager /// @param nftId nft's id /// @param liquidity liquidity amount to remove /// @param deadline removeLiquidity deadline function _removeLiquidity(uint256 nftId, uint128 liquidity, uint256 deadline) internal { IBasePositionManager.RemoveLiquidityParams memory removeLiq = IBasePositionManager .RemoveLiquidityParams({ tokenId: nftId, liquidity: liquidity, amount0Min: 0, amount1Min: 0, deadline: deadline }); IBasePositionManager(address(nft)).removeLiquidity(removeLiq); } /// @dev claim fee of nft from posManager /// @param nftId nft's id /// @param deadline claimFee deadline /// @param syncFee is need to sync new fee or not function _claimFee(uint256 nftId, uint256 deadline, bool syncFee) internal { if (syncFee) { IBasePositionManager(address(nft)).syncFeeGrowth(nftId); } IBasePositionManager.BurnRTokenParams memory burnRToken = IBasePositionManager .BurnRTokenParams({tokenId: nftId, amount0Min: 0, amount1Min: 0, deadline: deadline}); IBasePositionManager(address(nft)).burnRTokens(burnRToken); } /// @dev transfer tokens from removeLiquidity (and burnRToken if any) to receiver /// @param token0 address of token0 /// @param token1 address of token1 /// @param amount0Min minimum amount of token0 should receive /// @param amount1Min minimum amount of token1 should receive /// @param receiver receiver of tokens /// @param isReceiveNative should unwrap wrapped native or not function _transferTokens( address token0, address token1, uint256 amount0Min, uint256 amount1Min, address receiver, bool isReceiveNative ) internal { IBasePositionManager posManager = IBasePositionManager(address(nft)); if (isReceiveNative) { // expect to receive in native token if (weth == token0) { // receive in native for token0 posManager.unwrapWeth(amount0Min, receiver); posManager.transferAllTokens(token1, amount1Min, receiver); return; } if (weth == token1) { // receive in native for token1 posManager.transferAllTokens(token0, amount0Min, receiver); posManager.unwrapWeth(amount1Min, receiver); return; } } posManager.transferAllTokens(token0, amount0Min, receiver); posManager.transferAllTokens(token1, amount1Min, receiver); } /** * HELPER MATH FUNCTIONS ************************* */ function getRewardCalculationData( uint256 nftId, uint256 pId ) public view override returns (RewardCalculationData memory data) { LMPoolInfo storage pool = pools[pId]; StakeInfo storage stake = stakes[nftId][pId]; data.secondsPerLiquidityNow = helper.getActiveTime(pool.poolAddress, address(nft), nftId); data.feeNow = helper.getSignedFeePool(pool.poolAddress, address(nft), nftId); data.vestingVolume = _calculateVestingVolume(data.feeNow, stake.feeFirst, pool.feeTarget); data.totalSecondsUnclaimed = _calculateSecondsUnclaimed( pool.startTime, pool.endTime, pool.totalSecondsClaimed ); unchecked { data.secondsPerLiquidity = data.secondsPerLiquidityNow - stake.secondsPerLiquidityLast; } data.secondsClaim = stake.liquidity * data.secondsPerLiquidity; } /** * @dev feeFirst = (liq * max(feeNow - feeTarget, feeFirst) + liqAdd * feeNow) / liqNew */ function _calculateFeeFirstAfterJoin( int256 feeFirst, int256 feeNow, uint256 feeTarget, uint256 liquidity, uint256 liquidityAdd, uint256 nftId ) internal view returns (int256) { if (feeTarget == 0) { return 0; } int256 feeFirstCurrent = feeNow - int256(feeTarget) < feeFirst ? feeFirst : feeNow - int256(feeTarget); int256 numerator = int256(liquidity) * feeFirstCurrent + int256(liquidityAdd) * helper.getSignedFee(address(nft), nftId); int256 denominator = int256(liquidity + liquidityAdd); return numerator / denominator; } /** * @dev vesting = min((feeNow - feeFirst) / feeTarget, 1) */ function _calculateVestingVolume( int256 feeNow, int256 feeFirst, uint256 feeTarget ) internal pure returns (uint256) { if (feeTarget == 0) { return PRECISION; } uint256 feeInside = uint256(feeNow - feeFirst); return KSMath.min((feeInside * PRECISION) / feeTarget, PRECISION); } /** * @dev secondsUnclaimed = (max(currentTime, endTime) - startTime) - secondsClaimed */ function _calculateSecondsUnclaimed( uint256 startTime, uint256 endTime, uint256 totalSecondsClaimed ) internal view returns (uint256) { uint256 totalSeconds = KSMath.max(_getBlockTime(), endTime) - startTime; uint256 totalSecondsScaled = totalSeconds * (1 << 96); return totalSecondsScaled > totalSecondsClaimed ? totalSecondsScaled - totalSecondsClaimed : 0; } /** * @dev rewardHarvested = L * rewardRate * secondsPerLiquidity */ function _calculateRewardHarvest( uint256 liquidity, uint256 rewardUnclaimed, uint256 totalSecondsUnclaimed, uint256 secondsPerLiquidity ) internal pure returns (uint256) { return (liquidity * rewardUnclaimed * secondsPerLiquidity) / totalSecondsUnclaimed; } /** * @dev rewardCollected = Max(rewardHarvested * vestingVolume - rewardLast, 0); */ function _calculateRewardCollected( uint256 rewardHarvested, uint256 vestingVolume, uint256 rewardLast ) internal pure returns (uint256) { uint256 rewardNow = (rewardHarvested * vestingVolume) / PRECISION; return rewardNow > rewardLast ? rewardNow - rewardLast : 0; } function _getBlockTime() internal view virtual returns (uint32) { return uint32(block.timestamp); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; library KSMath { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? b : a; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {IKyberSwapElasticLMEvents} from './IKyberSwapElasticLMEvents.sol'; import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol'; interface IKyberSwapElasticLM is IKyberSwapElasticLMEvents { struct RewardData { address rewardToken; uint256 rewardUnclaimed; } struct LMPoolInfo { address poolAddress; uint32 startTime; uint32 endTime; uint256 totalSecondsClaimed; // scaled by (1 << 96) RewardData[] rewards; uint256 feeTarget; uint256 numStakes; } struct PositionInfo { address owner; uint256 liquidity; } struct StakeInfo { uint128 secondsPerLiquidityLast; uint256[] rewardLast; uint256[] rewardPending; uint256[] rewardHarvested; int256 feeFirst; uint256 liquidity; } // input data in harvestMultiplePools function struct HarvestData { uint256[] pIds; } // avoid stack too deep error struct RewardCalculationData { uint128 secondsPerLiquidityNow; int256 feeNow; uint256 vestingVolume; uint256 totalSecondsUnclaimed; uint256 secondsPerLiquidity; uint256 secondsClaim; // scaled by (1 << 96) } /** * @dev Add new pool to LM * @param poolAddr pool address * @param startTime start time of liquidity mining * @param endTime end time of liquidity mining * @param rewardTokens reward token list for pool * @param rewardAmounts reward amount of list token * @param feeTarget fee target for pool * */ function addPool( address poolAddr, uint32 startTime, uint32 endTime, address[] calldata rewardTokens, uint256[] calldata rewardAmounts, uint256 feeTarget ) external; /** * @dev Renew a pool to start another LM program * @param pId pool id to update * @param startTime start time of liquidity mining * @param endTime end time of liquidity mining * @param rewardAmounts reward amount of list token * @param feeTarget fee target for pool * */ function renewPool( uint256 pId, uint32 startTime, uint32 endTime, uint256[] calldata rewardAmounts, uint256 feeTarget ) external; /** * @dev Deposit NFT * @param nftIds list nft id * */ function deposit(uint256[] calldata nftIds) external; /** * @dev Deposit NFTs into the pool and join farms if applicable * @param pId pool id to join farm * @param nftIds List of NFT ids from BasePositionManager, should match with the pId * */ function depositAndJoin(uint256 pId, uint256[] calldata nftIds) external; /** * @dev Withdraw NFT, must exit all pool before call. * @param nftIds list nft id * */ function withdraw(uint256[] calldata nftIds) external; /** * @dev Join pools * @param pId pool id to join * @param nftIds nfts to join * @param liqs list liquidity value to join each nft * */ function join(uint256 pId, uint256[] calldata nftIds, uint256[] calldata liqs) external; /** * @dev Exit from pools * @param pId pool ids to exit * @param nftIds list nfts id * @param liqs list liquidity value to exit from each nft * */ function exit(uint256 pId, uint256[] calldata nftIds, uint256[] calldata liqs) external; /** * @dev Claim rewards for a list of pools for a list of nft positions * @param nftIds List of NFT ids to harvest * @param datas List of pool ids to harvest for each nftId, encoded into bytes */ function harvestMultiplePools(uint256[] calldata nftIds, bytes[] calldata datas) external; /** * @dev remove liquidity from elastic for a list of nft position, also update on farm * @param nftId to remove * @param liquidity liquidity amount to remove from nft * @param amount0Min expected min amount of token0 should receive * @param amount1Min expected min amount of token1 should receive * @param deadline deadline of this tx * @param isReceiveNative should unwrap native or not * @param claimFeeAndRewards also claim LP Fee and farm rewards */ function removeLiquidity( uint256 nftId, uint128 liquidity, uint256 amount0Min, uint256 amount1Min, uint256 deadline, bool isReceiveNative, bool[2] calldata claimFeeAndRewards ) external; /** * @dev Claim fee from elastic for a list of nft positions * @param nftIds List of NFT ids to claim * @param amount0Min expected min amount of token0 should receive * @param amount1Min expected min amount of token1 should receive * @param poolAddress address of Elastic pool of those nfts * @param isReceiveNative should unwrap native or not * @param deadline deadline of this tx */ function claimFee( uint256[] calldata nftIds, uint256 amount0Min, uint256 amount1Min, address poolAddress, bool isReceiveNative, uint256 deadline ) external; /** * @dev Operator only. Call to withdraw all reward from list pools. * @param rewards list reward address erc20 token * @param amounts amount to withdraw * */ function emergencyWithdrawForOwner( address[] calldata rewards, uint256[] calldata amounts ) external; /** * @dev Withdraw NFT, can call any time, reward will be reset. Must enable this func by operator * @param pIds list pool to withdraw * */ function emergencyWithdraw(uint256[] calldata pIds) external; /** * @dev get list of pool that this nft joined * @param nftId to get */ function getJoinedPools(uint256 nftId) external view returns (uint256[] memory poolIds); /** * @dev get list of pool that this nft joined, only in a specific range * @param nftId to get * @param fromIndex index from * @param toIndex index to */ function getJoinedPoolsInRange( uint256 nftId, uint256 fromIndex, uint256 toIndex ) external view returns (uint256[] memory poolIds); /** * @dev get user's info (staked info) of a nft in a pool * @param nftId to get * @param pId to get */ function getUserInfo( uint256 nftId, uint256 pId ) external view returns (uint256 liquidity, uint256[] memory rewardPending, uint256[] memory rewardLast); /** * @dev get pool info * @param pId to get */ function getPoolInfo( uint256 pId ) external view returns ( address poolAddress, uint32 startTime, uint32 endTime, uint256 totalSecondsClaimed, uint256 feeTarget, uint256 numStakes, //index reward => reward data address[] memory rewardTokens, uint256[] memory rewardUnclaimeds ); /** * @dev get list of deposited nfts of an address * @param user address of user to get */ function getDepositedNFTs(address user) external view returns (uint256[] memory listNFTs); function nft() external view returns (IERC721); function poolLength() external view returns (uint256); function getRewardCalculationData( uint256 nftId, uint256 pId ) external view returns (RewardCalculationData memory data); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IKSElasticLMHelper { function checkPool( address pAddress, address nftContract, uint256 nftId ) external view returns (bool); /// @dev use virtual to be overrided to mock data for fuzz tests function getActiveTime( address pAddr, address nftContract, uint256 nftId ) external view returns (uint128); function getSignedFee(address nftContract, uint256 nftId) external view returns (int256); function getSignedFeePool( address poolAddress, address nftContract, uint256 nftId ) external view returns (int256); function getLiq(address nftContract, uint256 nftId) external view returns (uint128); function getPair(address nftContract, uint256 nftId) external view returns (address, address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; interface IBasePositionManager { struct Position { // the nonce for permits uint96 nonce; // the address that is approved for spending this token address operator; // the ID of the pool with which this token is connected uint80 poolId; // the tick range of the position int24 tickLower; int24 tickUpper; // the liquidity of the position uint128 liquidity; // the current rToken that the position owed uint256 rTokenOwed; // fee growth per unit of liquidity as of the last update to liquidity uint256 feeGrowthInsideLast; } struct PoolInfo { address token0; uint16 fee; address token1; } struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; int24[2] ticksPrevious; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; } struct IncreaseLiquidityParams { uint256 tokenId; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct RemoveLiquidityParams { uint256 tokenId; uint128 liquidity; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct BurnRTokenParams { uint256 tokenId; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } function positions( uint256 tokenId ) external view returns (Position memory pos, PoolInfo memory info); function addressToPoolId(address pool) external view returns (uint80); function WETH() external view returns (address); function mint( MintParams calldata params ) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); function addLiquidity( IncreaseLiquidityParams calldata params ) external payable returns (uint128 liquidity, uint256 amount0, uint256 amount1, uint256 additionalRTokenOwed); function removeLiquidity( RemoveLiquidityParams calldata params ) external returns (uint256 amount0, uint256 amount1, uint256 additionalRTokenOwed); function syncFeeGrowth(uint256 tokenId) external returns (uint256 additionalRTokenOwed); function burnRTokens( BurnRTokenParams calldata params ) external returns (uint256 rTokenQty, uint256 amount0, uint256 amount1); function transferAllTokens(address token, uint256 minAmount, address recipient) external payable; function unwrapWeth(uint256 minAmount, address recipient) external payable; }
// SPDX-License-Identifier: agpl-3.0 pragma solidity >=0.8.0; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {IFactory} from './IFactory.sol'; interface IPoolStorage { struct PoolData { uint160 sqrtP; int24 nearestCurrentTick; int24 currentTick; bool locked; uint128 baseL; uint128 reinvestL; uint128 reinvestLLast; uint256 feeGrowthGlobal; uint128 secondsPerLiquidityGlobal; uint32 secondsPerLiquidityUpdateTime; } // data stored for each initialized individual tick struct TickData { // gross liquidity of all positions in tick uint128 liquidityGross; // liquidity quantity to be added | removed when tick is crossed up | down int128 liquidityNet; // fee growth per unit of liquidity on the other side of this tick (relative to current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 feeGrowthOutside; // seconds spent on the other side of this tick (relative to current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint128 secondsPerLiquidityOutside; } /// @notice The contract that deployed the pool, which must adhere to the IFactory interface /// @return The contract address function factory() external view returns (IFactory); /// @notice The first of the two tokens of the pool, sorted by address /// @return The token contract address function token0() external view returns (IERC20); /// @notice The second of the two tokens of the pool, sorted by address /// @return The token contract address function token1() external view returns (IERC20); /// @notice The fee to be charged for a swap in basis points /// @return The swap fee in basis points function swapFeeBps() external view returns (uint16); /// @notice The pool tick distance /// @dev Ticks can only be initialized and used at multiples of this value /// It remains an int24 to avoid casting even though it is >= 1. /// e.g: a tickDistance of 5 means ticks can be initialized every 5th tick, i.e., ..., -10, -5, 0, 5, 10, ... /// @return The tick distance function tickDistance() external view returns (int24); /// @notice Maximum gross liquidity that an initialized tick can have /// @dev This is to prevent overflow the pool's active base liquidity (uint128) /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool /// @return The max amount of liquidity per tick function maxTickLiquidity() external view returns (uint128); /// @notice Look up information about a specific tick in the pool /// @param tick The tick to look up /// @return liquidityGross total liquidity amount from positions that uses this tick as a lower or upper tick /// liquidityNet how much liquidity changes when the pool tick crosses above the tick /// feeGrowthOutside the fee growth on the other side of the tick relative to the current tick /// secondsPerLiquidityOutside the seconds spent on the other side of the tick relative to the current tick function ticks(int24 tick) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside, uint128 secondsPerLiquidityOutside ); /// @notice Returns the previous and next initialized ticks of a specific tick /// @dev If specified tick is uninitialized, the returned values are zero. /// @param tick The tick to look up function initializedTicks(int24 tick) external view returns (int24 previous, int24 next); /// @notice Returns the information about a position by the position's key /// @return liquidity the liquidity quantity of the position /// @return feeGrowthInsideLast fee growth inside the tick range as of the last mint / burn action performed function getPositions( address owner, int24 tickLower, int24 tickUpper ) external view returns (uint128 liquidity, uint256 feeGrowthInsideLast); /// @notice Fetches the pool's prices, ticks and lock status /// @return sqrtP sqrt of current price: sqrt(token1/token0) /// @return currentTick pool's current tick /// @return nearestCurrentTick pool's nearest initialized tick that is <= currentTick /// @return locked true if pool is locked, false otherwise function getPoolState() external view returns ( uint160 sqrtP, int24 currentTick, int24 nearestCurrentTick, bool locked ); /// @notice Fetches the pool's liquidity values /// @return baseL pool's base liquidity without reinvest liqudity /// @return reinvestL the liquidity is reinvested into the pool /// @return reinvestLLast last cached value of reinvestL, used for calculating reinvestment token qty function getLiquidityState() external view returns ( uint128 baseL, uint128 reinvestL, uint128 reinvestLLast ); /// @return feeGrowthGlobal All-time fee growth per unit of liquidity of the pool function getFeeGrowthGlobal() external view returns (uint256); /// @return secondsPerLiquidityGlobal All-time seconds per unit of liquidity of the pool /// @return lastUpdateTime The timestamp in which secondsPerLiquidityGlobal was last updated function getSecondsPerLiquidityData() external view returns (uint128 secondsPerLiquidityGlobal, uint32 lastUpdateTime); /// @notice Calculates and returns the active time per unit of liquidity until current block.timestamp /// @param tickLower The lower tick (of a position) /// @param tickUpper The upper tick (of a position) /// @return secondsPerLiquidityInside active time (multiplied by 2^96) /// between the 2 ticks, per unit of liquidity. function getSecondsPerLiquidityInside(int24 tickLower, int24 tickUpper) external view returns (uint128 secondsPerLiquidityInside); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; abstract contract KSAdmin { address public admin; mapping(address => bool) public operators; // address => bool event TransferAdmin(address indexed admin); event UpdateOperator(address indexed user, bool grantOrRevoke); modifier isAdmin() { require(msg.sender == admin, 'forbidden'); _; } modifier isOperator() { require(operators[msg.sender], 'forbidden'); _; } constructor() { admin = msg.sender; operators[msg.sender] = true; } function transferAdmin(address _admin) external virtual isAdmin { require(_admin != address(0), 'forbidden'); admin = _admin; emit TransferAdmin(_admin); } function updateOperator(address user, bool grantOrRevoke) external isAdmin { operators[user] = grantOrRevoke; emit UpdateOperator(user, grantOrRevoke); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT 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 pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {IKSElasticLMHelper} from './IKSElasticLMHelper.sol'; interface IKyberSwapElasticLMEvents { event AddPool( uint256 indexed pId, address poolAddress, uint32 startTime, uint32 endTime, uint256 feeTarget ); event RenewPool(uint256 indexed pid, uint32 startTime, uint32 endTime, uint256 feeTarget); event Deposit(address sender, uint256 indexed nftId); event Withdraw(address sender, uint256 indexed nftId); event Join(uint256 indexed nftId, uint256 indexed pId, uint256 indexed liq); event Exit(address to, uint256 indexed nftId, uint256 indexed pId, uint256 indexed liq); event SyncLiq(uint256 indexed nftId, uint256 indexed pId, uint256 indexed liq); event Harvest(uint256 indexed nftId, address to, address reward, uint256 indexed amount); event EmergencyEnabled(); event UpdateSpecialFeatureEnabled(bool enableOrDisable); event EmergencyWithdrawForOwner(address reward, uint256 indexed amount); event EmergencyWithdraw(address sender, uint256 indexed nftId); event LMHelperUpdated(IKSElasticLMHelper helper); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount ) external returns (bool); /** * @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); }
// SPDX-License-Identifier: agpl-3.0 pragma solidity >=0.8.0; /// @title KyberSwap v2 factory /// @notice Deploys KyberSwap v2 pools and manages control over government fees interface IFactory { /// @notice Emitted when a pool is created /// @param token0 First pool token by address sort order /// @param token1 Second pool token by address sort order /// @param swapFeeBps Fee to be collected upon every swap in the pool, in basis points /// @param tickDistance Minimum number of ticks between initialized ticks /// @param pool The address of the created pool event PoolCreated( address indexed token0, address indexed token1, uint16 indexed swapFeeBps, int24 tickDistance, address pool ); /// @notice Emitted when a new fee is enabled for pool creation via the factory /// @param swapFeeBps Fee to be collected upon every swap in the pool, in basis points /// @param tickDistance Minimum number of ticks between initialized ticks for pools created with the given fee event SwapFeeEnabled(uint16 indexed swapFeeBps, int24 indexed tickDistance); /// @notice Emitted when vesting period changes /// @param vestingPeriod The maximum time duration for which LP fees /// are proportionally burnt upon LP removals event VestingPeriodUpdated(uint32 vestingPeriod); /// @notice Emitted when configMaster changes /// @param oldConfigMaster configMaster before the update /// @param newConfigMaster configMaster after the update event ConfigMasterUpdated(address oldConfigMaster, address newConfigMaster); /// @notice Emitted when fee configuration changes /// @param feeTo Recipient of government fees /// @param governmentFeeBps Fee amount, in basis points, /// to be collected out of the fee charged for a pool swap event FeeConfigurationUpdated(address feeTo, uint16 governmentFeeBps); /// @notice Emitted when whitelist feature is enabled event WhitelistEnabled(); /// @notice Emitted when whitelist feature is disabled event WhitelistDisabled(); /// @notice Returns the maximum time duration for which LP fees /// are proportionally burnt upon LP removals function vestingPeriod() external view returns (uint32); /// @notice Returns the tick distance for a specified fee. /// @dev Once added, cannot be updated or removed. /// @param swapFeeBps Swap fee, in basis points. /// @return The tick distance. Returns 0 if fee has not been added. function feeAmountTickDistance(uint16 swapFeeBps) external view returns (int24); /// @notice Returns the address which can update the fee configuration function configMaster() external view returns (address); /// @notice Returns the keccak256 hash of the Pool creation code /// This is used for pre-computation of pool addresses function poolInitHash() external view returns (bytes32); /// @notice Fetches the recipient of government fees /// and current government fee charged in basis points function feeConfiguration() external view returns (address _feeTo, uint16 _governmentFeeBps); /// @notice Returns the status of whitelisting feature of NFT managers /// If true, anyone can mint liquidity tokens /// Otherwise, only whitelisted NFT manager(s) are allowed to mint liquidity tokens function whitelistDisabled() external view returns (bool); //// @notice Returns all whitelisted NFT managers /// If the whitelisting feature is turned on, /// only whitelisted NFT manager(s) are allowed to mint liquidity tokens function getWhitelistedNFTManagers() external view returns (address[] memory); /// @notice Checks if sender is a whitelisted NFT manager /// If the whitelisting feature is turned on, /// only whitelisted NFT manager(s) are allowed to mint liquidity tokens /// @param sender address to be checked /// @return true if sender is a whistelisted NFT manager, false otherwise function isWhitelistedNFTManager(address sender) external view returns (bool); /// @notice Returns the pool address for a given pair of tokens and a swap fee /// @dev Token order does not matter /// @param tokenA Contract address of either token0 or token1 /// @param tokenB Contract address of the other token /// @param swapFeeBps Fee to be collected upon every swap in the pool, in basis points /// @return pool The pool address. Returns null address if it does not exist function getPool( address tokenA, address tokenB, uint16 swapFeeBps ) external view returns (address pool); /// @notice Fetch parameters to be used for pool creation /// @dev Called by the pool constructor to fetch the parameters of the pool /// @return factory The factory address /// @return token0 First pool token by address sort order /// @return token1 Second pool token by address sort order /// @return swapFeeBps Fee to be collected upon every swap in the pool, in basis points /// @return tickDistance Minimum number of ticks between initialized ticks function parameters() external view returns ( address factory, address token0, address token1, uint16 swapFeeBps, int24 tickDistance ); /// @notice Creates a pool for the given two tokens and fee /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param swapFeeBps Desired swap fee for the pool, in basis points /// @dev Token order does not matter. tickDistance is determined from the fee. /// Call will revert under any of these conditions: /// 1) pool already exists /// 2) invalid swap fee /// 3) invalid token arguments /// @return pool The address of the newly created pool function createPool( address tokenA, address tokenB, uint16 swapFeeBps ) external returns (address pool); /// @notice Enables a fee amount with the given tickDistance /// @dev Fee amounts may never be removed once enabled /// @param swapFeeBps The fee amount to enable, in basis points /// @param tickDistance The distance between ticks to be enforced for all pools created with the given fee amount function enableSwapFee(uint16 swapFeeBps, int24 tickDistance) external; /// @notice Updates the address which can update the fee configuration /// @dev Must be called by the current configMaster function updateConfigMaster(address) external; /// @notice Updates the vesting period /// @dev Must be called by the current configMaster function updateVestingPeriod(uint32) external; /// @notice Updates the address receiving government fees and fee quantity /// @dev Only configMaster is able to perform the update /// @param feeTo Address to receive government fees collected from pools /// @param governmentFeeBps Fee amount, in basis points, /// to be collected out of the fee charged for a pool swap function updateFeeConfiguration(address feeTo, uint16 governmentFeeBps) external; /// @notice Enables the whitelisting feature /// @dev Only configMaster is able to perform the update function enableWhitelist() external; /// @notice Disables the whitelisting feature /// @dev Only configMaster is able to perform the update function disableWhitelist() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IERC721","name":"_nft","type":"address"},{"internalType":"contract IKSElasticLMHelper","name":"_helper","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pId","type":"uint256"},{"indexed":false,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"feeTarget","type":"uint256"}],"name":"AddPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[],"name":"EmergencyEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"reward","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdrawForOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"liq","type":"uint256"}],"name":"Exit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"reward","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"liq","type":"uint256"}],"name":"Join","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IKSElasticLMHelper","name":"helper","type":"address"}],"name":"LMHelperUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"feeTarget","type":"uint256"}],"name":"RenewPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"liq","type":"uint256"}],"name":"SyncLiq","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"TransferAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"grantOrRevoke","type":"bool"}],"name":"UpdateOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enableOrDisable","type":"bool"}],"name":"UpdateSpecialFeatureEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"rewardAmounts","type":"uint256[]"},{"internalType":"uint256","name":"feeTarget","type":"uint256"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"bool","name":"isReceiveNative","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"claimFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pId","type":"uint256"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"depositAndJoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyEnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"rewards","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"emergencyWithdrawForOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pId","type":"uint256"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"uint256[]","name":"liqs","type":"uint256[]"}],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getDepositedNFTs","outputs":[{"internalType":"uint256[]","name":"listNFTs","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getJoinedPools","outputs":[{"internalType":"uint256[]","name":"poolIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"fromIndex","type":"uint256"},{"internalType":"uint256","name":"toIndex","type":"uint256"}],"name":"getJoinedPoolsInRange","outputs":[{"internalType":"uint256[]","name":"poolIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pId","type":"uint256"}],"name":"getPoolInfo","outputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint256","name":"totalSecondsClaimed","type":"uint256"},{"internalType":"uint256","name":"feeTarget","type":"uint256"},{"internalType":"uint256","name":"numStakes","type":"uint256"},{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"rewardUnclaimeds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"pId","type":"uint256"}],"name":"getRewardCalculationData","outputs":[{"components":[{"internalType":"uint128","name":"secondsPerLiquidityNow","type":"uint128"},{"internalType":"int256","name":"feeNow","type":"int256"},{"internalType":"uint256","name":"vestingVolume","type":"uint256"},{"internalType":"uint256","name":"totalSecondsUnclaimed","type":"uint256"},{"internalType":"uint256","name":"secondsPerLiquidity","type":"uint256"},{"internalType":"uint256","name":"secondsClaim","type":"uint256"}],"internalType":"struct IKyberSwapElasticLM.RewardCalculationData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"pId","type":"uint256"}],"name":"getUserInfo","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256[]","name":"rewardPending","type":"uint256[]"},{"internalType":"uint256[]","name":"rewardLast","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"bytes[]","name":"datas","type":"bytes[]"}],"name":"harvestMultiplePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isEmergencyWithdrawnNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pId","type":"uint256"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"uint256[]","name":"liqs","type":"uint256[]"}],"name":"join","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nft","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pools","outputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint256","name":"totalSecondsClaimed","type":"uint256"},{"internalType":"uint256","name":"feeTarget","type":"uint256"},{"internalType":"uint256","name":"numStakes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"positions","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"isReceiveNative","type":"bool"},{"internalType":"bool[2]","name":"claimFeeAndRewards","type":"bool[2]"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pId","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint256[]","name":"rewardAmounts","type":"uint256[]"},{"internalType":"uint256","name":"feeTarget","type":"uint256"}],"name":"renewPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"specialFeatureEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakes","outputs":[{"internalType":"uint128","name":"secondsPerLiquidityLast","type":"uint128"},{"internalType":"int256","name":"feeFirst","type":"int256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IKSElasticLMHelper","name":"_helper","type":"address"}],"name":"updateHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"grantOrRevoke","type":"bool"}],"name":"updateOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enableOrDisable","type":"bool"}],"name":"updateSpecialFeatureEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162005f7738038062005f77833981016040819052620000349162000125565b600160008181558154336001600160a01b031991821681178455825260026020908152604092839020805460ff19169094179093556001600160a01b038581166080819052600380549093169186169190911790915581516315ab88c960e31b81529151909263ad5c46489260048082019391829003018186803b158015620000bc57600080fd5b505afa158015620000d1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000f7919062000164565b6001600160a01b031660a052506200018b9050565b6001600160a01b03811681146200012257600080fd5b50565b600080604083850312156200013957600080fd5b825162000146816200010c565b602084015190925062000159816200010c565b809150509250929050565b6000602082840312156200017757600080fd5b815162000184816200010c565b9392505050565b60805160a051615d3a6200023d600039600081816102fa01528181614681015261478501526000818161038001528181610faf01528181611d2501528181612128015281816123d2015281816125fd01528181612a0301528181612e1801528181612eca01528181613355015281816134900152818161366001528181613c3301528181613d8a015281816144f5015281816145c901528181614650015281816149820152614b100152615d3a6000f3fe6080604052600436106101fd5760003560e01c806375829def1161010d578063b36b26c5116100a0578063c7ca58701161006f578063c7ca58701461074b578063d1941b061461076b578063dc168a921461078b578063e7762a0c146107ba578063f851a4401461082f57600080fd5b8063b36b26c5146106bc578063b63ff916146106dc578063b82562751461070c578063bb5ae7751461072c57600080fd5b806399fbab88116100dc57806399fbab881461052f578063ac4afa381461058e578063affe737914610631578063b221e5fd1461064657600080fd5b806375829def146104af5780638bcc4166146104cf57806391fb2f15146104ef578063983d95ce1461050f57600080fd5b806347ccca021161019057806361657b121161015f57806361657b121461040f57806366b5a6641461042f578063683f3eda1461044f5780636d44a3b21461046f578063705b5bef1461048f57600080fd5b806347ccca021461036e57806349b35168146103a257806350523cea146103cf578063598b8e71146103ef57600080fd5b80632f380b35116101cc5780632f380b35146102b45780633fc8cef3146102e857806341e817ab14610334578063430ccd9b1461035457600080fd5b8063078ded5d14610209578063081e3eda1461022b57806313e7c9d814610254578063180f80361461029457600080fd5b3661020457005b600080fd5b34801561021557600080fd5b5061022961022436600461515c565b61084f565b005b34801561023757600080fd5b5061024160045481565b6040519081526020015b60405180910390f35b34801561026057600080fd5b5061028461026f3660046151e7565b60026020526000908152604090205460ff1681565b604051901515815260200161024b565b3480156102a057600080fd5b506102296102af366004615204565b610b0b565b3480156102c057600080fd5b506102d46102cf36600461526f565b610c8d565b60405161024b9897969594939291906152c3565b3480156102f457600080fd5b5061031c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161024b565b34801561034057600080fd5b5061022961034f366004615363565b610e37565b34801561036057600080fd5b50600b546102849060ff1681565b34801561037a57600080fd5b5061031c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ae57600080fd5b506103c26103bd3660046153dc565b61118b565b60405161024b9190615408565b3480156103db57600080fd5b506102296103ea366004615429565b6112e3565b3480156103fb57600080fd5b5061022961040a366004615446565b611361565b34801561041b57600080fd5b5061022961042a366004615204565b6113d3565b34801561043b57600080fd5b5061022961044a366004615363565b611507565b34801561045b57600080fd5b5061022961046a366004615487565b6115d8565b34801561047b57600080fd5b5061022961048a3660046154d2565b611674565b34801561049b57600080fd5b506103c26104aa36600461526f565b6116fd565b3480156104bb57600080fd5b506102296104ca3660046151e7565b6117b5565b3480156104db57600080fd5b506102296104ea3660046151e7565b61184f565b3480156104fb57600080fd5b5061022961050a36600461550b565b6118c7565b34801561051b57600080fd5b5061022961052a366004615446565b611b60565b34801561053b57600080fd5b5061056f61054a36600461526f565b600660205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161024b565b34801561059a57600080fd5b506105f06105a936600461526f565b60056020526000908152604090208054600182015460038301546004909301546001600160a01b0383169363ffffffff600160a01b8504811694600160c01b900416929186565b604080516001600160a01b0397909716875263ffffffff958616602088015293909416928501929092526060840152608083015260a082015260c00161024b565b34801561063d57600080fd5b50610229611e30565b34801561065257600080fd5b506106976106613660046155b5565b60076020908152600092835260408084209091529082529020805460048201546005909201546001600160801b03909116919083565b604080516001600160801b03909416845260208401929092529082015260600161024b565b3480156106c857600080fd5b506103c26106d73660046151e7565b611ed5565b3480156106e857600080fd5b506102846106f736600461526f565b600a6020526000908152604090205460ff1681565b34801561071857600080fd5b506102296107273660046155d7565b611eff565b34801561073857600080fd5b50600b5461028490610100900460ff1681565b34801561075757600080fd5b50610229610766366004615672565b6122ad565b34801561077757600080fd5b50610229610786366004615446565b6126d6565b34801561079757600080fd5b506107ab6107a63660046155b5565b612b10565b60405161024b939291906156ea565b3480156107c657600080fd5b506107da6107d53660046155b5565b612d81565b60405161024b9190600060c0820190506001600160801b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561083b57600080fd5b5060015461031c906001600160a01b031681565b3360009081526002602052604090205460ff166108875760405162461bcd60e51b815260040161087e90615715565b60405180910390fd5b6000868152600560205260409020805463ffffffff428116600160a01b9092041611806108c45750805463ffffffff428116600160c01b90920416105b6109105760405162461bcd60e51b815260206004820152601960248201527f72656e65773a20696e76616c696420706f6f6c20737461746500000000000000604482015260640161087e565b6002810154831461095b5760405162461bcd60e51b81526020600482015260156024820152740e4cadccaee7440d2dcecc2d8d2c840d8cadccee8d605b1b604482015260640161087e565b4263ffffffff168663ffffffff1611801561098157508563ffffffff168563ffffffff16115b6109c45760405162461bcd60e51b815260206004820152601460248201527372656e65773a20696e76616c69642074696d657360601b604482015260640161087e565b600481015415610a0f5760405162461bcd60e51b815260206004820152601660248201527572656e65773a20706f6f6c20686173207374616b657360501b604482015260640161087e565b805463ffffffff868116600160c01b0263ffffffff60c01b19918916600160a01b029190911667ffffffffffffffff60a01b1990921691909117178155600060018201819055600382018390555b83811015610ab757848482818110610a7757610a77615738565b90506020020135826002018281548110610a9357610a93615738565b6000918252602090912060016002909202010155610ab081615764565b9050610a5d565b506040805163ffffffff80891682528716602082015290810183905287907feda7bcc7e20158ff9fa87a4200758e927bbb3c8823e648403bdd6053b96dd0ad9060600160405180910390a250505050505050565b60026000541415610b2e5760405162461bcd60e51b815260040161087e9061577f565b60026000558281808214610b545760405162461bcd60e51b815260040161087e906157b6565b60005b85811015610c7f573360066000898985818110610b7657610b76615738565b60209081029290920135835250810191909152604001600020546001600160a01b031614610bdb5760405162461bcd60e51b81526020600482015260126024820152713430b93b32b9ba1d103737ba1037bbb732b960711b604482015260640161087e565b6000858583818110610bef57610bef615738565b9050602002810190610c0191906157de565b810190610c0e9190615892565b905060005b815151811015610c6c57610c5c898985818110610c3257610c32615738565b9050602002013583600001518381518110610c4f57610c4f615738565b6020026020010151612fc9565b610c6581615764565b9050610c13565b505080610c7890615764565b9050610b57565b505060016000555050505050565b6000818152600560205260409020805460018201546003830154600484015460028501546001600160a01b0385169563ffffffff600160a01b8704811696600160c01b900416949392916060918291806001600160401b03811115610cf457610cf4615824565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b509350806001600160401b03811115610d3857610d38615824565b604051908082528060200260200182016040528015610d61578160200160208202803683370190505b50925060005b81811015610e2957826002018181548110610d8457610d84615738565b600091825260209091206002909102015485516001600160a01b0390911690869083908110610db557610db5615738565b60200260200101906001600160a01b031690816001600160a01b031681525050826002018181548110610dea57610dea615738565b906000526020600020906002020160010154848281518110610e0e57610e0e615738565b6020908102919091010152610e2281615764565b9050610d67565b505050919395975091939597565b60026000541415610e5a5760405162461bcd60e51b815260040161087e9061577f565b60026000558281808214610e805760405162461bcd60e51b815260040161087e906157b6565b8660045411610ea15760405162461bcd60e51b815260040161087e90615966565b6000878152600560205260409020805463ffffffff428116600160a01b9092041611801590610ee357508054600160c01b900463ffffffff164263ffffffff16105b610f1e5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b60005b8681101561117b5733600660008a8a85818110610f4057610f40615738565b60209081029290920135835250810191909152604001600020546001600160a01b031614610f9c5760405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b604482015260640161087e565b6003546001600160a01b0316635c6d96a97f00000000000000000000000000000000000000000000000000000000000000008a8a85818110610fe057610fe0615738565b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160206040518083038186803b15801561102d57600080fd5b505afa158015611041573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611065919061598f565b6001600160801b0316600660008a8a8581811061108457611084615738565b905060200201358152602001908152602001600020600101819055506000600760008a8a858181106110b8576110b8615738565b90506020020135815260200190815260200160002060008b8152602001908152602001600020905080600501546000141561112e5761112989898481811061110257611102615738565b905060200201358b89898681811061111c5761111c615738565b9050602002013586613303565b61116a565b61116a89898481811061114357611143615738565b905060200201358b89898681811061115d5761115d615738565b90506020020135866137a9565b5061117481615764565b9050610f21565b5050600160005550505050505050565b6060818311156111d35760405162461bcd60e51b81526020600482015260136024820152720cce4deda92dcc8caf0407c40e8de92dcc8caf606b1b604482015260640161087e565b60008481526008602052604090206111ea90613a36565b821061122c5760405162461bcd60e51b81526020600482015260116024820152700e8de92dcc8caf0407c7a40d8cadccee8d607b1b604482015260640161087e565b61123683836159ac565b6112419060016159c3565b6001600160401b0381111561125857611258615824565b604051908082528060200260200182016040528015611281578160200160208202803683370190505b509050825b8281116112db5760008581526008602052604090206112a59082613a40565b826112b086846159ac565b815181106112c0576112c0615738565b60209081029190910101526112d481615764565b9050611286565b509392505050565b6001546001600160a01b0316331461130d5760405162461bcd60e51b815260040161087e90615715565b600b80548215156101000261ff00199091161790556040517f294aa6bf970997b8c55a069e787eae16138f63ad315362696337d14ef42281ea9061135690831515815260200190565b60405180910390a150565b600260005414156113845760405162461bcd60e51b815260040161087e9061577f565b60026000819055506113ca600083838080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250613a53915050565b50506001600055565b6001546001600160a01b031633146113fd5760405162461bcd60e51b815260040161087e90615715565b828180821461141e5760405162461bcd60e51b815260040161087e906157b6565b60005b858110156114fe5761147287878381811061143e5761143e615738565b905060200201602081019061145391906151e7565b3387878581811061146657611466615738565b90506020020135613eda565b84848281811061148457611484615738565b905060200201357f4042b7789d1f6c4d5a798b447cfb918e82b64dd68b81d78ddc4dd1944ba5c51c8888848181106114be576114be615738565b90506020020160208101906114d391906151e7565b6040516001600160a01b03909116815260200160405180910390a26114f781615764565b9050611421565b50505050505050565b6002600054141561152a5760405162461bcd60e51b815260040161087e9061577f565b600260005582818082146115505760405162461bcd60e51b815260040161087e906157b6565b86600454116115715760405162461bcd60e51b815260040161087e90615966565b60005b858110156115c9576115b987878381811061159157611591615738565b90506020020135898787858181106115ab576115ab615738565b905060200201356001613faa565b6115c281615764565b9050611574565b50506001600055505050505050565b600b54610100900460ff166115ff5760405162461bcd60e51b815260040161087e906159db565b600260005414156116225760405162461bcd60e51b815260040161087e9061577f565b600260008190555061166a8383838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613a53915050565b5050600160005550565b6001546001600160a01b0316331461169e5760405162461bcd60e51b815260040161087e90615715565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915591519182527f2ee52be9d342458b3d25e07faada7ff9bc06723b4aa24edb6321ac1316b8a9dd910160405180910390a25050565b60008181526008602052604081206060919061171890613a36565b9050806001600160401b0381111561173257611732615824565b60405190808252806020026020018201604052801561175b578160200160208202803683370190505b50915060005b818110156117ae5760008481526008602052604090206117819082613a40565b83828151811061179357611793615738565b60209081029190910101526117a781615764565b9050611761565b5050919050565b6001546001600160a01b031633146117df5760405162461bcd60e51b815260040161087e90615715565b6001600160a01b0381166118055760405162461bcd60e51b815260040161087e90615715565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fda7b0a7bc965abdec8a1a995575a891838264c2968e14bd456c5391827b7aa3090600090a250565b6001546001600160a01b031633146118795760405162461bcd60e51b815260040161087e90615715565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f7b9adf13852d5b3e153f2a442b9aa3a4570da8f9b9046c60410b17e8034fe33c90602001611356565b3360009081526002602052604090205460ff166118f65760405162461bcd60e51b815260040161087e90615715565b83828082146119175760405162461bcd60e51b815260040161087e906157b6565b4263ffffffff168963ffffffff161015801561193e57508863ffffffff168863ffffffff16115b6119835760405162461bcd60e51b8152602060048201526016602482015275616464506f6f6c3a20696e76616c69642074696d657360501b604482015260640161087e565b6000600454905060006005600083815260200190815260200160002090508b8160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8160000160146101000a81548163ffffffff021916908363ffffffff160217905550898160000160186101000a81548163ffffffff021916908363ffffffff1602179055506000816001018190555084816003018190555060005b88811015611ae3578160020160405180604001604052808c8c85818110611a4f57611a4f615738565b9050602002016020810190611a6491906151e7565b6001600160a01b031681526020018a8a85818110611a8457611a84615738565b60209081029290920135909252835460018082018655600095865294829020845160029092020180546001600160a01b0319166001600160a01b0390921691909117815592015191909201555080611adb81615764565b915050611a26565b5060048054906000611af483615764565b9091555050604080516001600160a01b038e16815263ffffffff8d811660208301528c168183015260608101879052905183917f251199ba7b3e7a12b779b3f606eaf369cecc0eac8bcbacaadcf08079e8c5940f919081900360800190a2505050505050505050505050565b60026000541415611b835760405162461bcd60e51b815260040161087e9061577f565b6002600090815533905b82811015611e2557816001600160a01b031660066000868685818110611bb557611bb5615738565b60209081029290920135835250810191909152604001600020546001600160a01b031614611c1b5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b611c4e60086000868685818110611c3457611c34615738565b905060200201358152602001908152602001600020613a36565b15611c9b5760405162461bcd60e51b815260206004820152601860248201527f77697468647261773a206e6f7420657869746564207965740000000000000000604482015260640161087e565b60066000858584818110611cb157611cb1615738565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560010155611d1a848483818110611cf357611cf3615738565b6001600160a01b0386166000908152600960209081526040909120939102013590506144c0565b611d2357600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd3084878786818110611d6657611d66615738565b905060200201356040518463ffffffff1660e01b8152600401611d8b93929190615a12565b600060405180830381600087803b158015611da557600080fd5b505af1158015611db9573d6000803e3d6000fd5b50505050838382818110611dcf57611dcf615738565b6040516001600160a01b038616815260209182029390930135927f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436492500160405180910390a2611e1e81615764565b9050611b8d565b505060016000555050565b6001546001600160a01b03163314611e5a5760405162461bcd60e51b815260040161087e90615715565b600b5460ff1615611e9d5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015260640161087e565b600b805460ff191660011790556040517f1d8c7af3ae0426053ea40080543aa1cbe5bea5cdb7a55888b4cca96eea0493e490600090a1565b6001600160a01b0381166000908152600960205260409020606090611ef9906144cc565b92915050565b60026000541415611f225760405162461bcd60e51b815260040161087e9061577f565b6002600055600b54610100900460ff16611f4e5760405162461bcd60e51b815260040161087e906159db565b804263ffffffff161115611f985760405162461bcd60e51b815260206004820152601160248201527018db185a5b5199594e88195e1c1a5c9959607a1b604482015260640161087e565b6000878790509050600080856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611fdc57600080fd5b505afa158015611ff0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120149190615a36565b866001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561204d57600080fd5b505afa158015612061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120859190615a36565b9150915060005b8381101561228d5733600660008d8d858181106120ab576120ab615738565b60209081029290920135835250810191909152604001600020546001600160a01b0316146121115760405162461bcd60e51b815260206004820152601360248201527231b630b4b6a332b29d103737ba1037bbb732b960691b604482015260640161087e565b60035460009081906001600160a01b0316626349fb7f00000000000000000000000000000000000000000000000000000000000000008f8f8781811061215957612159615738565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401604080518083038186803b1580156121a557600080fd5b505afa1580156121b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121dd9190615a53565b91509150846001600160a01b0316826001600160a01b03161480156122135750836001600160a01b0316816001600160a01b0316145b61225f5760405162461bcd60e51b815260206004820152601e60248201527f636c61696d4665653a20746f6b656e2070616972206e6f74206d617463680000604482015260640161087e565b6122838d8d8581811061227457612274615738565b905060200201358860016144d9565b505060010161208c565b5061229c82828a8a338a61464e565b505060016000555050505050505050565b600260005414156122d05760405162461bcd60e51b815260040161087e9061577f565b6002600055600b54610100900460ff166122fc5760405162461bcd60e51b815260040161087e906159db565b824263ffffffff1611156123525760405162461bcd60e51b815260206004820152601860248201527f72656d6f76654c69717569646974793a20657870697265640000000000000000604482015260640161087e565b6000878152600660205260409020546001600160a01b031633146123b85760405162461bcd60e51b815260206004820152601a60248201527f72656d6f76654c69717569646974793a206e6f74206f776e6572000000000000604482015260640161087e565b600354604051635c6d96a960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018a90526000921690635c6d96a99060440160206040518083038186803b15801561242557600080fd5b505afa158015612439573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245d919061598f565b6001600160801b031690506000876001600160801b031611801561248a575080876001600160801b031611155b6124e15760405162461bcd60e51b815260206004820152602260248201527f72656d6f76654c69717569646974793a20696e76616c6964206c697175696469604482015261747960f01b606482015260840161087e565b6124f46001600160801b038816826159ac565b6000898152600660209081526040808320600101849055600890915281209192509061251f906144cc565b905060005b81518110156125e35760008a81526007602052604081208351829085908590811061255157612551615738565b60200260200101518152602001908152602001600020600501549050600084821161257d576000612587565b61258785836159ac565b905080156125d9576125d98c8585815181106125a5576125a5615738565b602002602001015183896001600281106125c1576125c1615738565b6020020160208101906125d49190615429565b613faa565b5050600101612524565b50600354604051626349fb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018c90526000928392911690626349fb90604401604080518083038186803b15801561265157600080fd5b505afa158015612665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126899190615a53565b915091506126988b8b89614918565b6126a56020860186615429565b156126b6576126b68b8860006144d9565b6126c482828b8b338b61464e565b50506001600055505050505050505050565b600260005414156126f95760405162461bcd60e51b815260040161087e9061577f565b60026000908155600b54339160ff909116905b83811015612b0457826001600160a01b03166006600087878581811061273457612734615738565b60209081029290920135835250810191909152604001600020546001600160a01b03161461279a5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b6001600a60008787858181106127b2576127b2615738565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055506000612813600860008888868181106127f9576127f9615738565b9050602002013581526020019081526020016000206144cc565b905060005b81518110156128f057600082828151811061283557612835615738565b60209081029190910181015160008181526005909252604082206004018054600019019055915060079089898781811061287157612871615738565b602090810292909201358352508181019290925260409081016000908120848252909252812080546001600160801b0319168155906128b36001830182615077565b6128c1600283016000615077565b6128cf600383016000615077565b50600060048201819055600590910155506128e981615764565b9050612818565b506006600087878581811061290757612907615738565b60209081029290920135835250810191909152604001600090812080546001600160a01b03191681556001015582612a015761297586868481811061294e5761294e615738565b6001600160a01b0388166000908152600960209081526040909120939102013590506144c0565b61297e57600080fd5b60005b81518110156129ff57600082828151811061299e5761299e615738565b602002602001015190506129e581600860008b8b898181106129c2576129c2615738565b9050602002013581526020019081526020016000206144c090919063ffffffff16565b6129ee57600080fd5b506129f881615764565b9050612981565b505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd3086898987818110612a4457612a44615738565b905060200201356040518463ffffffff1660e01b8152600401612a6993929190615a12565b600060405180830381600087803b158015612a8357600080fd5b505af1158015612a97573d6000803e3d6000fd5b50505050858583818110612aad57612aad615738565b6040516001600160a01b038816815260209182029390930135927f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd969592500160405180910390a250612afd81615764565b905061270c565b50506001600055505050565b600081815260056020818152604080842086855260078352818520868652909252832091820154606092839291612b895760405162461bcd60e51b815260206004820152601b60248201527f67657455736572496e666f3a206e6f74206a6f696e6564207965740000000000604482015260640161087e565b60028201546001600160401b03811115612ba557612ba5615824565b604051908082528060200260200182016040528015612bce578160200160208202803683370190505b5060028301549094506001600160401b03811115612bee57612bee615824565b604051908082528060200260200182016040528015612c17578160200160208202803683370190505b5092506000612c268888612d81565b905060005b6002840154811015612d6f576000612c778460050154866002018481548110612c5657612c56615738565b906000526020600020906002020160010154856060015186608001516149b9565b90506000612cd382866003018581548110612c9457612c94615738565b9060005260206000200154612ca991906159c3565b8560400151876001018681548110612cc357612cc3615738565b90600052602060002001546149e4565b905080856002018481548110612ceb57612ceb615738565b9060005260206000200154612d0091906159c3565b888481518110612d1257612d12615738565b602002602001018181525050846001018381548110612d3357612d33615738565b9060005260206000200154878481518110612d5057612d50615738565b602002602001018181525050505080612d6890615764565b9050612c2b565b50816005015495505050509250925092565b612dc36040518060c0016040528060006001600160801b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000828152600560209081526040808320868452600783528184208685529092529182902060035482549351632106297960e11b8152929391926001600160a01b039182169263420c52f292612e42929116907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615a12565b60206040518083038186803b158015612e5a57600080fd5b505afa158015612e6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e92919061598f565b6001600160801b0316835260035482546040516339bb866b60e11b81526001600160a01b03928316926373770cd692612ef4929116907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615a12565b60206040518083038186803b158015612f0c57600080fd5b505afa158015612f20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f449190615a82565b6020840181905260048201546003840154612f60929190614a1b565b604084015281546001830154612f8e9163ffffffff600160a01b8204811692600160c01b9092041690614a64565b6060840152805483516001600160801b03918216900316608084018190526005820154612fbb9190615a9b565b60a084015250909392505050565b8060045411612fea5760405162461bcd60e51b815260040161087e90615966565b60008181526005602081815260408084208685526006835281852054600784528286208787529093529320918201546001600160a01b0390911691906130725760405162461bcd60e51b815260206004820152601760248201527f686172766573743a206e6f74206a6f696e656420796574000000000000000000604482015260640161087e565b600061307e8686612d81565b90508060a0015184600101600082825461309891906159c3565b9091555050805182546001600160801b0319166001600160801b0390911617825560005b60028501548110156114fe5760006130e78460050154876002018481548110612c5657612c56615738565b90508015613161578084600301838154811061310557613105615738565b90600052602060002001600082825461311e91906159c3565b925050819055508086600201838154811061313b5761313b615738565b9060005260206000209060020201600101600082825461315b91906159ac565b90915550505b60006131a085600301848154811061317b5761317b615738565b90600052602060002001548560400151876001018681548110612cc357612cc3615738565b90506000818660020185815481106131ba576131ba615738565b90600052602060002001546131cf91906159c3565b905080156132ef57811561321257818660010185815481106131f3576131f3615738565b90600052602060002001600082825461320c91906159c3565b90915550505b600086600201858154811061322957613229615738565b906000526020600020018190555061327088600201858154811061324f5761324f615738565b60009182526020909120600290910201546001600160a01b03168883613eda565b808a7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd26703898b60020188815481106132a9576132a9615738565b60009182526020909120600290910201546040516132e692916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a35b505050806132fc90615764565b90506130bc565b600084815260066020908152604080832060078352818420878552909252918290206003548454935163d7aee3bd60e01b8152929391926001600160a01b039182169263d7aee3bd9261337f929116907f0000000000000000000000000000000000000000000000000000000000000000908b90600401615a12565b60206040518083038186803b15801561339757600080fd5b505afa1580156133ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cf9190615aba565b6134105760405162461bcd60e51b81526020600482015260126024820152711a9bda5b8e881a5b9d985b1a59081c1bdbdb60721b604482015260640161087e565b8315801590613423575081600101548411155b6134635760405162461bcd60e51b81526020600482015260116024820152706a6f696e3a20696e76616c6964206c697160781b604482015260640161087e565b6003548354604051632106297960e11b81526001600160a01b039283169263420c52f2926134ba929116907f0000000000000000000000000000000000000000000000000000000000000000908b90600401615a12565b60206040518083038186803b1580156134d257600080fd5b505afa1580156134e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061350a919061598f565b81546001600160801b0319166001600160801b039190911617815560028301546001600160401b0381111561354157613541615824565b60405190808252806020026020018201604052801561356a578160200160208202803683370190505b508051613581916001840191602090910190615098565b5060028301546001600160401b0381111561359e5761359e615824565b6040519080825280602002602001820160405280156135c7578160200160208202803683370190505b5080516135de916002840191602090910190615098565b5060028301546001600160401b038111156135fb576135fb615824565b604051908082528060200260200182016040528015613624578160200160208202803683370190505b50805161363b916003840191602090910190615098565b506003830154156136f05760035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018990529091169063a51dc8f29060440160206040518083038186803b1580156136b257600080fd5b505afa1580156136c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ea9190615a82565b60048201555b6005810184905560048301805490600061370983615764565b909155505060008681526008602052604090206137269086614ab8565b6137725760405162461bcd60e51b815260206004820152601760248201527f4661696c20746f20616464206a6f696e6564506f6f6c73000000000000000000604482015260640161087e565b8385877f5d48292d83151281e6ea967de9fd35716c713dc76c11beb42d78ed5110270f7360405160405180910390a4505050505050565b60008481526006602090815260408083206007835281842087855290925290912083158015906137eb5750600182015460058201546137e890866159c3565b11155b61382b5760405162461bcd60e51b815260206004820152601160248201527073796e633a20696e76616c6964206c697160781b604482015260640161087e565b60006138378787612d81565b905060005b60028501548110156139815760006138678460050154876002018481548110612c5657612c56615738565b905080156138e1578084600301838154811061388557613885615738565b90600052602060002001600082825461389e91906159c3565b92505081905550808660020183815481106138bb576138bb615738565b906000526020600020906002020160010160008282546138db91906159ac565b90915550505b60006138fb85600301848154811061317b5761317b615738565b9050801561396e578085600101848154811061391957613919615738565b90600052602060002001600082825461393291906159c3565b925050819055508085600201848154811061394f5761394f615738565b90600052602060002001600082825461396891906159c3565b90915550505b50508061397a90615764565b905061383c565b508060a0015184600101600082825461399a91906159c3565b9091555050805182546001600160801b0319166001600160801b0390911617825560048201546020820151600386015460058501546139dd93929190898c614ac4565b8260040181905550848260050160008282546139f991906159c3565b90915550506040518590879089907ff31cd5db84a4ab16cd339c510d5a60c63ef5818c538aa67046f5bc0dca794cd390600090a450505050505050565b6000611ef9825490565b6000613a4c8383614be6565b9392505050565b600b5460ff1615613a9f5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b8015613b51578260045411613ac65760405162461bcd60e51b815260040161087e90615966565b600083815260056020526040902054429063ffffffff808316600160a01b9092041611801590613b14575060008481526005602052604090205463ffffffff600160c01b9091048116908216105b613b4f5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b505b3360005b8351811015613ed357600a6000858381518110613b7457613b74615738565b60209081029190910181015182528101919091526040016000205460ff1615613bd85760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b613c28848281518110613bed57613bed615738565b602002602001015160096000856001600160a01b03166001600160a01b03168152602001908152602001600020614ab890919063ffffffff16565b613c3157600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd8330878581518110613c7457613c74615738565b60200260200101516040518463ffffffff1660e01b8152600401613c9a93929190615a12565b600060405180830381600087803b158015613cb457600080fd5b505af1158015613cc8573d6000803e3d6000fd5b50505050838181518110613cde57613cde615738565b60200260200101517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c83604051613d2491906001600160a01b0391909116815260200190565b60405180910390a28160066000868481518110613d4357613d43615738565b6020908102919091018101518252810191909152604001600090812080546001600160a01b0319166001600160a01b03938416179055600354865191921690635c6d96a9907f000000000000000000000000000000000000000000000000000000000000000090889086908110613dbc57613dbc615738565b60200260200101516040518363ffffffff1660e01b8152600401613df59291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613e0d57600080fd5b505afa158015613e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e45919061598f565b9050806001600160801b031660066000878581518110613e6757613e67615738565b60200260200101518152602001908152602001600020600101819055508315613eca57613eca858381518110613e9f57613e9f615738565b602002602001015187836001600160801b0316600560008b8152602001908152602001600020613303565b50600101613b55565b5050505050565b6001600160a01b038316613f91576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613f35576040519150601f19603f3d011682016040523d82523d6000602084013e613f3a565b606091505b5050905080613f8b5760405162461bcd60e51b815260206004820152601c60248201527f7472616e736665722072657761726420746f6b656e206661696c656400000000604482015260640161087e565b50505050565b613fa56001600160a01b0384168383614c10565b505050565b600083815260056020908152604080832087845260068352818420546007845282852088865290935292206001600160a01b03909116903382148061401c57508254600160c01b900463ffffffff164263ffffffff1611801561401c57503360009081526002602052604090205460ff165b6140725760405162461bcd60e51b815260206004820152602160248201527f657869743a206e6f74206f776e6572206f7220706f6f6c206e6f7420656e64656044820152601960fa1b606482015260840161087e565b600581015485158015906140865750808611155b6140c65760405162461bcd60e51b8152602060048201526011602482015270657869743a20696e76616c6964206c697160781b604482015260640161087e565b60006140d287836159ac565b905060006140e08a8a612d81565b90508060a001518660010160008282546140fa91906159c3565b9091555050805184546001600160801b0319166001600160801b039091161784556005840182905560005b600287015481101561439957600061414c85896002018481548110612c5657612c56615738565b905080156141c6578086600301838154811061416a5761416a615738565b90600052602060002001600082825461418391906159c3565b92505081905550808860020183815481106141a0576141a0615738565b906000526020600020906002020160010160008282546141c091906159ac565b90915550505b60006142058760030184815481106141e0576141e0615738565b90600052602060002001548560400151896001018681548110612cc357612cc3615738565b9050600087600201848154811061421e5761421e615738565b9060005260206000200154905081600014614275578188600101858154811061424957614249615738565b90600052602060002001600082825461426291906159c3565b90915550614272905082826159c3565b90505b8015614385578a1561436257600088600201858154811061429857614298615738565b90600052602060002001819055506142df8a60020185815481106142be576142be615738565b60009182526020909120600290910201546001600160a01b03168a83613eda565b808e7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd267038b8d600201888154811061431857614318615738565b600091825260209091206002909102015460405161435592916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a3614385565b8088600201858154811061437857614378615738565b6000918252602090912001555b5050508061439290615764565b9050614125565b508161447b5760008a81526007602090815260408083208c8452909152812080546001600160801b0319168155906143d46001830182615077565b6143e2600283016000615077565b6143f0600383016000615077565b5060006004828101829055600590920181905590870180549161441283615ad7565b909155505060008a815260086020526040902061442f908a6144c0565b61447b5760405162461bcd60e51b815260206004820152601a60248201527f4661696c20746f2072656d6f7665206a6f696e6564506f6f6c73000000000000604482015260640161087e565b60405133815288908a908c907f275029c7b988945c03ac5499c0d532fce79ce36efab42e1b3f180a62001cad2c9060200160405180910390a450505050505050505050565b6000613a4c8383614c62565b60606000613a4c83614d55565b801561457b57604051630c479e6560e21b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063311e799490602401602060405180830381600087803b15801561454157600080fd5b505af1158015614555573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145799190615a82565b505b60408051608081018252848152600060208201818152828401918252606083018681529351637686c6e960e11b815283516004820152905160248201529051604482015291516064830152907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ed0d8dd2906084015b606060405180830381600087803b15801561461657600080fd5b505af115801561462a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fe9190615aee565b7f0000000000000000000000000000000000000000000000000000000000000000811561484a57866001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614156147795760405163bac37ef760e01b8152600481018690526001600160a01b03848116602483015282169063bac37ef790604401600060405180830381600087803b1580156146f957600080fd5b505af115801561470d573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c1915061474190899088908890600401615b1c565b600060405180830381600087803b15801561475b57600080fd5b505af115801561476f573d6000803e3d6000fd5b5050505050614910565b856001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316141561484a5760405163bf1316c160e01b81526001600160a01b0382169063bf1316c1906147e3908a9089908890600401615b1c565b600060405180830381600087803b1580156147fd57600080fd5b505af1158015614811573d6000803e3d6000fd5b505060405163bac37ef760e01b8152600481018790526001600160a01b0386811660248301528416925063bac37ef79150604401614741565b60405163bf1316c160e01b81526001600160a01b0382169063bf1316c19061487a908a9089908890600401615b1c565b600060405180830381600087803b15801561489457600080fd5b505af11580156148a8573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c191506148dc90899088908890600401615b1c565b600060405180830381600087803b1580156148f657600080fd5b505af115801561490a573d6000803e3d6000fd5b50505050505b505050505050565b6040805160a0810182528481526001600160801b03848116602083019081526000838501818152606085019182526080850187815295516398e04d7760e01b81528551600482015292519093166024830152915160448201529051606482015291516084830152907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906398e04d779060a4016145fc565b600082826149c78688615a9b565b6149d19190615a9b565b6149db9190615b55565b95945050505050565b60008064e8d4a510006149f78587615a9b565b614a019190615b55565b9050828111614a115760006149db565b6149db83826159ac565b600081614a2e575064e8d4a51000613a4c565b6000614a3a8486615b69565b90506149db83614a4f64e8d4a5100084615a9b565b614a599190615b55565b64e8d4a51000614db1565b60008084614a784263ffffffff1686614dc7565b614a8291906159ac565b90506000614a9482600160601b615a9b565b9050838111614aa4576000614aae565b614aae84826159ac565b9695505050505050565b6000613a4c8383614dde565b600084614ad357506000614aae565b600087614ae08789615b69565b12614af457614aef8688615b69565b614af6565b875b60035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018790529293506000929091169063a51dc8f29060440160206040518083038186803b158015614b6857600080fd5b505afa158015614b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ba09190615a82565b614baa9086615ba8565b614bb48388615ba8565b614bbe9190615c2d565b90506000614bcc86886159c3565b9050614bd88183615c6e565b9a9950505050505050505050565b6000826000018281548110614bfd57614bfd615738565b9060005260206000200154905092915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613fa5908490614e2d565b60008181526001830160205260408120548015614d4b576000614c866001836159ac565b8554909150600090614c9a906001906159ac565b9050818114614cff576000866000018281548110614cba57614cba615738565b9060005260206000200154905080876000018481548110614cdd57614cdd615738565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614d1057614d10615c9c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ef9565b6000915050611ef9565b606081600001805480602002602001604051908101604052809291908181526020018280548015614da557602002820191906000526020600020905b815481526020019060010190808311614d91575b50505050509050919050565b600081831015614dc15782613a4c565b50919050565b600081831015614dd75781613a4c565b5090919050565b6000818152600183016020526040812054614e2557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ef9565b506000611ef9565b6000614e82826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614eff9092919063ffffffff16565b805190915015613fa55780806020019051810190614ea09190615aba565b613fa55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161087e565b6060614f0e8484600085614f16565b949350505050565b606082471015614f775760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161087e565b843b614fc55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161087e565b600080866001600160a01b03168587604051614fe19190615cde565b60006040518083038185875af1925050503d806000811461501e576040519150601f19603f3d011682016040523d82523d6000602084013e615023565b606091505b509150915061503382828661503e565b979650505050505050565b6060831561504d575081613a4c565b82511561505d5782518084602001fd5b8160405162461bcd60e51b815260040161087e9190615cfa565b508054600082559060005260206000209081019061509591906150e3565b50565b8280548282559060005260206000209081019282156150d3579160200282015b828111156150d35782518255916020019190600101906150b8565b506150df9291506150e3565b5090565b5b808211156150df57600081556001016150e4565b803563ffffffff8116811461510c57600080fd5b919050565b60008083601f84011261512357600080fd5b5081356001600160401b0381111561513a57600080fd5b6020830191508360208260051b850101111561515557600080fd5b9250929050565b60008060008060008060a0878903121561517557600080fd5b86359550615185602088016150f8565b9450615193604088016150f8565b935060608701356001600160401b038111156151ae57600080fd5b6151ba89828a01615111565b979a9699509497949695608090950135949350505050565b6001600160a01b038116811461509557600080fd5b6000602082840312156151f957600080fd5b8135613a4c816151d2565b6000806000806040858703121561521a57600080fd5b84356001600160401b038082111561523157600080fd5b61523d88838901615111565b9096509450602087013591508082111561525657600080fd5b5061526387828801615111565b95989497509550505050565b60006020828403121561528157600080fd5b5035919050565b600081518084526020808501945080840160005b838110156152b85781518752958201959082019060010161529c565b509495945050505050565b6001600160a01b03898116825263ffffffff8981166020808501919091529089166040840152606083018890526080830187905260a0830186905261010060c08401819052855190840181905260009261012085019287810192855b8181101561533d57845184168652948201949382019360010161531f565b505050505082810360e08401526153548185615288565b9b9a5050505050505050505050565b60008060008060006060868803121561537b57600080fd5b8535945060208601356001600160401b038082111561539957600080fd5b6153a589838a01615111565b909650945060408801359150808211156153be57600080fd5b506153cb88828901615111565b969995985093965092949392505050565b6000806000606084860312156153f157600080fd5b505081359360208301359350604090920135919050565b602081526000613a4c6020830184615288565b801515811461509557600080fd5b60006020828403121561543b57600080fd5b8135613a4c8161541b565b6000806020838503121561545957600080fd5b82356001600160401b0381111561546f57600080fd5b61547b85828601615111565b90969095509350505050565b60008060006040848603121561549c57600080fd5b8335925060208401356001600160401b038111156154b957600080fd5b6154c586828701615111565b9497909650939450505050565b600080604083850312156154e557600080fd5b82356154f0816151d2565b915060208301356155008161541b565b809150509250929050565b60008060008060008060008060c0898b03121561552757600080fd5b8835615532816151d2565b975061554060208a016150f8565b965061554e60408a016150f8565b955060608901356001600160401b038082111561556a57600080fd5b6155768c838d01615111565b909750955060808b013591508082111561558f57600080fd5b5061559c8b828c01615111565b999c989b50969995989497949560a00135949350505050565b600080604083850312156155c857600080fd5b50508035926020909101359150565b600080600080600080600060c0888a0312156155f257600080fd5b87356001600160401b0381111561560857600080fd5b6156148a828b01615111565b90985096505060208801359450604088013593506060880135615636816151d2565b925060808801356156468161541b565b8092505060a0880135905092959891949750929550565b6001600160801b038116811461509557600080fd5b600080600080600080600061010080898b03121561568f57600080fd5b8835975060208901356156a18161565d565b965060408901359550606089013594506080890135935060a08901356156c68161541b565b92508881018a10156156d757600080fd5b5060c08801905092959891949750929550565b8381526060602082015260006157036060830185615288565b8281036040840152614aae8185615288565b6020808252600990820152683337b93134b23232b760b91b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156157785761577861574e565b5060010190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600e908201526d0d2dcecc2d8d2c840d8cadccee8d60931b604082015260600190565b6000808335601e198436030181126157f557600080fd5b8301803591506001600160401b0382111561580f57600080fd5b60200191503681900382131561515557600080fd5b634e487b7160e01b600052604160045260246000fd5b604051602081016001600160401b038111828210171561585c5761585c615824565b60405290565b604051601f8201601f191681016001600160401b038111828210171561588a5761588a615824565b604052919050565b600060208083850312156158a557600080fd5b82356001600160401b03808211156158bc57600080fd5b81850191508282870312156158d057600080fd5b6158d861583a565b8235828111156158e757600080fd5b80840193505086601f8401126158fc57600080fd5b82358281111561590e5761590e615824565b8060051b925061591f858401615862565b818152928401850192858101908985111561593957600080fd5b948601945b848610156159575785358252948601949086019061593e565b83525090979650505050505050565b6020808252600f908201526e506f6f6c206e6f742065786973747360881b604082015260600190565b6000602082840312156159a157600080fd5b8151613a4c8161565d565b6000828210156159be576159be61574e565b500390565b600082198211156159d6576159d661574e565b500190565b60208082526018908201527f7370656369616c20666561747572652064697361626c65640000000000000000604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060208284031215615a4857600080fd5b8151613a4c816151d2565b60008060408385031215615a6657600080fd5b8251615a71816151d2565b6020840151909250615500816151d2565b600060208284031215615a9457600080fd5b5051919050565b6000816000190483118215151615615ab557615ab561574e565b500290565b600060208284031215615acc57600080fd5b8151613a4c8161541b565b600081615ae657615ae661574e565b506000190190565b600080600060608486031215615b0357600080fd5b8351925060208401519150604084015190509250925092565b6001600160a01b0393841681526020810192909252909116604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082615b6457615b64615b3f565b500490565b60008083128015600160ff1b850184121615615b8757615b8761574e565b6001600160ff1b0384018313811615615ba257615ba261574e565b50500390565b60006001600160ff1b0381841382841380821686840486111615615bce57615bce61574e565b600160ff1b6000871282811687830589121615615bed57615bed61574e565b60008712925087820587128484161615615c0957615c0961574e565b87850587128184161615615c1f57615c1f61574e565b505050929093029392505050565b600080821280156001600160ff1b0384900385131615615c4f57615c4f61574e565b600160ff1b8390038412811615615c6857615c6861574e565b50500190565b600082615c7d57615c7d615b3f565b600160ff1b821460001984141615615c9757615c9761574e565b500590565b634e487b7160e01b600052603160045260246000fd5b60005b83811015615ccd578181015183820152602001615cb5565b83811115613f8b5750506000910152565b60008251615cf0818460208701615cb2565b9190910192915050565b6020815260008251806020840152615d19816040850160208701615cb2565b601f01601f1916919091016040019291505056fea164736f6c6343000809000a000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48000000000000000000000000035be3f4fd8239a35a7f120756d4d69e5c5e10870
Deployed Bytecode
0x6080604052600436106101fd5760003560e01c806375829def1161010d578063b36b26c5116100a0578063c7ca58701161006f578063c7ca58701461074b578063d1941b061461076b578063dc168a921461078b578063e7762a0c146107ba578063f851a4401461082f57600080fd5b8063b36b26c5146106bc578063b63ff916146106dc578063b82562751461070c578063bb5ae7751461072c57600080fd5b806399fbab88116100dc57806399fbab881461052f578063ac4afa381461058e578063affe737914610631578063b221e5fd1461064657600080fd5b806375829def146104af5780638bcc4166146104cf57806391fb2f15146104ef578063983d95ce1461050f57600080fd5b806347ccca021161019057806361657b121161015f57806361657b121461040f57806366b5a6641461042f578063683f3eda1461044f5780636d44a3b21461046f578063705b5bef1461048f57600080fd5b806347ccca021461036e57806349b35168146103a257806350523cea146103cf578063598b8e71146103ef57600080fd5b80632f380b35116101cc5780632f380b35146102b45780633fc8cef3146102e857806341e817ab14610334578063430ccd9b1461035457600080fd5b8063078ded5d14610209578063081e3eda1461022b57806313e7c9d814610254578063180f80361461029457600080fd5b3661020457005b600080fd5b34801561021557600080fd5b5061022961022436600461515c565b61084f565b005b34801561023757600080fd5b5061024160045481565b6040519081526020015b60405180910390f35b34801561026057600080fd5b5061028461026f3660046151e7565b60026020526000908152604090205460ff1681565b604051901515815260200161024b565b3480156102a057600080fd5b506102296102af366004615204565b610b0b565b3480156102c057600080fd5b506102d46102cf36600461526f565b610c8d565b60405161024b9897969594939291906152c3565b3480156102f457600080fd5b5061031c7f000000000000000000000000420000000000000000000000000000000000000681565b6040516001600160a01b03909116815260200161024b565b34801561034057600080fd5b5061022961034f366004615363565b610e37565b34801561036057600080fd5b50600b546102849060ff1681565b34801561037a57600080fd5b5061031c7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081565b3480156103ae57600080fd5b506103c26103bd3660046153dc565b61118b565b60405161024b9190615408565b3480156103db57600080fd5b506102296103ea366004615429565b6112e3565b3480156103fb57600080fd5b5061022961040a366004615446565b611361565b34801561041b57600080fd5b5061022961042a366004615204565b6113d3565b34801561043b57600080fd5b5061022961044a366004615363565b611507565b34801561045b57600080fd5b5061022961046a366004615487565b6115d8565b34801561047b57600080fd5b5061022961048a3660046154d2565b611674565b34801561049b57600080fd5b506103c26104aa36600461526f565b6116fd565b3480156104bb57600080fd5b506102296104ca3660046151e7565b6117b5565b3480156104db57600080fd5b506102296104ea3660046151e7565b61184f565b3480156104fb57600080fd5b5061022961050a36600461550b565b6118c7565b34801561051b57600080fd5b5061022961052a366004615446565b611b60565b34801561053b57600080fd5b5061056f61054a36600461526f565b600660205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161024b565b34801561059a57600080fd5b506105f06105a936600461526f565b60056020526000908152604090208054600182015460038301546004909301546001600160a01b0383169363ffffffff600160a01b8504811694600160c01b900416929186565b604080516001600160a01b0397909716875263ffffffff958616602088015293909416928501929092526060840152608083015260a082015260c00161024b565b34801561063d57600080fd5b50610229611e30565b34801561065257600080fd5b506106976106613660046155b5565b60076020908152600092835260408084209091529082529020805460048201546005909201546001600160801b03909116919083565b604080516001600160801b03909416845260208401929092529082015260600161024b565b3480156106c857600080fd5b506103c26106d73660046151e7565b611ed5565b3480156106e857600080fd5b506102846106f736600461526f565b600a6020526000908152604090205460ff1681565b34801561071857600080fd5b506102296107273660046155d7565b611eff565b34801561073857600080fd5b50600b5461028490610100900460ff1681565b34801561075757600080fd5b50610229610766366004615672565b6122ad565b34801561077757600080fd5b50610229610786366004615446565b6126d6565b34801561079757600080fd5b506107ab6107a63660046155b5565b612b10565b60405161024b939291906156ea565b3480156107c657600080fd5b506107da6107d53660046155b5565b612d81565b60405161024b9190600060c0820190506001600160801b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561083b57600080fd5b5060015461031c906001600160a01b031681565b3360009081526002602052604090205460ff166108875760405162461bcd60e51b815260040161087e90615715565b60405180910390fd5b6000868152600560205260409020805463ffffffff428116600160a01b9092041611806108c45750805463ffffffff428116600160c01b90920416105b6109105760405162461bcd60e51b815260206004820152601960248201527f72656e65773a20696e76616c696420706f6f6c20737461746500000000000000604482015260640161087e565b6002810154831461095b5760405162461bcd60e51b81526020600482015260156024820152740e4cadccaee7440d2dcecc2d8d2c840d8cadccee8d605b1b604482015260640161087e565b4263ffffffff168663ffffffff1611801561098157508563ffffffff168563ffffffff16115b6109c45760405162461bcd60e51b815260206004820152601460248201527372656e65773a20696e76616c69642074696d657360601b604482015260640161087e565b600481015415610a0f5760405162461bcd60e51b815260206004820152601660248201527572656e65773a20706f6f6c20686173207374616b657360501b604482015260640161087e565b805463ffffffff868116600160c01b0263ffffffff60c01b19918916600160a01b029190911667ffffffffffffffff60a01b1990921691909117178155600060018201819055600382018390555b83811015610ab757848482818110610a7757610a77615738565b90506020020135826002018281548110610a9357610a93615738565b6000918252602090912060016002909202010155610ab081615764565b9050610a5d565b506040805163ffffffff80891682528716602082015290810183905287907feda7bcc7e20158ff9fa87a4200758e927bbb3c8823e648403bdd6053b96dd0ad9060600160405180910390a250505050505050565b60026000541415610b2e5760405162461bcd60e51b815260040161087e9061577f565b60026000558281808214610b545760405162461bcd60e51b815260040161087e906157b6565b60005b85811015610c7f573360066000898985818110610b7657610b76615738565b60209081029290920135835250810191909152604001600020546001600160a01b031614610bdb5760405162461bcd60e51b81526020600482015260126024820152713430b93b32b9ba1d103737ba1037bbb732b960711b604482015260640161087e565b6000858583818110610bef57610bef615738565b9050602002810190610c0191906157de565b810190610c0e9190615892565b905060005b815151811015610c6c57610c5c898985818110610c3257610c32615738565b9050602002013583600001518381518110610c4f57610c4f615738565b6020026020010151612fc9565b610c6581615764565b9050610c13565b505080610c7890615764565b9050610b57565b505060016000555050505050565b6000818152600560205260409020805460018201546003830154600484015460028501546001600160a01b0385169563ffffffff600160a01b8704811696600160c01b900416949392916060918291806001600160401b03811115610cf457610cf4615824565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b509350806001600160401b03811115610d3857610d38615824565b604051908082528060200260200182016040528015610d61578160200160208202803683370190505b50925060005b81811015610e2957826002018181548110610d8457610d84615738565b600091825260209091206002909102015485516001600160a01b0390911690869083908110610db557610db5615738565b60200260200101906001600160a01b031690816001600160a01b031681525050826002018181548110610dea57610dea615738565b906000526020600020906002020160010154848281518110610e0e57610e0e615738565b6020908102919091010152610e2281615764565b9050610d67565b505050919395975091939597565b60026000541415610e5a5760405162461bcd60e51b815260040161087e9061577f565b60026000558281808214610e805760405162461bcd60e51b815260040161087e906157b6565b8660045411610ea15760405162461bcd60e51b815260040161087e90615966565b6000878152600560205260409020805463ffffffff428116600160a01b9092041611801590610ee357508054600160c01b900463ffffffff164263ffffffff16105b610f1e5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b60005b8681101561117b5733600660008a8a85818110610f4057610f40615738565b60209081029290920135835250810191909152604001600020546001600160a01b031614610f9c5760405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b604482015260640161087e565b6003546001600160a01b0316635c6d96a97f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4808a8a85818110610fe057610fe0615738565b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160206040518083038186803b15801561102d57600080fd5b505afa158015611041573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611065919061598f565b6001600160801b0316600660008a8a8581811061108457611084615738565b905060200201358152602001908152602001600020600101819055506000600760008a8a858181106110b8576110b8615738565b90506020020135815260200190815260200160002060008b8152602001908152602001600020905080600501546000141561112e5761112989898481811061110257611102615738565b905060200201358b89898681811061111c5761111c615738565b9050602002013586613303565b61116a565b61116a89898481811061114357611143615738565b905060200201358b89898681811061115d5761115d615738565b90506020020135866137a9565b5061117481615764565b9050610f21565b5050600160005550505050505050565b6060818311156111d35760405162461bcd60e51b81526020600482015260136024820152720cce4deda92dcc8caf0407c40e8de92dcc8caf606b1b604482015260640161087e565b60008481526008602052604090206111ea90613a36565b821061122c5760405162461bcd60e51b81526020600482015260116024820152700e8de92dcc8caf0407c7a40d8cadccee8d607b1b604482015260640161087e565b61123683836159ac565b6112419060016159c3565b6001600160401b0381111561125857611258615824565b604051908082528060200260200182016040528015611281578160200160208202803683370190505b509050825b8281116112db5760008581526008602052604090206112a59082613a40565b826112b086846159ac565b815181106112c0576112c0615738565b60209081029190910101526112d481615764565b9050611286565b509392505050565b6001546001600160a01b0316331461130d5760405162461bcd60e51b815260040161087e90615715565b600b80548215156101000261ff00199091161790556040517f294aa6bf970997b8c55a069e787eae16138f63ad315362696337d14ef42281ea9061135690831515815260200190565b60405180910390a150565b600260005414156113845760405162461bcd60e51b815260040161087e9061577f565b60026000819055506113ca600083838080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250613a53915050565b50506001600055565b6001546001600160a01b031633146113fd5760405162461bcd60e51b815260040161087e90615715565b828180821461141e5760405162461bcd60e51b815260040161087e906157b6565b60005b858110156114fe5761147287878381811061143e5761143e615738565b905060200201602081019061145391906151e7565b3387878581811061146657611466615738565b90506020020135613eda565b84848281811061148457611484615738565b905060200201357f4042b7789d1f6c4d5a798b447cfb918e82b64dd68b81d78ddc4dd1944ba5c51c8888848181106114be576114be615738565b90506020020160208101906114d391906151e7565b6040516001600160a01b03909116815260200160405180910390a26114f781615764565b9050611421565b50505050505050565b6002600054141561152a5760405162461bcd60e51b815260040161087e9061577f565b600260005582818082146115505760405162461bcd60e51b815260040161087e906157b6565b86600454116115715760405162461bcd60e51b815260040161087e90615966565b60005b858110156115c9576115b987878381811061159157611591615738565b90506020020135898787858181106115ab576115ab615738565b905060200201356001613faa565b6115c281615764565b9050611574565b50506001600055505050505050565b600b54610100900460ff166115ff5760405162461bcd60e51b815260040161087e906159db565b600260005414156116225760405162461bcd60e51b815260040161087e9061577f565b600260008190555061166a8383838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613a53915050565b5050600160005550565b6001546001600160a01b0316331461169e5760405162461bcd60e51b815260040161087e90615715565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915591519182527f2ee52be9d342458b3d25e07faada7ff9bc06723b4aa24edb6321ac1316b8a9dd910160405180910390a25050565b60008181526008602052604081206060919061171890613a36565b9050806001600160401b0381111561173257611732615824565b60405190808252806020026020018201604052801561175b578160200160208202803683370190505b50915060005b818110156117ae5760008481526008602052604090206117819082613a40565b83828151811061179357611793615738565b60209081029190910101526117a781615764565b9050611761565b5050919050565b6001546001600160a01b031633146117df5760405162461bcd60e51b815260040161087e90615715565b6001600160a01b0381166118055760405162461bcd60e51b815260040161087e90615715565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fda7b0a7bc965abdec8a1a995575a891838264c2968e14bd456c5391827b7aa3090600090a250565b6001546001600160a01b031633146118795760405162461bcd60e51b815260040161087e90615715565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f7b9adf13852d5b3e153f2a442b9aa3a4570da8f9b9046c60410b17e8034fe33c90602001611356565b3360009081526002602052604090205460ff166118f65760405162461bcd60e51b815260040161087e90615715565b83828082146119175760405162461bcd60e51b815260040161087e906157b6565b4263ffffffff168963ffffffff161015801561193e57508863ffffffff168863ffffffff16115b6119835760405162461bcd60e51b8152602060048201526016602482015275616464506f6f6c3a20696e76616c69642074696d657360501b604482015260640161087e565b6000600454905060006005600083815260200190815260200160002090508b8160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8160000160146101000a81548163ffffffff021916908363ffffffff160217905550898160000160186101000a81548163ffffffff021916908363ffffffff1602179055506000816001018190555084816003018190555060005b88811015611ae3578160020160405180604001604052808c8c85818110611a4f57611a4f615738565b9050602002016020810190611a6491906151e7565b6001600160a01b031681526020018a8a85818110611a8457611a84615738565b60209081029290920135909252835460018082018655600095865294829020845160029092020180546001600160a01b0319166001600160a01b0390921691909117815592015191909201555080611adb81615764565b915050611a26565b5060048054906000611af483615764565b9091555050604080516001600160a01b038e16815263ffffffff8d811660208301528c168183015260608101879052905183917f251199ba7b3e7a12b779b3f606eaf369cecc0eac8bcbacaadcf08079e8c5940f919081900360800190a2505050505050505050505050565b60026000541415611b835760405162461bcd60e51b815260040161087e9061577f565b6002600090815533905b82811015611e2557816001600160a01b031660066000868685818110611bb557611bb5615738565b60209081029290920135835250810191909152604001600020546001600160a01b031614611c1b5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b611c4e60086000868685818110611c3457611c34615738565b905060200201358152602001908152602001600020613a36565b15611c9b5760405162461bcd60e51b815260206004820152601860248201527f77697468647261773a206e6f7420657869746564207965740000000000000000604482015260640161087e565b60066000858584818110611cb157611cb1615738565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560010155611d1a848483818110611cf357611cf3615738565b6001600160a01b0386166000908152600960209081526040909120939102013590506144c0565b611d2357600080fd5b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03166323b872dd3084878786818110611d6657611d66615738565b905060200201356040518463ffffffff1660e01b8152600401611d8b93929190615a12565b600060405180830381600087803b158015611da557600080fd5b505af1158015611db9573d6000803e3d6000fd5b50505050838382818110611dcf57611dcf615738565b6040516001600160a01b038616815260209182029390930135927f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436492500160405180910390a2611e1e81615764565b9050611b8d565b505060016000555050565b6001546001600160a01b03163314611e5a5760405162461bcd60e51b815260040161087e90615715565b600b5460ff1615611e9d5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015260640161087e565b600b805460ff191660011790556040517f1d8c7af3ae0426053ea40080543aa1cbe5bea5cdb7a55888b4cca96eea0493e490600090a1565b6001600160a01b0381166000908152600960205260409020606090611ef9906144cc565b92915050565b60026000541415611f225760405162461bcd60e51b815260040161087e9061577f565b6002600055600b54610100900460ff16611f4e5760405162461bcd60e51b815260040161087e906159db565b804263ffffffff161115611f985760405162461bcd60e51b815260206004820152601160248201527018db185a5b5199594e88195e1c1a5c9959607a1b604482015260640161087e565b6000878790509050600080856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611fdc57600080fd5b505afa158015611ff0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120149190615a36565b866001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561204d57600080fd5b505afa158015612061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120859190615a36565b9150915060005b8381101561228d5733600660008d8d858181106120ab576120ab615738565b60209081029290920135835250810191909152604001600020546001600160a01b0316146121115760405162461bcd60e51b815260206004820152601360248201527231b630b4b6a332b29d103737ba1037bbb732b960691b604482015260640161087e565b60035460009081906001600160a01b0316626349fb7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4808f8f8781811061215957612159615738565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401604080518083038186803b1580156121a557600080fd5b505afa1580156121b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121dd9190615a53565b91509150846001600160a01b0316826001600160a01b03161480156122135750836001600160a01b0316816001600160a01b0316145b61225f5760405162461bcd60e51b815260206004820152601e60248201527f636c61696d4665653a20746f6b656e2070616972206e6f74206d617463680000604482015260640161087e565b6122838d8d8581811061227457612274615738565b905060200201358860016144d9565b505060010161208c565b5061229c82828a8a338a61464e565b505060016000555050505050505050565b600260005414156122d05760405162461bcd60e51b815260040161087e9061577f565b6002600055600b54610100900460ff166122fc5760405162461bcd60e51b815260040161087e906159db565b824263ffffffff1611156123525760405162461bcd60e51b815260206004820152601860248201527f72656d6f76654c69717569646974793a20657870697265640000000000000000604482015260640161087e565b6000878152600660205260409020546001600160a01b031633146123b85760405162461bcd60e51b815260206004820152601a60248201527f72656d6f76654c69717569646974793a206e6f74206f776e6572000000000000604482015260640161087e565b600354604051635c6d96a960e01b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018a90526000921690635c6d96a99060440160206040518083038186803b15801561242557600080fd5b505afa158015612439573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245d919061598f565b6001600160801b031690506000876001600160801b031611801561248a575080876001600160801b031611155b6124e15760405162461bcd60e51b815260206004820152602260248201527f72656d6f76654c69717569646974793a20696e76616c6964206c697175696469604482015261747960f01b606482015260840161087e565b6124f46001600160801b038816826159ac565b6000898152600660209081526040808320600101849055600890915281209192509061251f906144cc565b905060005b81518110156125e35760008a81526007602052604081208351829085908590811061255157612551615738565b60200260200101518152602001908152602001600020600501549050600084821161257d576000612587565b61258785836159ac565b905080156125d9576125d98c8585815181106125a5576125a5615738565b602002602001015183896001600281106125c1576125c1615738565b6020020160208101906125d49190615429565b613faa565b5050600101612524565b50600354604051626349fb60e01b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018c90526000928392911690626349fb90604401604080518083038186803b15801561265157600080fd5b505afa158015612665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126899190615a53565b915091506126988b8b89614918565b6126a56020860186615429565b156126b6576126b68b8860006144d9565b6126c482828b8b338b61464e565b50506001600055505050505050505050565b600260005414156126f95760405162461bcd60e51b815260040161087e9061577f565b60026000908155600b54339160ff909116905b83811015612b0457826001600160a01b03166006600087878581811061273457612734615738565b60209081029290920135835250810191909152604001600020546001600160a01b03161461279a5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b6001600a60008787858181106127b2576127b2615738565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055506000612813600860008888868181106127f9576127f9615738565b9050602002013581526020019081526020016000206144cc565b905060005b81518110156128f057600082828151811061283557612835615738565b60209081029190910181015160008181526005909252604082206004018054600019019055915060079089898781811061287157612871615738565b602090810292909201358352508181019290925260409081016000908120848252909252812080546001600160801b0319168155906128b36001830182615077565b6128c1600283016000615077565b6128cf600383016000615077565b50600060048201819055600590910155506128e981615764565b9050612818565b506006600087878581811061290757612907615738565b60209081029290920135835250810191909152604001600090812080546001600160a01b03191681556001015582612a015761297586868481811061294e5761294e615738565b6001600160a01b0388166000908152600960209081526040909120939102013590506144c0565b61297e57600080fd5b60005b81518110156129ff57600082828151811061299e5761299e615738565b602002602001015190506129e581600860008b8b898181106129c2576129c2615738565b9050602002013581526020019081526020016000206144c090919063ffffffff16565b6129ee57600080fd5b506129f881615764565b9050612981565b505b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03166323b872dd3086898987818110612a4457612a44615738565b905060200201356040518463ffffffff1660e01b8152600401612a6993929190615a12565b600060405180830381600087803b158015612a8357600080fd5b505af1158015612a97573d6000803e3d6000fd5b50505050858583818110612aad57612aad615738565b6040516001600160a01b038816815260209182029390930135927f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd969592500160405180910390a250612afd81615764565b905061270c565b50506001600055505050565b600081815260056020818152604080842086855260078352818520868652909252832091820154606092839291612b895760405162461bcd60e51b815260206004820152601b60248201527f67657455736572496e666f3a206e6f74206a6f696e6564207965740000000000604482015260640161087e565b60028201546001600160401b03811115612ba557612ba5615824565b604051908082528060200260200182016040528015612bce578160200160208202803683370190505b5060028301549094506001600160401b03811115612bee57612bee615824565b604051908082528060200260200182016040528015612c17578160200160208202803683370190505b5092506000612c268888612d81565b905060005b6002840154811015612d6f576000612c778460050154866002018481548110612c5657612c56615738565b906000526020600020906002020160010154856060015186608001516149b9565b90506000612cd382866003018581548110612c9457612c94615738565b9060005260206000200154612ca991906159c3565b8560400151876001018681548110612cc357612cc3615738565b90600052602060002001546149e4565b905080856002018481548110612ceb57612ceb615738565b9060005260206000200154612d0091906159c3565b888481518110612d1257612d12615738565b602002602001018181525050846001018381548110612d3357612d33615738565b9060005260206000200154878481518110612d5057612d50615738565b602002602001018181525050505080612d6890615764565b9050612c2b565b50816005015495505050509250925092565b612dc36040518060c0016040528060006001600160801b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000828152600560209081526040808320868452600783528184208685529092529182902060035482549351632106297960e11b8152929391926001600160a01b039182169263420c52f292612e42929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908a90600401615a12565b60206040518083038186803b158015612e5a57600080fd5b505afa158015612e6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e92919061598f565b6001600160801b0316835260035482546040516339bb866b60e11b81526001600160a01b03928316926373770cd692612ef4929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908a90600401615a12565b60206040518083038186803b158015612f0c57600080fd5b505afa158015612f20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f449190615a82565b6020840181905260048201546003840154612f60929190614a1b565b604084015281546001830154612f8e9163ffffffff600160a01b8204811692600160c01b9092041690614a64565b6060840152805483516001600160801b03918216900316608084018190526005820154612fbb9190615a9b565b60a084015250909392505050565b8060045411612fea5760405162461bcd60e51b815260040161087e90615966565b60008181526005602081815260408084208685526006835281852054600784528286208787529093529320918201546001600160a01b0390911691906130725760405162461bcd60e51b815260206004820152601760248201527f686172766573743a206e6f74206a6f696e656420796574000000000000000000604482015260640161087e565b600061307e8686612d81565b90508060a0015184600101600082825461309891906159c3565b9091555050805182546001600160801b0319166001600160801b0390911617825560005b60028501548110156114fe5760006130e78460050154876002018481548110612c5657612c56615738565b90508015613161578084600301838154811061310557613105615738565b90600052602060002001600082825461311e91906159c3565b925050819055508086600201838154811061313b5761313b615738565b9060005260206000209060020201600101600082825461315b91906159ac565b90915550505b60006131a085600301848154811061317b5761317b615738565b90600052602060002001548560400151876001018681548110612cc357612cc3615738565b90506000818660020185815481106131ba576131ba615738565b90600052602060002001546131cf91906159c3565b905080156132ef57811561321257818660010185815481106131f3576131f3615738565b90600052602060002001600082825461320c91906159c3565b90915550505b600086600201858154811061322957613229615738565b906000526020600020018190555061327088600201858154811061324f5761324f615738565b60009182526020909120600290910201546001600160a01b03168883613eda565b808a7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd26703898b60020188815481106132a9576132a9615738565b60009182526020909120600290910201546040516132e692916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a35b505050806132fc90615764565b90506130bc565b600084815260066020908152604080832060078352818420878552909252918290206003548454935163d7aee3bd60e01b8152929391926001600160a01b039182169263d7aee3bd9261337f929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908b90600401615a12565b60206040518083038186803b15801561339757600080fd5b505afa1580156133ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cf9190615aba565b6134105760405162461bcd60e51b81526020600482015260126024820152711a9bda5b8e881a5b9d985b1a59081c1bdbdb60721b604482015260640161087e565b8315801590613423575081600101548411155b6134635760405162461bcd60e51b81526020600482015260116024820152706a6f696e3a20696e76616c6964206c697160781b604482015260640161087e565b6003548354604051632106297960e11b81526001600160a01b039283169263420c52f2926134ba929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908b90600401615a12565b60206040518083038186803b1580156134d257600080fd5b505afa1580156134e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061350a919061598f565b81546001600160801b0319166001600160801b039190911617815560028301546001600160401b0381111561354157613541615824565b60405190808252806020026020018201604052801561356a578160200160208202803683370190505b508051613581916001840191602090910190615098565b5060028301546001600160401b0381111561359e5761359e615824565b6040519080825280602002602001820160405280156135c7578160200160208202803683370190505b5080516135de916002840191602090910190615098565b5060028301546001600160401b038111156135fb576135fb615824565b604051908082528060200260200182016040528015613624578160200160208202803683370190505b50805161363b916003840191602090910190615098565b506003830154156136f05760035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018990529091169063a51dc8f29060440160206040518083038186803b1580156136b257600080fd5b505afa1580156136c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ea9190615a82565b60048201555b6005810184905560048301805490600061370983615764565b909155505060008681526008602052604090206137269086614ab8565b6137725760405162461bcd60e51b815260206004820152601760248201527f4661696c20746f20616464206a6f696e6564506f6f6c73000000000000000000604482015260640161087e565b8385877f5d48292d83151281e6ea967de9fd35716c713dc76c11beb42d78ed5110270f7360405160405180910390a4505050505050565b60008481526006602090815260408083206007835281842087855290925290912083158015906137eb5750600182015460058201546137e890866159c3565b11155b61382b5760405162461bcd60e51b815260206004820152601160248201527073796e633a20696e76616c6964206c697160781b604482015260640161087e565b60006138378787612d81565b905060005b60028501548110156139815760006138678460050154876002018481548110612c5657612c56615738565b905080156138e1578084600301838154811061388557613885615738565b90600052602060002001600082825461389e91906159c3565b92505081905550808660020183815481106138bb576138bb615738565b906000526020600020906002020160010160008282546138db91906159ac565b90915550505b60006138fb85600301848154811061317b5761317b615738565b9050801561396e578085600101848154811061391957613919615738565b90600052602060002001600082825461393291906159c3565b925050819055508085600201848154811061394f5761394f615738565b90600052602060002001600082825461396891906159c3565b90915550505b50508061397a90615764565b905061383c565b508060a0015184600101600082825461399a91906159c3565b9091555050805182546001600160801b0319166001600160801b0390911617825560048201546020820151600386015460058501546139dd93929190898c614ac4565b8260040181905550848260050160008282546139f991906159c3565b90915550506040518590879089907ff31cd5db84a4ab16cd339c510d5a60c63ef5818c538aa67046f5bc0dca794cd390600090a450505050505050565b6000611ef9825490565b6000613a4c8383614be6565b9392505050565b600b5460ff1615613a9f5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b8015613b51578260045411613ac65760405162461bcd60e51b815260040161087e90615966565b600083815260056020526040902054429063ffffffff808316600160a01b9092041611801590613b14575060008481526005602052604090205463ffffffff600160c01b9091048116908216105b613b4f5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b505b3360005b8351811015613ed357600a6000858381518110613b7457613b74615738565b60209081029190910181015182528101919091526040016000205460ff1615613bd85760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b613c28848281518110613bed57613bed615738565b602002602001015160096000856001600160a01b03166001600160a01b03168152602001908152602001600020614ab890919063ffffffff16565b613c3157600080fd5b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03166323b872dd8330878581518110613c7457613c74615738565b60200260200101516040518463ffffffff1660e01b8152600401613c9a93929190615a12565b600060405180830381600087803b158015613cb457600080fd5b505af1158015613cc8573d6000803e3d6000fd5b50505050838181518110613cde57613cde615738565b60200260200101517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c83604051613d2491906001600160a01b0391909116815260200190565b60405180910390a28160066000868481518110613d4357613d43615738565b6020908102919091018101518252810191909152604001600090812080546001600160a01b0319166001600160a01b03938416179055600354865191921690635c6d96a9907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48090889086908110613dbc57613dbc615738565b60200260200101516040518363ffffffff1660e01b8152600401613df59291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613e0d57600080fd5b505afa158015613e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e45919061598f565b9050806001600160801b031660066000878581518110613e6757613e67615738565b60200260200101518152602001908152602001600020600101819055508315613eca57613eca858381518110613e9f57613e9f615738565b602002602001015187836001600160801b0316600560008b8152602001908152602001600020613303565b50600101613b55565b5050505050565b6001600160a01b038316613f91576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613f35576040519150601f19603f3d011682016040523d82523d6000602084013e613f3a565b606091505b5050905080613f8b5760405162461bcd60e51b815260206004820152601c60248201527f7472616e736665722072657761726420746f6b656e206661696c656400000000604482015260640161087e565b50505050565b613fa56001600160a01b0384168383614c10565b505050565b600083815260056020908152604080832087845260068352818420546007845282852088865290935292206001600160a01b03909116903382148061401c57508254600160c01b900463ffffffff164263ffffffff1611801561401c57503360009081526002602052604090205460ff165b6140725760405162461bcd60e51b815260206004820152602160248201527f657869743a206e6f74206f776e6572206f7220706f6f6c206e6f7420656e64656044820152601960fa1b606482015260840161087e565b600581015485158015906140865750808611155b6140c65760405162461bcd60e51b8152602060048201526011602482015270657869743a20696e76616c6964206c697160781b604482015260640161087e565b60006140d287836159ac565b905060006140e08a8a612d81565b90508060a001518660010160008282546140fa91906159c3565b9091555050805184546001600160801b0319166001600160801b039091161784556005840182905560005b600287015481101561439957600061414c85896002018481548110612c5657612c56615738565b905080156141c6578086600301838154811061416a5761416a615738565b90600052602060002001600082825461418391906159c3565b92505081905550808860020183815481106141a0576141a0615738565b906000526020600020906002020160010160008282546141c091906159ac565b90915550505b60006142058760030184815481106141e0576141e0615738565b90600052602060002001548560400151896001018681548110612cc357612cc3615738565b9050600087600201848154811061421e5761421e615738565b9060005260206000200154905081600014614275578188600101858154811061424957614249615738565b90600052602060002001600082825461426291906159c3565b90915550614272905082826159c3565b90505b8015614385578a1561436257600088600201858154811061429857614298615738565b90600052602060002001819055506142df8a60020185815481106142be576142be615738565b60009182526020909120600290910201546001600160a01b03168a83613eda565b808e7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd267038b8d600201888154811061431857614318615738565b600091825260209091206002909102015460405161435592916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a3614385565b8088600201858154811061437857614378615738565b6000918252602090912001555b5050508061439290615764565b9050614125565b508161447b5760008a81526007602090815260408083208c8452909152812080546001600160801b0319168155906143d46001830182615077565b6143e2600283016000615077565b6143f0600383016000615077565b5060006004828101829055600590920181905590870180549161441283615ad7565b909155505060008a815260086020526040902061442f908a6144c0565b61447b5760405162461bcd60e51b815260206004820152601a60248201527f4661696c20746f2072656d6f7665206a6f696e6564506f6f6c73000000000000604482015260640161087e565b60405133815288908a908c907f275029c7b988945c03ac5499c0d532fce79ce36efab42e1b3f180a62001cad2c9060200160405180910390a450505050505050505050565b6000613a4c8383614c62565b60606000613a4c83614d55565b801561457b57604051630c479e6560e21b8152600481018490527f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03169063311e799490602401602060405180830381600087803b15801561454157600080fd5b505af1158015614555573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145799190615a82565b505b60408051608081018252848152600060208201818152828401918252606083018681529351637686c6e960e11b815283516004820152905160248201529051604482015291516064830152907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03169063ed0d8dd2906084015b606060405180830381600087803b15801561461657600080fd5b505af115801561462a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fe9190615aee565b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480811561484a57866001600160a01b03167f00000000000000000000000042000000000000000000000000000000000000066001600160a01b031614156147795760405163bac37ef760e01b8152600481018690526001600160a01b03848116602483015282169063bac37ef790604401600060405180830381600087803b1580156146f957600080fd5b505af115801561470d573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c1915061474190899088908890600401615b1c565b600060405180830381600087803b15801561475b57600080fd5b505af115801561476f573d6000803e3d6000fd5b5050505050614910565b856001600160a01b03167f00000000000000000000000042000000000000000000000000000000000000066001600160a01b0316141561484a5760405163bf1316c160e01b81526001600160a01b0382169063bf1316c1906147e3908a9089908890600401615b1c565b600060405180830381600087803b1580156147fd57600080fd5b505af1158015614811573d6000803e3d6000fd5b505060405163bac37ef760e01b8152600481018790526001600160a01b0386811660248301528416925063bac37ef79150604401614741565b60405163bf1316c160e01b81526001600160a01b0382169063bf1316c19061487a908a9089908890600401615b1c565b600060405180830381600087803b15801561489457600080fd5b505af11580156148a8573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c191506148dc90899088908890600401615b1c565b600060405180830381600087803b1580156148f657600080fd5b505af115801561490a573d6000803e3d6000fd5b50505050505b505050505050565b6040805160a0810182528481526001600160801b03848116602083019081526000838501818152606085019182526080850187815295516398e04d7760e01b81528551600482015292519093166024830152915160448201529051606482015291516084830152907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b0316906398e04d779060a4016145fc565b600082826149c78688615a9b565b6149d19190615a9b565b6149db9190615b55565b95945050505050565b60008064e8d4a510006149f78587615a9b565b614a019190615b55565b9050828111614a115760006149db565b6149db83826159ac565b600081614a2e575064e8d4a51000613a4c565b6000614a3a8486615b69565b90506149db83614a4f64e8d4a5100084615a9b565b614a599190615b55565b64e8d4a51000614db1565b60008084614a784263ffffffff1686614dc7565b614a8291906159ac565b90506000614a9482600160601b615a9b565b9050838111614aa4576000614aae565b614aae84826159ac565b9695505050505050565b6000613a4c8383614dde565b600084614ad357506000614aae565b600087614ae08789615b69565b12614af457614aef8688615b69565b614af6565b875b60035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018790529293506000929091169063a51dc8f29060440160206040518083038186803b158015614b6857600080fd5b505afa158015614b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ba09190615a82565b614baa9086615ba8565b614bb48388615ba8565b614bbe9190615c2d565b90506000614bcc86886159c3565b9050614bd88183615c6e565b9a9950505050505050505050565b6000826000018281548110614bfd57614bfd615738565b9060005260206000200154905092915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613fa5908490614e2d565b60008181526001830160205260408120548015614d4b576000614c866001836159ac565b8554909150600090614c9a906001906159ac565b9050818114614cff576000866000018281548110614cba57614cba615738565b9060005260206000200154905080876000018481548110614cdd57614cdd615738565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614d1057614d10615c9c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ef9565b6000915050611ef9565b606081600001805480602002602001604051908101604052809291908181526020018280548015614da557602002820191906000526020600020905b815481526020019060010190808311614d91575b50505050509050919050565b600081831015614dc15782613a4c565b50919050565b600081831015614dd75781613a4c565b5090919050565b6000818152600183016020526040812054614e2557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ef9565b506000611ef9565b6000614e82826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614eff9092919063ffffffff16565b805190915015613fa55780806020019051810190614ea09190615aba565b613fa55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161087e565b6060614f0e8484600085614f16565b949350505050565b606082471015614f775760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161087e565b843b614fc55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161087e565b600080866001600160a01b03168587604051614fe19190615cde565b60006040518083038185875af1925050503d806000811461501e576040519150601f19603f3d011682016040523d82523d6000602084013e615023565b606091505b509150915061503382828661503e565b979650505050505050565b6060831561504d575081613a4c565b82511561505d5782518084602001fd5b8160405162461bcd60e51b815260040161087e9190615cfa565b508054600082559060005260206000209081019061509591906150e3565b50565b8280548282559060005260206000209081019282156150d3579160200282015b828111156150d35782518255916020019190600101906150b8565b506150df9291506150e3565b5090565b5b808211156150df57600081556001016150e4565b803563ffffffff8116811461510c57600080fd5b919050565b60008083601f84011261512357600080fd5b5081356001600160401b0381111561513a57600080fd5b6020830191508360208260051b850101111561515557600080fd5b9250929050565b60008060008060008060a0878903121561517557600080fd5b86359550615185602088016150f8565b9450615193604088016150f8565b935060608701356001600160401b038111156151ae57600080fd5b6151ba89828a01615111565b979a9699509497949695608090950135949350505050565b6001600160a01b038116811461509557600080fd5b6000602082840312156151f957600080fd5b8135613a4c816151d2565b6000806000806040858703121561521a57600080fd5b84356001600160401b038082111561523157600080fd5b61523d88838901615111565b9096509450602087013591508082111561525657600080fd5b5061526387828801615111565b95989497509550505050565b60006020828403121561528157600080fd5b5035919050565b600081518084526020808501945080840160005b838110156152b85781518752958201959082019060010161529c565b509495945050505050565b6001600160a01b03898116825263ffffffff8981166020808501919091529089166040840152606083018890526080830187905260a0830186905261010060c08401819052855190840181905260009261012085019287810192855b8181101561533d57845184168652948201949382019360010161531f565b505050505082810360e08401526153548185615288565b9b9a5050505050505050505050565b60008060008060006060868803121561537b57600080fd5b8535945060208601356001600160401b038082111561539957600080fd5b6153a589838a01615111565b909650945060408801359150808211156153be57600080fd5b506153cb88828901615111565b969995985093965092949392505050565b6000806000606084860312156153f157600080fd5b505081359360208301359350604090920135919050565b602081526000613a4c6020830184615288565b801515811461509557600080fd5b60006020828403121561543b57600080fd5b8135613a4c8161541b565b6000806020838503121561545957600080fd5b82356001600160401b0381111561546f57600080fd5b61547b85828601615111565b90969095509350505050565b60008060006040848603121561549c57600080fd5b8335925060208401356001600160401b038111156154b957600080fd5b6154c586828701615111565b9497909650939450505050565b600080604083850312156154e557600080fd5b82356154f0816151d2565b915060208301356155008161541b565b809150509250929050565b60008060008060008060008060c0898b03121561552757600080fd5b8835615532816151d2565b975061554060208a016150f8565b965061554e60408a016150f8565b955060608901356001600160401b038082111561556a57600080fd5b6155768c838d01615111565b909750955060808b013591508082111561558f57600080fd5b5061559c8b828c01615111565b999c989b50969995989497949560a00135949350505050565b600080604083850312156155c857600080fd5b50508035926020909101359150565b600080600080600080600060c0888a0312156155f257600080fd5b87356001600160401b0381111561560857600080fd5b6156148a828b01615111565b90985096505060208801359450604088013593506060880135615636816151d2565b925060808801356156468161541b565b8092505060a0880135905092959891949750929550565b6001600160801b038116811461509557600080fd5b600080600080600080600061010080898b03121561568f57600080fd5b8835975060208901356156a18161565d565b965060408901359550606089013594506080890135935060a08901356156c68161541b565b92508881018a10156156d757600080fd5b5060c08801905092959891949750929550565b8381526060602082015260006157036060830185615288565b8281036040840152614aae8185615288565b6020808252600990820152683337b93134b23232b760b91b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156157785761577861574e565b5060010190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600e908201526d0d2dcecc2d8d2c840d8cadccee8d60931b604082015260600190565b6000808335601e198436030181126157f557600080fd5b8301803591506001600160401b0382111561580f57600080fd5b60200191503681900382131561515557600080fd5b634e487b7160e01b600052604160045260246000fd5b604051602081016001600160401b038111828210171561585c5761585c615824565b60405290565b604051601f8201601f191681016001600160401b038111828210171561588a5761588a615824565b604052919050565b600060208083850312156158a557600080fd5b82356001600160401b03808211156158bc57600080fd5b81850191508282870312156158d057600080fd5b6158d861583a565b8235828111156158e757600080fd5b80840193505086601f8401126158fc57600080fd5b82358281111561590e5761590e615824565b8060051b925061591f858401615862565b818152928401850192858101908985111561593957600080fd5b948601945b848610156159575785358252948601949086019061593e565b83525090979650505050505050565b6020808252600f908201526e506f6f6c206e6f742065786973747360881b604082015260600190565b6000602082840312156159a157600080fd5b8151613a4c8161565d565b6000828210156159be576159be61574e565b500390565b600082198211156159d6576159d661574e565b500190565b60208082526018908201527f7370656369616c20666561747572652064697361626c65640000000000000000604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060208284031215615a4857600080fd5b8151613a4c816151d2565b60008060408385031215615a6657600080fd5b8251615a71816151d2565b6020840151909250615500816151d2565b600060208284031215615a9457600080fd5b5051919050565b6000816000190483118215151615615ab557615ab561574e565b500290565b600060208284031215615acc57600080fd5b8151613a4c8161541b565b600081615ae657615ae661574e565b506000190190565b600080600060608486031215615b0357600080fd5b8351925060208401519150604084015190509250925092565b6001600160a01b0393841681526020810192909252909116604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082615b6457615b64615b3f565b500490565b60008083128015600160ff1b850184121615615b8757615b8761574e565b6001600160ff1b0384018313811615615ba257615ba261574e565b50500390565b60006001600160ff1b0381841382841380821686840486111615615bce57615bce61574e565b600160ff1b6000871282811687830589121615615bed57615bed61574e565b60008712925087820587128484161615615c0957615c0961574e565b87850587128184161615615c1f57615c1f61574e565b505050929093029392505050565b600080821280156001600160ff1b0384900385131615615c4f57615c4f61574e565b600160ff1b8390038412811615615c6857615c6861574e565b50500190565b600082615c7d57615c7d615b3f565b600160ff1b821460001984141615615c9757615c9761574e565b500590565b634e487b7160e01b600052603160045260246000fd5b60005b83811015615ccd578181015183820152602001615cb5565b83811115613f8b5750506000910152565b60008251615cf0818460208701615cb2565b9190910192915050565b6020815260008251806020840152615d19816040850160208701615cb2565b601f01601f1916919091016040019291505056fea164736f6c6343000809000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48000000000000000000000000035be3f4fd8239a35a7f120756d4d69e5c5e10870
-----Decoded View---------------
Arg [0] : _nft (address): 0xe222fBE074A436145b255442D919E4E3A6c6a480
Arg [1] : _helper (address): 0x35BE3F4fd8239A35a7F120756D4D69e5C5e10870
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480
Arg [1] : 00000000000000000000000035be3f4fd8239a35a7f120756d4d69e5c5e10870
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BSC | 29.82% | $0.644065 | 4,249.8978 | $2,737.21 | |
BASE | 19.20% | $3,822.29 | 0.4611 | $1,762.4 | |
BASE | 3.32% | $0.645414 | 471.676 | $304.43 | |
BASE | 0.01% | $0.000002 | 740,000 | $1.37 | |
ARB | 8.66% | $0.644065 | 1,233.8507 | $794.68 | |
ARB | 5.30% | $3,448.67 | 0.141 | $486.36 | |
ARB | 2.24% | $0.723237 | 284.4387 | $205.72 | |
ARB | 0.77% | $0.601654 | 117.9732 | $70.98 | |
ARB | 0.23% | $3,800.18 | 0.00558657 | $21.23 | |
ARB | 0.11% | $0.999979 | 10.4808 | $10.48 | |
OP | 14.47% | $1.77 | 749.9093 | $1,328.09 | |
OP | 0.33% | $3,816.87 | 0.00784124 | $29.93 | |
OP | 0.06% | $0.644033 | 8.4704 | $5.46 | |
POL | 10.35% | $3,821.58 | 0.2485 | $949.74 | |
POL | 2.15% | $0.64396 | 306.1352 | $197.14 | |
POL | <0.01% | $1.73 | 0.0716 | $0.1239 | |
ETH | 2.25% | $0.644065 | 320.9995 | $206.74 | |
ETH | 0.34% | $3,800.18 | 0.00823924 | $31.31 | |
ETH | 0.33% | $3,346.51 | 0.00913038 | $30.55 | |
LINEA | 0.07% | $0.644425 | 10.3684 | $6.68 |
[ 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.