Latest 25 from a total of 9,628 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Remove Liquidity | 4369089 | 671 days ago | IN | 0 ETH | 0.00037759 | ||||
| Remove Liquidity | 4056655 | 683 days ago | IN | 0 ETH | 0.00056558 | ||||
| Remove Liquidity | 4056452 | 683 days ago | IN | 0 ETH | 0.00059351 | ||||
| Remove Liquidity | 4051618 | 683 days ago | IN | 0 ETH | 0.0006387 | ||||
| Remove Liquidity | 3836639 | 691 days ago | IN | 0 ETH | 0.00051452 | ||||
| Remove Liquidity | 3763082 | 694 days ago | IN | 0 ETH | 0.0005341 | ||||
| Remove Liquidity | 3670865 | 697 days ago | IN | 0 ETH | 0.00034833 | ||||
| Remove Liquidity | 3415993 | 707 days ago | IN | 0 ETH | 0.00025366 | ||||
| Remove Liquidity | 3359503 | 709 days ago | IN | 0 ETH | 0.00035525 | ||||
| Remove Liquidity | 3306562 | 711 days ago | IN | 0 ETH | 0.00034501 | ||||
| Remove Liquidity | 3245951 | 713 days ago | IN | 0 ETH | 0.0005798 | ||||
| Remove Liquidity | 3105201 | 718 days ago | IN | 0 ETH | 0.0003302 | ||||
| Remove Liquidity | 3100220 | 718 days ago | IN | 0 ETH | 0.00033635 | ||||
| Remove Liquidity | 3098455 | 718 days ago | IN | 0 ETH | 0.0002747 | ||||
| Remove Liquidity | 3086204 | 718 days ago | IN | 0 ETH | 0.00037454 | ||||
| Remove Liquidity | 3070079 | 719 days ago | IN | 0 ETH | 0.00036604 | ||||
| Remove Liquidity | 2588636 | 736 days ago | IN | 0 ETH | 0.00031656 | ||||
| Remove Liquidity | 2588632 | 736 days ago | IN | 0 ETH | 0.00023217 | ||||
| Remove Liquidity | 2588579 | 736 days ago | IN | 0 ETH | 0.00023681 | ||||
| Remove Liquidity | 2419398 | 742 days ago | IN | 0 ETH | 0.00027962 | ||||
| Remove Liquidity | 2387270 | 743 days ago | IN | 0 ETH | 0.00024442 | ||||
| Remove Liquidity | 2309408 | 746 days ago | IN | 0 ETH | 0.00029827 | ||||
| Remove Liquidity | 2247907 | 748 days ago | IN | 0 ETH | 0.00035098 | ||||
| Remove Liquidity | 2247886 | 748 days ago | IN | 0 ETH | 0.00039362 | ||||
| Remove Liquidity | 2226103 | 749 days ago | IN | 0 ETH | 0.00029429 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
KyberSwapElasticLM
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity)
/**
*Submitted for verification at scrollscan.com on 2023-10-18
*/
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
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;
}
}
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);
}
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);
}
/**
* @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);
}
/**
* @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;
}
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);
}
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;
}
/**
* @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);
}
/// @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;
}
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);
}
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);
}
}
/**
* @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);
}
}
}
}
/**
* @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");
}
}
}
/**
* @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);
}
/**
* @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;
}
}
/**
* @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;
}
}
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 || liquidityNew == 0) {
// should transfer reward if claimReward is true or remove all liquidity
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);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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
60c06040523480156200001157600080fd5b5060405162005fa938038062005fa9833981016040819052620000349162000125565b600160008181558154336001600160a01b031991821681178455825260026020908152604092839020805460ff19169094179093556001600160a01b038581166080819052600380549093169186169190911790915581516315ab88c960e31b81529151909263ad5c46489260048082019391829003018186803b158015620000bc57600080fd5b505afa158015620000d1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000f7919062000164565b6001600160a01b031660a052506200018b9050565b6001600160a01b03811681146200012257600080fd5b50565b600080604083850312156200013957600080fd5b825162000146816200010c565b602084015190925062000159816200010c565b809150509250929050565b6000602082840312156200017757600080fd5b815162000184816200010c565b9392505050565b60805160a051615d6c6200023d600039600081816102fa0152818161468a015261478e01526000818161038001528181610faf01528181611d2501528181612128015281816123d2015281816125fd01528181612a0301528181612e1801528181612eca01528181613355015281816134900152818161366001528181613c3301528181613d8a015281816144fe015281816145d2015281816146590152818161498b0152614b190152615d6c6000f3fe6080604052600436106101fd5760003560e01c806375829def1161010d578063b36b26c5116100a0578063c7ca58701161006f578063c7ca58701461074b578063d1941b061461076b578063dc168a921461078b578063e7762a0c146107ba578063f851a4401461082f57600080fd5b8063b36b26c5146106bc578063b63ff916146106dc578063b82562751461070c578063bb5ae7751461072c57600080fd5b806399fbab88116100dc57806399fbab881461052f578063ac4afa381461058e578063affe737914610631578063b221e5fd1461064657600080fd5b806375829def146104af5780638bcc4166146104cf57806391fb2f15146104ef578063983d95ce1461050f57600080fd5b806347ccca021161019057806361657b121161015f57806361657b121461040f57806366b5a6641461042f578063683f3eda1461044f5780636d44a3b21461046f578063705b5bef1461048f57600080fd5b806347ccca021461036e57806349b35168146103a257806350523cea146103cf578063598b8e71146103ef57600080fd5b80632f380b35116101cc5780632f380b35146102b45780633fc8cef3146102e857806341e817ab14610334578063430ccd9b1461035457600080fd5b8063078ded5d14610209578063081e3eda1461022b57806313e7c9d814610254578063180f80361461029457600080fd5b3661020457005b600080fd5b34801561021557600080fd5b50610229610224366004615165565b61084f565b005b34801561023757600080fd5b5061024160045481565b6040519081526020015b60405180910390f35b34801561026057600080fd5b5061028461026f3660046151f0565b60026020526000908152604090205460ff1681565b604051901515815260200161024b565b3480156102a057600080fd5b506102296102af36600461520d565b610b0b565b3480156102c057600080fd5b506102d46102cf366004615278565b610c8d565b60405161024b9897969594939291906152cc565b3480156102f457600080fd5b5061031c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161024b565b34801561034057600080fd5b5061022961034f36600461536c565b610e37565b34801561036057600080fd5b50600b546102849060ff1681565b34801561037a57600080fd5b5061031c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ae57600080fd5b506103c26103bd3660046153e5565b61118b565b60405161024b9190615411565b3480156103db57600080fd5b506102296103ea366004615432565b6112e3565b3480156103fb57600080fd5b5061022961040a36600461544f565b611361565b34801561041b57600080fd5b5061022961042a36600461520d565b6113d3565b34801561043b57600080fd5b5061022961044a36600461536c565b611507565b34801561045b57600080fd5b5061022961046a366004615490565b6115d8565b34801561047b57600080fd5b5061022961048a3660046154db565b611674565b34801561049b57600080fd5b506103c26104aa366004615278565b6116fd565b3480156104bb57600080fd5b506102296104ca3660046151f0565b6117b5565b3480156104db57600080fd5b506102296104ea3660046151f0565b61184f565b3480156104fb57600080fd5b5061022961050a366004615514565b6118c7565b34801561051b57600080fd5b5061022961052a36600461544f565b611b60565b34801561053b57600080fd5b5061056f61054a366004615278565b600660205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161024b565b34801561059a57600080fd5b506105f06105a9366004615278565b60056020526000908152604090208054600182015460038301546004909301546001600160a01b0383169363ffffffff600160a01b8504811694600160c01b900416929186565b604080516001600160a01b0397909716875263ffffffff958616602088015293909416928501929092526060840152608083015260a082015260c00161024b565b34801561063d57600080fd5b50610229611e30565b34801561065257600080fd5b506106976106613660046155be565b60076020908152600092835260408084209091529082529020805460048201546005909201546001600160801b03909116919083565b604080516001600160801b03909416845260208401929092529082015260600161024b565b3480156106c857600080fd5b506103c26106d73660046151f0565b611ed5565b3480156106e857600080fd5b506102846106f7366004615278565b600a6020526000908152604090205460ff1681565b34801561071857600080fd5b506102296107273660046155e0565b611eff565b34801561073857600080fd5b50600b5461028490610100900460ff1681565b34801561075757600080fd5b5061022961076636600461567b565b6122ad565b34801561077757600080fd5b5061022961078636600461544f565b6126d6565b34801561079757600080fd5b506107ab6107a63660046155be565b612b10565b60405161024b939291906156f3565b3480156107c657600080fd5b506107da6107d53660046155be565b612d81565b60405161024b9190600060c0820190506001600160801b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561083b57600080fd5b5060015461031c906001600160a01b031681565b3360009081526002602052604090205460ff166108875760405162461bcd60e51b815260040161087e9061571e565b60405180910390fd5b6000868152600560205260409020805463ffffffff428116600160a01b9092041611806108c45750805463ffffffff428116600160c01b90920416105b6109105760405162461bcd60e51b815260206004820152601960248201527f72656e65773a20696e76616c696420706f6f6c20737461746500000000000000604482015260640161087e565b6002810154831461095b5760405162461bcd60e51b81526020600482015260156024820152740e4cadccaee7440d2dcecc2d8d2c840d8cadccee8d605b1b604482015260640161087e565b4263ffffffff168663ffffffff1611801561098157508563ffffffff168563ffffffff16115b6109c45760405162461bcd60e51b815260206004820152601460248201527372656e65773a20696e76616c69642074696d657360601b604482015260640161087e565b600481015415610a0f5760405162461bcd60e51b815260206004820152601660248201527572656e65773a20706f6f6c20686173207374616b657360501b604482015260640161087e565b805463ffffffff868116600160c01b0263ffffffff60c01b19918916600160a01b029190911667ffffffffffffffff60a01b1990921691909117178155600060018201819055600382018390555b83811015610ab757848482818110610a7757610a77615741565b90506020020135826002018281548110610a9357610a93615741565b6000918252602090912060016002909202010155610ab08161576d565b9050610a5d565b506040805163ffffffff80891682528716602082015290810183905287907feda7bcc7e20158ff9fa87a4200758e927bbb3c8823e648403bdd6053b96dd0ad9060600160405180910390a250505050505050565b60026000541415610b2e5760405162461bcd60e51b815260040161087e90615788565b60026000558281808214610b545760405162461bcd60e51b815260040161087e906157bf565b60005b85811015610c7f573360066000898985818110610b7657610b76615741565b60209081029290920135835250810191909152604001600020546001600160a01b031614610bdb5760405162461bcd60e51b81526020600482015260126024820152713430b93b32b9ba1d103737ba1037bbb732b960711b604482015260640161087e565b6000858583818110610bef57610bef615741565b9050602002810190610c0191906157e7565b810190610c0e919061589b565b905060005b815151811015610c6c57610c5c898985818110610c3257610c32615741565b9050602002013583600001518381518110610c4f57610c4f615741565b6020026020010151612fc9565b610c658161576d565b9050610c13565b505080610c789061576d565b9050610b57565b505060016000555050505050565b6000818152600560205260409020805460018201546003830154600484015460028501546001600160a01b0385169563ffffffff600160a01b8704811696600160c01b900416949392916060918291806001600160401b03811115610cf457610cf461582d565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b509350806001600160401b03811115610d3857610d3861582d565b604051908082528060200260200182016040528015610d61578160200160208202803683370190505b50925060005b81811015610e2957826002018181548110610d8457610d84615741565b600091825260209091206002909102015485516001600160a01b0390911690869083908110610db557610db5615741565b60200260200101906001600160a01b031690816001600160a01b031681525050826002018181548110610dea57610dea615741565b906000526020600020906002020160010154848281518110610e0e57610e0e615741565b6020908102919091010152610e228161576d565b9050610d67565b505050919395975091939597565b60026000541415610e5a5760405162461bcd60e51b815260040161087e90615788565b60026000558281808214610e805760405162461bcd60e51b815260040161087e906157bf565b8660045411610ea15760405162461bcd60e51b815260040161087e9061596f565b6000878152600560205260409020805463ffffffff428116600160a01b9092041611801590610ee357508054600160c01b900463ffffffff164263ffffffff16105b610f1e5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b60005b8681101561117b5733600660008a8a85818110610f4057610f40615741565b60209081029290920135835250810191909152604001600020546001600160a01b031614610f9c5760405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b604482015260640161087e565b6003546001600160a01b0316635c6d96a97f00000000000000000000000000000000000000000000000000000000000000008a8a85818110610fe057610fe0615741565b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160206040518083038186803b15801561102d57600080fd5b505afa158015611041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110659190615998565b6001600160801b0316600660008a8a8581811061108457611084615741565b905060200201358152602001908152602001600020600101819055506000600760008a8a858181106110b8576110b8615741565b90506020020135815260200190815260200160002060008b8152602001908152602001600020905080600501546000141561112e5761112989898481811061110257611102615741565b905060200201358b89898681811061111c5761111c615741565b9050602002013586613303565b61116a565b61116a89898481811061114357611143615741565b905060200201358b89898681811061115d5761115d615741565b90506020020135866137a9565b506111748161576d565b9050610f21565b5050600160005550505050505050565b6060818311156111d35760405162461bcd60e51b81526020600482015260136024820152720cce4deda92dcc8caf0407c40e8de92dcc8caf606b1b604482015260640161087e565b60008481526008602052604090206111ea90613a36565b821061122c5760405162461bcd60e51b81526020600482015260116024820152700e8de92dcc8caf0407c7a40d8cadccee8d607b1b604482015260640161087e565b61123683836159b5565b6112419060016159cc565b6001600160401b038111156112585761125861582d565b604051908082528060200260200182016040528015611281578160200160208202803683370190505b509050825b8281116112db5760008581526008602052604090206112a59082613a40565b826112b086846159b5565b815181106112c0576112c0615741565b60209081029190910101526112d48161576d565b9050611286565b509392505050565b6001546001600160a01b0316331461130d5760405162461bcd60e51b815260040161087e9061571e565b600b80548215156101000261ff00199091161790556040517f294aa6bf970997b8c55a069e787eae16138f63ad315362696337d14ef42281ea9061135690831515815260200190565b60405180910390a150565b600260005414156113845760405162461bcd60e51b815260040161087e90615788565b60026000819055506113ca600083838080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250613a53915050565b50506001600055565b6001546001600160a01b031633146113fd5760405162461bcd60e51b815260040161087e9061571e565b828180821461141e5760405162461bcd60e51b815260040161087e906157bf565b60005b858110156114fe5761147287878381811061143e5761143e615741565b905060200201602081019061145391906151f0565b3387878581811061146657611466615741565b90506020020135613eda565b84848281811061148457611484615741565b905060200201357f4042b7789d1f6c4d5a798b447cfb918e82b64dd68b81d78ddc4dd1944ba5c51c8888848181106114be576114be615741565b90506020020160208101906114d391906151f0565b6040516001600160a01b03909116815260200160405180910390a26114f78161576d565b9050611421565b50505050505050565b6002600054141561152a5760405162461bcd60e51b815260040161087e90615788565b600260005582818082146115505760405162461bcd60e51b815260040161087e906157bf565b86600454116115715760405162461bcd60e51b815260040161087e9061596f565b60005b858110156115c9576115b987878381811061159157611591615741565b90506020020135898787858181106115ab576115ab615741565b905060200201356001613faa565b6115c28161576d565b9050611574565b50506001600055505050505050565b600b54610100900460ff166115ff5760405162461bcd60e51b815260040161087e906159e4565b600260005414156116225760405162461bcd60e51b815260040161087e90615788565b600260008190555061166a8383838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613a53915050565b5050600160005550565b6001546001600160a01b0316331461169e5760405162461bcd60e51b815260040161087e9061571e565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915591519182527f2ee52be9d342458b3d25e07faada7ff9bc06723b4aa24edb6321ac1316b8a9dd910160405180910390a25050565b60008181526008602052604081206060919061171890613a36565b9050806001600160401b038111156117325761173261582d565b60405190808252806020026020018201604052801561175b578160200160208202803683370190505b50915060005b818110156117ae5760008481526008602052604090206117819082613a40565b83828151811061179357611793615741565b60209081029190910101526117a78161576d565b9050611761565b5050919050565b6001546001600160a01b031633146117df5760405162461bcd60e51b815260040161087e9061571e565b6001600160a01b0381166118055760405162461bcd60e51b815260040161087e9061571e565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fda7b0a7bc965abdec8a1a995575a891838264c2968e14bd456c5391827b7aa3090600090a250565b6001546001600160a01b031633146118795760405162461bcd60e51b815260040161087e9061571e565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f7b9adf13852d5b3e153f2a442b9aa3a4570da8f9b9046c60410b17e8034fe33c90602001611356565b3360009081526002602052604090205460ff166118f65760405162461bcd60e51b815260040161087e9061571e565b83828082146119175760405162461bcd60e51b815260040161087e906157bf565b4263ffffffff168963ffffffff161015801561193e57508863ffffffff168863ffffffff16115b6119835760405162461bcd60e51b8152602060048201526016602482015275616464506f6f6c3a20696e76616c69642074696d657360501b604482015260640161087e565b6000600454905060006005600083815260200190815260200160002090508b8160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8160000160146101000a81548163ffffffff021916908363ffffffff160217905550898160000160186101000a81548163ffffffff021916908363ffffffff1602179055506000816001018190555084816003018190555060005b88811015611ae3578160020160405180604001604052808c8c85818110611a4f57611a4f615741565b9050602002016020810190611a6491906151f0565b6001600160a01b031681526020018a8a85818110611a8457611a84615741565b60209081029290920135909252835460018082018655600095865294829020845160029092020180546001600160a01b0319166001600160a01b0390921691909117815592015191909201555080611adb8161576d565b915050611a26565b5060048054906000611af48361576d565b9091555050604080516001600160a01b038e16815263ffffffff8d811660208301528c168183015260608101879052905183917f251199ba7b3e7a12b779b3f606eaf369cecc0eac8bcbacaadcf08079e8c5940f919081900360800190a2505050505050505050505050565b60026000541415611b835760405162461bcd60e51b815260040161087e90615788565b6002600090815533905b82811015611e2557816001600160a01b031660066000868685818110611bb557611bb5615741565b60209081029290920135835250810191909152604001600020546001600160a01b031614611c1b5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b611c4e60086000868685818110611c3457611c34615741565b905060200201358152602001908152602001600020613a36565b15611c9b5760405162461bcd60e51b815260206004820152601860248201527f77697468647261773a206e6f7420657869746564207965740000000000000000604482015260640161087e565b60066000858584818110611cb157611cb1615741565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560010155611d1a848483818110611cf357611cf3615741565b6001600160a01b0386166000908152600960209081526040909120939102013590506144c9565b611d2357600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd3084878786818110611d6657611d66615741565b905060200201356040518463ffffffff1660e01b8152600401611d8b93929190615a1b565b600060405180830381600087803b158015611da557600080fd5b505af1158015611db9573d6000803e3d6000fd5b50505050838382818110611dcf57611dcf615741565b6040516001600160a01b038616815260209182029390930135927f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436492500160405180910390a2611e1e8161576d565b9050611b8d565b505060016000555050565b6001546001600160a01b03163314611e5a5760405162461bcd60e51b815260040161087e9061571e565b600b5460ff1615611e9d5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015260640161087e565b600b805460ff191660011790556040517f1d8c7af3ae0426053ea40080543aa1cbe5bea5cdb7a55888b4cca96eea0493e490600090a1565b6001600160a01b0381166000908152600960205260409020606090611ef9906144d5565b92915050565b60026000541415611f225760405162461bcd60e51b815260040161087e90615788565b6002600055600b54610100900460ff16611f4e5760405162461bcd60e51b815260040161087e906159e4565b804263ffffffff161115611f985760405162461bcd60e51b815260206004820152601160248201527018db185a5b5199594e88195e1c1a5c9959607a1b604482015260640161087e565b6000878790509050600080856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611fdc57600080fd5b505afa158015611ff0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120149190615a3f565b866001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561204d57600080fd5b505afa158015612061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120859190615a3f565b9150915060005b8381101561228d5733600660008d8d858181106120ab576120ab615741565b60209081029290920135835250810191909152604001600020546001600160a01b0316146121115760405162461bcd60e51b815260206004820152601360248201527231b630b4b6a332b29d103737ba1037bbb732b960691b604482015260640161087e565b60035460009081906001600160a01b0316626349fb7f00000000000000000000000000000000000000000000000000000000000000008f8f8781811061215957612159615741565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401604080518083038186803b1580156121a557600080fd5b505afa1580156121b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121dd9190615a5c565b91509150846001600160a01b0316826001600160a01b03161480156122135750836001600160a01b0316816001600160a01b0316145b61225f5760405162461bcd60e51b815260206004820152601e60248201527f636c61696d4665653a20746f6b656e2070616972206e6f74206d617463680000604482015260640161087e565b6122838d8d8581811061227457612274615741565b905060200201358860016144e2565b505060010161208c565b5061229c82828a8a338a614657565b505060016000555050505050505050565b600260005414156122d05760405162461bcd60e51b815260040161087e90615788565b6002600055600b54610100900460ff166122fc5760405162461bcd60e51b815260040161087e906159e4565b824263ffffffff1611156123525760405162461bcd60e51b815260206004820152601860248201527f72656d6f76654c69717569646974793a20657870697265640000000000000000604482015260640161087e565b6000878152600660205260409020546001600160a01b031633146123b85760405162461bcd60e51b815260206004820152601a60248201527f72656d6f76654c69717569646974793a206e6f74206f776e6572000000000000604482015260640161087e565b600354604051635c6d96a960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018a90526000921690635c6d96a99060440160206040518083038186803b15801561242557600080fd5b505afa158015612439573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245d9190615998565b6001600160801b031690506000876001600160801b031611801561248a575080876001600160801b031611155b6124e15760405162461bcd60e51b815260206004820152602260248201527f72656d6f76654c69717569646974793a20696e76616c6964206c697175696469604482015261747960f01b606482015260840161087e565b6124f46001600160801b038816826159b5565b6000898152600660209081526040808320600101849055600890915281209192509061251f906144d5565b905060005b81518110156125e35760008a81526007602052604081208351829085908590811061255157612551615741565b60200260200101518152602001908152602001600020600501549050600084821161257d576000612587565b61258785836159b5565b905080156125d9576125d98c8585815181106125a5576125a5615741565b602002602001015183896001600281106125c1576125c1615741565b6020020160208101906125d49190615432565b613faa565b5050600101612524565b50600354604051626349fb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018c90526000928392911690626349fb90604401604080518083038186803b15801561265157600080fd5b505afa158015612665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126899190615a5c565b915091506126988b8b89614921565b6126a56020860186615432565b156126b6576126b68b8860006144e2565b6126c482828b8b338b614657565b50506001600055505050505050505050565b600260005414156126f95760405162461bcd60e51b815260040161087e90615788565b60026000908155600b54339160ff909116905b83811015612b0457826001600160a01b03166006600087878581811061273457612734615741565b60209081029290920135835250810191909152604001600020546001600160a01b03161461279a5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b6001600a60008787858181106127b2576127b2615741565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055506000612813600860008888868181106127f9576127f9615741565b9050602002013581526020019081526020016000206144d5565b905060005b81518110156128f057600082828151811061283557612835615741565b60209081029190910181015160008181526005909252604082206004018054600019019055915060079089898781811061287157612871615741565b602090810292909201358352508181019290925260409081016000908120848252909252812080546001600160801b0319168155906128b36001830182615080565b6128c1600283016000615080565b6128cf600383016000615080565b50600060048201819055600590910155506128e98161576d565b9050612818565b506006600087878581811061290757612907615741565b60209081029290920135835250810191909152604001600090812080546001600160a01b03191681556001015582612a015761297586868481811061294e5761294e615741565b6001600160a01b0388166000908152600960209081526040909120939102013590506144c9565b61297e57600080fd5b60005b81518110156129ff57600082828151811061299e5761299e615741565b602002602001015190506129e581600860008b8b898181106129c2576129c2615741565b9050602002013581526020019081526020016000206144c990919063ffffffff16565b6129ee57600080fd5b506129f88161576d565b9050612981565b505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd3086898987818110612a4457612a44615741565b905060200201356040518463ffffffff1660e01b8152600401612a6993929190615a1b565b600060405180830381600087803b158015612a8357600080fd5b505af1158015612a97573d6000803e3d6000fd5b50505050858583818110612aad57612aad615741565b6040516001600160a01b038816815260209182029390930135927f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd969592500160405180910390a250612afd8161576d565b905061270c565b50506001600055505050565b600081815260056020818152604080842086855260078352818520868652909252832091820154606092839291612b895760405162461bcd60e51b815260206004820152601b60248201527f67657455736572496e666f3a206e6f74206a6f696e6564207965740000000000604482015260640161087e565b60028201546001600160401b03811115612ba557612ba561582d565b604051908082528060200260200182016040528015612bce578160200160208202803683370190505b5060028301549094506001600160401b03811115612bee57612bee61582d565b604051908082528060200260200182016040528015612c17578160200160208202803683370190505b5092506000612c268888612d81565b905060005b6002840154811015612d6f576000612c778460050154866002018481548110612c5657612c56615741565b906000526020600020906002020160010154856060015186608001516149c2565b90506000612cd382866003018581548110612c9457612c94615741565b9060005260206000200154612ca991906159cc565b8560400151876001018681548110612cc357612cc3615741565b90600052602060002001546149ed565b905080856002018481548110612ceb57612ceb615741565b9060005260206000200154612d0091906159cc565b888481518110612d1257612d12615741565b602002602001018181525050846001018381548110612d3357612d33615741565b9060005260206000200154878481518110612d5057612d50615741565b602002602001018181525050505080612d689061576d565b9050612c2b565b50816005015495505050509250925092565b612dc36040518060c0016040528060006001600160801b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000828152600560209081526040808320868452600783528184208685529092529182902060035482549351632106297960e11b8152929391926001600160a01b039182169263420c52f292612e42929116907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615a1b565b60206040518083038186803b158015612e5a57600080fd5b505afa158015612e6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e929190615998565b6001600160801b0316835260035482546040516339bb866b60e11b81526001600160a01b03928316926373770cd692612ef4929116907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615a1b565b60206040518083038186803b158015612f0c57600080fd5b505afa158015612f20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f449190615a8b565b6020840181905260048201546003840154612f60929190614a24565b604084015281546001830154612f8e9163ffffffff600160a01b8204811692600160c01b9092041690614a6d565b6060840152805483516001600160801b03918216900316608084018190526005820154612fbb9190615aa4565b60a084015250909392505050565b8060045411612fea5760405162461bcd60e51b815260040161087e9061596f565b60008181526005602081815260408084208685526006835281852054600784528286208787529093529320918201546001600160a01b0390911691906130725760405162461bcd60e51b815260206004820152601760248201527f686172766573743a206e6f74206a6f696e656420796574000000000000000000604482015260640161087e565b600061307e8686612d81565b90508060a0015184600101600082825461309891906159cc565b9091555050805182546001600160801b0319166001600160801b0390911617825560005b60028501548110156114fe5760006130e78460050154876002018481548110612c5657612c56615741565b90508015613161578084600301838154811061310557613105615741565b90600052602060002001600082825461311e91906159cc565b925050819055508086600201838154811061313b5761313b615741565b9060005260206000209060020201600101600082825461315b91906159b5565b90915550505b60006131a085600301848154811061317b5761317b615741565b90600052602060002001548560400151876001018681548110612cc357612cc3615741565b90506000818660020185815481106131ba576131ba615741565b90600052602060002001546131cf91906159cc565b905080156132ef57811561321257818660010185815481106131f3576131f3615741565b90600052602060002001600082825461320c91906159cc565b90915550505b600086600201858154811061322957613229615741565b906000526020600020018190555061327088600201858154811061324f5761324f615741565b60009182526020909120600290910201546001600160a01b03168883613eda565b808a7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd26703898b60020188815481106132a9576132a9615741565b60009182526020909120600290910201546040516132e692916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a35b505050806132fc9061576d565b90506130bc565b600084815260066020908152604080832060078352818420878552909252918290206003548454935163d7aee3bd60e01b8152929391926001600160a01b039182169263d7aee3bd9261337f929116907f0000000000000000000000000000000000000000000000000000000000000000908b90600401615a1b565b60206040518083038186803b15801561339757600080fd5b505afa1580156133ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cf9190615ac3565b6134105760405162461bcd60e51b81526020600482015260126024820152711a9bda5b8e881a5b9d985b1a59081c1bdbdb60721b604482015260640161087e565b8315801590613423575081600101548411155b6134635760405162461bcd60e51b81526020600482015260116024820152706a6f696e3a20696e76616c6964206c697160781b604482015260640161087e565b6003548354604051632106297960e11b81526001600160a01b039283169263420c52f2926134ba929116907f0000000000000000000000000000000000000000000000000000000000000000908b90600401615a1b565b60206040518083038186803b1580156134d257600080fd5b505afa1580156134e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061350a9190615998565b81546001600160801b0319166001600160801b039190911617815560028301546001600160401b038111156135415761354161582d565b60405190808252806020026020018201604052801561356a578160200160208202803683370190505b5080516135819160018401916020909101906150a1565b5060028301546001600160401b0381111561359e5761359e61582d565b6040519080825280602002602001820160405280156135c7578160200160208202803683370190505b5080516135de9160028401916020909101906150a1565b5060028301546001600160401b038111156135fb576135fb61582d565b604051908082528060200260200182016040528015613624578160200160208202803683370190505b50805161363b9160038401916020909101906150a1565b506003830154156136f05760035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018990529091169063a51dc8f29060440160206040518083038186803b1580156136b257600080fd5b505afa1580156136c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ea9190615a8b565b60048201555b600581018490556004830180549060006137098361576d565b909155505060008681526008602052604090206137269086614ac1565b6137725760405162461bcd60e51b815260206004820152601760248201527f4661696c20746f20616464206a6f696e6564506f6f6c73000000000000000000604482015260640161087e565b8385877f5d48292d83151281e6ea967de9fd35716c713dc76c11beb42d78ed5110270f7360405160405180910390a4505050505050565b60008481526006602090815260408083206007835281842087855290925290912083158015906137eb5750600182015460058201546137e890866159cc565b11155b61382b5760405162461bcd60e51b815260206004820152601160248201527073796e633a20696e76616c6964206c697160781b604482015260640161087e565b60006138378787612d81565b905060005b60028501548110156139815760006138678460050154876002018481548110612c5657612c56615741565b905080156138e1578084600301838154811061388557613885615741565b90600052602060002001600082825461389e91906159cc565b92505081905550808660020183815481106138bb576138bb615741565b906000526020600020906002020160010160008282546138db91906159b5565b90915550505b60006138fb85600301848154811061317b5761317b615741565b9050801561396e578085600101848154811061391957613919615741565b90600052602060002001600082825461393291906159cc565b925050819055508085600201848154811061394f5761394f615741565b90600052602060002001600082825461396891906159cc565b90915550505b50508061397a9061576d565b905061383c565b508060a0015184600101600082825461399a91906159cc565b9091555050805182546001600160801b0319166001600160801b0390911617825560048201546020820151600386015460058501546139dd93929190898c614acd565b8260040181905550848260050160008282546139f991906159cc565b90915550506040518590879089907ff31cd5db84a4ab16cd339c510d5a60c63ef5818c538aa67046f5bc0dca794cd390600090a450505050505050565b6000611ef9825490565b6000613a4c8383614bef565b9392505050565b600b5460ff1615613a9f5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b8015613b51578260045411613ac65760405162461bcd60e51b815260040161087e9061596f565b600083815260056020526040902054429063ffffffff808316600160a01b9092041611801590613b14575060008481526005602052604090205463ffffffff600160c01b9091048116908216105b613b4f5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b505b3360005b8351811015613ed357600a6000858381518110613b7457613b74615741565b60209081029190910181015182528101919091526040016000205460ff1615613bd85760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b613c28848281518110613bed57613bed615741565b602002602001015160096000856001600160a01b03166001600160a01b03168152602001908152602001600020614ac190919063ffffffff16565b613c3157600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd8330878581518110613c7457613c74615741565b60200260200101516040518463ffffffff1660e01b8152600401613c9a93929190615a1b565b600060405180830381600087803b158015613cb457600080fd5b505af1158015613cc8573d6000803e3d6000fd5b50505050838181518110613cde57613cde615741565b60200260200101517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c83604051613d2491906001600160a01b0391909116815260200190565b60405180910390a28160066000868481518110613d4357613d43615741565b6020908102919091018101518252810191909152604001600090812080546001600160a01b0319166001600160a01b03938416179055600354865191921690635c6d96a9907f000000000000000000000000000000000000000000000000000000000000000090889086908110613dbc57613dbc615741565b60200260200101516040518363ffffffff1660e01b8152600401613df59291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613e0d57600080fd5b505afa158015613e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e459190615998565b9050806001600160801b031660066000878581518110613e6757613e67615741565b60200260200101518152602001908152602001600020600101819055508315613eca57613eca858381518110613e9f57613e9f615741565b602002602001015187836001600160801b0316600560008b8152602001908152602001600020613303565b50600101613b55565b5050505050565b6001600160a01b038316613f91576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613f35576040519150601f19603f3d011682016040523d82523d6000602084013e613f3a565b606091505b5050905080613f8b5760405162461bcd60e51b815260206004820152601c60248201527f7472616e736665722072657761726420746f6b656e206661696c656400000000604482015260640161087e565b50505050565b613fa56001600160a01b0384168383614c19565b505050565b600083815260056020908152604080832087845260068352818420546007845282852088865290935292206001600160a01b03909116903382148061401c57508254600160c01b900463ffffffff164263ffffffff1611801561401c57503360009081526002602052604090205460ff165b6140725760405162461bcd60e51b815260206004820152602160248201527f657869743a206e6f74206f776e6572206f7220706f6f6c206e6f7420656e64656044820152601960fa1b606482015260840161087e565b600581015485158015906140865750808611155b6140c65760405162461bcd60e51b8152602060048201526011602482015270657869743a20696e76616c6964206c697160781b604482015260640161087e565b60006140d287836159b5565b905060006140e08a8a612d81565b90508060a001518660010160008282546140fa91906159cc565b9091555050805184546001600160801b0319166001600160801b039091161784556005840182905560005b60028701548110156143a257600061414c85896002018481548110612c5657612c56615741565b905080156141c6578086600301838154811061416a5761416a615741565b90600052602060002001600082825461418391906159cc565b92505081905550808860020183815481106141a0576141a0615741565b906000526020600020906002020160010160008282546141c091906159b5565b90915550505b60006142058760030184815481106141e0576141e0615741565b90600052602060002001548560400151896001018681548110612cc357612cc3615741565b9050600087600201848154811061421e5761421e615741565b9060005260206000200154905081600014614275578188600101858154811061424957614249615741565b90600052602060002001600082825461426291906159cc565b90915550614272905082826159cc565b90505b801561438e578a80614285575085155b1561436b5760008860020185815481106142a1576142a1615741565b90600052602060002001819055506142e88a60020185815481106142c7576142c7615741565b60009182526020909120600290910201546001600160a01b03168a83613eda565b808e7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd267038b8d600201888154811061432157614321615741565b600091825260209091206002909102015460405161435e92916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a361438e565b8088600201858154811061438157614381615741565b6000918252602090912001555b5050508061439b9061576d565b9050614125565b50816144845760008a81526007602090815260408083208c8452909152812080546001600160801b0319168155906143dd6001830182615080565b6143eb600283016000615080565b6143f9600383016000615080565b5060006004828101829055600590920181905590870180549161441b83615ae0565b909155505060008a8152600860205260409020614438908a6144c9565b6144845760405162461bcd60e51b815260206004820152601a60248201527f4661696c20746f2072656d6f7665206a6f696e6564506f6f6c73000000000000604482015260640161087e565b60405133815288908a908c907f275029c7b988945c03ac5499c0d532fce79ce36efab42e1b3f180a62001cad2c9060200160405180910390a450505050505050505050565b6000613a4c8383614c6b565b60606000613a4c83614d5e565b801561458457604051630c479e6560e21b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063311e799490602401602060405180830381600087803b15801561454a57600080fd5b505af115801561455e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145829190615a8b565b505b60408051608081018252848152600060208201818152828401918252606083018681529351637686c6e960e11b815283516004820152905160248201529051604482015291516064830152907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ed0d8dd2906084015b606060405180830381600087803b15801561461f57600080fd5b505af1158015614633573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fe9190615af7565b7f0000000000000000000000000000000000000000000000000000000000000000811561485357866001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614156147825760405163bac37ef760e01b8152600481018690526001600160a01b03848116602483015282169063bac37ef790604401600060405180830381600087803b15801561470257600080fd5b505af1158015614716573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c1915061474a90899088908890600401615b25565b600060405180830381600087803b15801561476457600080fd5b505af1158015614778573d6000803e3d6000fd5b5050505050614919565b856001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614156148535760405163bf1316c160e01b81526001600160a01b0382169063bf1316c1906147ec908a9089908890600401615b25565b600060405180830381600087803b15801561480657600080fd5b505af115801561481a573d6000803e3d6000fd5b505060405163bac37ef760e01b8152600481018790526001600160a01b0386811660248301528416925063bac37ef7915060440161474a565b60405163bf1316c160e01b81526001600160a01b0382169063bf1316c190614883908a9089908890600401615b25565b600060405180830381600087803b15801561489d57600080fd5b505af11580156148b1573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c191506148e590899088908890600401615b25565b600060405180830381600087803b1580156148ff57600080fd5b505af1158015614913573d6000803e3d6000fd5b50505050505b505050505050565b6040805160a0810182528481526001600160801b03848116602083019081526000838501818152606085019182526080850187815295516398e04d7760e01b81528551600482015292519093166024830152915160448201529051606482015291516084830152907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906398e04d779060a401614605565b600082826149d08688615aa4565b6149da9190615aa4565b6149e49190615b5e565b95945050505050565b60008064e8d4a51000614a008587615aa4565b614a0a9190615b5e565b9050828111614a1a5760006149e4565b6149e483826159b5565b600081614a37575064e8d4a51000613a4c565b6000614a438486615b72565b90506149e483614a5864e8d4a5100084615aa4565b614a629190615b5e565b64e8d4a51000614dba565b60008084614a814263ffffffff1686614dd0565b614a8b91906159b5565b90506000614a9d82600160601b615aa4565b9050838111614aad576000614ab7565b614ab784826159b5565b9695505050505050565b6000613a4c8383614de7565b600084614adc57506000614ab7565b600087614ae98789615b72565b12614afd57614af88688615b72565b614aff565b875b60035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018790529293506000929091169063a51dc8f29060440160206040518083038186803b158015614b7157600080fd5b505afa158015614b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ba99190615a8b565b614bb39086615bb1565b614bbd8388615bb1565b614bc79190615c36565b90506000614bd586886159cc565b9050614be18183615c77565b9a9950505050505050505050565b6000826000018281548110614c0657614c06615741565b9060005260206000200154905092915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613fa5908490614e36565b60008181526001830160205260408120548015614d54576000614c8f6001836159b5565b8554909150600090614ca3906001906159b5565b9050818114614d08576000866000018281548110614cc357614cc3615741565b9060005260206000200154905080876000018481548110614ce657614ce6615741565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614d1957614d19615ca5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ef9565b6000915050611ef9565b606081600001805480602002602001604051908101604052809291908181526020018280548015614dae57602002820191906000526020600020905b815481526020019060010190808311614d9a575b50505050509050919050565b600081831015614dca5782613a4c565b50919050565b600081831015614de05781613a4c565b5090919050565b6000818152600183016020526040812054614e2e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ef9565b506000611ef9565b6000614e8b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614f089092919063ffffffff16565b805190915015613fa55780806020019051810190614ea99190615ac3565b613fa55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161087e565b6060614f178484600085614f1f565b949350505050565b606082471015614f805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161087e565b843b614fce5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161087e565b600080866001600160a01b03168587604051614fea9190615ce7565b60006040518083038185875af1925050503d8060008114615027576040519150601f19603f3d011682016040523d82523d6000602084013e61502c565b606091505b509150915061503c828286615047565b979650505050505050565b60608315615056575081613a4c565b8251156150665782518084602001fd5b8160405162461bcd60e51b815260040161087e9190615d03565b508054600082559060005260206000209081019061509e91906150ec565b50565b8280548282559060005260206000209081019282156150dc579160200282015b828111156150dc5782518255916020019190600101906150c1565b506150e89291506150ec565b5090565b5b808211156150e857600081556001016150ed565b803563ffffffff8116811461511557600080fd5b919050565b60008083601f84011261512c57600080fd5b5081356001600160401b0381111561514357600080fd5b6020830191508360208260051b850101111561515e57600080fd5b9250929050565b60008060008060008060a0878903121561517e57600080fd5b8635955061518e60208801615101565b945061519c60408801615101565b935060608701356001600160401b038111156151b757600080fd5b6151c389828a0161511a565b979a9699509497949695608090950135949350505050565b6001600160a01b038116811461509e57600080fd5b60006020828403121561520257600080fd5b8135613a4c816151db565b6000806000806040858703121561522357600080fd5b84356001600160401b038082111561523a57600080fd5b6152468883890161511a565b9096509450602087013591508082111561525f57600080fd5b5061526c8782880161511a565b95989497509550505050565b60006020828403121561528a57600080fd5b5035919050565b600081518084526020808501945080840160005b838110156152c1578151875295820195908201906001016152a5565b509495945050505050565b6001600160a01b03898116825263ffffffff8981166020808501919091529089166040840152606083018890526080830187905260a0830186905261010060c08401819052855190840181905260009261012085019287810192855b81811015615346578451841686529482019493820193600101615328565b505050505082810360e084015261535d8185615291565b9b9a5050505050505050505050565b60008060008060006060868803121561538457600080fd5b8535945060208601356001600160401b03808211156153a257600080fd5b6153ae89838a0161511a565b909650945060408801359150808211156153c757600080fd5b506153d48882890161511a565b969995985093965092949392505050565b6000806000606084860312156153fa57600080fd5b505081359360208301359350604090920135919050565b602081526000613a4c6020830184615291565b801515811461509e57600080fd5b60006020828403121561544457600080fd5b8135613a4c81615424565b6000806020838503121561546257600080fd5b82356001600160401b0381111561547857600080fd5b6154848582860161511a565b90969095509350505050565b6000806000604084860312156154a557600080fd5b8335925060208401356001600160401b038111156154c257600080fd5b6154ce8682870161511a565b9497909650939450505050565b600080604083850312156154ee57600080fd5b82356154f9816151db565b9150602083013561550981615424565b809150509250929050565b60008060008060008060008060c0898b03121561553057600080fd5b883561553b816151db565b975061554960208a01615101565b965061555760408a01615101565b955060608901356001600160401b038082111561557357600080fd5b61557f8c838d0161511a565b909750955060808b013591508082111561559857600080fd5b506155a58b828c0161511a565b999c989b50969995989497949560a00135949350505050565b600080604083850312156155d157600080fd5b50508035926020909101359150565b600080600080600080600060c0888a0312156155fb57600080fd5b87356001600160401b0381111561561157600080fd5b61561d8a828b0161511a565b9098509650506020880135945060408801359350606088013561563f816151db565b9250608088013561564f81615424565b8092505060a0880135905092959891949750929550565b6001600160801b038116811461509e57600080fd5b600080600080600080600061010080898b03121561569857600080fd5b8835975060208901356156aa81615666565b965060408901359550606089013594506080890135935060a08901356156cf81615424565b92508881018a10156156e057600080fd5b5060c08801905092959891949750929550565b83815260606020820152600061570c6060830185615291565b8281036040840152614ab78185615291565b6020808252600990820152683337b93134b23232b760b91b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141561578157615781615757565b5060010190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600e908201526d0d2dcecc2d8d2c840d8cadccee8d60931b604082015260600190565b6000808335601e198436030181126157fe57600080fd5b8301803591506001600160401b0382111561581857600080fd5b60200191503681900382131561515e57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051602081016001600160401b03811182821017156158655761586561582d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156158935761589361582d565b604052919050565b600060208083850312156158ae57600080fd5b82356001600160401b03808211156158c557600080fd5b81850191508282870312156158d957600080fd5b6158e1615843565b8235828111156158f057600080fd5b80840193505086601f84011261590557600080fd5b8235828111156159175761591761582d565b8060051b925061592885840161586b565b818152928401850192858101908985111561594257600080fd5b948601945b8486101561596057853582529486019490860190615947565b83525090979650505050505050565b6020808252600f908201526e506f6f6c206e6f742065786973747360881b604082015260600190565b6000602082840312156159aa57600080fd5b8151613a4c81615666565b6000828210156159c7576159c7615757565b500390565b600082198211156159df576159df615757565b500190565b60208082526018908201527f7370656369616c20666561747572652064697361626c65640000000000000000604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060208284031215615a5157600080fd5b8151613a4c816151db565b60008060408385031215615a6f57600080fd5b8251615a7a816151db565b6020840151909250615509816151db565b600060208284031215615a9d57600080fd5b5051919050565b6000816000190483118215151615615abe57615abe615757565b500290565b600060208284031215615ad557600080fd5b8151613a4c81615424565b600081615aef57615aef615757565b506000190190565b600080600060608486031215615b0c57600080fd5b8351925060208401519150604084015190509250925092565b6001600160a01b0393841681526020810192909252909116604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082615b6d57615b6d615b48565b500490565b60008083128015600160ff1b850184121615615b9057615b90615757565b6001600160ff1b0384018313811615615bab57615bab615757565b50500390565b60006001600160ff1b0381841382841380821686840486111615615bd757615bd7615757565b600160ff1b6000871282811687830589121615615bf657615bf6615757565b60008712925087820587128484161615615c1257615c12615757565b87850587128184161615615c2857615c28615757565b505050929093029392505050565b600080821280156001600160ff1b0384900385131615615c5857615c58615757565b600160ff1b8390038412811615615c7157615c71615757565b50500190565b600082615c8657615c86615b48565b600160ff1b821460001984141615615ca057615ca0615757565b500590565b634e487b7160e01b600052603160045260246000fd5b60005b83811015615cd6578181015183820152602001615cbe565b83811115613f8b5750506000910152565b60008251615cf9818460208701615cbb565b9190910192915050565b6020815260008251806020840152615d22816040850160208701615cbb565b601f01601f1916919091016040019291505056fea2646970667358221220de26c0958ae74edf1ddc20c03f2316cd4bc437fc1d1fcce795748fd6ecd805eb64736f6c63430008090033000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4800000000000000000000000006afeb9edd6cf44fa8e89b1eee28284e6dd7705c8
Deployed Bytecode
0x6080604052600436106101fd5760003560e01c806375829def1161010d578063b36b26c5116100a0578063c7ca58701161006f578063c7ca58701461074b578063d1941b061461076b578063dc168a921461078b578063e7762a0c146107ba578063f851a4401461082f57600080fd5b8063b36b26c5146106bc578063b63ff916146106dc578063b82562751461070c578063bb5ae7751461072c57600080fd5b806399fbab88116100dc57806399fbab881461052f578063ac4afa381461058e578063affe737914610631578063b221e5fd1461064657600080fd5b806375829def146104af5780638bcc4166146104cf57806391fb2f15146104ef578063983d95ce1461050f57600080fd5b806347ccca021161019057806361657b121161015f57806361657b121461040f57806366b5a6641461042f578063683f3eda1461044f5780636d44a3b21461046f578063705b5bef1461048f57600080fd5b806347ccca021461036e57806349b35168146103a257806350523cea146103cf578063598b8e71146103ef57600080fd5b80632f380b35116101cc5780632f380b35146102b45780633fc8cef3146102e857806341e817ab14610334578063430ccd9b1461035457600080fd5b8063078ded5d14610209578063081e3eda1461022b57806313e7c9d814610254578063180f80361461029457600080fd5b3661020457005b600080fd5b34801561021557600080fd5b50610229610224366004615165565b61084f565b005b34801561023757600080fd5b5061024160045481565b6040519081526020015b60405180910390f35b34801561026057600080fd5b5061028461026f3660046151f0565b60026020526000908152604090205460ff1681565b604051901515815260200161024b565b3480156102a057600080fd5b506102296102af36600461520d565b610b0b565b3480156102c057600080fd5b506102d46102cf366004615278565b610c8d565b60405161024b9897969594939291906152cc565b3480156102f457600080fd5b5061031c7f000000000000000000000000530000000000000000000000000000000000000481565b6040516001600160a01b03909116815260200161024b565b34801561034057600080fd5b5061022961034f36600461536c565b610e37565b34801561036057600080fd5b50600b546102849060ff1681565b34801561037a57600080fd5b5061031c7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081565b3480156103ae57600080fd5b506103c26103bd3660046153e5565b61118b565b60405161024b9190615411565b3480156103db57600080fd5b506102296103ea366004615432565b6112e3565b3480156103fb57600080fd5b5061022961040a36600461544f565b611361565b34801561041b57600080fd5b5061022961042a36600461520d565b6113d3565b34801561043b57600080fd5b5061022961044a36600461536c565b611507565b34801561045b57600080fd5b5061022961046a366004615490565b6115d8565b34801561047b57600080fd5b5061022961048a3660046154db565b611674565b34801561049b57600080fd5b506103c26104aa366004615278565b6116fd565b3480156104bb57600080fd5b506102296104ca3660046151f0565b6117b5565b3480156104db57600080fd5b506102296104ea3660046151f0565b61184f565b3480156104fb57600080fd5b5061022961050a366004615514565b6118c7565b34801561051b57600080fd5b5061022961052a36600461544f565b611b60565b34801561053b57600080fd5b5061056f61054a366004615278565b600660205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161024b565b34801561059a57600080fd5b506105f06105a9366004615278565b60056020526000908152604090208054600182015460038301546004909301546001600160a01b0383169363ffffffff600160a01b8504811694600160c01b900416929186565b604080516001600160a01b0397909716875263ffffffff958616602088015293909416928501929092526060840152608083015260a082015260c00161024b565b34801561063d57600080fd5b50610229611e30565b34801561065257600080fd5b506106976106613660046155be565b60076020908152600092835260408084209091529082529020805460048201546005909201546001600160801b03909116919083565b604080516001600160801b03909416845260208401929092529082015260600161024b565b3480156106c857600080fd5b506103c26106d73660046151f0565b611ed5565b3480156106e857600080fd5b506102846106f7366004615278565b600a6020526000908152604090205460ff1681565b34801561071857600080fd5b506102296107273660046155e0565b611eff565b34801561073857600080fd5b50600b5461028490610100900460ff1681565b34801561075757600080fd5b5061022961076636600461567b565b6122ad565b34801561077757600080fd5b5061022961078636600461544f565b6126d6565b34801561079757600080fd5b506107ab6107a63660046155be565b612b10565b60405161024b939291906156f3565b3480156107c657600080fd5b506107da6107d53660046155be565b612d81565b60405161024b9190600060c0820190506001600160801b0383511682526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561083b57600080fd5b5060015461031c906001600160a01b031681565b3360009081526002602052604090205460ff166108875760405162461bcd60e51b815260040161087e9061571e565b60405180910390fd5b6000868152600560205260409020805463ffffffff428116600160a01b9092041611806108c45750805463ffffffff428116600160c01b90920416105b6109105760405162461bcd60e51b815260206004820152601960248201527f72656e65773a20696e76616c696420706f6f6c20737461746500000000000000604482015260640161087e565b6002810154831461095b5760405162461bcd60e51b81526020600482015260156024820152740e4cadccaee7440d2dcecc2d8d2c840d8cadccee8d605b1b604482015260640161087e565b4263ffffffff168663ffffffff1611801561098157508563ffffffff168563ffffffff16115b6109c45760405162461bcd60e51b815260206004820152601460248201527372656e65773a20696e76616c69642074696d657360601b604482015260640161087e565b600481015415610a0f5760405162461bcd60e51b815260206004820152601660248201527572656e65773a20706f6f6c20686173207374616b657360501b604482015260640161087e565b805463ffffffff868116600160c01b0263ffffffff60c01b19918916600160a01b029190911667ffffffffffffffff60a01b1990921691909117178155600060018201819055600382018390555b83811015610ab757848482818110610a7757610a77615741565b90506020020135826002018281548110610a9357610a93615741565b6000918252602090912060016002909202010155610ab08161576d565b9050610a5d565b506040805163ffffffff80891682528716602082015290810183905287907feda7bcc7e20158ff9fa87a4200758e927bbb3c8823e648403bdd6053b96dd0ad9060600160405180910390a250505050505050565b60026000541415610b2e5760405162461bcd60e51b815260040161087e90615788565b60026000558281808214610b545760405162461bcd60e51b815260040161087e906157bf565b60005b85811015610c7f573360066000898985818110610b7657610b76615741565b60209081029290920135835250810191909152604001600020546001600160a01b031614610bdb5760405162461bcd60e51b81526020600482015260126024820152713430b93b32b9ba1d103737ba1037bbb732b960711b604482015260640161087e565b6000858583818110610bef57610bef615741565b9050602002810190610c0191906157e7565b810190610c0e919061589b565b905060005b815151811015610c6c57610c5c898985818110610c3257610c32615741565b9050602002013583600001518381518110610c4f57610c4f615741565b6020026020010151612fc9565b610c658161576d565b9050610c13565b505080610c789061576d565b9050610b57565b505060016000555050505050565b6000818152600560205260409020805460018201546003830154600484015460028501546001600160a01b0385169563ffffffff600160a01b8704811696600160c01b900416949392916060918291806001600160401b03811115610cf457610cf461582d565b604051908082528060200260200182016040528015610d1d578160200160208202803683370190505b509350806001600160401b03811115610d3857610d3861582d565b604051908082528060200260200182016040528015610d61578160200160208202803683370190505b50925060005b81811015610e2957826002018181548110610d8457610d84615741565b600091825260209091206002909102015485516001600160a01b0390911690869083908110610db557610db5615741565b60200260200101906001600160a01b031690816001600160a01b031681525050826002018181548110610dea57610dea615741565b906000526020600020906002020160010154848281518110610e0e57610e0e615741565b6020908102919091010152610e228161576d565b9050610d67565b505050919395975091939597565b60026000541415610e5a5760405162461bcd60e51b815260040161087e90615788565b60026000558281808214610e805760405162461bcd60e51b815260040161087e906157bf565b8660045411610ea15760405162461bcd60e51b815260040161087e9061596f565b6000878152600560205260409020805463ffffffff428116600160a01b9092041611801590610ee357508054600160c01b900463ffffffff164263ffffffff16105b610f1e5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b60005b8681101561117b5733600660008a8a85818110610f4057610f40615741565b60209081029290920135835250810191909152604001600020546001600160a01b031614610f9c5760405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b604482015260640161087e565b6003546001600160a01b0316635c6d96a97f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4808a8a85818110610fe057610fe0615741565b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602002919091013560248301525060440160206040518083038186803b15801561102d57600080fd5b505afa158015611041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110659190615998565b6001600160801b0316600660008a8a8581811061108457611084615741565b905060200201358152602001908152602001600020600101819055506000600760008a8a858181106110b8576110b8615741565b90506020020135815260200190815260200160002060008b8152602001908152602001600020905080600501546000141561112e5761112989898481811061110257611102615741565b905060200201358b89898681811061111c5761111c615741565b9050602002013586613303565b61116a565b61116a89898481811061114357611143615741565b905060200201358b89898681811061115d5761115d615741565b90506020020135866137a9565b506111748161576d565b9050610f21565b5050600160005550505050505050565b6060818311156111d35760405162461bcd60e51b81526020600482015260136024820152720cce4deda92dcc8caf0407c40e8de92dcc8caf606b1b604482015260640161087e565b60008481526008602052604090206111ea90613a36565b821061122c5760405162461bcd60e51b81526020600482015260116024820152700e8de92dcc8caf0407c7a40d8cadccee8d607b1b604482015260640161087e565b61123683836159b5565b6112419060016159cc565b6001600160401b038111156112585761125861582d565b604051908082528060200260200182016040528015611281578160200160208202803683370190505b509050825b8281116112db5760008581526008602052604090206112a59082613a40565b826112b086846159b5565b815181106112c0576112c0615741565b60209081029190910101526112d48161576d565b9050611286565b509392505050565b6001546001600160a01b0316331461130d5760405162461bcd60e51b815260040161087e9061571e565b600b80548215156101000261ff00199091161790556040517f294aa6bf970997b8c55a069e787eae16138f63ad315362696337d14ef42281ea9061135690831515815260200190565b60405180910390a150565b600260005414156113845760405162461bcd60e51b815260040161087e90615788565b60026000819055506113ca600083838080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509250613a53915050565b50506001600055565b6001546001600160a01b031633146113fd5760405162461bcd60e51b815260040161087e9061571e565b828180821461141e5760405162461bcd60e51b815260040161087e906157bf565b60005b858110156114fe5761147287878381811061143e5761143e615741565b905060200201602081019061145391906151f0565b3387878581811061146657611466615741565b90506020020135613eda565b84848281811061148457611484615741565b905060200201357f4042b7789d1f6c4d5a798b447cfb918e82b64dd68b81d78ddc4dd1944ba5c51c8888848181106114be576114be615741565b90506020020160208101906114d391906151f0565b6040516001600160a01b03909116815260200160405180910390a26114f78161576d565b9050611421565b50505050505050565b6002600054141561152a5760405162461bcd60e51b815260040161087e90615788565b600260005582818082146115505760405162461bcd60e51b815260040161087e906157bf565b86600454116115715760405162461bcd60e51b815260040161087e9061596f565b60005b858110156115c9576115b987878381811061159157611591615741565b90506020020135898787858181106115ab576115ab615741565b905060200201356001613faa565b6115c28161576d565b9050611574565b50506001600055505050505050565b600b54610100900460ff166115ff5760405162461bcd60e51b815260040161087e906159e4565b600260005414156116225760405162461bcd60e51b815260040161087e90615788565b600260008190555061166a8383838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613a53915050565b5050600160005550565b6001546001600160a01b0316331461169e5760405162461bcd60e51b815260040161087e9061571e565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915591519182527f2ee52be9d342458b3d25e07faada7ff9bc06723b4aa24edb6321ac1316b8a9dd910160405180910390a25050565b60008181526008602052604081206060919061171890613a36565b9050806001600160401b038111156117325761173261582d565b60405190808252806020026020018201604052801561175b578160200160208202803683370190505b50915060005b818110156117ae5760008481526008602052604090206117819082613a40565b83828151811061179357611793615741565b60209081029190910101526117a78161576d565b9050611761565b5050919050565b6001546001600160a01b031633146117df5760405162461bcd60e51b815260040161087e9061571e565b6001600160a01b0381166118055760405162461bcd60e51b815260040161087e9061571e565b600180546001600160a01b0319166001600160a01b0383169081179091556040517fda7b0a7bc965abdec8a1a995575a891838264c2968e14bd456c5391827b7aa3090600090a250565b6001546001600160a01b031633146118795760405162461bcd60e51b815260040161087e9061571e565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f7b9adf13852d5b3e153f2a442b9aa3a4570da8f9b9046c60410b17e8034fe33c90602001611356565b3360009081526002602052604090205460ff166118f65760405162461bcd60e51b815260040161087e9061571e565b83828082146119175760405162461bcd60e51b815260040161087e906157bf565b4263ffffffff168963ffffffff161015801561193e57508863ffffffff168863ffffffff16115b6119835760405162461bcd60e51b8152602060048201526016602482015275616464506f6f6c3a20696e76616c69642074696d657360501b604482015260640161087e565b6000600454905060006005600083815260200190815260200160002090508b8160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8160000160146101000a81548163ffffffff021916908363ffffffff160217905550898160000160186101000a81548163ffffffff021916908363ffffffff1602179055506000816001018190555084816003018190555060005b88811015611ae3578160020160405180604001604052808c8c85818110611a4f57611a4f615741565b9050602002016020810190611a6491906151f0565b6001600160a01b031681526020018a8a85818110611a8457611a84615741565b60209081029290920135909252835460018082018655600095865294829020845160029092020180546001600160a01b0319166001600160a01b0390921691909117815592015191909201555080611adb8161576d565b915050611a26565b5060048054906000611af48361576d565b9091555050604080516001600160a01b038e16815263ffffffff8d811660208301528c168183015260608101879052905183917f251199ba7b3e7a12b779b3f606eaf369cecc0eac8bcbacaadcf08079e8c5940f919081900360800190a2505050505050505050505050565b60026000541415611b835760405162461bcd60e51b815260040161087e90615788565b6002600090815533905b82811015611e2557816001600160a01b031660066000868685818110611bb557611bb5615741565b60209081029290920135835250810191909152604001600020546001600160a01b031614611c1b5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b611c4e60086000868685818110611c3457611c34615741565b905060200201358152602001908152602001600020613a36565b15611c9b5760405162461bcd60e51b815260206004820152601860248201527f77697468647261773a206e6f7420657869746564207965740000000000000000604482015260640161087e565b60066000858584818110611cb157611cb1615741565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560010155611d1a848483818110611cf357611cf3615741565b6001600160a01b0386166000908152600960209081526040909120939102013590506144c9565b611d2357600080fd5b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03166323b872dd3084878786818110611d6657611d66615741565b905060200201356040518463ffffffff1660e01b8152600401611d8b93929190615a1b565b600060405180830381600087803b158015611da557600080fd5b505af1158015611db9573d6000803e3d6000fd5b50505050838382818110611dcf57611dcf615741565b6040516001600160a01b038616815260209182029390930135927f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436492500160405180910390a2611e1e8161576d565b9050611b8d565b505060016000555050565b6001546001600160a01b03163314611e5a5760405162461bcd60e51b815260040161087e9061571e565b600b5460ff1615611e9d5760405162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015260640161087e565b600b805460ff191660011790556040517f1d8c7af3ae0426053ea40080543aa1cbe5bea5cdb7a55888b4cca96eea0493e490600090a1565b6001600160a01b0381166000908152600960205260409020606090611ef9906144d5565b92915050565b60026000541415611f225760405162461bcd60e51b815260040161087e90615788565b6002600055600b54610100900460ff16611f4e5760405162461bcd60e51b815260040161087e906159e4565b804263ffffffff161115611f985760405162461bcd60e51b815260206004820152601160248201527018db185a5b5199594e88195e1c1a5c9959607a1b604482015260640161087e565b6000878790509050600080856001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611fdc57600080fd5b505afa158015611ff0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120149190615a3f565b866001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561204d57600080fd5b505afa158015612061573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120859190615a3f565b9150915060005b8381101561228d5733600660008d8d858181106120ab576120ab615741565b60209081029290920135835250810191909152604001600020546001600160a01b0316146121115760405162461bcd60e51b815260206004820152601360248201527231b630b4b6a332b29d103737ba1037bbb732b960691b604482015260640161087e565b60035460009081906001600160a01b0316626349fb7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4808f8f8781811061215957612159615741565b6040516001600160e01b031960e087901b1681526001600160a01b0390941660048501526020029190910135602483015250604401604080518083038186803b1580156121a557600080fd5b505afa1580156121b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121dd9190615a5c565b91509150846001600160a01b0316826001600160a01b03161480156122135750836001600160a01b0316816001600160a01b0316145b61225f5760405162461bcd60e51b815260206004820152601e60248201527f636c61696d4665653a20746f6b656e2070616972206e6f74206d617463680000604482015260640161087e565b6122838d8d8581811061227457612274615741565b905060200201358860016144e2565b505060010161208c565b5061229c82828a8a338a614657565b505060016000555050505050505050565b600260005414156122d05760405162461bcd60e51b815260040161087e90615788565b6002600055600b54610100900460ff166122fc5760405162461bcd60e51b815260040161087e906159e4565b824263ffffffff1611156123525760405162461bcd60e51b815260206004820152601860248201527f72656d6f76654c69717569646974793a20657870697265640000000000000000604482015260640161087e565b6000878152600660205260409020546001600160a01b031633146123b85760405162461bcd60e51b815260206004820152601a60248201527f72656d6f76654c69717569646974793a206e6f74206f776e6572000000000000604482015260640161087e565b600354604051635c6d96a960e01b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018a90526000921690635c6d96a99060440160206040518083038186803b15801561242557600080fd5b505afa158015612439573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245d9190615998565b6001600160801b031690506000876001600160801b031611801561248a575080876001600160801b031611155b6124e15760405162461bcd60e51b815260206004820152602260248201527f72656d6f76654c69717569646974793a20696e76616c6964206c697175696469604482015261747960f01b606482015260840161087e565b6124f46001600160801b038816826159b5565b6000898152600660209081526040808320600101849055600890915281209192509061251f906144d5565b905060005b81518110156125e35760008a81526007602052604081208351829085908590811061255157612551615741565b60200260200101518152602001908152602001600020600501549050600084821161257d576000612587565b61258785836159b5565b905080156125d9576125d98c8585815181106125a5576125a5615741565b602002602001015183896001600281106125c1576125c1615741565b6020020160208101906125d49190615432565b613faa565b5050600101612524565b50600354604051626349fb60e01b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018c90526000928392911690626349fb90604401604080518083038186803b15801561265157600080fd5b505afa158015612665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126899190615a5c565b915091506126988b8b89614921565b6126a56020860186615432565b156126b6576126b68b8860006144e2565b6126c482828b8b338b614657565b50506001600055505050505050505050565b600260005414156126f95760405162461bcd60e51b815260040161087e90615788565b60026000908155600b54339160ff909116905b83811015612b0457826001600160a01b03166006600087878581811061273457612734615741565b60209081029290920135835250810191909152604001600020546001600160a01b03161461279a5760405162461bcd60e51b81526020600482015260136024820152723bb4ba34323930bb9d103737ba1037bbb732b960691b604482015260640161087e565b6001600a60008787858181106127b2576127b2615741565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055506000612813600860008888868181106127f9576127f9615741565b9050602002013581526020019081526020016000206144d5565b905060005b81518110156128f057600082828151811061283557612835615741565b60209081029190910181015160008181526005909252604082206004018054600019019055915060079089898781811061287157612871615741565b602090810292909201358352508181019290925260409081016000908120848252909252812080546001600160801b0319168155906128b36001830182615080565b6128c1600283016000615080565b6128cf600383016000615080565b50600060048201819055600590910155506128e98161576d565b9050612818565b506006600087878581811061290757612907615741565b60209081029290920135835250810191909152604001600090812080546001600160a01b03191681556001015582612a015761297586868481811061294e5761294e615741565b6001600160a01b0388166000908152600960209081526040909120939102013590506144c9565b61297e57600080fd5b60005b81518110156129ff57600082828151811061299e5761299e615741565b602002602001015190506129e581600860008b8b898181106129c2576129c2615741565b9050602002013581526020019081526020016000206144c990919063ffffffff16565b6129ee57600080fd5b506129f88161576d565b9050612981565b505b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03166323b872dd3086898987818110612a4457612a44615741565b905060200201356040518463ffffffff1660e01b8152600401612a6993929190615a1b565b600060405180830381600087803b158015612a8357600080fd5b505af1158015612a97573d6000803e3d6000fd5b50505050858583818110612aad57612aad615741565b6040516001600160a01b038816815260209182029390930135927f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd969592500160405180910390a250612afd8161576d565b905061270c565b50506001600055505050565b600081815260056020818152604080842086855260078352818520868652909252832091820154606092839291612b895760405162461bcd60e51b815260206004820152601b60248201527f67657455736572496e666f3a206e6f74206a6f696e6564207965740000000000604482015260640161087e565b60028201546001600160401b03811115612ba557612ba561582d565b604051908082528060200260200182016040528015612bce578160200160208202803683370190505b5060028301549094506001600160401b03811115612bee57612bee61582d565b604051908082528060200260200182016040528015612c17578160200160208202803683370190505b5092506000612c268888612d81565b905060005b6002840154811015612d6f576000612c778460050154866002018481548110612c5657612c56615741565b906000526020600020906002020160010154856060015186608001516149c2565b90506000612cd382866003018581548110612c9457612c94615741565b9060005260206000200154612ca991906159cc565b8560400151876001018681548110612cc357612cc3615741565b90600052602060002001546149ed565b905080856002018481548110612ceb57612ceb615741565b9060005260206000200154612d0091906159cc565b888481518110612d1257612d12615741565b602002602001018181525050846001018381548110612d3357612d33615741565b9060005260206000200154878481518110612d5057612d50615741565b602002602001018181525050505080612d689061576d565b9050612c2b565b50816005015495505050509250925092565b612dc36040518060c0016040528060006001600160801b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000828152600560209081526040808320868452600783528184208685529092529182902060035482549351632106297960e11b8152929391926001600160a01b039182169263420c52f292612e42929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908a90600401615a1b565b60206040518083038186803b158015612e5a57600080fd5b505afa158015612e6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e929190615998565b6001600160801b0316835260035482546040516339bb866b60e11b81526001600160a01b03928316926373770cd692612ef4929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908a90600401615a1b565b60206040518083038186803b158015612f0c57600080fd5b505afa158015612f20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f449190615a8b565b6020840181905260048201546003840154612f60929190614a24565b604084015281546001830154612f8e9163ffffffff600160a01b8204811692600160c01b9092041690614a6d565b6060840152805483516001600160801b03918216900316608084018190526005820154612fbb9190615aa4565b60a084015250909392505050565b8060045411612fea5760405162461bcd60e51b815260040161087e9061596f565b60008181526005602081815260408084208685526006835281852054600784528286208787529093529320918201546001600160a01b0390911691906130725760405162461bcd60e51b815260206004820152601760248201527f686172766573743a206e6f74206a6f696e656420796574000000000000000000604482015260640161087e565b600061307e8686612d81565b90508060a0015184600101600082825461309891906159cc565b9091555050805182546001600160801b0319166001600160801b0390911617825560005b60028501548110156114fe5760006130e78460050154876002018481548110612c5657612c56615741565b90508015613161578084600301838154811061310557613105615741565b90600052602060002001600082825461311e91906159cc565b925050819055508086600201838154811061313b5761313b615741565b9060005260206000209060020201600101600082825461315b91906159b5565b90915550505b60006131a085600301848154811061317b5761317b615741565b90600052602060002001548560400151876001018681548110612cc357612cc3615741565b90506000818660020185815481106131ba576131ba615741565b90600052602060002001546131cf91906159cc565b905080156132ef57811561321257818660010185815481106131f3576131f3615741565b90600052602060002001600082825461320c91906159cc565b90915550505b600086600201858154811061322957613229615741565b906000526020600020018190555061327088600201858154811061324f5761324f615741565b60009182526020909120600290910201546001600160a01b03168883613eda565b808a7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd26703898b60020188815481106132a9576132a9615741565b60009182526020909120600290910201546040516132e692916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a35b505050806132fc9061576d565b90506130bc565b600084815260066020908152604080832060078352818420878552909252918290206003548454935163d7aee3bd60e01b8152929391926001600160a01b039182169263d7aee3bd9261337f929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908b90600401615a1b565b60206040518083038186803b15801561339757600080fd5b505afa1580156133ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cf9190615ac3565b6134105760405162461bcd60e51b81526020600482015260126024820152711a9bda5b8e881a5b9d985b1a59081c1bdbdb60721b604482015260640161087e565b8315801590613423575081600101548411155b6134635760405162461bcd60e51b81526020600482015260116024820152706a6f696e3a20696e76616c6964206c697160781b604482015260640161087e565b6003548354604051632106297960e11b81526001600160a01b039283169263420c52f2926134ba929116907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480908b90600401615a1b565b60206040518083038186803b1580156134d257600080fd5b505afa1580156134e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061350a9190615998565b81546001600160801b0319166001600160801b039190911617815560028301546001600160401b038111156135415761354161582d565b60405190808252806020026020018201604052801561356a578160200160208202803683370190505b5080516135819160018401916020909101906150a1565b5060028301546001600160401b0381111561359e5761359e61582d565b6040519080825280602002602001820160405280156135c7578160200160208202803683370190505b5080516135de9160028401916020909101906150a1565b5060028301546001600160401b038111156135fb576135fb61582d565b604051908082528060200260200182016040528015613624578160200160208202803683370190505b50805161363b9160038401916020909101906150a1565b506003830154156136f05760035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018990529091169063a51dc8f29060440160206040518083038186803b1580156136b257600080fd5b505afa1580156136c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ea9190615a8b565b60048201555b600581018490556004830180549060006137098361576d565b909155505060008681526008602052604090206137269086614ac1565b6137725760405162461bcd60e51b815260206004820152601760248201527f4661696c20746f20616464206a6f696e6564506f6f6c73000000000000000000604482015260640161087e565b8385877f5d48292d83151281e6ea967de9fd35716c713dc76c11beb42d78ed5110270f7360405160405180910390a4505050505050565b60008481526006602090815260408083206007835281842087855290925290912083158015906137eb5750600182015460058201546137e890866159cc565b11155b61382b5760405162461bcd60e51b815260206004820152601160248201527073796e633a20696e76616c6964206c697160781b604482015260640161087e565b60006138378787612d81565b905060005b60028501548110156139815760006138678460050154876002018481548110612c5657612c56615741565b905080156138e1578084600301838154811061388557613885615741565b90600052602060002001600082825461389e91906159cc565b92505081905550808660020183815481106138bb576138bb615741565b906000526020600020906002020160010160008282546138db91906159b5565b90915550505b60006138fb85600301848154811061317b5761317b615741565b9050801561396e578085600101848154811061391957613919615741565b90600052602060002001600082825461393291906159cc565b925050819055508085600201848154811061394f5761394f615741565b90600052602060002001600082825461396891906159cc565b90915550505b50508061397a9061576d565b905061383c565b508060a0015184600101600082825461399a91906159cc565b9091555050805182546001600160801b0319166001600160801b0390911617825560048201546020820151600386015460058501546139dd93929190898c614acd565b8260040181905550848260050160008282546139f991906159cc565b90915550506040518590879089907ff31cd5db84a4ab16cd339c510d5a60c63ef5818c538aa67046f5bc0dca794cd390600090a450505050505050565b6000611ef9825490565b6000613a4c8383614bef565b9392505050565b600b5460ff1615613a9f5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b8015613b51578260045411613ac65760405162461bcd60e51b815260040161087e9061596f565b600083815260056020526040902054429063ffffffff808316600160a01b9092041611801590613b14575060008481526005602052604090205463ffffffff600160c01b9091048116908216105b613b4f5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642074696d6560a01b604482015260640161087e565b505b3360005b8351811015613ed357600a6000858381518110613b7457613b74615741565b60209081029190910181015182528101919091526040016000205460ff1615613bd85760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1b1bddd959081d1bc819195c1bdcda5d60521b604482015260640161087e565b613c28848281518110613bed57613bed615741565b602002602001015160096000856001600160a01b03166001600160a01b03168152602001908152602001600020614ac190919063ffffffff16565b613c3157600080fd5b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03166323b872dd8330878581518110613c7457613c74615741565b60200260200101516040518463ffffffff1660e01b8152600401613c9a93929190615a1b565b600060405180830381600087803b158015613cb457600080fd5b505af1158015613cc8573d6000803e3d6000fd5b50505050838181518110613cde57613cde615741565b60200260200101517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c83604051613d2491906001600160a01b0391909116815260200190565b60405180910390a28160066000868481518110613d4357613d43615741565b6020908102919091018101518252810191909152604001600090812080546001600160a01b0319166001600160a01b03938416179055600354865191921690635c6d96a9907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48090889086908110613dbc57613dbc615741565b60200260200101516040518363ffffffff1660e01b8152600401613df59291906001600160a01b03929092168252602082015260400190565b60206040518083038186803b158015613e0d57600080fd5b505afa158015613e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e459190615998565b9050806001600160801b031660066000878581518110613e6757613e67615741565b60200260200101518152602001908152602001600020600101819055508315613eca57613eca858381518110613e9f57613e9f615741565b602002602001015187836001600160801b0316600560008b8152602001908152602001600020613303565b50600101613b55565b5050505050565b6001600160a01b038316613f91576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613f35576040519150601f19603f3d011682016040523d82523d6000602084013e613f3a565b606091505b5050905080613f8b5760405162461bcd60e51b815260206004820152601c60248201527f7472616e736665722072657761726420746f6b656e206661696c656400000000604482015260640161087e565b50505050565b613fa56001600160a01b0384168383614c19565b505050565b600083815260056020908152604080832087845260068352818420546007845282852088865290935292206001600160a01b03909116903382148061401c57508254600160c01b900463ffffffff164263ffffffff1611801561401c57503360009081526002602052604090205460ff165b6140725760405162461bcd60e51b815260206004820152602160248201527f657869743a206e6f74206f776e6572206f7220706f6f6c206e6f7420656e64656044820152601960fa1b606482015260840161087e565b600581015485158015906140865750808611155b6140c65760405162461bcd60e51b8152602060048201526011602482015270657869743a20696e76616c6964206c697160781b604482015260640161087e565b60006140d287836159b5565b905060006140e08a8a612d81565b90508060a001518660010160008282546140fa91906159cc565b9091555050805184546001600160801b0319166001600160801b039091161784556005840182905560005b60028701548110156143a257600061414c85896002018481548110612c5657612c56615741565b905080156141c6578086600301838154811061416a5761416a615741565b90600052602060002001600082825461418391906159cc565b92505081905550808860020183815481106141a0576141a0615741565b906000526020600020906002020160010160008282546141c091906159b5565b90915550505b60006142058760030184815481106141e0576141e0615741565b90600052602060002001548560400151896001018681548110612cc357612cc3615741565b9050600087600201848154811061421e5761421e615741565b9060005260206000200154905081600014614275578188600101858154811061424957614249615741565b90600052602060002001600082825461426291906159cc565b90915550614272905082826159cc565b90505b801561438e578a80614285575085155b1561436b5760008860020185815481106142a1576142a1615741565b90600052602060002001819055506142e88a60020185815481106142c7576142c7615741565b60009182526020909120600290910201546001600160a01b03168a83613eda565b808e7f1ec92956b13869de207e232e60c65e35826c5e12b7fdc6d70b083b5a4fd267038b8d600201888154811061432157614321615741565b600091825260209091206002909102015460405161435e92916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a361438e565b8088600201858154811061438157614381615741565b6000918252602090912001555b5050508061439b9061576d565b9050614125565b50816144845760008a81526007602090815260408083208c8452909152812080546001600160801b0319168155906143dd6001830182615080565b6143eb600283016000615080565b6143f9600383016000615080565b5060006004828101829055600590920181905590870180549161441b83615ae0565b909155505060008a8152600860205260409020614438908a6144c9565b6144845760405162461bcd60e51b815260206004820152601a60248201527f4661696c20746f2072656d6f7665206a6f696e6564506f6f6c73000000000000604482015260640161087e565b60405133815288908a908c907f275029c7b988945c03ac5499c0d532fce79ce36efab42e1b3f180a62001cad2c9060200160405180910390a450505050505050505050565b6000613a4c8383614c6b565b60606000613a4c83614d5e565b801561458457604051630c479e6560e21b8152600481018490527f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03169063311e799490602401602060405180830381600087803b15801561454a57600080fd5b505af115801561455e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145829190615a8b565b505b60408051608081018252848152600060208201818152828401918252606083018681529351637686c6e960e11b815283516004820152905160248201529051604482015291516064830152907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b03169063ed0d8dd2906084015b606060405180830381600087803b15801561461f57600080fd5b505af1158015614633573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fe9190615af7565b7f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480811561485357866001600160a01b03167f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031614156147825760405163bac37ef760e01b8152600481018690526001600160a01b03848116602483015282169063bac37ef790604401600060405180830381600087803b15801561470257600080fd5b505af1158015614716573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c1915061474a90899088908890600401615b25565b600060405180830381600087803b15801561476457600080fd5b505af1158015614778573d6000803e3d6000fd5b5050505050614919565b856001600160a01b03167f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031614156148535760405163bf1316c160e01b81526001600160a01b0382169063bf1316c1906147ec908a9089908890600401615b25565b600060405180830381600087803b15801561480657600080fd5b505af115801561481a573d6000803e3d6000fd5b505060405163bac37ef760e01b8152600481018790526001600160a01b0386811660248301528416925063bac37ef7915060440161474a565b60405163bf1316c160e01b81526001600160a01b0382169063bf1316c190614883908a9089908890600401615b25565b600060405180830381600087803b15801561489d57600080fd5b505af11580156148b1573d6000803e3d6000fd5b505060405163bf1316c160e01b81526001600160a01b038416925063bf1316c191506148e590899088908890600401615b25565b600060405180830381600087803b1580156148ff57600080fd5b505af1158015614913573d6000803e3d6000fd5b50505050505b505050505050565b6040805160a0810182528481526001600160801b03848116602083019081526000838501818152606085019182526080850187815295516398e04d7760e01b81528551600482015292519093166024830152915160448201529051606482015291516084830152907f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4806001600160a01b0316906398e04d779060a401614605565b600082826149d08688615aa4565b6149da9190615aa4565b6149e49190615b5e565b95945050505050565b60008064e8d4a51000614a008587615aa4565b614a0a9190615b5e565b9050828111614a1a5760006149e4565b6149e483826159b5565b600081614a37575064e8d4a51000613a4c565b6000614a438486615b72565b90506149e483614a5864e8d4a5100084615aa4565b614a629190615b5e565b64e8d4a51000614dba565b60008084614a814263ffffffff1686614dd0565b614a8b91906159b5565b90506000614a9d82600160601b615aa4565b9050838111614aad576000614ab7565b614ab784826159b5565b9695505050505050565b6000613a4c8383614de7565b600084614adc57506000614ab7565b600087614ae98789615b72565b12614afd57614af88688615b72565b614aff565b875b60035460405163528ee47960e11b81526001600160a01b037f000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a48081166004830152602482018790529293506000929091169063a51dc8f29060440160206040518083038186803b158015614b7157600080fd5b505afa158015614b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ba99190615a8b565b614bb39086615bb1565b614bbd8388615bb1565b614bc79190615c36565b90506000614bd586886159cc565b9050614be18183615c77565b9a9950505050505050505050565b6000826000018281548110614c0657614c06615741565b9060005260206000200154905092915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052613fa5908490614e36565b60008181526001830160205260408120548015614d54576000614c8f6001836159b5565b8554909150600090614ca3906001906159b5565b9050818114614d08576000866000018281548110614cc357614cc3615741565b9060005260206000200154905080876000018481548110614ce657614ce6615741565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614d1957614d19615ca5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ef9565b6000915050611ef9565b606081600001805480602002602001604051908101604052809291908181526020018280548015614dae57602002820191906000526020600020905b815481526020019060010190808311614d9a575b50505050509050919050565b600081831015614dca5782613a4c565b50919050565b600081831015614de05781613a4c565b5090919050565b6000818152600183016020526040812054614e2e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ef9565b506000611ef9565b6000614e8b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614f089092919063ffffffff16565b805190915015613fa55780806020019051810190614ea99190615ac3565b613fa55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161087e565b6060614f178484600085614f1f565b949350505050565b606082471015614f805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161087e565b843b614fce5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161087e565b600080866001600160a01b03168587604051614fea9190615ce7565b60006040518083038185875af1925050503d8060008114615027576040519150601f19603f3d011682016040523d82523d6000602084013e61502c565b606091505b509150915061503c828286615047565b979650505050505050565b60608315615056575081613a4c565b8251156150665782518084602001fd5b8160405162461bcd60e51b815260040161087e9190615d03565b508054600082559060005260206000209081019061509e91906150ec565b50565b8280548282559060005260206000209081019282156150dc579160200282015b828111156150dc5782518255916020019190600101906150c1565b506150e89291506150ec565b5090565b5b808211156150e857600081556001016150ed565b803563ffffffff8116811461511557600080fd5b919050565b60008083601f84011261512c57600080fd5b5081356001600160401b0381111561514357600080fd5b6020830191508360208260051b850101111561515e57600080fd5b9250929050565b60008060008060008060a0878903121561517e57600080fd5b8635955061518e60208801615101565b945061519c60408801615101565b935060608701356001600160401b038111156151b757600080fd5b6151c389828a0161511a565b979a9699509497949695608090950135949350505050565b6001600160a01b038116811461509e57600080fd5b60006020828403121561520257600080fd5b8135613a4c816151db565b6000806000806040858703121561522357600080fd5b84356001600160401b038082111561523a57600080fd5b6152468883890161511a565b9096509450602087013591508082111561525f57600080fd5b5061526c8782880161511a565b95989497509550505050565b60006020828403121561528a57600080fd5b5035919050565b600081518084526020808501945080840160005b838110156152c1578151875295820195908201906001016152a5565b509495945050505050565b6001600160a01b03898116825263ffffffff8981166020808501919091529089166040840152606083018890526080830187905260a0830186905261010060c08401819052855190840181905260009261012085019287810192855b81811015615346578451841686529482019493820193600101615328565b505050505082810360e084015261535d8185615291565b9b9a5050505050505050505050565b60008060008060006060868803121561538457600080fd5b8535945060208601356001600160401b03808211156153a257600080fd5b6153ae89838a0161511a565b909650945060408801359150808211156153c757600080fd5b506153d48882890161511a565b969995985093965092949392505050565b6000806000606084860312156153fa57600080fd5b505081359360208301359350604090920135919050565b602081526000613a4c6020830184615291565b801515811461509e57600080fd5b60006020828403121561544457600080fd5b8135613a4c81615424565b6000806020838503121561546257600080fd5b82356001600160401b0381111561547857600080fd5b6154848582860161511a565b90969095509350505050565b6000806000604084860312156154a557600080fd5b8335925060208401356001600160401b038111156154c257600080fd5b6154ce8682870161511a565b9497909650939450505050565b600080604083850312156154ee57600080fd5b82356154f9816151db565b9150602083013561550981615424565b809150509250929050565b60008060008060008060008060c0898b03121561553057600080fd5b883561553b816151db565b975061554960208a01615101565b965061555760408a01615101565b955060608901356001600160401b038082111561557357600080fd5b61557f8c838d0161511a565b909750955060808b013591508082111561559857600080fd5b506155a58b828c0161511a565b999c989b50969995989497949560a00135949350505050565b600080604083850312156155d157600080fd5b50508035926020909101359150565b600080600080600080600060c0888a0312156155fb57600080fd5b87356001600160401b0381111561561157600080fd5b61561d8a828b0161511a565b9098509650506020880135945060408801359350606088013561563f816151db565b9250608088013561564f81615424565b8092505060a0880135905092959891949750929550565b6001600160801b038116811461509e57600080fd5b600080600080600080600061010080898b03121561569857600080fd5b8835975060208901356156aa81615666565b965060408901359550606089013594506080890135935060a08901356156cf81615424565b92508881018a10156156e057600080fd5b5060c08801905092959891949750929550565b83815260606020820152600061570c6060830185615291565b8281036040840152614ab78185615291565b6020808252600990820152683337b93134b23232b760b91b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141561578157615781615757565b5060010190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252600e908201526d0d2dcecc2d8d2c840d8cadccee8d60931b604082015260600190565b6000808335601e198436030181126157fe57600080fd5b8301803591506001600160401b0382111561581857600080fd5b60200191503681900382131561515e57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051602081016001600160401b03811182821017156158655761586561582d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156158935761589361582d565b604052919050565b600060208083850312156158ae57600080fd5b82356001600160401b03808211156158c557600080fd5b81850191508282870312156158d957600080fd5b6158e1615843565b8235828111156158f057600080fd5b80840193505086601f84011261590557600080fd5b8235828111156159175761591761582d565b8060051b925061592885840161586b565b818152928401850192858101908985111561594257600080fd5b948601945b8486101561596057853582529486019490860190615947565b83525090979650505050505050565b6020808252600f908201526e506f6f6c206e6f742065786973747360881b604082015260600190565b6000602082840312156159aa57600080fd5b8151613a4c81615666565b6000828210156159c7576159c7615757565b500390565b600082198211156159df576159df615757565b500190565b60208082526018908201527f7370656369616c20666561747572652064697361626c65640000000000000000604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060208284031215615a5157600080fd5b8151613a4c816151db565b60008060408385031215615a6f57600080fd5b8251615a7a816151db565b6020840151909250615509816151db565b600060208284031215615a9d57600080fd5b5051919050565b6000816000190483118215151615615abe57615abe615757565b500290565b600060208284031215615ad557600080fd5b8151613a4c81615424565b600081615aef57615aef615757565b506000190190565b600080600060608486031215615b0c57600080fd5b8351925060208401519150604084015190509250925092565b6001600160a01b0393841681526020810192909252909116604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082615b6d57615b6d615b48565b500490565b60008083128015600160ff1b850184121615615b9057615b90615757565b6001600160ff1b0384018313811615615bab57615bab615757565b50500390565b60006001600160ff1b0381841382841380821686840486111615615bd757615bd7615757565b600160ff1b6000871282811687830589121615615bf657615bf6615757565b60008712925087820587128484161615615c1257615c12615757565b87850587128184161615615c2857615c28615757565b505050929093029392505050565b600080821280156001600160ff1b0384900385131615615c5857615c58615757565b600160ff1b8390038412811615615c7157615c71615757565b50500190565b600082615c8657615c86615b48565b600160ff1b821460001984141615615ca057615ca0615757565b500590565b634e487b7160e01b600052603160045260246000fd5b60005b83811015615cd6578181015183820152602001615cbe565b83811115613f8b5750506000910152565b60008251615cf9818460208701615cbb565b9190910192915050565b6020815260008251806020840152615d22816040850160208701615cbb565b601f01601f1916919091016040019291505056fea2646970667358221220de26c0958ae74edf1ddc20c03f2316cd4bc437fc1d1fcce795748fd6ecd805eb64736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a4800000000000000000000000006afeb9edd6cf44fa8e89b1eee28284e6dd7705c8
-----Decoded View---------------
Arg [0] : _nft (address): 0xe222fBE074A436145b255442D919E4E3A6c6a480
Arg [1] : _helper (address): 0x6AFeb9EDd6Cf44fA8E89b1eee28284e6dD7705C8
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000e222fbe074a436145b255442d919e4e3a6c6a480
Arg [1] : 0000000000000000000000006afeb9edd6cf44fa8e89b1eee28284e6dd7705c8
Deployed Bytecode Sourcemap
61779:29202:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64924:1038;;;;;;;;;;-1:-1:-1;64924:1038:0;;;;;:::i;:::-;;:::i;:::-;;62137:25;;;;;;;;;;;;;;;;;;;1424::1;;;1412:2;1397:18;62137:25:0;;;;;;;;33587:41;;;;;;;;;;-1:-1:-1;33587:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2013:14:1;;2006:22;1988:41;;1976:2;1961:18;33587:41:0;1848:187:1;69717:491:0;;;;;;;;;;-1:-1:-1;69717:491:0;;;;;:::i;:::-;;:::i;74810:948::-;;;;;;;;;;-1:-1:-1;74810:948:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;:::i;62052:29::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4979:32:1;;;4961:51;;4949:2;4934:18;62052:29:0;4815:203:1;68508:789:0;;;;;;;;;;-1:-1:-1;68508:789:0;;;;;:::i;:::-;;:::i;62745:28::-;;;;;;;;;;-1:-1:-1;62745:28:0;;;;;;;;61981;;;;;;;;;;;;;;;73068:484;;;;;;;;;;-1:-1:-1;73068:484:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;63655:182::-;;;;;;;;;;-1:-1:-1;63655:182:0;;;;;:::i;:::-;;:::i;66007:121::-;;;;;;;;;;-1:-1:-1;66007:121:0;;;;;:::i;:::-;;:::i;68091:372::-;;;;;;;;;;-1:-1:-1;68091:372:0;;;;;:::i;:::-;;:::i;69342:330::-;;;;;;;;;;-1:-1:-1;69342:330:0;;;;;:::i;:::-;;:::i;66173:190::-;;;;;;;;;;-1:-1:-1;66173:190:0;;;;;:::i;:::-;;:::i;34218:168::-;;;;;;;;;;-1:-1:-1;34218:168:0;;;;;:::i;:::-;;:::i;72711:312::-;;;;;;;;;;-1:-1:-1;72711:312:0;;;;;:::i;:::-;;:::i;34035:177::-;;;;;;;;;;-1:-1:-1;34035:177:0;;;;;:::i;:::-;;:::i;63843:134::-;;;;;;;;;;-1:-1:-1;63843:134:0;;;;;:::i;:::-;;:::i;64022:857::-;;;;;;;;;;-1:-1:-1;64022:857:0;;;;;:::i;:::-;;:::i;66408:524::-;;;;;;;;;;-1:-1:-1;66408:524:0;;;;;:::i;:::-;;:::i;62271:49::-;;;;;;;;;;-1:-1:-1;62271:49:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;62271:49:0;;;;;;;;;;-1:-1:-1;;;;;10763:32:1;;;10745:51;;10827:2;10812:18;;10805:34;;;;10718:18;62271:49:0;10571:274:1;62192:43:0;;;;;;;;;;-1:-1:-1;62192:43:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;62192:43:0;;;;-1:-1:-1;;;62192:43:0;;;;;-1:-1:-1;;;62192:43:0;;;;;;;;;;;-1:-1:-1;;;;;11151:32:1;;;;11133:51;;11203:10;11249:15;;;11244:2;11229:18;;11222:43;11301:15;;;;11281:18;;;11274:43;;;;11348:2;11333:18;;11326:34;11391:3;11376:19;;11369:35;11171:3;11420:19;;11413:35;11120:3;11105:19;62192:43:0;10850:604:1;63418:158:0;;;;;;;;;;;;;:::i;62360:63::-;;;;;;;;;;-1:-1:-1;62360:63:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;62360:63:0;;;;;;;;;;;-1:-1:-1;;;;;11930:47:1;;;11912:66;;12009:2;11994:18;;11987:34;;;;12037:18;;;12030:34;11900:2;11885:18;62360:63:0;11712:358:1;75803:140:0;;;;;;;;;;-1:-1:-1;75803:140:0;;;;;:::i;:::-;;:::i;62683:55::-;;;;;;;;;;-1:-1:-1;62683:55:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;71671:995;;;;;;;;;;-1:-1:-1;71671:995:0;;;;;:::i;:::-;;:::i;62778:33::-;;;;;;;;;;-1:-1:-1;62778:33:0;;;;;;;;;;;70253:1373;;;;;;;;;;-1:-1:-1;70253:1373:0;;;;;:::i;:::-;;:::i;66977:1069::-;;;;;;;;;;-1:-1:-1;66977:1069:0;;;;;:::i;:::-;;:::i;73597:1168::-;;;;;;;;;;-1:-1:-1;73597:1168:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;87570:861::-;;;;;;;;;;-1:-1:-1;87570:861:0;;;;;:::i;:::-;;:::i;:::-;;;;;;14674:4:1;14716:3;14705:9;14701:19;14693:27;;-1:-1:-1;;;;;14757:6:1;14751:13;14747:54;14736:9;14729:73;14858:4;14850:6;14846:17;14840:24;14833:4;14822:9;14818:20;14811:54;14921:4;14913:6;14909:17;14903:24;14896:4;14885:9;14881:20;14874:54;14984:4;14976:6;14972:17;14966:24;14959:4;14948:9;14944:20;14937:54;15047:4;15039:6;15035:17;15029:24;15022:4;15011:9;15007:20;15000:54;15110:4;15102:6;15098:17;15092:24;15085:4;15074:9;15070:20;15063:54;14506:617;;;;;33562:20:0;;;;;;;;;;-1:-1:-1;33562:20:0;;;;-1:-1:-1;;;;;33562:20:0;;;64924:1038;33904:10;33894:21;;;;:9;:21;;;;;;;;33886:43;;;;-1:-1:-1;;;33886:43:0;;;;;;;:::i;:::-;;;;;;;;;65109:23:::1;65135:10:::0;;;:5:::1;:10;::::0;;;;65225:14;;:32:::1;90956:15:::0;65225:32;::::1;-1:-1:-1::0;;;65225:14:0;;::::1;;:32;::::0;:66:::1;;-1:-1:-1::0;65261:12:0;;:30:::1;90956:15:::0;65261:30;::::1;-1:-1:-1::0;;;65261:12:0;;::::1;;:30;65225:66;65209:125;;;::::0;-1:-1:-1;;;65209:125:0;;15667:2:1;65209:125:0::1;::::0;::::1;15649:21:1::0;15706:2;15686:18;;;15679:30;15745:27;15725:18;;;15718:55;15790:18;;65209:125:0::1;15465:349:1::0;65209:125:0::1;65349:12;::::0;::::1;:19:::0;:43;::::1;65341:77;;;::::0;-1:-1:-1;;;65341:77:0;;16021:2:1;65341:77:0::1;::::0;::::1;16003:21:1::0;16060:2;16040:18;;;16033:30;-1:-1:-1;;;16079:18:1;;;16072:51;16140:18;;65341:77:0::1;15819:345:1::0;65341:77:0::1;90956:15:::0;65475:27:::1;;:9;:27;;;:50;;;;;65516:9;65506:19;;:7;:19;;;65475:50;65467:83;;;::::0;-1:-1:-1;;;65467:83:0;;16371:2:1;65467:83:0::1;::::0;::::1;16353:21:1::0;16410:2;16390:18;;;16383:30;-1:-1:-1;;;16429:18:1;;;16422:50;16489:18;;65467:83:0::1;16169:344:1::0;65467:83:0::1;65595:14;::::0;::::1;::::0;:19;65587:54:::1;;;::::0;-1:-1:-1;;;65587:54:0;;16720:2:1;65587:54:0::1;::::0;::::1;16702:21:1::0;16759:2;16739:18;;;16732:30;-1:-1:-1;;;16778:18:1;;;16771:52;16840:18;;65587:54:0::1;16518:346:1::0;65587:54:0::1;65650:26:::0;;::::1;65683:22:::0;;::::1;-1:-1:-1::0;;;65683:22:0::1;-1:-1:-1::0;;;;65650:26:0;;::::1;-1:-1:-1::0;;;65650:26:0::1;65683:22:::0;;;;-1:-1:-1;;;;65683:22:0;;;;;;;::::1;::::0;;65650:14:::1;-1:-1:-1::0;65712:24:0;::::1;:28:::0;;;65747:14:::1;::::0;::::1;:26:::0;;;65782:118:::1;65802:24:::0;;::::1;65782:118;;;65876:13;;65890:1;65876:16;;;;;;;:::i;:::-;;;;;;;65842:4;:12;;65855:1;65842:15;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;:31:::1;:15;::::0;;::::1;;:31;:50:::0;65828:3:::1;::::0;::::1;:::i;:::-;;;65782:118;;;-1:-1:-1::0;65911:45:0::1;::::0;;17481:10:1;17518:15;;;17500:34;;17570:15;;17565:2;17550:18;;17543:43;17602:18;;;17595:34;;;65921:3:0;;65911:45:::1;::::0;17459:2:1;17444:18;65911:45:0::1;;;;;;;65102:860;64924:1038:::0;;;;;;:::o;69717:491::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;69861:6;69876:5;62876:6;;::::1;62868:33;;;;-1:-1:-1::0;;;62868:33:0::1;;;;;;;:::i;:::-;69905:9:::2;69900:303;69916:17:::0;;::::2;69900:303;;;69987:10;69957:9;:20;69967:6:::0;;69974:1;69967:9;;::::2;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;69957:20:::0;;-1:-1:-1;69957:20:0;::::2;::::0;;;;;;-1:-1:-1;69957:20:0;:26;-1:-1:-1;;;;;69957:26:0::2;:40;69949:71;;;::::0;-1:-1:-1;;;69949:71:0;;18545:2:1;69949:71:0::2;::::0;::::2;18527:21:1::0;18584:2;18564:18;;;18557:30;-1:-1:-1;;;18603:18:1;;;18596:48;18661:18;;69949:71:0::2;18343:342:1::0;69949:71:0::2;70029:23;70066:5;;70072:1;70066:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;70055:35;;;;;;;:::i;:::-;70029:61;;70104:9;70099:97;70119:9:::0;;:16;70115:20;::::2;70099:97;;;70153:33;70162:6;;70169:1;70162:9;;;;;;;:::i;:::-;;;;;;;70173:4;:9;;;70183:1;70173:12;;;;;;;;:::i;:::-;;;;;;;70153:8;:33::i;:::-;70137:3;::::0;::::2;:::i;:::-;;;70099:97;;;;69940:263;69935:3;;;;:::i;:::-;;;69900:303;;;-1:-1:-1::0;;60790:1:0;61742:7;:22;-1:-1:-1;;;;;69717:491:0:o;74810:948::-;74904:19;75220:10;;;:5;:10;;;;;75253:16;;;75360:24;;;75403:14;;;;75436;;;;75476:12;;;:19;-1:-1:-1;;;;;75253:16:0;;;75288:14;-1:-1:-1;;;75288:14:0;;;;;-1:-1:-1;;;75319:12:0;;;;75360:24;75403:14;75436;75105:29;;;;75476:19;-1:-1:-1;;;;;75517:21:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;75517:21:0;;75502:36;;75578:6;-1:-1:-1;;;;;75564:21:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;75564:21:0;;75545:40;;75597:9;75592:161;75616:6;75612:1;:10;75592:161;;;75656:4;:12;;75669:1;75656:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:27;75638:15;;-1:-1:-1;;;;;75656:27:0;;;;75638:12;;75651:1;;75638:15;;;;;;:::i;:::-;;;;;;:45;-1:-1:-1;;;;;75638:45:0;;;-1:-1:-1;;;;;75638:45:0;;;;;75714:4;:12;;75727:1;75714:15;;;;;;;;:::i;:::-;;;;;;;;;;;:31;;;75692:16;75709:1;75692:19;;;;;;;;:::i;:::-;;;;;;;;;;:53;75624:3;;;:::i;:::-;;;75592:161;;;;75187:571;;74810:948;;;;;;;;;:::o;68508:789::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;68650:6;68665:4;62876:6;;::::1;62868:33;;;;-1:-1:-1::0;;;62868:33:0::1;;;;;;;:::i;:::-;68706:3:::2;68693:10;;:16;68685:44;;;;-1:-1:-1::0;;;68685:44:0::2;;;;;;;:::i;:::-;68736:23;68762:10:::0;;;:5:::2;:10;::::0;;;;68787:14;;:33:::2;90956:15:::0;68787:33;::::2;-1:-1:-1::0;;;68787:14:0;;::::2;;:33;::::0;::::2;::::0;:67:::2;;-1:-1:-1::0;68842:12:0;;-1:-1:-1;;;68842:12:0;::::2;;;90956:15:::0;68824:30:::2;;;68787:67;68779:92;;;::::0;-1:-1:-1;;;68779:92:0;;21633:2:1;68779:92:0::2;::::0;::::2;21615:21:1::0;21672:2;21652:18;;;21645:30;-1:-1:-1;;;21691:18:1;;;21684:42;21743:18;;68779:92:0::2;21431:336:1::0;68779:92:0::2;68883:9;68878:414;68898:17:::0;;::::2;68878:414;;;68969:10;68939:9;:20;68949:6:::0;;68956:1;68949:9;;::::2;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;68939:20:::0;;-1:-1:-1;68939:20:0;::::2;::::0;;;;;;-1:-1:-1;68939:20:0;:26;-1:-1:-1;;;;;68939:26:0::2;:40;68931:62;;;::::0;-1:-1:-1;;;68931:62:0;;21974:2:1;68931:62:0::2;::::0;::::2;21956:21:1::0;22013:1;21993:18;;;21986:29;-1:-1:-1;;;22031:18:1;;;22024:39;22080:18;;68931:62:0::2;21772:332:1::0;68931:62:0::2;69035:6;::::0;-1:-1:-1;;;;;69035:6:0::2;:13;69057:3;69063:6:::0;;69070:1;69063:9;;::::2;;;;;:::i;:::-;69035:38;::::0;-1:-1:-1;;;;;;69035:38:0::2;::::0;;;;;;-1:-1:-1;;;;;10763:32:1;;;69035:38:0::2;::::0;::::2;10745:51:1::0;69063:9:0::2;;::::0;;;::::2;;10812:18:1::0;;;10805:34;-1:-1:-1;10718:18:1;;69035:38:0::2;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;69002:71:0::2;:9;:20;69012:6;;69019:1;69012:9;;;;;;;:::i;:::-;;;;;;;69002:20;;;;;;;;;;;:30;;:71;;;;69082:23;69108:6;:17;69115:6;;69122:1;69115:9;;;;;;;:::i;:::-;;;;;;;69108:17;;;;;;;;;;;:22;69126:3;69108:22;;;;;;;;;;;69082:48;;69143:5;:15;;;69162:1;69143:20;69139:146;;;69176:36;69182:6;;69189:1;69182:9;;;;;;;:::i;:::-;;;;;;;69193:3;69198:4;;69203:1;69198:7;;;;;;;:::i;:::-;;;;;;;69207:4;69176:5;:36::i;:::-;69139:146;;;69239:36;69245:6;;69252:1;69245:9;;;;;;;:::i;:::-;;;;;;;69256:3;69261:4;;69266:1;69261:7;;;;;;;:::i;:::-;;;;;;;69270:4;69239:5;:36::i;:::-;-1:-1:-1::0;68917:3:0::2;::::0;::::2;:::i;:::-;;;68878:414;;;-1:-1:-1::0;;60790:1:0;61742:7;:22;-1:-1:-1;;;;;;;68508:789:0:o;73068:484::-;73193:24;73247:7;73234:9;:20;;73226:52;;;;-1:-1:-1;;;73226:52:0;;22567:2:1;73226:52:0;;;22549:21:1;22606:2;22586:18;;;22579:30;-1:-1:-1;;;22625:18:1;;;22618:49;22684:18;;73226:52:0;22365:343:1;73226:52:0;73303:18;;;;:11;:18;;;;;:27;;:25;:27::i;:::-;73293:7;:37;73285:67;;;;-1:-1:-1;;;73285:67:0;;22915:2:1;73285:67:0;;;22897:21:1;22954:2;22934:18;;;22927:30;-1:-1:-1;;;22973:18:1;;;22966:47;23030:18;;73285:67:0;22713:341:1;73285:67:0;73383:19;73393:9;73383:7;:19;:::i;:::-;:23;;73405:1;73383:23;:::i;:::-;-1:-1:-1;;;;;73369:38:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73369:38:0;-1:-1:-1;73359:48:0;-1:-1:-1;73435:9:0;73414:133;73455:7;73446:5;:16;73414:133;;73511:18;;;;:11;:18;;;;;:28;;73533:5;73511:21;:28::i;:::-;73482:7;73490:17;73498:9;73490:5;:17;:::i;:::-;73482:26;;;;;;;;:::i;:::-;;;;;;;;;;:57;73464:7;;;:::i;:::-;;;73414:133;;;;73068:484;;;;;:::o;63655:182::-;33818:5;;-1:-1:-1;;;;;33818:5:0;33804:10;:19;33796:41;;;;-1:-1:-1;;;33796:41:0;;;;;;;:::i;:::-;63736:21:::1;:39:::0;;;::::1;;;;-1:-1:-1::0;;63736:39:0;;::::1;;::::0;;63787:44:::1;::::0;::::1;::::0;::::1;::::0;63760:15;2013:14:1;2006:22;1988:41;;1976:2;1961:18;;1848:187;63787:44:0::1;;;;;;;;63655:182:::0;:::o;66007:121::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;;;;66089:33:::1;66105:1;66108:6;;66089:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;-1:-1:-1;66089:33:0;-1:-1:-1;66089:15:0::1;::::0;-1:-1:-1;;66089:33:0:i:1;:::-;-1:-1:-1::0;;60790:1:0;61742:7;:22;66007:121::o;68091:372::-;33818:5;;-1:-1:-1;;;;;33818:5:0;33804:10;:19;33796:41;;;;-1:-1:-1;;;33796:41:0;;;;;;;:::i;:::-;68240:7;68256;62876:6;;::::1;62868:33;;;;-1:-1:-1::0;;;62868:33:0::1;;;;;;;:::i;:::-;68287:9:::2;68282:176;68302:18:::0;;::::2;68282:176;;;68336:51;68352:7;;68360:1;68352:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;68364;68376:7;;68384:1;68376:10;;;;;;;:::i;:::-;;;;;;;68336:15;:51::i;:::-;68439:7;;68447:1;68439:10;;;;;;;:::i;:::-;;;;;;;68401:49;68427:7;;68435:1;68427:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;68401:49;::::0;-1:-1:-1;;;;;4979:32:1;;;4961:51;;4949:2;4934:18;68401:49:0::2;;;;;;;68322:3;::::0;::::2;:::i;:::-;;;68282:176;;;;33844:1:::1;;68091:372:::0;;;;:::o;69342:330::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;69484:6;69499:4;62876:6;;::::1;62868:33;;;;-1:-1:-1::0;;;62868:33:0::1;;;;;;;:::i;:::-;69540:3:::2;69527:10;;:16;69519:44;;;;-1:-1:-1::0;;;69519:44:0::2;;;;;;;:::i;:::-;69575:9;69570:97;69590:17:::0;;::::2;69570:97;;;69623:36;69629:6;;69636:1;69629:9;;;;;;;:::i;:::-;;;;;;;69640:3;69645:4;;69650:1;69645:7;;;;;;;:::i;:::-;;;;;;;69654:4;69623:5;:36::i;:::-;69609:3;::::0;::::2;:::i;:::-;;;69570:97;;;-1:-1:-1::0;;60790:1:0;61742:7;:22;-1:-1:-1;;;;;;69342:330:0:o;66173:190::-;62972:21;;;;;;;62964:58;;;;-1:-1:-1;;;62964:58:0;;;;;;;:::i;:::-;60834:1:::1;61430:7;;:19;;61422:63;;;;-1:-1:-1::0;;;61422:63:0::1;;;;;;;:::i;:::-;60834:1;61563:7;:18;;;;66323:34:::2;66339:3;66344:6;;66323:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;66352:4:0::2;::::0;-1:-1:-1;66323:15:0::2;::::0;-1:-1:-1;;66323:34:0:i:2;:::-;-1:-1:-1::0;;60790:1:0::1;61742:7;:22:::0;-1:-1:-1;66173:190:0:o;34218:168::-;33818:5;;-1:-1:-1;;;;;33818:5:0;33804:10;:19;33796:41;;;;-1:-1:-1;;;33796:41:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;34300:15:0;::::1;;::::0;;;:9:::1;:15;::::0;;;;;;;;:31;;-1:-1:-1;;34300:31:0::1;::::0;::::1;;::::0;;::::1;::::0;;;34345:35;;1988:41:1;;;34345:35:0::1;::::0;1961:18:1;34345:35:0::1;;;;;;;34218:168:::0;;:::o;72711:312::-;72838:14;72855:18;;;:11;:18;;;;;72802:24;;72838:14;72855:27;;:25;:27::i;:::-;72838:44;;72913:6;-1:-1:-1;;;;;72899:21:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72899:21:0;;72889:31;;72932:9;72927:91;72951:6;72947:1;:10;72927:91;;;72986:18;;;;:11;:18;;;;;:24;;73008:1;72986:21;:24::i;:::-;72973:7;72981:1;72973:10;;;;;;;;:::i;:::-;;;;;;;;;;:37;72959:3;;;:::i;:::-;;;72927:91;;;;72831:192;72711:312;;;:::o;34035:177::-;33818:5;;-1:-1:-1;;;;;33818:5:0;33804:10;:19;33796:41;;;;-1:-1:-1;;;33796:41:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;34114:20:0;::::1;34106:42;;;;-1:-1:-1::0;;;34106:42:0::1;;;;;;;:::i;:::-;34157:5;:14:::0;;-1:-1:-1;;;;;;34157:14:0::1;-1:-1:-1::0;;;;;34157:14:0;::::1;::::0;;::::1;::::0;;;34185:21:::1;::::0;::::1;::::0;-1:-1:-1;;34185:21:0::1;34035:177:::0;:::o;63843:134::-;33818:5;;-1:-1:-1;;;;;33818:5:0;33804:10;:19;33796:41;;;;-1:-1:-1;;;33796:41:0;;;;;;;:::i;:::-;63917:6:::1;:16:::0;;-1:-1:-1;;;;;;63917:16:0::1;-1:-1:-1::0;;;;;63917:16:0;::::1;::::0;;::::1;::::0;;;63947:24:::1;::::0;4961:51:1;;;63947:24:0::1;::::0;4949:2:1;4934:18;63947:24:0::1;4815:203:1::0;64022:857:0;33904:10;33894:21;;;;:9;:21;;;;;;;;33886:43;;;;-1:-1:-1;;;33886:43:0;;;;;;;:::i;:::-;64256:12;64277:13;62876:6;;::::1;62868:33;;;;-1:-1:-1::0;;;62868:33:0::1;;;;;;;:::i;:::-;90956:15:::0;64314:28:::2;;:9;:28;;;;:51;;;;;64356:9;64346:19;;:7;:19;;;64314:51;64306:86;;;::::0;-1:-1:-1;;;64306:86:0;;24111:2:1;64306:86:0::2;::::0;::::2;24093:21:1::0;24150:2;24130:18;;;24123:30;-1:-1:-1;;;24169:18:1;;;24162:52;24231:18;;64306:86:0::2;23909:346:1::0;64306:86:0::2;64399:11;64413:10;;64399:24;;64442:23;64468:5;:10;64474:3;64468:10;;;;;;;;;;;64442:36;;64506:11;64487:4;:16;;;:30;;;;;-1:-1:-1::0;;;;;64487:30:0::2;;;;;-1:-1:-1::0;;;;;64487:30:0::2;;;;;;64541:9;64524:4;:14;;;:26;;;;;;;;;;;;;;;;;;64572:7;64557:4;:12;;;:22;;;;;;;;;;;;;;;;;;64613:1;64586:4;:24;;:28;;;;64638:9;64621:4;:14;;:26;;;;64661:9;64656:131;64676:23:::0;;::::2;64656:131;;;64715:4;:12;;64733:45;;;;;;;;64744:12;;64757:1;64744:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;64733:45:0::2;;;;;64761:13;;64775:1;64761:16;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;64733:45:::0;;;64715:64;;::::2;::::0;;::::2;::::0;;-1:-1:-1;64715:64:0;;;;;;;;;::::2;::::0;;::::2;;::::0;;-1:-1:-1;;;;;;64715:64:0::2;-1:-1:-1::0;;;;;64715:64:0;;::::2;::::0;;;::::2;::::0;;;::::2;::::0;;;;::::2;::::0;-1:-1:-1;64701:3:0;::::2;::::0;::::2;:::i;:::-;;;;64656:131;;;-1:-1:-1::0;64793:10:0::2;:12:::0;;;:10:::2;:12;::::0;::::2;:::i;:::-;::::0;;;-1:-1:-1;;64817:56:0::2;::::0;;-1:-1:-1;;;;;24505:32:1;;24487:51;;24557:10;24603:15;;;24598:2;24583:18;;24576:43;24655:15;;24635:18;;;24628:43;24702:2;24687:18;;24680:34;;;64817:56:0;;64825:3;;64817:56:::2;::::0;;;;;24474:3:1;64817:56:0;;::::2;64299:580;;33936:1:::1;;64022:857:::0;;;;;;;;:::o;66408:524::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;;;66508:10:::1;::::0;66525:402:::1;66545:17:::0;;::::1;66525:402;;;66616:6;-1:-1:-1::0;;;;;66586:36:0::1;:9;:20;66596:6;;66603:1;66596:9;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;66586:20:::0;;-1:-1:-1;66586:20:0;::::1;::::0;;;;;;-1:-1:-1;66586:20:0;:26;-1:-1:-1;;;;;66586:26:0::1;:36;66578:68;;;::::0;-1:-1:-1;;;66578:68:0;;24927:2:1;66578:68:0::1;::::0;::::1;24909:21:1::0;24966:2;24946:18;;;24939:30;-1:-1:-1;;;24985:18:1;;;24978:49;25044:18;;66578:68:0::1;24725:343:1::0;66578:68:0::1;66663:31;:11;:22;66675:6;;66682:1;66675:9;;;;;;;:::i;:::-;;;;;;;66663:22;;;;;;;;;;;:29;:31::i;:::-;:36:::0;66655:73:::1;;;::::0;-1:-1:-1;;;66655:73:0;;25275:2:1;66655:73:0::1;::::0;::::1;25257:21:1::0;25314:2;25294:18;;;25287:30;25353:26;25333:18;;;25326:54;25397:18;;66655:73:0::1;25073:348:1::0;66655:73:0::1;66744:9;:20;66754:6;;66761:1;66754:9;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;66744:20:::0;;-1:-1:-1;66744:20:0;::::1;::::0;;;;;;-1:-1:-1;66744:20:0;;;66737:27;;-1:-1:-1;;;;;;66737:27:0::1;::::0;;;::::1;::::0;66781:37:::1;66808:6:::0;;66815:1;66808:9;;::::1;;;;;:::i;:::-;-1:-1:-1::0;;;;;66781:19:0;::::1;;::::0;;;:11:::1;66808:9;66781:19:::0;;;;;;;;66808:9;::::1;;;::::0;-1:-1:-1;66781:26:0::1;:37::i;:::-;66773:46;;;::::0;::::1;;66828:3;-1:-1:-1::0;;;;;66828:16:0::1;;66853:4;66860:6;66868;;66875:1;66868:9;;;;;;;:::i;:::-;;;;;;;66828:50;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;66909:6;;66916:1;66909:9;;;;;;;:::i;:::-;66892:27;::::0;-1:-1:-1;;;;;4979:32:1;;4961:51;;66909:9:0::1;::::0;;::::1;::::0;;;::::1;;::::0;66892:27:::1;::::0;-1:-1:-1;4934:18:1;66892:27:0::1;;;;;;;66564:3;::::0;::::1;:::i;:::-;;;66525:402;;;-1:-1:-1::0;;60790:1:0;61742:7;:22;-1:-1:-1;;66408:524:0:o;63418:158::-;33818:5;;-1:-1:-1;;;;;33818:5:0;33804:10;:19;33796:41;;;;-1:-1:-1;;;33796:41:0;;;;;;;:::i;:::-;63476:16:::1;::::0;::::1;;63475:17;63467:43;;;::::0;-1:-1:-1;;;63467:43:0;;26008:2:1;63467:43:0::1;::::0;::::1;25990:21:1::0;26047:2;26027:18;;;26020:30;-1:-1:-1;;;26066:18:1;;;26059:43;26119:18;;63467:43:0::1;25806:337:1::0;63467:43:0::1;63517:16;:23:::0;;-1:-1:-1;;63517:23:0::1;63536:4;63517:23;::::0;;63552:18:::1;::::0;::::1;::::0;63517:16:::1;::::0;63552:18:::1;63418:158::o:0;75803:140::-;-1:-1:-1;;;;;75911:17:0;;;;;;:11;:17;;;;;75866:25;;75911:26;;:24;:26::i;:::-;75900:37;75803:140;-1:-1:-1;;75803:140:0:o;71671:995::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;62972:21:::1;::::0;::::1;::::0;::::1;;;62964:58;;;;-1:-1:-1::0;;;62964:58:0::1;;;;;;;:::i;:::-;71942:8:::0;90956:15;71923:27:::2;;;;71915:57;;;::::0;-1:-1:-1;;;71915:57:0;;26350:2:1;71915:57:0::2;::::0;::::2;26332:21:1::0;26389:2;26369:18;;;26362:30;-1:-1:-1;;;26408:18:1;;;26401:47;26465:18;;71915:57:0::2;26148:341:1::0;71915:57:0::2;71981:14;71998:6;;:13;;71981:30;;72019:14;72035::::0;72083:11:::2;-1:-1:-1::0;;;;;72070:32:0::2;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72135:11;-1:-1:-1::0;;;;;72122:32:0::2;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72018:146;;;;72178:9;72173:395;72193:6;72189:1;:10;72173:395;;;72250:10;72220:9;:20;72230:6:::0;;72237:1;72230:9;;::::2;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;72220:20:::0;;-1:-1:-1;72220:20:0;::::2;::::0;;;;;;-1:-1:-1;72220:20:0;:26;-1:-1:-1;;;;;72220:26:0::2;:40;72212:72;;;::::0;-1:-1:-1;;;72212:72:0;;26966:2:1;72212:72:0::2;::::0;::::2;26948:21:1::0;27005:2;26985:18;;;26978:30;-1:-1:-1;;;27024:18:1;;;27017:49;27083:18;;72212:72:0::2;26764:343:1::0;72212:72:0::2;72336:6;::::0;72296:17:::2;::::0;;;-1:-1:-1;;;;;72336:6:0::2;:14;72359:3;72365:6:::0;;72372:1;72365:9;;::::2;;;;;:::i;:::-;72336:39;::::0;-1:-1:-1;;;;;;72336:39:0::2;::::0;;;;;;-1:-1:-1;;;;;10763:32:1;;;72336:39:0::2;::::0;::::2;10745:51:1::0;72365:9:0::2;;::::0;;;::::2;;10812:18:1::0;;;10805:34;-1:-1:-1;10718:18:1;;72336:39:0::2;::::0;::::2;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;72295:80;;;;72405:6;-1:-1:-1::0;;;;;72392:19:0::2;:9;-1:-1:-1::0;;;;;72392:19:0::2;;:42;;;;;72428:6;-1:-1:-1::0;;;;;72415:19:0::2;:9;-1:-1:-1::0;;;;;72415:19:0::2;;72392:42;72384:85;;;::::0;-1:-1:-1;;;72384:85:0;;27704:2:1;72384:85:0::2;::::0;::::2;27686:21:1::0;27743:2;27723:18;;;27716:30;27782:32;27762:18;;;27755:60;27832:18;;72384:85:0::2;27502:354:1::0;72384:85:0::2;72480:36;72490:6;;72497:1;72490:9;;;;;;;:::i;:::-;;;;;;;72501:8;72511:4;72480:9;:36::i;:::-;-1:-1:-1::0;;72548:3:0::2;;72173:395;;;;72576:84;72592:6;72600;72608:10;72620;72632;72644:15;72576;:84::i;:::-;-1:-1:-1::0;;60790:1:0;61742:7;:22;-1:-1:-1;;;;;;;;71671:995:0:o;70253:1373::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;62972:21:::1;::::0;::::1;::::0;::::1;;;62964:58;;;;-1:-1:-1::0;;;62964:58:0::1;;;;;;;:::i;:::-;70559:8:::0;90956:15;70540:27:::2;;;;70532:64;;;::::0;-1:-1:-1;;;70532:64:0;;28063:2:1;70532:64:0::2;::::0;::::2;28045:21:1::0;28102:2;28082:18;;;28075:30;28141:26;28121:18;;;28114:54;28185:18;;70532:64:0::2;27861:348:1::0;70532:64:0::2;70611:16;::::0;;;:9:::2;:16;::::0;;;;:22;-1:-1:-1;;;;;70611:22:0::2;70637:10;70611:36;70603:75;;;::::0;-1:-1:-1;;;70603:75:0;;28416:2:1;70603:75:0::2;::::0;::::2;28398:21:1::0;28455:2;28435:18;;;28428:30;28494:28;28474:18;;;28467:56;28540:18;;70603:75:0::2;28214:350:1::0;70603:75:0::2;70710:6;::::0;:34:::2;::::0;-1:-1:-1;;;70710:34:0;;-1:-1:-1;;;;;70732:3:0::2;10763:32:1::0;;70710:34:0::2;::::0;::::2;10745:51:1::0;10812:18;;;10805:34;;;-1:-1:-1;;70710:6:0::2;::::0;:13:::2;::::0;10718:18:1;;70710:34:0::2;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;70687:57:0::2;;;70771:1;70759:9;-1:-1:-1::0;;;;;70759:13:0::2;;:42;;;;;70789:12;70776:9;-1:-1:-1::0;;;;;70776:25:0::2;;;70759:42;70751:89;;;::::0;-1:-1:-1;;;70751:89:0;;28771:2:1;70751:89:0::2;::::0;::::2;28753:21:1::0;28810:2;28790:18;;;28783:30;28849:34;28829:18;;;28822:62;-1:-1:-1;;;28900:18:1;;;28893:32;28942:19;;70751:89:0::2;28569:398:1::0;70751:89:0::2;70849:25;-1:-1:-1::0;;;;;70849:25:0;::::2;::::0;::::2;:::i;:::-;70881:16;::::0;;;:9:::2;:16;::::0;;;;;;;:26:::2;;:41:::0;;;70958:11:::2;:18:::0;;;;;70849:25;;-1:-1:-1;70881:16:0;70958:27:::2;::::0;:25:::2;:27::i;:::-;70931:54;;70997:9;70992:341;71012:7;:14;71008:1;:18;70992:341;;;71039:23;71065:13:::0;;;:6:::2;:13;::::0;;;;71079:10;;71039:23;;71079:7;;71087:1;;71079:10;::::2;;;;;:::i;:::-;;;;;;;71065:25;;;;;;;;;;;:35;;;71039:61;;71109:16;71146:12;71128:15;:30;:67;;71194:1;71128:67;;;71161:30;71179:12:::0;71161:15;:30:::2;:::i;:::-;71109:86:::0;-1:-1:-1;71210:12:0;;71206:75:::2;;71224:57;71230:5;71237:7;71245:1;71237:10;;;;;;;;:::i;:::-;;;;;;;71249:8;71259:18;71278:1;71259:21;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;71224:5;:57::i;:::-;-1:-1:-1::0;;71313:3:0::2;;70992:341;;;-1:-1:-1::0;71376:6:0::2;::::0;:35:::2;::::0;-1:-1:-1;;;71376:35:0;;-1:-1:-1;;;;;71399:3:0::2;10763:32:1::0;;71376:35:0::2;::::0;::::2;10745:51:1::0;10812:18;;;10805:34;;;-1:-1:-1;;;;71376:6:0;::::2;::::0;:14:::2;::::0;10718:18:1;;71376:35:0::2;::::0;::::2;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71341:70;;;;71418:44;71435:5;71442:9;71453:8;71418:16;:44::i;:::-;71473:21;;::::0;::::2;:18:::0;:21:::2;:::i;:::-;71469:60;;;71496:33;71506:5;71513:8;71523:5;71496:9;:33::i;:::-;71536:84;71552:6;71560;71568:10;71580;71592;71604:15;71536;:84::i;:::-;-1:-1:-1::0;;60790:1:0;61742:7;:22;-1:-1:-1;;;;;;;;;70253:1373:0:o;66977:1069::-;60834:1;61430:7;;:19;;61422:63;;;;-1:-1:-1;;;61422:63:0;;;;;;;:::i;:::-;60834:1;61563:7;:18;;;67145:16:::1;::::0;67086:10:::1;::::0;67145:16:::1;::::0;;::::1;::::0;67170:871:::1;67190:17:::0;;::::1;67170:871;;;67261:6;-1:-1:-1::0;;;;;67231:36:0::1;:9;:20;67241:6;;67248:1;67241:9;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;67231:20:::0;;-1:-1:-1;67231:20:0;::::1;::::0;;;;;;-1:-1:-1;67231:20:0;:26;-1:-1:-1;;;;;67231:26:0::1;:36;67223:68;;;::::0;-1:-1:-1;;;67223:68:0;;24927:2:1;67223:68:0::1;::::0;::::1;24909:21:1::0;24966:2;24946:18;;;24939:30;-1:-1:-1;;;24985:18:1;;;24978:49;25044:18;;67223:68:0::1;24725:343:1::0;67223:68:0::1;67339:4;67302:23;:34;67326:6;;67333:1;67326:9;;;;;;;:::i;:::-;;;;;;;67302:34;;;;;;;;;;;;:41;;;;;;;;;;;;;;;;;;67352:23;67378:31;:11;:22;67390:6;;67397:1;67390:9;;;;;;;:::i;:::-;;;;;;;67378:22;;;;;;;;;;;:29;:31::i;:::-;67352:57;;67423:9;67418:204;67442:6;:13;67438:1;:17;67418:204;;;67473:14;67490:6;67497:1;67490:9;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;67533:13:::1;::::0;;;:5:::1;:13:::0;;;;;;:23:::1;;:25:::0;;-1:-1:-1;;67533:25:0;;;67490:9;-1:-1:-1;67587:6:0::1;::::0;67594;;67601:1;67594:9;;::::1;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;67587:17:::0;;-1:-1:-1;67587:17:0;;::::1;::::0;;;;;;;;-1:-1:-1;67587:17:0;;;:25;;;;;;;;67580:32;;-1:-1:-1;;;;;;67580:32:0::1;::::0;;67587:25;67580:32:::1;::::0;;::::1;-1:-1:-1::0;67580:32:0::1;:::i;:::-;;;::::0;::::1;;;:::i;:::-;;;::::0;::::1;;;:::i;:::-;-1:-1:-1::0;67580:32:0::1;;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;-1:-1:-1;67457:3:0::1;::::0;::::1;:::i;:::-;;;67418:204;;;;67637:9;:20;67647:6;;67654:1;67647:9;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;67637:20:::0;;-1:-1:-1;67637:20:0;::::1;::::0;;;;;;-1:-1:-1;67637:20:0;;;67630:27;;-1:-1:-1;;;;;;67630:27:0::1;::::0;;;::::1;::::0;67673:17;67668:255:::1;;67711:37;67738:6;;67745:1;67738:9;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;67711:19:0;::::1;;::::0;;;:11:::1;67738:9;67711:19:::0;;;;;;;;67738:9;::::1;;;::::0;-1:-1:-1;67711:26:0::1;:37::i;:::-;67703:46;;;::::0;::::1;;67765:9;67760:154;67784:6;:13;67780:1;:17;67760:154;;;67817:14;67834:6;67841:1;67834:9;;;;;;;;:::i;:::-;;;;;;;67817:26;;67864:37;67894:6;67864:11;:22;67876:6;;67883:1;67876:9;;;;;;;:::i;:::-;;;;;;;67864:22;;;;;;;;;;;:29;;:37;;;;:::i;:::-;67856:46;;;::::0;::::1;;-1:-1:-1::0;67799:3:0::1;::::0;::::1;:::i;:::-;;;67760:154;;;;67668:255;67933:3;-1:-1:-1::0;;;;;67933:16:0::1;;67958:4;67965:6;67973;;67980:1;67973:9;;;;;;;:::i;:::-;;;;;;;67933:50;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;68023:6;;68030:1;68023:9;;;;;;;:::i;:::-;67997:36;::::0;-1:-1:-1;;;;;4979:32:1;;4961:51;;68023:9:0::1;::::0;;::::1;::::0;;;::::1;;::::0;67997:36:::1;::::0;-1:-1:-1;4934:18:1;67997:36:0::1;;;;;;;-1:-1:-1::0;67209:3:0::1;::::0;::::1;:::i;:::-;;;67170:871;;;-1:-1:-1::0;;60790:1:0;61742:7;:22;-1:-1:-1;;;66977:1069:0:o;73597:1168::-;73706:17;73842:10;;;:5;:10;;;;;;;;73885:13;;;:6;:13;;;;;:18;;;;;;;;73920:15;;;;73732:30;;;;73842:10;73912:59;;;;-1:-1:-1;;;73912:59:0;;29174:2:1;73912:59:0;;;29156:21:1;29213:2;29193:18;;;29186:30;29252:29;29232:18;;;29225:57;29299:18;;73912:59:0;28972:351:1;73912:59:0;74010:12;;;:19;-1:-1:-1;;;;;73996:34:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73996:34:0;-1:-1:-1;74064:12:0;;;:19;73980:50;;-1:-1:-1;;;;;;74050:34:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74050:34:0;;74037:47;;74093:33;74129:36;74154:5;74161:3;74129:24;:36::i;:::-;74093:72;;74177:9;74172:554;74196:12;;;:19;74192:23;;74172:554;;;74231:21;74255:172;74289:5;:15;;;74315:4;:12;;74328:1;74315:15;;;;;;;;:::i;:::-;;;;;;;;;;;:31;;;74357:4;:26;;;74394:4;:24;;;74255:23;:172::i;:::-;74231:196;;74436:23;74462:144;74525:13;74498:5;:21;;74520:1;74498:24;;;;;;;;:::i;:::-;;;;;;;;;:40;;;;:::i;:::-;74549:4;:18;;;74578:5;:16;;74595:1;74578:19;;;;;;;;:::i;:::-;;;;;;;;;74462:25;:144::i;:::-;74436:170;;74659:15;74634:5;:19;;74654:1;74634:22;;;;;;;;:::i;:::-;;;;;;;;;:40;;;;:::i;:::-;74615:13;74629:1;74615:16;;;;;;;;:::i;:::-;;;;;;:59;;;;;74699:5;:16;;74716:1;74699:19;;;;;;;;:::i;:::-;;;;;;;;;74683:10;74694:1;74683:13;;;;;;;;:::i;:::-;;;;;;:35;;;;;74222:504;;74217:3;;;;:::i;:::-;;;74172:554;;;;74744:5;:15;;;74732:27;;73809:956;;;73597:1168;;;;;:::o;87570:861::-;87682:33;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87682:33:0;87727:23;87753:10;;;:5;:10;;;;;;;;87796:13;;;:6;:13;;;;;:18;;;;;;;;;;87853:6;;87874:16;;87853:59;;-1:-1:-1;;;87853:59:0;;87753:10;;87796:18;;-1:-1:-1;;;;;87853:6:0;;;;:20;;:59;;87874:16;;;87900:3;;87803:5;;87853:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;87823:89:0;;;87933:6;;87957:16;;87933:62;;-1:-1:-1;;;87933:62:0;;-1:-1:-1;;;;;87933:6:0;;;;:23;;:62;;87957:16;;;87983:3;;87989:5;;87933:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87919:11;;;:76;;;88060:14;;;;88076;;;;88023:68;;87919:76;88060:14;88023:23;:68::i;:::-;88002:18;;;:89;88162:14;;88206:24;;;;88127:110;;88162:14;-1:-1:-1;;;88162:14:0;;;;;-1:-1:-1;;;88185:12:0;;;;;88127:26;:110::i;:::-;88098:26;;;:139;88320:29;;88290:27;;-1:-1:-1;;;;;88320:29:0;;;88290:59;;88263:86;:24;;;:86;;;88383:15;;;;:42;;88263:86;88383:42;:::i;:::-;88363:17;;;:62;-1:-1:-1;88363:4:0;;87570:861;-1:-1:-1;;;87570:861:0:o;83011:1519::-;83094:3;83081:10;;:16;83073:44;;;;-1:-1:-1;;;83073:44:0;;;;;;;:::i;:::-;83124:23;83150:10;;;:5;:10;;;;;;;;83184:16;;;:9;:16;;;;;:22;83239:6;:13;;;;;:18;;;;;;;;83274:15;;;;-1:-1:-1;;;;;83184:22:0;;;;83239:18;83266:55;;;;-1:-1:-1;;;83266:55:0;;29891:2:1;83266:55:0;;;29873:21:1;29930:2;29910:18;;;29903:30;29969:25;29949:18;;;29942:53;30012:18;;83266:55:0;29689:347:1;83266:55:0;83330:33;83366:36;83391:5;83398:3;83366:24;:36::i;:::-;83330:72;;83439:4;:17;;;83411:4;:24;;;:45;;;;;;;:::i;:::-;;;;-1:-1:-1;;83495:27:0;;83463:59;;-1:-1:-1;;;;;;83463:59:0;-1:-1:-1;;;;;83463:59:0;;;;;;-1:-1:-1;83529:996:0;83553:12;;;:19;83549:23;;83529:996;;;83588:21;83612:172;83646:5;:15;;;83672:4;:12;;83685:1;83672:15;;;;;;;;:::i;83612:172::-;83588:196;-1:-1:-1;83799:18:0;;83795:145;;83858:13;83830:5;:21;;83852:1;83830:24;;;;;;;;:::i;:::-;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;83917:13;83882:4;:12;;83895:1;83882:15;;;;;;;;:::i;:::-;;;;;;;;;;;:31;;;:48;;;;;;;:::i;:::-;;;;-1:-1:-1;;83795:145:0;83950:23;83976:128;84012:5;:21;;84034:1;84012:24;;;;;;;;:::i;:::-;;;;;;;;;84047:4;:18;;;84076:5;:16;;84093:1;84076:19;;;;;;;;:::i;83976:128::-;83950:154;;84115:21;84164:15;84139:5;:19;;84159:1;84139:22;;;;;;;;:::i;:::-;;;;;;;;;:40;;;;:::i;:::-;84115:64;-1:-1:-1;84192:18:0;;84188:330;;84227:20;;84223:89;;84285:15;84262:5;:16;;84279:1;84262:19;;;;;;;;:::i;:::-;;;;;;;;;:38;;;;;;;:::i;:::-;;;;-1:-1:-1;;84223:89:0;84347:1;84322:5;:19;;84342:1;84322:22;;;;;;;;:::i;:::-;;;;;;;;:26;;;;84359:67;84375:4;:12;;84388:1;84375:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:27;-1:-1:-1;;;;;84375:27:0;84404:6;84412:13;84359:15;:67::i;:::-;84494:13;84450:5;84442:66;84457:6;84465:4;:12;;84478:1;84465:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:27;84442:66;;;;;-1:-1:-1;;;;;84465:27:0;;-1:-1:-1;;;;;30271:15:1;;;30253:34;;30323:15;;30318:2;30303:18;;30296:43;30203:2;30188:18;;30041:304;84442:66:0;;;;;;;;84188:330;83579:946;;;83574:3;;;;:::i;:::-;;;83529:996;;77781:945;77903:29;77935:16;;;:9;:16;;;;;;;;77984:6;:13;;;;;:18;;;;;;;;;;78017:6;;78034:16;;78017:55;;-1:-1:-1;;;78017:55:0;;77935:16;;77984:18;;-1:-1:-1;;;;;78017:6:0;;;;:16;;:55;;78034:16;;;78060:3;;77945:5;;78017:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78009:86;;;;-1:-1:-1;;;78009:86:0;;30802:2:1;78009:86:0;;;30784:21:1;30841:2;30821:18;;;30814:30;-1:-1:-1;;;30860:18:1;;;30853:48;30918:18;;78009:86:0;30600:342:1;78009:86:0;78110:8;;;;;:37;;;78129:8;:18;;;78122:3;:25;;78110:37;78102:67;;;;-1:-1:-1;;;78102:67:0;;31149:2:1;78102:67:0;;;31131:21:1;31188:2;31168:18;;;31161:30;-1:-1:-1;;;31207:18:1;;;31200:47;31264:18;;78102:67:0;30947:341:1;78102:67:0;78210:6;;78231:16;;78210:59;;-1:-1:-1;;;78210:59:0;;-1:-1:-1;;;;;78210:6:0;;;;:20;;:59;;78231:16;;;78257:3;;78263:5;;78210:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78178:91;;-1:-1:-1;;;;;;78178:91:0;-1:-1:-1;;;;;78178:91:0;;;;;;;78309:12;;;:19;-1:-1:-1;;;;;78295:34:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78295:34:0;-1:-1:-1;78276:53:0;;;;:16;;;;:53;;;;;;:::i;:::-;-1:-1:-1;78372:12:0;;;:19;-1:-1:-1;;;;;78358:34:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78358:34:0;-1:-1:-1;78336:56:0;;;;:19;;;;:56;;;;;;:::i;:::-;-1:-1:-1;78437:12:0;;;:19;-1:-1:-1;;;;;78423:34:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78423:34:0;-1:-1:-1;78399:58:0;;;;:21;;;;:58;;;;;;:::i;:::-;-1:-1:-1;78468:14:0;;;;:19;78464:99;;78515:6;;:40;;-1:-1:-1;;;78515:40:0;;-1:-1:-1;;;;;78543:3:0;10763:32:1;;78515:40:0;;;10745:51:1;10812:18;;;10805:34;;;78515:6:0;;;;:19;;10718:18:1;;78515:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78498:14;;;:57;78464:99;78569:15;;;:21;;;78597:14;;;:16;;;:14;:16;;;:::i;:::-;;;;-1:-1:-1;;78630:18:0;;;;:11;:18;;;;;:27;;78653:3;78630:22;:27::i;:::-;78622:63;;;;-1:-1:-1;;;78622:63:0;;31495:2:1;78622:63:0;;;31477:21:1;31534:2;31514:18;;;31507:30;31573:25;31553:18;;;31546:53;31616:18;;78622:63:0;31293:347:1;78622:63:0;78716:3;78711;78704:5;78699:21;;;;;;;;;;77896:830;;77781:945;;;;:::o;78923:1499::-;79045:29;79077:16;;;:9;:16;;;;;;;;79126:6;:13;;;;;:18;;;;;;;;;79161:8;;;;;:55;;-1:-1:-1;79198:18:0;;;;79179:15;;;;79173:21;;:3;:21;:::i;:::-;:43;;79161:55;79153:85;;;;-1:-1:-1;;;79153:85:0;;31847:2:1;79153:85:0;;;31829:21:1;31886:2;31866:18;;;31859:30;-1:-1:-1;;;31905:18:1;;;31898:47;31962:18;;79153:85:0;31645:341:1;79153:85:0;79247:33;79283:36;79308:5;79315:3;79283:24;:36::i;:::-;79247:72;;79333:9;79328:730;79352:12;;;:19;79348:23;;79328:730;;;79387:21;79411:172;79445:5;:15;;;79471:4;:12;;79484:1;79471:15;;;;;;;;:::i;79411:172::-;79387:196;-1:-1:-1;79598:18:0;;79594:145;;79657:13;79629:5;:21;;79651:1;79629:24;;;;;;;;:::i;:::-;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;79716:13;79681:4;:12;;79694:1;79681:15;;;;;;;;:::i;:::-;;;;;;;;;;;:31;;;:48;;;;;;;:::i;:::-;;;;-1:-1:-1;;79594:145:0;79749:23;79775:128;79811:5;:21;;79833:1;79811:24;;;;;;;;:::i;79775:128::-;79749:154;-1:-1:-1;79918:20:0;;79914:137;;79974:15;79951:5;:16;;79968:1;79951:19;;;;;;;;:::i;:::-;;;;;;;;;:38;;;;;;;:::i;:::-;;;;;;;;80026:15;80000:5;:19;;80020:1;80000:22;;;;;;;;:::i;:::-;;;;;;;;;:41;;;;;;;:::i;:::-;;;;-1:-1:-1;;79914:137:0;79378:680;;79373:3;;;;:::i;:::-;;;79328:730;;;;80094:4;:17;;;80066:4;:24;;;:45;;;;;;;:::i;:::-;;;;-1:-1:-1;;80150:27:0;;80118:59;;-1:-1:-1;;;;;;80118:59:0;-1:-1:-1;;;;;80118:59:0;;;;;;80237:14;;;;80260:11;;;;80280:14;;;;80303:15;;;;80201:150;;80237:14;80260:11;80280:14;80327:3;80339:5;80201:27;:150::i;:::-;80184:5;:14;;:167;;;;80377:3;80358:5;:15;;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;80392:24:0;;80412:3;;80407;;80400:5;;80392:24;;;;;79038:1384;;;78923:1499;;;;:::o;57758:114::-;57818:7;57845:19;57853:3;50787:18;;50704:109;58226:137;58297:7;58332:22;58336:3;58348:5;58332:3;:22::i;:::-;58324:31;58226:137;-1:-1:-1;;;58226:137:0:o;76265:1329::-;76389:16;;;;76388:17;76380:52;;;;-1:-1:-1;;;76380:52:0;;32193:2:1;76380:52:0;;;32175:21:1;32232:2;32212:18;;;32205:30;-1:-1:-1;;;32251:18:1;;;32244:52;32313:18;;76380:52:0;31991:346:1;76380:52:0;76445:9;76441:292;;;76528:3;76515:10;;:16;76507:44;;;;-1:-1:-1;;;76507:44:0;;;;;;;:::i;:::-;76560:17;76622:10;;;:5;:10;;;;;:20;90956:15;;76622:34;;;;-1:-1:-1;;;76622:20:0;;;;:34;;;;:69;;-1:-1:-1;76673:10:0;;;;:5;:10;;;;;:18;;-1:-1:-1;;;76673:18:0;;;;;76660:31;;;;76622:69;76604:121;;;;-1:-1:-1;;;76604:121:0;;21633:2:1;76604:121:0;;;21615:21:1;21672:2;21652:18;;;21645:30;-1:-1:-1;;;21691:18:1;;;21684:42;21743:18;;76604:121:0;21431:336:1;76604:121:0;76456:277;76441:292;76758:10;76741:14;76777:812;76801:6;:13;76797:1;:17;76777:812;;;76917:23;:34;76941:6;76948:1;76941:9;;;;;;;;:::i;:::-;;;;;;;;;;;;76917:34;;;;;;;;;;-1:-1:-1;76917:34:0;;;;76916:35;76908:70;;;;-1:-1:-1;;;76908:70:0;;32193:2:1;76908:70:0;;;32175:21:1;32232:2;32212:18;;;32205:30;-1:-1:-1;;;32251:18:1;;;32244:52;32313:18;;76908:70:0;31991:346:1;76908:70:0;77060:34;77084:6;77091:1;77084:9;;;;;;;;:::i;:::-;;;;;;;77060:11;:19;77072:6;-1:-1:-1;;;;;77060:19:0;-1:-1:-1;;;;;77060:19:0;;;;;;;;;;;;:23;;:34;;;;:::i;:::-;77052:43;;;;;;77104:3;-1:-1:-1;;;;;77104:16:0;;77121:6;77137:4;77144:6;77151:1;77144:9;;;;;;;;:::i;:::-;;;;;;;77104:50;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77184:6;77191:1;77184:9;;;;;;;;:::i;:::-;;;;;;;77168:26;77176:6;77168:26;;;;;-1:-1:-1;;;;;4979:32:1;;;;4961:51;;4949:2;4934:18;;4815:203;77168:26:0;;;;;;;;77263:6;77234:9;:20;77244:6;77251:1;77244:9;;;;;;;;:::i;:::-;;;;;;;;;;;;77234:20;;;;;;;;;;-1:-1:-1;77234:20:0;;;:35;;-1:-1:-1;;;;;;77234:35:0;-1:-1:-1;;;;;77234:35:0;;;;;;77298:6;;77326:9;;-1:-1:-1;;77298:6:0;;:13;;77320:3;;77326:9;;77333:1;;77326:9;;;;;;:::i;:::-;;;;;;;77298:38;;;;;;;;;;;;;;;-1:-1:-1;;;;;10763:32:1;;;;10745:51;;10827:2;10812:18;;10805:34;10733:2;10718:18;;10571:274;77298:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77278:58;;77378:9;-1:-1:-1;;;;;77345:42:0;:9;:20;77355:6;77362:1;77355:9;;;;;;;;:::i;:::-;;;;;;;77345:20;;;;;;;;;;;:30;;:42;;;;77464:9;77460:80;;;77486:44;77492:6;77499:1;77492:9;;;;;;;;:::i;:::-;;;;;;;77503:3;77508:9;-1:-1:-1;;;;;77486:44:0;77519:5;:10;77525:3;77519:10;;;;;;;;;;;77486:5;:44::i;:::-;-1:-1:-1;77569:3:0;;76777:812;;;;76373:1221;76265:1329;;;:::o;84577:355::-;-1:-1:-1;;;;;84693:20:0;;84689:238;;84725:12;84751:8;-1:-1:-1;;;;;84743:22:0;84773:7;84743:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84724:61;;;84802:7;84794:48;;;;-1:-1:-1;;;84794:48:0;;32754:2:1;84794:48:0;;;32736:21:1;32793:2;32773:18;;;32766:30;32832;32812:18;;;32805:58;32880:18;;84794:48:0;32552:352:1;84794:48:0;84715:135;84577:355;;;:::o;84689:238::-;84865:54;-1:-1:-1;;;;;84865:35:0;;84901:8;84911:7;84865:35;:54::i;:::-;84577:355;;;:::o;80620:2272::-;80735:23;80761:10;;;:5;:10;;;;;;;;80795:16;;;:9;:16;;;;;:22;80850:6;:13;;;;;:18;;;;;;;;-1:-1:-1;;;;;80795:22:0;;;;80903:10;80893:20;;;:81;;-1:-1:-1;80936:12:0;;-1:-1:-1;;;80936:12:0;;;;90956:15;80918:30;;;:55;;;;-1:-1:-1;80962:10:0;80952:21;;;;:9;:21;;;;;;;;80918:55;80877:148;;;;-1:-1:-1;;;80877:148:0;;33111:2:1;80877:148:0;;;33093:21:1;33150:2;33130:18;;;33123:30;33189:34;33169:18;;;33162:62;-1:-1:-1;;;33240:18:1;;;33233:31;33281:19;;80877:148:0;32909:397:1;80877:148:0;81057:15;;;;81087:8;;;;;:31;;;81106:12;81099:3;:19;;81087:31;81079:61;;;;-1:-1:-1;;;81079:61:0;;33513:2:1;81079:61:0;;;33495:21:1;33552:2;33532:18;;;33525:30;-1:-1:-1;;;33571:18:1;;;33564:47;33628:18;;81079:61:0;33311:341:1;81079:61:0;81149:20;81172:18;81187:3;81172:12;:18;:::i;:::-;81149:41;;81197:33;81233:36;81258:5;81265:3;81233:24;:36::i;:::-;81197:72;;81306:4;:17;;;81278:4;:24;;;:45;;;;;;;:::i;:::-;;;;-1:-1:-1;;81362:27:0;;81330:59;;-1:-1:-1;;;;;;81330:59:0;-1:-1:-1;;;;;81330:59:0;;;;;;81396:15;;;:30;;;-1:-1:-1;81433:1233:0;81457:12;;;:19;81453:23;;81433:1233;;;81492:21;81516:169;81550:12;81573:4;:12;;81586:1;81573:15;;;;;;;;:::i;81516:169::-;81492:193;-1:-1:-1;81700:18:0;;81696:145;;81759:13;81731:5;:21;;81753:1;81731:24;;;;;;;;:::i;:::-;;;;;;;;;:41;;;;;;;:::i;:::-;;;;;;;;81818:13;81783:4;:12;;81796:1;81783:15;;;;;;;;:::i;:::-;;;;;;;;;;;:31;;;:48;;;;;;;:::i;:::-;;;;-1:-1:-1;;81696:145:0;81851:23;81877:128;81913:5;:21;;81935:1;81913:24;;;;;;;;:::i;:::-;;;;;;;;;81948:4;:18;;;81977:5;:16;;81994:1;81977:19;;;;;;;;:::i;81877:128::-;81851:154;;82016:21;82040:5;:19;;82060:1;82040:22;;;;;;;;:::i;:::-;;;;;;;;;82016:46;;82075:15;82094:1;82075:20;82071:128;;82131:15;82108:5;:16;;82125:1;82108:19;;;;;;;;:::i;:::-;;;;;;;;;:38;;;;;;;:::i;:::-;;;;-1:-1:-1;82157:32:0;;-1:-1:-1;82174:15:0;82157:32;;:::i;:::-;;;82071:128;82213:18;;82209:450;;82248:11;:32;;;-1:-1:-1;82263:17:0;;82248:32;82244:406;;;82404:1;82379:5;:19;;82399:1;82379:22;;;;;;;;:::i;:::-;;;;;;;;:26;;;;82418:67;82434:4;:12;;82447:1;82434:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:27;-1:-1:-1;;;;;82434:27:0;82463:6;82471:13;82418:15;:67::i;:::-;82555:13;82511:5;82503:66;82518:6;82526:4;:12;;82539:1;82526:15;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:27;82503:66;;;;;-1:-1:-1;;;;;82526:27:0;;-1:-1:-1;;;;;30271:15:1;;;30253:34;;30323:15;;30318:2;30303:18;;30296:43;30203:2;30188:18;;30041:304;82503:66:0;;;;;;;;82244:406;;;82625:13;82600:5;:19;;82620:1;82600:22;;;;;;;;:::i;:::-;;;;;;;;;;:38;82244:406;81483:1183;;;81478:3;;;;:::i;:::-;;;81433:1233;;;-1:-1:-1;82676:17:0;82672:170;;82711:13;;;;:6;:13;;;;;;;;:18;;;;;;;;82704:25;;-1:-1:-1;;;;;;82704:25:0;;;82711:18;82704:25;;;;82711:13;82704:25;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;82704:25:0;;;;;;;;;;;;;;;82738:14;;;:16;;;;;;:::i;:::-;;;;-1:-1:-1;;82773:18:0;;;;:11;:18;;;;;:30;;82799:3;82773:25;:30::i;:::-;82765:69;;;;-1:-1:-1;;;82765:69:0;;34000:2:1;82765:69:0;;;33982:21:1;34039:2;34019:18;;;34012:30;34078:28;34058:18;;;34051:56;34124:18;;82765:69:0;33798:350:1;82765:69:0;82853:33;;82858:10;4961:51:1;;82882:3:0;;82877;;82870:5;;82853:33;;4949:2:1;4934:18;82853:33:0;;;;;;;80728:2164;;;;;;80620:2272;;;;:::o;57303:137::-;57373:4;57397:35;57405:3;57425:5;57397:7;:35::i;58913:263::-;58973:16;59002:22;59027:19;59035:3;59027:7;:19::i;85737:439::-;85843:7;85839:85;;;85861:55;;-1:-1:-1;;;85861:55:0;;;;;1424:25:1;;;85890:3:0;-1:-1:-1;;;;;85861:48:0;;;;1397:18:1;;85861:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;85839:85;85990:113;;;;;;;;;;;-1:-1:-1;85990:113:0;;;;;;;;;;;;;;;;;;86112:58;;-1:-1:-1;;;86112:58:0;;34573:13:1;;86112:58:0;;;34555:32:1;34625:24;;34603:20;;;34596:54;34688:24;;34666:20;;;34659:54;34751:24;;34729:20;;;34722:54;85990:113:0;86141:3;-1:-1:-1;;;;;86112:46:0;;;;34527:19:1;;86112:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;86583:913::-;86834:3;86848:511;;;;86934:6;-1:-1:-1;;;;;86926:14:0;:4;-1:-1:-1;;;;;86926:14:0;;86922:211;;;86994:43;;-1:-1:-1;;;86994:43:0;;;;;35272:25:1;;;-1:-1:-1;;;;;35333:32:1;;;35313:18;;;35306:60;86994:21:0;;;;;35245:18:1;;86994:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;87048:58:0;;-1:-1:-1;;;87048:58:0;;-1:-1:-1;;;;;87048:28:0;;;-1:-1:-1;87048:28:0;;-1:-1:-1;87048:58:0;;87077:6;;87085:10;;87097:8;;87048:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87117:7;;;86922:211;87153:6;-1:-1:-1;;;;;87145:14:0;:4;-1:-1:-1;;;;;87145:14:0;;87141:211;;;87213:58;;-1:-1:-1;;;87213:58:0;;-1:-1:-1;;;;;87213:28:0;;;;;:58;;87242:6;;87250:10;;87262:8;;87213:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;87282:43:0;;-1:-1:-1;;;87282:43:0;;;;;35272:25:1;;;-1:-1:-1;;;;;35333:32:1;;;35313:18;;;35306:60;87282:21:0;;;-1:-1:-1;87282:21:0;;-1:-1:-1;35245:18:1;;87282:43:0;35098:274:1;87141:211:0;87367:58;;-1:-1:-1;;;87367:58:0;;-1:-1:-1;;;;;87367:28:0;;;;;:58;;87396:6;;87404:10;;87416:8;;87367:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;87432:58:0;;-1:-1:-1;;;87432:58:0;;-1:-1:-1;;;;;87432:28:0;;;-1:-1:-1;87432:28:0;;-1:-1:-1;87432:58:0;;87461:6;;87469:10;;87481:8;;87432:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86764:732;86583:913;;;;;;;:::o;85117:446::-;85293:194;;;;;;;;;;;-1:-1:-1;;;;;85293:194:0;;;;;;;;;-1:-1:-1;85293:194:0;;;;;;;;;;;;;;;;;;85496:61;;-1:-1:-1;;;85496:61:0;;35998:13:1;;85496:61:0;;;35980:32:1;36054:24;;36050:65;;;36028:20;;;36021:95;36154:24;;36132:20;;;36125:54;36217:24;;36195:20;;;36188:54;36280:24;;36258:20;;;36251:54;85293:194:0;85525:3;-1:-1:-1;;;;;85496:50:0;;;;35952:19:1;;85496:61:0;35757:554:1;90175:289:0;90360:7;90437:21;90414:19;90384:27;90396:15;90384:9;:27;:::i;:::-;:49;;;;:::i;:::-;90383:75;;;;:::i;:::-;90376:82;90175:289;-1:-1:-1;;;;;90175:289:0:o;90567:298::-;90713:7;;62126:4;90750:31;90768:13;90750:15;:31;:::i;:::-;90749:45;;;;:::i;:::-;90729:65;;90820:10;90808:9;:22;:51;;90858:1;90808:51;;;90833:22;90845:10;90833:9;:22;:::i;89258:326::-;89385:7;89405:14;89401:53;;-1:-1:-1;62126:4:0;89430:16;;89401:53;89460:17;89488;89497:8;89488:6;:17;:::i;:::-;89460:46;-1:-1:-1;89520:58:0;89557:9;89532:21;62126:4;89460:46;89532:21;:::i;:::-;89531:35;;;;:::i;:::-;62126:4;89520:10;:58::i;89691:398::-;89835:7;;89913:9;89874:36;90956:15;89874:36;;89902:7;89874:10;:36::i;:::-;:48;;;;:::i;:::-;89851:71;-1:-1:-1;89929:26:0;89958:24;89851:71;-1:-1:-1;;;89958:24:0;:::i;:::-;89929:53;;90017:19;89996:18;:40;:87;;90082:1;89996:87;;;90039:40;90060:19;90039:18;:40;:::i;:::-;89989:94;89691:398;-1:-1:-1;;;;;;89691:398:0:o;56996:131::-;57063:4;57087:32;57092:3;57112:5;57087:4;:32::i;88542:635::-;88744:6;88763:14;88759:45;;-1:-1:-1;88795:1:0;88788:8;;88759:45;88810:22;88864:8;88835:26;88851:9;88835:6;:26;:::i;:::-;:37;:91;;88900:26;88916:9;88900:6;:26;:::i;:::-;88835:91;;;88882:8;88835:91;89034:6;;:40;;-1:-1:-1;;;89034:40:0;;-1:-1:-1;;;;;89062:3:0;10763:32:1;;89034:40:0;;;10745:51:1;10812:18;;;10805:34;;;88810:116:0;;-1:-1:-1;;;89034:6:0;;;;:19;;10718:18:1;;89034:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89004:70;;89011:12;89004:70;:::i;:::-;88952:42;88979:15;88959:9;88952:42;:::i;:::-;:122;;;;:::i;:::-;88933:141;-1:-1:-1;89081:18:0;89109:24;89121:12;89109:9;:24;:::i;:::-;89081:53;-1:-1:-1;89148:23:0;89081:53;89148:9;:23;:::i;:::-;89141:30;88542:635;-1:-1:-1;;;;;;;;;;88542:635:0:o;51167:120::-;51234:7;51261:3;:11;;51273:5;51261:18;;;;;;;;:::i;:::-;;;;;;;;;51254:25;;51167:120;;;;:::o;42931:211::-;43075:58;;;-1:-1:-1;;;;;10763:32:1;;43075:58:0;;;10745:51:1;10812:18;;;;10805:34;;;43075:58:0;;;;;;;;;;10718:18:1;;;;43075:58:0;;;;;;;;-1:-1:-1;;;;;43075:58:0;-1:-1:-1;;;43075:58:0;;;43048:86;;43068:5;;43048:19;:86::i;48983:1420::-;49049:4;49188:19;;;:12;;;:19;;;;;;49224:15;;49220:1176;;49599:21;49623:14;49636:1;49623:10;:14;:::i;:::-;49672:18;;49599:38;;-1:-1:-1;49652:17:0;;49672:22;;49693:1;;49672:22;:::i;:::-;49652:42;;49728:13;49715:9;:26;49711:405;;49762:17;49782:3;:11;;49794:9;49782:22;;;;;;;;:::i;:::-;;;;;;;;;49762:42;;49936:9;49907:3;:11;;49919:13;49907:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;50021:23;;;:12;;;:23;;;;;:36;;;49711:405;50197:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;50292:3;:12;;:19;50305:5;50292:19;;;;;;;;;;;50285:26;;;50335:4;50328:11;;;;;;;49220:1176;50379:5;50372:12;;;;;51837:111;51893:16;51929:3;:11;;51922:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51837:111;;;:::o;186:101::-;244:7;272:1;267;:6;;:14;;280:1;267:14;;;-1:-1:-1;276:1:0;186:101;-1:-1:-1;186:101:0:o;79:::-;137:7;165:1;160;:6;;:14;;173:1;160:14;;;-1:-1:-1;169:1:0;;79:101;-1:-1:-1;79:101:0:o;48393:414::-;48456:4;50586:19;;;:12;;;:19;;;;;;48473:327;;-1:-1:-1;48516:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;48699:18;;48677:19;;;:12;;;:19;;;;;;:40;;;;48732:11;;48473:327;-1:-1:-1;48783:5:0;48776:12;;45504:716;45928:23;45954:69;45982:4;45954:69;;;;;;;;;;;;;;;;;45962:5;-1:-1:-1;;;;;45954:27:0;;;:69;;;;;:::i;:::-;46038:17;;45928:95;;-1:-1:-1;46038:21:0;46034:179;;46135:10;46124:30;;;;;;;;;;;;:::i;:::-;46116:85;;;;-1:-1:-1;;;46116:85:0;;38205:2:1;46116:85:0;;;38187:21:1;38244:2;38224:18;;;38217:30;38283:34;38263:18;;;38256:62;-1:-1:-1;;;38334:18:1;;;38327:40;38384:19;;46116:85:0;38003:406:1;37880:229:0;38017:12;38049:52;38071:6;38079:4;38085:1;38088:12;38049:21;:52::i;:::-;38042:59;37880:229;-1:-1:-1;;;;37880:229:0:o;39000:510::-;39170:12;39228:5;39203:21;:30;;39195:81;;;;-1:-1:-1;;;39195:81:0;;38616:2:1;39195:81:0;;;38598:21:1;38655:2;38635:18;;;38628:30;38694:34;38674:18;;;38667:62;-1:-1:-1;;;38745:18:1;;;38738:36;38791:19;;39195:81:0;38414:402:1;39195:81:0;35397:20;;39287:60;;;;-1:-1:-1;;;39287:60:0;;39023:2:1;39287:60:0;;;39005:21:1;39062:2;39042:18;;;39035:30;39101:31;39081:18;;;39074:59;39150:18;;39287:60:0;38821:353:1;39287:60:0;39361:12;39375:23;39402:6;-1:-1:-1;;;;;39402:11:0;39421:5;39428:4;39402:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39360:73;;;;39451:51;39468:7;39477:10;39489:12;39451:16;:51::i;:::-;39444:58;39000:510;-1:-1:-1;;;;;;;39000:510:0:o;41686:712::-;41836:12;41865:7;41861:530;;;-1:-1:-1;41896:10:0;41889:17;;41861:530;42010:17;;:21;42006:374;;42208:10;42202:17;42269:15;42256:10;42252:2;42248:19;42241:44;42006:374;42351:12;42344:20;;-1:-1:-1;;;42344:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:163:1;81:20;;141:10;130:22;;120:33;;110:61;;167:1;164;157:12;110:61;14:163;;;:::o;182:367::-;245:8;255:6;309:3;302:4;294:6;290:17;286:27;276:55;;327:1;324;317:12;276:55;-1:-1:-1;350:20:1;;-1:-1:-1;;;;;382:30:1;;379:50;;;425:1;422;415:12;379:50;462:4;454:6;450:17;438:29;;522:3;515:4;505:6;502:1;498:14;490:6;486:27;482:38;479:47;476:67;;;539:1;536;529:12;476:67;182:367;;;;;:::o;554:719::-;674:6;682;690;698;706;714;767:3;755:9;746:7;742:23;738:33;735:53;;;784:1;781;774:12;735:53;820:9;807:23;797:33;;849:37;882:2;871:9;867:18;849:37;:::i;:::-;839:47;;905:37;938:2;927:9;923:18;905:37;:::i;:::-;895:47;;993:2;982:9;978:18;965:32;-1:-1:-1;;;;;1012:6:1;1009:30;1006:50;;;1052:1;1049;1042:12;1006:50;1091:70;1153:7;1144:6;1133:9;1129:22;1091:70;:::i;:::-;554:719;;;;-1:-1:-1;554:719:1;;;;;1262:3;1247:19;;;1234:33;;554:719;-1:-1:-1;;;;554:719:1:o;1460:131::-;-1:-1:-1;;;;;1535:31:1;;1525:42;;1515:70;;1581:1;1578;1571:12;1596:247;1655:6;1708:2;1696:9;1687:7;1683:23;1679:32;1676:52;;;1724:1;1721;1714:12;1676:52;1763:9;1750:23;1782:31;1807:5;1782:31;:::i;2040:784::-;2173:6;2181;2189;2197;2250:2;2238:9;2229:7;2225:23;2221:32;2218:52;;;2266:1;2263;2256:12;2218:52;2306:9;2293:23;-1:-1:-1;;;;;2376:2:1;2368:6;2365:14;2362:34;;;2392:1;2389;2382:12;2362:34;2431:70;2493:7;2484:6;2473:9;2469:22;2431:70;:::i;:::-;2520:8;;-1:-1:-1;2405:96:1;-1:-1:-1;2608:2:1;2593:18;;2580:32;;-1:-1:-1;2624:16:1;;;2621:36;;;2653:1;2650;2643:12;2621:36;;2692:72;2756:7;2745:8;2734:9;2730:24;2692:72;:::i;:::-;2040:784;;;;-1:-1:-1;2783:8:1;-1:-1:-1;;;;2040:784:1:o;2829:180::-;2888:6;2941:2;2929:9;2920:7;2916:23;2912:32;2909:52;;;2957:1;2954;2947:12;2909:52;-1:-1:-1;2980:23:1;;2829:180;-1:-1:-1;2829:180:1:o;3014:435::-;3067:3;3105:5;3099:12;3132:6;3127:3;3120:19;3158:4;3187:2;3182:3;3178:12;3171:19;;3224:2;3217:5;3213:14;3245:1;3255:169;3269:6;3266:1;3263:13;3255:169;;;3330:13;;3318:26;;3364:12;;;;3399:15;;;;3291:1;3284:9;3255:169;;;-1:-1:-1;3440:3:1;;3014:435;-1:-1:-1;;;;;3014:435:1:o;3454:1356::-;-1:-1:-1;;;;;3976:15:1;;;3958:34;;4032:10;4078:15;;;4011:2;4058:18;;;4051:43;;;;4130:15;;;4125:2;4110:18;;4103:43;4177:2;4162:18;;4155:34;;;4220:3;4205:19;;4198:35;;;3938:3;4249:19;;4242:35;;;3867:3;4308;4293:19;;4286:31;;;4366:13;;3893:18;;;4388:22;;;3838:4;;4441:3;4426:19;;;4468:15;;;;3838:4;4511:178;4525:6;4522:1;4519:13;4511:178;;;4590:13;;4586:22;;4574:35;;4629:12;;;;4664:15;;;;4547:1;4540:9;4511:178;;;4515:3;;;;;4735:9;4730:3;4726:19;4720:3;4709:9;4705:19;4698:48;4763:41;4800:3;4792:6;4763:41;:::i;:::-;4755:49;3454:1356;-1:-1:-1;;;;;;;;;;;3454:1356:1:o;5023:841::-;5154:6;5162;5170;5178;5186;5239:2;5227:9;5218:7;5214:23;5210:32;5207:52;;;5255:1;5252;5245:12;5207:52;5291:9;5278:23;5268:33;;5352:2;5341:9;5337:18;5324:32;-1:-1:-1;;;;;5416:2:1;5408:6;5405:14;5402:34;;;5432:1;5429;5422:12;5402:34;5471:70;5533:7;5524:6;5513:9;5509:22;5471:70;:::i;:::-;5560:8;;-1:-1:-1;5445:96:1;-1:-1:-1;5648:2:1;5633:18;;5620:32;;-1:-1:-1;5664:16:1;;;5661:36;;;5693:1;5690;5683:12;5661:36;;5732:72;5796:7;5785:8;5774:9;5770:24;5732:72;:::i;:::-;5023:841;;;;-1:-1:-1;5023:841:1;;-1:-1:-1;5823:8:1;;5706:98;5023:841;-1:-1:-1;;;5023:841:1:o;6092:316::-;6169:6;6177;6185;6238:2;6226:9;6217:7;6213:23;6209:32;6206:52;;;6254:1;6251;6244:12;6206:52;-1:-1:-1;;6277:23:1;;;6347:2;6332:18;;6319:32;;-1:-1:-1;6398:2:1;6383:18;;;6370:32;;6092:316;-1:-1:-1;6092:316:1:o;6413:261::-;6592:2;6581:9;6574:21;6555:4;6612:56;6664:2;6653:9;6649:18;6641:6;6612:56;:::i;6679:118::-;6765:5;6758:13;6751:21;6744:5;6741:32;6731:60;;6787:1;6784;6777:12;6802:241;6858:6;6911:2;6899:9;6890:7;6886:23;6882:32;6879:52;;;6927:1;6924;6917:12;6879:52;6966:9;6953:23;6985:28;7007:5;6985:28;:::i;7048:437::-;7134:6;7142;7195:2;7183:9;7174:7;7170:23;7166:32;7163:52;;;7211:1;7208;7201:12;7163:52;7251:9;7238:23;-1:-1:-1;;;;;7276:6:1;7273:30;7270:50;;;7316:1;7313;7306:12;7270:50;7355:70;7417:7;7408:6;7397:9;7393:22;7355:70;:::i;:::-;7444:8;;7329:96;;-1:-1:-1;7048:437:1;-1:-1:-1;;;;7048:437:1:o;8268:505::-;8363:6;8371;8379;8432:2;8420:9;8411:7;8407:23;8403:32;8400:52;;;8448:1;8445;8438:12;8400:52;8484:9;8471:23;8461:33;;8545:2;8534:9;8530:18;8517:32;-1:-1:-1;;;;;8564:6:1;8561:30;8558:50;;;8604:1;8601;8594:12;8558:50;8643:70;8705:7;8696:6;8685:9;8681:22;8643:70;:::i;:::-;8268:505;;8732:8;;-1:-1:-1;8617:96:1;;-1:-1:-1;;;;8268:505:1:o;8778:382::-;8843:6;8851;8904:2;8892:9;8883:7;8879:23;8875:32;8872:52;;;8920:1;8917;8910:12;8872:52;8959:9;8946:23;8978:31;9003:5;8978:31;:::i;:::-;9028:5;-1:-1:-1;9085:2:1;9070:18;;9057:32;9098:30;9057:32;9098:30;:::i;:::-;9147:7;9137:17;;;8778:382;;;;;:::o;9443:1123::-;9599:6;9607;9615;9623;9631;9639;9647;9655;9708:3;9696:9;9687:7;9683:23;9679:33;9676:53;;;9725:1;9722;9715:12;9676:53;9764:9;9751:23;9783:31;9808:5;9783:31;:::i;:::-;9833:5;-1:-1:-1;9857:37:1;9890:2;9875:18;;9857:37;:::i;:::-;9847:47;;9913:37;9946:2;9935:9;9931:18;9913:37;:::i;:::-;9903:47;;10001:2;9990:9;9986:18;9973:32;-1:-1:-1;;;;;10065:2:1;10057:6;10054:14;10051:34;;;10081:1;10078;10071:12;10051:34;10120:70;10182:7;10173:6;10162:9;10158:22;10120:70;:::i;:::-;10209:8;;-1:-1:-1;10094:96:1;-1:-1:-1;10297:3:1;10282:19;;10269:33;;-1:-1:-1;10314:16:1;;;10311:36;;;10343:1;10340;10333:12;10311:36;;10382:72;10446:7;10435:8;10424:9;10420:24;10382:72;:::i;:::-;9443:1123;;;;-1:-1:-1;9443:1123:1;;;;;;10356:98;;10555:3;10540:19;10527:33;;9443:1123;-1:-1:-1;;;;9443:1123:1:o;11459:248::-;11527:6;11535;11588:2;11576:9;11567:7;11563:23;11559:32;11556:52;;;11604:1;11601;11594:12;11556:52;-1:-1:-1;;11627:23:1;;;11697:2;11682:18;;;11669:32;;-1:-1:-1;11459:248:1:o;12075:914::-;12203:6;12211;12219;12227;12235;12243;12251;12304:3;12292:9;12283:7;12279:23;12275:33;12272:53;;;12321:1;12318;12311:12;12272:53;12361:9;12348:23;-1:-1:-1;;;;;12386:6:1;12383:30;12380:50;;;12426:1;12423;12416:12;12380:50;12465:70;12527:7;12518:6;12507:9;12503:22;12465:70;:::i;:::-;12554:8;;-1:-1:-1;12439:96:1;-1:-1:-1;;12636:2:1;12621:18;;12608:32;;-1:-1:-1;12687:2:1;12672:18;;12659:32;;-1:-1:-1;12741:2:1;12726:18;;12713:32;12754:31;12713:32;12754:31;:::i;:::-;12804:5;-1:-1:-1;12861:3:1;12846:19;;12833:33;12875:30;12833:33;12875:30;:::i;:::-;12924:7;12914:17;;;12978:3;12967:9;12963:19;12950:33;12940:43;;12075:914;;;;;;;;;;:::o;12994:146::-;-1:-1:-1;;;;;13073:5:1;13069:46;13062:5;13059:57;13049:85;;13130:1;13127;13120:12;13145:815;13277:6;13285;13293;13301;13309;13317;13325;13356:3;13400:2;13388:9;13379:7;13375:23;13371:32;13368:52;;;13416:1;13413;13406:12;13368:52;13452:9;13439:23;13429:33;;13512:2;13501:9;13497:18;13484:32;13525:31;13550:5;13525:31;:::i;:::-;13575:5;-1:-1:-1;13627:2:1;13612:18;;13599:32;;-1:-1:-1;13678:2:1;13663:18;;13650:32;;-1:-1:-1;13729:3:1;13714:19;;13701:33;;-1:-1:-1;13786:3:1;13771:19;;13758:33;13800:30;13758:33;13800:30;:::i;:::-;13849:7;-1:-1:-1;13871:18:1;;;13868:31;-1:-1:-1;13865:51:1;;;13912:1;13909;13902:12;13865:51;;13950:3;13939:9;13935:19;13925:29;;13145:815;;;;;;;;;;:::o;13965:536::-;14250:6;14239:9;14232:25;14293:2;14288;14277:9;14273:18;14266:30;14213:4;14319:56;14371:2;14360:9;14356:18;14348:6;14319:56;:::i;:::-;14423:9;14415:6;14411:22;14406:2;14395:9;14391:18;14384:50;14451:44;14488:6;14480;14451:44;:::i;15128:332::-;15330:2;15312:21;;;15369:1;15349:18;;;15342:29;-1:-1:-1;;;15402:2:1;15387:18;;15380:39;15451:2;15436:18;;15128:332::o;16869:127::-;16930:10;16925:3;16921:20;16918:1;16911:31;16961:4;16958:1;16951:15;16985:4;16982:1;16975:15;17001:127;17062:10;17057:3;17053:20;17050:1;17043:31;17093:4;17090:1;17083:15;17117:4;17114:1;17107:15;17133:135;17172:3;-1:-1:-1;;17193:17:1;;17190:43;;;17213:18;;:::i;:::-;-1:-1:-1;17260:1:1;17249:13;;17133:135::o;17640:355::-;17842:2;17824:21;;;17881:2;17861:18;;;17854:30;17920:33;17915:2;17900:18;;17893:61;17986:2;17971:18;;17640:355::o;18000:338::-;18202:2;18184:21;;;18241:2;18221:18;;;18214:30;-1:-1:-1;;;18275:2:1;18260:18;;18253:44;18329:2;18314:18;;18000:338::o;18690:521::-;18767:4;18773:6;18833:11;18820:25;18927:2;18923:7;18912:8;18896:14;18892:29;18888:43;18868:18;18864:68;18854:96;;18946:1;18943;18936:12;18854:96;18973:33;;19025:20;;;-1:-1:-1;;;;;;19057:30:1;;19054:50;;;19100:1;19097;19090:12;19054:50;19133:4;19121:17;;-1:-1:-1;19164:14:1;19160:27;;;19150:38;;19147:58;;;19201:1;19198;19191:12;19216:127;19277:10;19272:3;19268:20;19265:1;19258:31;19308:4;19305:1;19298:15;19332:4;19329:1;19322:15;19348:251;19420:2;19414:9;19462:2;19450:15;;-1:-1:-1;;;;;19480:34:1;;19516:22;;;19477:62;19474:88;;;19542:18;;:::i;:::-;19578:2;19571:22;19348:251;:::o;19604:275::-;19675:2;19669:9;19740:2;19721:13;;-1:-1:-1;;19717:27:1;19705:40;;-1:-1:-1;;;;;19760:34:1;;19796:22;;;19757:62;19754:88;;;19822:18;;:::i;:::-;19858:2;19851:22;19604:275;;-1:-1:-1;19604:275:1:o;19884:1198::-;19971:6;20002:2;20045;20033:9;20024:7;20020:23;20016:32;20013:52;;;20061:1;20058;20051:12;20013:52;20101:9;20088:23;-1:-1:-1;;;;;20171:2:1;20163:6;20160:14;20157:34;;;20187:1;20184;20177:12;20157:34;20225:6;20214:9;20210:22;20200:32;;20266:2;20261;20252:7;20248:16;20244:25;20241:45;;;20282:1;20279;20272:12;20241:45;20308:22;;:::i;:::-;20368:2;20355:16;20396:2;20386:8;20383:16;20380:36;;;20412:1;20409;20402:12;20380:36;20443:8;20439:2;20435:17;20425:27;;;20490:7;20483:4;20479:2;20475:13;20471:27;20461:55;;20512:1;20509;20502:12;20461:55;20548:2;20535:16;20570:2;20566;20563:10;20560:36;;;20576:18;;:::i;:::-;20622:2;20619:1;20615:10;20605:20;;20645:28;20669:2;20665;20661:11;20645:28;:::i;:::-;20707:15;;;20777:11;;;20773:20;;;20738:12;;;;20805:19;;;20802:39;;;20837:1;20834;20827:12;20802:39;20861:11;;;;20881:142;20897:6;20892:3;20889:15;20881:142;;;20963:17;;20951:30;;20914:12;;;;21001;;;;20881:142;;;21032:20;;-1:-1:-1;21039:5:1;;19884:1198;-1:-1:-1;;;;;;;19884:1198:1:o;21087:339::-;21289:2;21271:21;;;21328:2;21308:18;;;21301:30;-1:-1:-1;;;21362:2:1;21347:18;;21340:45;21417:2;21402:18;;21087:339::o;22109:251::-;22179:6;22232:2;22220:9;22211:7;22207:23;22203:32;22200:52;;;22248:1;22245;22238:12;22200:52;22280:9;22274:16;22299:31;22324:5;22299:31;:::i;23059:125::-;23099:4;23127:1;23124;23121:8;23118:34;;;23132:18;;:::i;:::-;-1:-1:-1;23169:9:1;;23059:125::o;23189:128::-;23229:3;23260:1;23256:6;23253:1;23250:13;23247:39;;;23266:18;;:::i;:::-;-1:-1:-1;23302:9:1;;23189:128::o;23322:348::-;23524:2;23506:21;;;23563:2;23543:18;;;23536:30;23602:26;23597:2;23582:18;;23575:54;23661:2;23646:18;;23322:348::o;25426:375::-;-1:-1:-1;;;;;25684:15:1;;;25666:34;;25736:15;;;;25731:2;25716:18;;25709:43;25783:2;25768:18;;25761:34;;;;25616:2;25601:18;;25426:375::o;26494:265::-;26578:6;26631:2;26619:9;26610:7;26606:23;26602:32;26599:52;;;26647:1;26644;26637:12;26599:52;26679:9;26673:16;26698:31;26723:5;26698:31;:::i;27112:385::-;27191:6;27199;27252:2;27240:9;27231:7;27227:23;27223:32;27220:52;;;27268:1;27265;27258:12;27220:52;27300:9;27294:16;27319:31;27344:5;27319:31;:::i;:::-;27419:2;27404:18;;27398:25;27369:5;;-1:-1:-1;27432:33:1;27398:25;27432:33;:::i;29328:183::-;29397:6;29450:2;29438:9;29429:7;29425:23;29421:32;29418:52;;;29466:1;29463;29456:12;29418:52;-1:-1:-1;29489:16:1;;29328:183;-1:-1:-1;29328:183:1:o;29516:168::-;29556:7;29622:1;29618;29614:6;29610:14;29607:1;29604:21;29599:1;29592:9;29585:17;29581:45;29578:71;;;29629:18;;:::i;:::-;-1:-1:-1;29669:9:1;;29516:168::o;30350:245::-;30417:6;30470:2;30458:9;30449:7;30445:23;30441:32;30438:52;;;30486:1;30483;30476:12;30438:52;30518:9;30512:16;30537:28;30559:5;30537:28;:::i;33657:136::-;33696:3;33724:5;33714:39;;33733:18;;:::i;:::-;-1:-1:-1;;;33769:18:1;;33657:136::o;34787:306::-;34875:6;34883;34891;34944:2;34932:9;34923:7;34919:23;34915:32;34912:52;;;34960:1;34957;34950:12;34912:52;34989:9;34983:16;34973:26;;35039:2;35028:9;35024:18;35018:25;35008:35;;35083:2;35072:9;35068:18;35062:25;35052:35;;34787:306;;;;;:::o;35377:375::-;-1:-1:-1;;;;;35635:15:1;;;35617:34;;35682:2;35667:18;;35660:34;;;;35730:15;;;35725:2;35710:18;;35703:43;35567:2;35552:18;;35377:375::o;36316:127::-;36377:10;36372:3;36368:20;36365:1;36358:31;36408:4;36405:1;36398:15;36432:4;36429:1;36422:15;36448:120;36488:1;36514;36504:35;;36519:18;;:::i;:::-;-1:-1:-1;36553:9:1;;36448:120::o;36573:267::-;36612:4;36641:9;;;36666:10;;-1:-1:-1;;;36685:19:1;;36678:27;;36662:44;36659:70;;;36709:18;;:::i;:::-;-1:-1:-1;;;;;36756:27:1;;36749:35;;36741:44;;36738:70;;;36788:18;;:::i;:::-;-1:-1:-1;;36825:9:1;;36573:267::o;36845:553::-;36884:7;-1:-1:-1;;;;;36954:9:1;;;36982;;;37007:11;;;37026:10;;;37020:17;;37003:35;37000:61;;;37041:18;;:::i;:::-;-1:-1:-1;;;37117:1:1;37110:9;;37135:11;;;37155;;;37148:19;;37131:37;37128:63;;;37171:18;;:::i;:::-;37217:1;37214;37210:9;37200:19;;37264:1;37260:2;37255:11;37252:1;37248:19;37243:2;37239;37235:11;37231:37;37228:63;;;37271:18;;:::i;:::-;37336:1;37332:2;37327:11;37324:1;37320:19;37315:2;37311;37307:11;37303:37;37300:63;;;37343:18;;:::i;:::-;-1:-1:-1;;;37383:9:1;;;;;36845:553;-1:-1:-1;;;36845:553:1:o;37403:265::-;37442:3;37470:9;;;37495:10;;-1:-1:-1;;;;;37514:27:1;;;37507:35;;37491:52;37488:78;;;37546:18;;:::i;:::-;-1:-1:-1;;;37593:19:1;;;37586:27;;37578:36;;37575:62;;;37617:18;;:::i;:::-;-1:-1:-1;;37653:9:1;;37403:265::o;37673:193::-;37712:1;37738;37728:35;;37743:18;;:::i;:::-;-1:-1:-1;;;37779:18:1;;-1:-1:-1;;37799:13:1;;37775:38;37772:64;;;37816:18;;:::i;:::-;-1:-1:-1;37850:10:1;;37673:193::o;37871:127::-;37932:10;37927:3;37923:20;37920:1;37913:31;37963:4;37960:1;37953:15;37987:4;37984:1;37977:15;39179:258;39251:1;39261:113;39275:6;39272:1;39269:13;39261:113;;;39351:11;;;39345:18;39332:11;;;39325:39;39297:2;39290:10;39261:113;;;39392:6;39389:1;39386:13;39383:48;;;-1:-1:-1;;39427:1:1;39409:16;;39402:27;39179:258::o;39442:274::-;39571:3;39609:6;39603:13;39625:53;39671:6;39666:3;39659:4;39651:6;39647:17;39625:53;:::i;:::-;39694:16;;;;;39442:274;-1:-1:-1;;39442:274:1:o;39721:383::-;39870:2;39859:9;39852:21;39833:4;39902:6;39896:13;39945:6;39940:2;39929:9;39925:18;39918:34;39961:66;40020:6;40015:2;40004:9;40000:18;39995:2;39987:6;39983:15;39961:66;:::i;:::-;40088:2;40067:15;-1:-1:-1;;40063:29:1;40048:45;;;;40095:2;40044:54;;39721:383;-1:-1:-1;;39721:383:1:o
Swarm Source
ipfs://de26c0958ae74edf1ddc20c03f2316cd4bc437fc1d1fcce795748fd6ecd805eb
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$4,835.73
Net Worth in ETH
Token Allocations
WSTETH
54.77%
KNC
28.95%
SWETH
9.58%
Others
6.70%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| BASE | 34.53% | $3,621.18 | 0.4611 | $1,669.67 | |
| BASE | 2.07% | $0.212076 | 471.676 | $100.03 | |
| BASE | 0.02% | $0.000001 | 740,000 | $0.8732 | |
| POL | 18.62% | $3,622.15 | 0.2485 | $900.18 | |
| POL | 1.34% | $0.211922 | 306.1352 | $64.88 | |
| BSC | 18.64% | $0.212076 | 4,249.8978 | $901.3 | |
| ARB | 9.58% | $3,285.28 | 0.141 | $463.32 | |
| ARB | 5.41% | $0.212092 | 1,233.8507 | $261.69 | |
| ARB | 1.04% | $0.176275 | 284.4387 | $50.14 | |
| ARB | 0.42% | $3,621.92 | 0.00558657 | $20.23 | |
| ARB | 0.22% | $0.999638 | 10.4808 | $10.48 | |
| ARB | 0.17% | $0.068371 | 117.9732 | $8.07 | |
| OP | 4.66% | $0.300623 | 749.9093 | $225.44 | |
| OP | 0.59% | $3,621.92 | 0.00784124 | $28.4 | |
| OP | 0.04% | $0.212092 | 8.4704 | $1.8 | |
| ETH | 1.41% | $0.212095 | 320.9995 | $68.08 | |
| ETH | 0.62% | $3,621.89 | 0.00823924 | $29.84 | |
| ETH | 0.60% | $3,187.92 | 0.00913038 | $29.11 | |
| LINEA | 0.05% | $0.212029 | 10.3684 | $2.2 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.