More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
GOBSstakingByOOGIES
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity)
/** *Submitted for verification at apescan.io on 2025-01-10 */ // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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); } // File: @openzeppelin/contracts/token/ERC721/IERC721.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; /** * @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`. * * 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; /** * @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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 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 address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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); } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); } // File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: contracts/GOBSStaking.sol pragma solidity ^0.8.17; /** * @title NFTStakingWithHoldRequirement * @notice Stake ERC721 tokens to earn ERC20 rewards (AFTR) from this contract's balance, * with optional locks of 30/60/90 days at higher multipliers (1.5x, 2x, 2.5x). * Additionally, users must hold at least one NFT from the `nftToHold` contract * to call any user-facing function (stake, claim, etc.). */ contract GOBSstakingByOOGIES is ReentrancyGuard, Ownable { // ---------------------------------------- // State Variables // ---------------------------------------- /// @notice The ERC721 contract whose NFTs we are staking. IERC721 public nftContract = IERC721(0xBEbaa24108d6a03C7331464270b95278bBBE6Ff7); /// @notice The ERC20 token used as the reward (must be deposited into this contract). IERC20 public rewardToken = IERC20(0x784E4ad4Aa27c6749bBc8A675128146b916Ed0f1); /** * @notice An additional ERC721 contract that users must hold * at least 1 NFT from in order to use the staking functions. */ IERC721 public nftToHold = IERC721(0x214cAE51c3BAE88515aAEfd8e1867E64502B0342); /// @notice Number of seconds in 1 day (used for integer division). uint256 public dayInSeconds = 1 days; /** * @notice Base daily reward rate (in wei). * e.g. 1 ether = 1 token/day if token has 18 decimals. */ uint256 public rewardRateNormal = 5 ether; /** * @notice Lock durations and multipliers (all editable by admin). * Example multipliers: 150 = 1.5x, 200 = 2x, 250 = 2.5x. */ uint256 public lockDuration30 = 30 days; uint256 public lockMultiplier30 = 150; // 1.5x uint256 public lockDuration60 = 60 days; uint256 public lockMultiplier60 = 200; // 2.0x uint256 public lockDuration90 = 90 days; uint256 public lockMultiplier90 = 250; // 2.5x /** * @notice NFT-specific multipliers: e.g., 150 = 1.5x, 200 = 2x. * If 0, treat it as 100 (1x). */ mapping(uint256 => uint256) public nftMultiplier; /// @notice Lock option choices enum LockOption { None, // no lock (normal staking) Lock30, // 30-day lock at lockMultiplier30 Lock60, // 60-day lock at lockMultiplier60 Lock90 // 90-day lock at lockMultiplier90 } /// @notice Info about each staked NFT. struct StakedNFT { address owner; // who staked it uint256 tokenId; // which token uint256 stakedAt; // when it was staked uint256 lastClaimedAt; // last time rewards were claimed LockOption lockOption; // which lock type uint256 lockStartedAt; // when current lock was set } /// @notice tokenId => staking info mapping(uint256 => StakedNFT) public stakedNFTs; /// @notice Keep track of all currently staked tokenIds (for enumerations). uint256[] private allStakedTokenIds; /// @notice tokenId => index in allStakedTokenIds mapping(uint256 => uint256) private allStakedTokenIndex; /// @notice For easy lookup of which tokenIds a user has staked. mapping(address => uint256[]) private userStakedTokens; /// @notice tokenId => index in userStakedTokens[user] mapping(uint256 => uint256) private userStakedTokensIndex; // ---------------------------------------- // Events // ---------------------------------------- event Staked(address indexed user, uint256 tokenId, LockOption lockOption); event Unstaked(address indexed user, uint256 tokenId); event RewardClaimed(address indexed user, uint256 tokenId, uint256 amount); event LockOptionChanged(address indexed user, uint256 tokenId, LockOption newLockOption); event TokensDeposited(address indexed from, uint256 amount); // ---------------------------------------- // Constructor // ---------------------------------------- constructor(address _initialOwner) Ownable(_initialOwner) {} // ---------------------------------------- // Modifiers // ---------------------------------------- /** * @dev Requires the caller to hold at least one NFT in the `nftToHold` collection. */ modifier onlyNftHolder() { require( nftToHold.balanceOf(msg.sender) > 0, "Must hold at least 1 NFT from the 'nftToHold' contract." ); _; } // ---------------------------------------- // Owner-Only Functions // ---------------------------------------- function setNftContract(IERC721 _nftContract) external onlyOwner { nftContract = _nftContract; } function setRewardToken(IERC20 _rewardToken) external onlyOwner { rewardToken = _rewardToken; } function setNftToHold(IERC721 _nftToHold) external onlyOwner { nftToHold = _nftToHold; } function setDayInSeconds(uint256 _seconds) external onlyOwner { dayInSeconds = _seconds; } function setRewardRateNormal(uint256 _normal) external onlyOwner { rewardRateNormal = _normal; } /** * @notice Update lock durations and/or multipliers for 30, 60, and 90 days. * Example multipliers: 150 => 1.5x, 200 => 2x, 250 => 2.5x. */ function setLockParams( uint256 _lockDuration30, uint256 _lockMultiplier30, uint256 _lockDuration60, uint256 _lockMultiplier60, uint256 _lockDuration90, uint256 _lockMultiplier90 ) external onlyOwner { lockDuration30 = _lockDuration30; lockMultiplier30 = _lockMultiplier30; lockDuration60 = _lockDuration60; lockMultiplier60 = _lockMultiplier60; lockDuration90 = _lockDuration90; lockMultiplier90 = _lockMultiplier90; } /** * @notice Set multipliers for multiple NFTs at once. * @param _tokenIds array of token IDs * @param _multipliers array of multipliers (e.g. 150 = 1.5x), must match length of _tokenIds */ function setNFTMultiplierBatch(uint256[] calldata _tokenIds, uint256[] calldata _multipliers) external onlyOwner { require(_tokenIds.length == _multipliers.length, "Array length mismatch"); for (uint256 i = 0; i < _tokenIds.length; i++) { nftMultiplier[_tokenIds[i]] = _multipliers[i]; } } // ---------------------------------- // Rescue functions (owner only) // ---------------------------------- function rescueNative(uint256 _amount) external onlyOwner { require(address(this).balance >= _amount, "Not enough native balance"); payable(msg.sender).transfer(_amount); } function rescueERC20(address _token, uint256 _amount) external onlyOwner { IERC20(_token).transfer(msg.sender, _amount); } // ---------------------------------------- // Deposit Rewards (ERC20) // ---------------------------------------- function depositTokens(uint256 amount) external nonReentrant onlyOwner { require(amount > 0, "Cannot deposit 0"); bool success = rewardToken.transferFrom(msg.sender, address(this), amount); require(success, "transferFrom failed"); emit TokensDeposited(msg.sender, amount); } function getContractBalance() external view returns (uint256) { return rewardToken.balanceOf(address(this)); } // ---------------------------------------- // Batch Operations (User-Facing) // ---------------------------------------- /** * @notice Stake multiple NFTs at once with a chosen lock option (None, Lock30, Lock60, Lock90). * @param _tokenIds array of token IDs * @param _lockOptions array of lock options */ function stakeBatch( uint256[] calldata _tokenIds, LockOption[] calldata _lockOptions ) external nonReentrant onlyNftHolder { require(_tokenIds.length == _lockOptions.length, "Array length mismatch"); for (uint256 i = 0; i < _tokenIds.length; i++) { _stakeInternal(_tokenIds[i], _lockOptions[i]); } } /** * @notice Unstake multiple NFTs at once. * Reverts if the lock period has not ended yet. */ function unstakeBatch(uint256[] calldata _tokenIds) external nonReentrant onlyNftHolder { for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; require(stakedNFTs[tokenId].owner == msg.sender, "Not staker"); _unstakeInternal(tokenId); } } /** * @notice Claim rewards for multiple NFTs at once. */ function claimRewardsBatch(uint256[] calldata _tokenIds) external nonReentrant onlyNftHolder { for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; require(stakedNFTs[tokenId].owner == msg.sender, "Not staker"); _claimRewards(tokenId); } } /** * @notice Lock multiple NFTs that are currently staked but unlocked (None). * Or if they were locked and the lock is finished, this also acts as “re-lock.” * @dev If the lock is still active and not finished, this will revert. */ function lockStakedNFTBatch( uint256[] calldata _tokenIds, LockOption[] calldata _lockOptions ) external nonReentrant onlyNftHolder { require(_tokenIds.length == _lockOptions.length, "Array length mismatch"); for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; require(stakedNFTs[tokenId].owner == msg.sender, "Not staker"); _lockStakedNFTInternal(tokenId, _lockOptions[i]); } } /** * @notice Re-lock multiple NFTs (choose any lock option) once your previous lock ended. * @dev If lock not ended, will revert; if not locked at all, will revert. */ function reLockBatch( uint256[] calldata _tokenIds, LockOption[] calldata _newLockOptions ) external nonReentrant onlyNftHolder { require(_tokenIds.length == _newLockOptions.length, "Array length mismatch"); for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; require(stakedNFTs[tokenId].owner == msg.sender, "Not staker"); _reLockInternal(tokenId, _newLockOptions[i]); } } // ---------------------------------------- // Batch Views (Claimable Rewards, etc.) // ---------------------------------------- /** * @notice Returns an array of claimable rewards for the given NFT IDs, in the same order. */ function claimableRewardsBatch(uint256[] calldata _tokenIds) external view returns (uint256[] memory) { uint256[] memory amounts = new uint256[](_tokenIds.length); for (uint256 i = 0; i < _tokenIds.length; i++) { amounts[i] = _claimableRewardsView(_tokenIds[i]); } return amounts; } /** * @notice Returns how many tokens (AFTR) this user generates per full day * across all staked NFTs, factoring in lock options and NFT multipliers. */ function generatingPerDay(address _user) external view returns (uint256) { uint256 totalDailyRate = 0; uint256[] memory tokenIds = userStakedTokens[_user]; for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; StakedNFT storage info = stakedNFTs[tokenId]; // sanity check if (info.owner != _user) continue; // figure out if still in lock period (uint256 chosenLockMult, bool inLock) = _getLockMultiplierAndStatus(info); uint256 baseDaily; if (inLock) { // still in lock => base rate * chosenLockMult baseDaily = (rewardRateNormal * chosenLockMult) / 100; } else { // not locked or lock ended => normal rate baseDaily = rewardRateNormal; } // apply NFT-specific multiplier uint256 nftMult = nftMultiplier[tokenId]; if (nftMult == 0) nftMult = 100; uint256 finalRate = (baseDaily * nftMult) / 100; totalDailyRate += finalRate; } return totalDailyRate; } // ---------------------------------------- // Internal (Single-Token) Logic // ---------------------------------------- // Called by the batch functions above. function _stakeInternal(uint256 _tokenId, LockOption _lockOption) internal { // Transfer NFT from user to this contract nftContract.transferFrom(msg.sender, address(this), _tokenId); // Record staking info StakedNFT storage info = stakedNFTs[_tokenId]; info.owner = msg.sender; info.tokenId = _tokenId; info.stakedAt = block.timestamp; info.lastClaimedAt = block.timestamp; info.lockOption = _lockOption; info.lockStartedAt = (_lockOption == LockOption.None) ? 0 : block.timestamp; // Add to global and user tracking _addToAllStakedTokenIds(_tokenId); _addToUserStakedTokens(msg.sender, _tokenId); emit Staked(msg.sender, _tokenId, _lockOption); } function _unstakeInternal(uint256 _tokenId) internal { StakedNFT storage info = stakedNFTs[_tokenId]; // if locked, ensure lock period ended if (info.lockOption != LockOption.None) { uint256 lockEnd = info.lockStartedAt + _getLockDuration(info.lockOption); require(block.timestamp >= lockEnd, "Lock period not over. Cannot unstake yet."); } // claim all rewards up to now _claimRewards(_tokenId); // transfer NFT back nftContract.transferFrom(address(this), info.owner, _tokenId); // cleanup _removeFromAllStakedTokenIds(_tokenId); _removeFromUserStakedTokens(info.owner, _tokenId); delete stakedNFTs[_tokenId]; emit Unstaked(info.owner, _tokenId); } /** * @dev Lock an NFT that is currently staked but: * - either has never been locked (lockOption == None), or * - was locked and its lock period is finished (so effectively “re-lock”). * If it's still locked and not finished, this reverts. */ function _lockStakedNFTInternal(uint256 _tokenId, LockOption _newLockOption) internal { StakedNFT storage info = stakedNFTs[_tokenId]; // Must be staked require(info.owner != address(0), "Not staked"); // If it's currently locked, check if the lock ended if (info.lockOption != LockOption.None) { uint256 lockEnd = info.lockStartedAt + _getLockDuration(info.lockOption); require(block.timestamp >= lockEnd, "Current lock not finished"); } // First claim everything earned so far (including any unlocked days) _claimRewards(_tokenId); // Set new lock info.lockOption = _newLockOption; info.lockStartedAt = block.timestamp; info.lastClaimedAt = block.timestamp; // so we start fresh emit LockOptionChanged(info.owner, _tokenId, _newLockOption); } /** * @dev Re-lock an NFT that was already locked, picking a new lock option * after the old lock has ended. Reverts if lock not over or was never locked. */ function _reLockInternal(uint256 _tokenId, LockOption _newLockOption) internal { StakedNFT storage info = stakedNFTs[_tokenId]; // Must already be locked with some option require(info.lockOption != LockOption.None, "NFT not currently locked"); // Ensure old lock ended uint256 lockEnd = info.lockStartedAt + _getLockDuration(info.lockOption); require(block.timestamp >= lockEnd, "Current lock not finished"); // Claim all rewards up to now _claimRewards(_tokenId); // Re-lock with the new option info.lockOption = _newLockOption; info.lockStartedAt = block.timestamp; info.lastClaimedAt = block.timestamp; emit LockOptionChanged(info.owner, _tokenId, _newLockOption); } // ---------------------------------------- // Reward Logic // ---------------------------------------- /** * @dev Internal function to calculate and transfer rewards from the contract’s balance. */ function _claimRewards(uint256 _tokenId) internal returns (uint256) { StakedNFT storage info = stakedNFTs[_tokenId]; uint256 currentTime = block.timestamp; uint256 lastClaimed = info.lastClaimedAt; // no time passed => no rewards if (currentTime <= lastClaimed) { return 0; } uint256 timeDiff = currentTime - lastClaimed; uint256 totalReward = 0; // figure out lock end uint256 lockEnd = (info.lockOption == LockOption.None) ? 0 : (info.lockStartedAt + _getLockDuration(info.lockOption)); // break the time into possible segments: locked vs. unlocked if (info.lockOption != LockOption.None) { // some lock option if (lastClaimed < lockEnd) { // portion in lock uint256 lockedSegmentEnd = (currentTime < lockEnd) ? currentTime : lockEnd; uint256 lockedTime = (lockedSegmentEnd > lastClaimed) ? lockedSegmentEnd - lastClaimed : 0; uint256 lockedDays = lockedTime / dayInSeconds; uint256 lockedMult = _getLockMultiplier(info.lockOption); // locked portion daily rate = rewardRateNormal * lockedMult/100 // we apply the NFT multiplier below uint256 lockedDailyRate = (rewardRateNormal * lockedMult) / 100; // NFT-specific multiplier uint256 nftMult = nftMultiplier[_tokenId]; if (nftMult == 0) nftMult = 100; // final locked portion = lockedDays * lockedDailyRate * (nftMult/100) uint256 lockedReward = lockedDays * ((lockedDailyRate * nftMult) / 100); totalReward += lockedReward; // portion after lock (if currentTime > lockEnd) if (currentTime > lockEnd) { uint256 postLockTime = currentTime - lockEnd; uint256 postLockDays = postLockTime / dayInSeconds; // post-lock daily rate => normal rate * NFT multiplier uint256 postLockDailyRate = (rewardRateNormal * nftMult) / 100; totalReward += postLockDays * postLockDailyRate; } } else { // entire interval is after lock ended uint256 daysCount = timeDiff / dayInSeconds; uint256 nftMult = nftMultiplier[_tokenId]; if (nftMult == 0) nftMult = 100; uint256 postLockDaily = (rewardRateNormal * nftMult) / 100; totalReward += daysCount * postLockDaily; } } else { // no lock => purely normal uint256 daysCount = timeDiff / dayInSeconds; uint256 nftMult = nftMultiplier[_tokenId]; if (nftMult == 0) nftMult = 100; uint256 daily = (rewardRateNormal * nftMult) / 100; totalReward += daysCount * daily; } // update lastClaimed info.lastClaimedAt = currentTime; // transfer from contract to staker if (totalReward > 0) { uint256 contractBal = rewardToken.balanceOf(address(this)); require(contractBal >= totalReward, "Not enough reward tokens in contract"); rewardToken.transfer(info.owner, totalReward); emit RewardClaimed(info.owner, _tokenId, totalReward); } return totalReward; } /** * @dev View-only version of claiming logic (no state changes). */ function _claimableRewardsView(uint256 _tokenId) internal view returns (uint256) { StakedNFT storage info = stakedNFTs[_tokenId]; if (info.owner == address(0)) return 0; // not staked uint256 currentTime = block.timestamp; uint256 lastClaimed = info.lastClaimedAt; if (currentTime <= lastClaimed) return 0; uint256 timeDiff = currentTime - lastClaimed; uint256 totalReward = 0; uint256 lockEnd = (info.lockOption == LockOption.None) ? 0 : (info.lockStartedAt + _getLockDuration(info.lockOption)); if (info.lockOption != LockOption.None) { if (lastClaimed < lockEnd) { uint256 lockedSegmentEnd = (currentTime < lockEnd) ? currentTime : lockEnd; uint256 lockedTime = (lockedSegmentEnd > lastClaimed) ? lockedSegmentEnd - lastClaimed : 0; uint256 lockedDays = lockedTime / dayInSeconds; uint256 lockedMult = _getLockMultiplier(info.lockOption); uint256 lockedDailyRate = (rewardRateNormal * lockedMult) / 100; uint256 nftMult = nftMultiplier[_tokenId]; if (nftMult == 0) nftMult = 100; uint256 lockedReward = lockedDays * ((lockedDailyRate * nftMult) / 100); totalReward += lockedReward; if (currentTime > lockEnd) { uint256 postLockTime = currentTime - lockEnd; uint256 postLockDays = postLockTime / dayInSeconds; uint256 postLockDaily = (rewardRateNormal * nftMult) / 100; totalReward += postLockDays * postLockDaily; } } else { // entire interval after lock uint256 daysCount = timeDiff / dayInSeconds; uint256 nftMult = nftMultiplier[_tokenId]; if (nftMult == 0) nftMult = 100; uint256 postLockDaily = (rewardRateNormal * nftMult) / 100; totalReward += daysCount * postLockDaily; } } else { // no lock uint256 daysCount = timeDiff / dayInSeconds; uint256 nftMult = nftMultiplier[_tokenId]; if (nftMult == 0) nftMult = 100; uint256 daily = (rewardRateNormal * nftMult) / 100; totalReward += daysCount * daily; } return totalReward; } // ---------------------------------------- // View Functions (Enumeration, etc.) // ---------------------------------------- function totalStaked() external view returns (uint256) { return allStakedTokenIds.length; } function getAllStakedNFTs() external view returns (StakedNFT[] memory) { uint256 length = allStakedTokenIds.length; StakedNFT[] memory result = new StakedNFT[](length); for (uint256 i = 0; i < length; i++) { uint256 tokenId = allStakedTokenIds[i]; result[i] = stakedNFTs[tokenId]; } return result; } function getStakedNFTsOf(address _wallet) external view returns (StakedNFT[] memory) { uint256[] storage tokenIds = userStakedTokens[_wallet]; uint256 length = tokenIds.length; StakedNFT[] memory result = new StakedNFT[](length); for (uint256 i = 0; i < length; i++) { uint256 tokenId = tokenIds[i]; result[i] = stakedNFTs[tokenId]; } return result; } // ---------------------------------------- // Internal Helpers // ---------------------------------------- function _addToAllStakedTokenIds(uint256 _tokenId) internal { allStakedTokenIndex[_tokenId] = allStakedTokenIds.length; allStakedTokenIds.push(_tokenId); } function _removeFromAllStakedTokenIds(uint256 _tokenId) internal { uint256 idx = allStakedTokenIndex[_tokenId]; uint256 lastIndex = allStakedTokenIds.length - 1; if (idx != lastIndex) { uint256 lastTokenId = allStakedTokenIds[lastIndex]; allStakedTokenIds[idx] = lastTokenId; allStakedTokenIndex[lastTokenId] = idx; } allStakedTokenIds.pop(); delete allStakedTokenIndex[_tokenId]; } function _addToUserStakedTokens(address _user, uint256 _tokenId) internal { userStakedTokensIndex[_tokenId] = userStakedTokens[_user].length; userStakedTokens[_user].push(_tokenId); } function _removeFromUserStakedTokens(address _user, uint256 _tokenId) internal { uint256 idx = userStakedTokensIndex[_tokenId]; uint256 lastIndex = userStakedTokens[_user].length - 1; if (idx != lastIndex) { uint256 lastTokenId = userStakedTokens[_user][lastIndex]; userStakedTokens[_user][idx] = lastTokenId; userStakedTokensIndex[lastTokenId] = idx; } userStakedTokens[_user].pop(); delete userStakedTokensIndex[_tokenId]; } /** * @dev Returns the configured lock duration (in seconds) for the chosen option. */ function _getLockDuration(LockOption option) internal view returns (uint256) { if (option == LockOption.Lock30) { return lockDuration30; } else if (option == LockOption.Lock60) { return lockDuration60; } else if (option == LockOption.Lock90) { return lockDuration90; } return 0; } /** * @dev Returns the lock multiplier (e.g. 150 => 1.5×) for the chosen lock option. */ function _getLockMultiplier(LockOption option) internal view returns (uint256) { if (option == LockOption.Lock30) { return lockMultiplier30; } else if (option == LockOption.Lock60) { return lockMultiplier60; } else if (option == LockOption.Lock90) { return lockMultiplier90; } return 100; // None => normal } /** * @dev Helper to see if a given staked NFT is still within its lock period, * plus the chosen lock multiplier. */ function _getLockMultiplierAndStatus( StakedNFT storage info ) internal view returns (uint256 chosenMultiplier, bool stillInLock) { if (info.lockOption == LockOption.None) { return (100, false); } uint256 duration = _getLockDuration(info.lockOption); uint256 endTime = info.lockStartedAt + duration; bool inLockPeriod = (block.timestamp < endTime); uint256 lockMult = _getLockMultiplier(info.lockOption); return (lockMult, inLockPeriod); } // ---------------------------------------- // Emergency / Forced Unstake (Owner Only) // ---------------------------------------- /** * @notice Forcibly return an array of staked NFTs to their respective owners. * No rewards are claimed or paid. Resets all internal tracking. * @param _tokenIds Array of token IDs to be returned. */ function emergencyReturnBatch(uint256[] calldata _tokenIds) external onlyOwner nonReentrant { for (uint256 i = 0; i < _tokenIds.length; i++) { uint256 tokenId = _tokenIds[i]; StakedNFT storage info = stakedNFTs[tokenId]; // If it's actually staked (owner != address(0)) if (info.owner != address(0)) { // Transfer NFT back to staker nftContract.transferFrom(address(this), info.owner, tokenId); // Remove from global array _removeFromAllStakedTokenIds(tokenId); // Remove from user array _removeFromUserStakedTokens(info.owner, tokenId); // Clear staking info (no rewards) delete stakedNFTs[tokenId]; } } } /** * @notice Forcibly return ALL currently staked NFTs to their respective owners. * No rewards are claimed or paid. Resets all internal tracking for each NFT. */ function emergencyReturnAllStaked() external onlyOwner nonReentrant { // Keep removing from the end of allStakedTokenIds until empty while (allStakedTokenIds.length > 0) { uint256 lastIndex = allStakedTokenIds.length - 1; uint256 tokenId = allStakedTokenIds[lastIndex]; StakedNFT storage info = stakedNFTs[tokenId]; if (info.owner != address(0)) { // Transfer NFT back to staker nftContract.transferFrom(address(this), info.owner, tokenId); // Remove from user array _removeFromUserStakedTokens(info.owner, tokenId); // Clear staking info delete stakedNFTs[tokenId]; } // Finally remove it from the global array allStakedTokenIds.pop(); } } /** * @notice Allow contract owner to withdraw any NFT directly to their own wallet, * ignoring normal staking rules. Use with care! * @param _tokenId Token ID to withdraw to the owner's wallet. */ function emergencyWithdrawNFT(uint256 _tokenId) external onlyOwner nonReentrant { nftContract.transferFrom(address(this), owner(), _tokenId); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"enum GOBSstakingByOOGIES.LockOption","name":"newLockOption","type":"uint8"}],"name":"LockOptionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"enum GOBSstakingByOOGIES.LockOption","name":"lockOption","type":"uint8"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"claimRewardsBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"claimableRewardsBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dayInSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyReturnAllStaked","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"emergencyReturnBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"emergencyWithdrawNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"generatingPerDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllStakedNFTs","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"stakedAt","type":"uint256"},{"internalType":"uint256","name":"lastClaimedAt","type":"uint256"},{"internalType":"enum GOBSstakingByOOGIES.LockOption","name":"lockOption","type":"uint8"},{"internalType":"uint256","name":"lockStartedAt","type":"uint256"}],"internalType":"struct GOBSstakingByOOGIES.StakedNFT[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"getStakedNFTsOf","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"stakedAt","type":"uint256"},{"internalType":"uint256","name":"lastClaimedAt","type":"uint256"},{"internalType":"enum GOBSstakingByOOGIES.LockOption","name":"lockOption","type":"uint8"},{"internalType":"uint256","name":"lockStartedAt","type":"uint256"}],"internalType":"struct GOBSstakingByOOGIES.StakedNFT[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDuration30","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDuration60","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDuration90","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockMultiplier30","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockMultiplier60","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockMultiplier90","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"enum GOBSstakingByOOGIES.LockOption[]","name":"_lockOptions","type":"uint8[]"}],"name":"lockStakedNFTBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nftContract","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftToHold","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"enum GOBSstakingByOOGIES.LockOption[]","name":"_newLockOptions","type":"uint8[]"}],"name":"reLockBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"rescueNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardRateNormal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seconds","type":"uint256"}],"name":"setDayInSeconds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockDuration30","type":"uint256"},{"internalType":"uint256","name":"_lockMultiplier30","type":"uint256"},{"internalType":"uint256","name":"_lockDuration60","type":"uint256"},{"internalType":"uint256","name":"_lockMultiplier60","type":"uint256"},{"internalType":"uint256","name":"_lockDuration90","type":"uint256"},{"internalType":"uint256","name":"_lockMultiplier90","type":"uint256"}],"name":"setLockParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_multipliers","type":"uint256[]"}],"name":"setNFTMultiplierBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_nftContract","type":"address"}],"name":"setNftContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_nftToHold","type":"address"}],"name":"setNftToHold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_normal","type":"uint256"}],"name":"setRewardRateNormal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_rewardToken","type":"address"}],"name":"setRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"enum GOBSstakingByOOGIES.LockOption[]","name":"_lockOptions","type":"uint8[]"}],"name":"stakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakedNFTs","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"stakedAt","type":"uint256"},{"internalType":"uint256","name":"lastClaimedAt","type":"uint256"},{"internalType":"enum GOBSstakingByOOGIES.LockOption","name":"lockOption","type":"uint8"},{"internalType":"uint256","name":"lockStartedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"unstakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600280546001600160a01b031990811673bebaa24108d6a03c7331464270b95278bbbe6ff71790915560038054821673784e4ad4aa27c6749bbc8a675128146b916ed0f11790556004805490911673214cae51c3bae88515aaefd8e1867e64502b034217905562015180600555674563918244f4000060065562278d006007556096600855624f1a0060095560c8600a556276a700600b5560fa600c55348015620000ad575f80fd5b5060405162002efb38038062002efb833981016040819052620000d09162000167565b60015f55806001600160a01b0381166200010357604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6200010e8162000116565b505062000196565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f6020828403121562000178575f80fd5b81516001600160a01b03811681146200018f575f80fd5b9392505050565b612d5780620001a45f395ff3fe608060405234801561000f575f80fd5b506004361061023f575f3560e01c80638cd4426d11610135578063dbb7a621116100b4578063f7c618c111610079578063f7c618c114610509578063f7e455d71461051c578063fae40fa01461053c578063fb64455b14610545578063ffd2d8291461054d575f80fd5b8063dbb7a621146104b5578063dd49756e146104bd578063e64a21f3146104d0578063efdd78e1146104e3578063f2fde38b146104f6575f80fd5b8063b2040612116100fa578063b20406121461040f578063b865749d14610418578063bf4bac391461047c578063d3abfe121461048f578063d56d229d146104a2575f80fd5b80638cd4426d146103d05780638da5cb5b146103e357806399ba918d146103f45780639ce98f0e146103fd578063ae63586c14610406575f80fd5b80636f9fb98a116101c15780637f4ca1d7116101865780637f4ca1d714610363578063817b1cd214610382578063888ce4af1461038a57806388c0771b146103aa5780638aee8127146103bd575f80fd5b80636f9fb98a1461032457806370becf5d1461032c578063715018a614610335578063760edace1461033d5780637dc3db8f14610350575f80fd5b80633af7a795116102075780633af7a795146102c5578063454aa669146102d857806352f5ad77146102eb578063646e6f8b146102fe57806366e4664a14610311575f80fd5b80630dfa1e96146102435780631a658ea01461025f578063224eb1291461027457806327711b2714610287578063398612b8146102b2575b5f80fd5b61024c60095481565b6040519081526020015b60405180910390f35b61027261026d366004612865565b610556565b005b610272610282366004612887565b610580565b60045461029a906001600160a01b031681565b6040516001600160a01b039091168152602001610256565b6102726102c03660046128e6565b61058d565b6102726102d33660046128e6565b6106f3565b6102726102e6366004612887565b61077a565b6102726102f9366004612865565b610800565b61027261030c36600461294d565b61082a565b61027261031f3660046128e6565b61093c565b61024c610a49565b61024c600b5481565b610272610ab8565b61024c61034b366004612865565b610acb565b61027261035e366004612887565b610c1c565b61024c610371366004612887565b600d6020525f908152604090205481565b600f5461024c565b61039d610398366004612865565b610c29565b60405161025691906129c0565b6102726103b8366004612887565b610d7a565b6102726103cb366004612865565b610e06565b6102726103de366004612a4a565b610e30565b6001546001600160a01b031661029a565b61024c60065481565b61024c60075481565b61024c60055481565b61024c600c5481565b61046a610426366004612887565b600e6020525f90815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909160ff9091169086565b60405161025696959493929190612a74565b61027261048a3660046128e6565b610eab565b61027261049d36600461294d565b610ff8565b60025461029a906001600160a01b031681565b610272611121565b6102726104cb366004612887565b61127f565b6102726104de36600461294d565b6113c9565b6102726104f1366004612ab7565b6114d0565b610272610504366004612865565b6114f5565b60035461029a906001600160a01b031681565b61052f61052a36600461294d565b61152f565b6040516102569190612af6565b61024c600a5481565b61039d6115d1565b61024c60085481565b61055e61170c565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b61058861170c565b600555565b610595611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156105e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106049190612b39565b1161062a5760405162461bcd60e51b815260040161062190612b50565b60405180910390fd5b8281146106495760405162461bcd60e51b815260040161062190612bad565b5f5b838110156106e3575f85858381811061066657610666612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b031633146106aa5760405162461bcd60e51b815260040161062190612bf0565b6106da818585858181106106c0576106c0612bdc565b90506020020160208101906106d59190612c14565b611790565b5060010161064b565b506106ed60015f55565b50505050565b6106fb61170c565b82811461071a5760405162461bcd60e51b815260040161062190612bad565b5f5b838110156107735782828281811061073657610736612bdc565b90506020020135600d5f87878581811061075257610752612bdc565b602090810292909201358352508101919091526040015f205560010161071c565b5050505050565b61078261170c565b804710156107d25760405162461bcd60e51b815260206004820152601960248201527f4e6f7420656e6f756768206e61746976652062616c616e6365000000000000006044820152606401610621565b604051339082156108fc029083905f818181858888f193505050501580156107fc573d5f803e3d5ffd5b5050565b61080861170c565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610832611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561087d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a19190612b39565b116108be5760405162461bcd60e51b815260040161062190612b50565b5f5b81811015610932575f8383838181106108db576108db612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b0316331461091f5760405162461bcd60e51b815260040161062190612bf0565b610928816118fc565b50506001016108c0565b506107fc60015f55565b610944611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561098f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b39190612b39565b116109d05760405162461bcd60e51b815260040161062190612b50565b8281146109ef5760405162461bcd60e51b815260040161062190612bad565b5f5b838110156106e357610a41858583818110610a0e57610a0e612bdc565b90506020020135848484818110610a2757610a27612bdc565b9050602002016020810190610a3c9190612c14565b611d28565b6001016109f1565b6003546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610a8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab39190612b39565b905090565b610ac061170c565b610ac95f611eb5565b565b6001600160a01b0381165f908152601160209081526040808320805482518185028101850190935280835284938493929190830182828015610b2a57602002820191905f5260205f20905b815481526020019060010190808311610b16575b505050505090505f5b8151811015610c13575f828281518110610b4f57610b4f612bdc565b6020908102919091018101515f818152600e90925260409091208054919250906001600160a01b03888116911614610b88575050610c0b565b5f80610b9383611f06565b915091505f8115610bbf57606483600654610bae9190612c46565b610bb89190612c5d565b9050610bc4565b506006545b5f858152600d602052604081205490819003610bde575060645b5f6064610beb8385612c46565b610bf59190612c5d565b9050610c01818b612c7c565b9950505050505050505b600101610b33565b50909392505050565b610c2461170c565b600655565b6001600160a01b0381165f90815260116020526040812080546060928167ffffffffffffffff811115610c5e57610c5e612c8f565b604051908082528060200260200182016040528015610c9757816020015b610c84612807565b815260200190600190039081610c7c5790505b5090505f5b82811015610d71575f848281548110610cb757610cb7612bdc565b5f918252602080832090910154808352600e8252604092839020835160c08101855281546001600160a01b0316815260018201549381019390935260028101549383019390935260038084015460608401526004840154919450919291608084019160ff1690811115610d2c57610d2c61298c565b6003811115610d3d57610d3d61298c565b8152602001600582015481525050838381518110610d5d57610d5d612bdc565b602090810291909101015250600101610c9c565b50949350505050565b610d8261170c565b610d8a611739565b6002546001600160a01b03166323b872dd30610dae6001546001600160a01b031690565b846040518463ffffffff1660e01b8152600401610dcd93929190612ca3565b5f604051808303815f87803b158015610de4575f80fd5b505af1158015610df6573d5f803e3d5ffd5b50505050610e0360015f55565b50565b610e0e61170c565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e3861170c565b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb906044016020604051808303815f875af1158015610e82573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ea69190612cc7565b505050565b610eb3611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610efe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f229190612b39565b11610f3f5760405162461bcd60e51b815260040161062190612b50565b828114610f5e5760405162461bcd60e51b815260040161062190612bad565b5f5b838110156106e3575f858583818110610f7b57610f7b612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b03163314610fbf5760405162461bcd60e51b815260040161062190612bf0565b610fef81858585818110610fd557610fd5612bdc565b9050602002016020810190610fea9190612c14565b611f7f565b50600101610f60565b61100061170c565b611008611739565b5f5b81811015610932575f83838381811061102557611025612bdc565b602090810292909201355f818152600e90935260409092208054929350916001600160a01b03161590506111175760025481546040516323b872dd60e01b81526001600160a01b03928316926323b872dd9261108b923092909116908790600401612ca3565b5f604051808303815f87803b1580156110a2575f80fd5b505af11580156110b4573d5f803e3d5ffd5b505050506110c1826120ee565b80546110d6906001600160a01b0316836121a4565b5f828152600e6020526040812080546001600160a01b031916815560018101829055600281018290556003810182905560048101805460ff19169055600501555b505060010161100a565b61112961170c565b611131611739565b600f541561127657600f545f9061114a90600190612ce6565b90505f600f828154811061116057611160612bdc565b5f918252602080832090910154808352600e90915260409091208054919250906001600160a01b03161561124a5760025481546040516323b872dd60e01b81526001600160a01b03928316926323b872dd926111c6923092909116908790600401612ca3565b5f604051808303815f87803b1580156111dd575f80fd5b505af11580156111ef573d5f803e3d5ffd5b5050825461120992506001600160a01b03169050836121a4565b5f828152600e6020526040812080546001600160a01b031916815560018101829055600281018290556003810182905560048101805460ff19169055600501555b600f80548061125b5761125b612cf9565b600190038181905f5260205f20015f90559055505050611131565b610ac960015f55565b611287611739565b61128f61170c565b5f81116112d15760405162461bcd60e51b815260206004820152601060248201526f043616e6e6f74206465706f73697420360841b6044820152606401610621565b6003546040516323b872dd60e01b81525f916001600160a01b0316906323b872dd9061130590339030908790600401612ca3565b6020604051808303815f875af1158015611321573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113459190612cc7565b90508061138a5760405162461bcd60e51b81526020600482015260136024820152721d1c985b9cd9995c919c9bdb4819985a5b1959606a1b6044820152606401610621565b60405182815233907f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e9060200160405180910390a250610e0360015f55565b6113d1611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561141c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114409190612b39565b1161145d5760405162461bcd60e51b815260040161062190612b50565b5f5b81811015610932575f83838381811061147a5761147a612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b031633146114be5760405162461bcd60e51b815260040161062190612bf0565b6114c7816122ba565b5060010161145f565b6114d861170c565b600795909555600893909355600991909155600a55600b55600c55565b6114fd61170c565b6001600160a01b03811661152657604051631e4fbdf760e01b81525f6004820152602401610621565b610e0381611eb5565b60605f8267ffffffffffffffff81111561154b5761154b612c8f565b604051908082528060200260200182016040528015611574578160200160208202803683370190505b5090505f5b838110156115c7576115a285858381811061159657611596612bdc565b90506020020135612483565b8282815181106115b4576115b4612bdc565b6020908102919091010152600101611579565b5090505b92915050565b600f546060905f8167ffffffffffffffff8111156115f1576115f1612c8f565b60405190808252806020026020018201604052801561162a57816020015b611617612807565b81526020019060019003908161160f5790505b5090505f5b82811015611705575f600f828154811061164b5761164b612bdc565b5f918252602080832090910154808352600e8252604092839020835160c08101855281546001600160a01b0316815260018201549381019390935260028101549383019390935260038084015460608401526004840154919450919291608084019160ff16908111156116c0576116c061298c565b60038111156116d1576116d161298c565b81526020016005820154815250508383815181106116f1576116f1612bdc565b60209081029190910101525060010161162f565b5092915050565b6001546001600160a01b03163314610ac95760405163118cdaa760e01b8152336004820152602401610621565b60025f540361178a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610621565b60025f55565b5f828152600e6020526040902080546001600160a01b03166117e15760405162461bcd60e51b815260206004820152600a602482015269139bdd081cdd185ad95960b21b6044820152606401610621565b5f600482015460ff1660038111156117fb576117fb61298c565b146118725760048101545f906118139060ff16612730565b82600501546118229190612c7c565b9050804210156118705760405162461bcd60e51b815260206004820152601960248201527810dd5c9c995b9d081b1bd8dac81b9bdd08199a5b9a5cda1959603a1b6044820152606401610621565b505b61187b836118fc565b5060048101805483919060ff1916600183600381111561189d5761189d61298c565b02179055504260058201819055600382015580546040516001600160a01b03909116907f60f10efe42a59033e0f0d69d2e985d0dda173e5b56058f8aab1db6a4a8d974f3906118ef9086908690612d0d565b60405180910390a2505050565b5f818152600e602052604081206003810154429080821161192157505f949350505050565b5f61192c8284612ce6565b90505f8080600487015460ff16600381111561194a5761194a61298c565b146119745760048601546119609060ff16612730565b866005015461196f9190612c7c565b611976565b5f5b90505f600487015460ff1660038111156119925761199261298c565b14611b275780841015611ac1575f8186106119ad57816119af565b855b90505f8582116119bf575f6119c9565b6119c98683612ce6565b90505f600554826119da9190612c5d565b60048a01549091505f906119f09060ff1661279b565b90505f606482600654611a039190612c46565b611a0d9190612c5d565b5f8e8152600d6020526040812054919250819003611a29575060645b5f6064611a368385612c46565b611a409190612c5d565b611a4a9086612c46565b9050611a56818a612c7c565b9850878c1115611ab5575f611a6b898e612ce6565b90505f60055482611a7c9190612c5d565b90505f606485600654611a8f9190612c46565b611a999190612c5d565b9050611aa58183612c46565b611aaf908d612c7c565b9b505050505b50505050505050611b89565b5f60055484611ad09190612c5d565b5f8a8152600d6020526040812054919250819003611aec575060645b5f606482600654611afd9190612c46565b611b079190612c5d565b9050611b138184612c46565b611b1d9086612c7c565b9450505050611b89565b5f60055484611b369190612c5d565b5f8a8152600d6020526040812054919250819003611b52575060645b5f606482600654611b639190612c46565b611b6d9190612c5d565b9050611b798184612c46565b611b839086612c7c565b94505050505b600386018590558115611d1d576003546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015611bdc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c009190612b39565b905082811015611c5e5760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f7567682072657761726420746f6b656e7320696e20636f6e746044820152631c9858dd60e21b6064820152608401610621565b600354875460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810186905291169063a9059cbb906044016020604051808303815f875af1158015611caf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd39190612cc7565b508654604080518b8152602081018690526001600160a01b03909216917ff01da32686223933d8a18a391060918c7f11a3648639edd87ae013e2e2731743910160405180910390a2505b509695505050505050565b6002546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611d5c90339030908790600401612ca3565b5f604051808303815f87803b158015611d73575f80fd5b505af1158015611d85573d5f803e3d5ffd5b5050505f838152600e6020526040902080546001600160a01b03191633178155600180820185905542600283018190556003808401919091556004830180549394508593909260ff19909116918490811115611de357611de361298c565b02179055505f826003811115611dfb57611dfb61298c565b14611e065742611e08565b5f5b6005820155611e5483600f80545f838152601060205260408120829055600182018355919091527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020155565b335f8181526011602081815260408084208054898652601284528286208190559383526001840181558452922001859055517f8acf475137e0cd74ca7f611d16b1e6383ec9a9c71a8e5b85967781b9c7214d11906118ef9086908690612d0d565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f8080600484015460ff166003811115611f2257611f2261298c565b03611f3257506064925f92509050565b60048301545f90611f459060ff16612730565b90505f818560050154611f589190612c7c565b6004860154909150428211905f90611f729060ff1661279b565b9791965090945050505050565b5f828152600e6020526040812090600482015460ff166003811115611fa657611fa661298c565b03611ff35760405162461bcd60e51b815260206004820152601860248201527f4e4654206e6f742063757272656e746c79206c6f636b656400000000000000006044820152606401610621565b60048101545f906120069060ff16612730565b82600501546120159190612c7c565b9050804210156120635760405162461bcd60e51b815260206004820152601960248201527810dd5c9c995b9d081b1bd8dac81b9bdd08199a5b9a5cda1959603a1b6044820152606401610621565b61206c846118fc565b5060048201805484919060ff1916600183600381111561208e5761208e61298c565b02179055504260058301819055600383015581546040516001600160a01b03909116907f60f10efe42a59033e0f0d69d2e985d0dda173e5b56058f8aab1db6a4a8d974f3906120e09087908790612d0d565b60405180910390a250505050565b5f81815260106020526040812054600f5490919061210e90600190612ce6565b9050808214612169575f600f828154811061212b5761212b612bdc565b905f5260205f200154905080600f848154811061214a5761214a612bdc565b5f91825260208083209091019290925591825260109052604090208290555b600f80548061217a5761217a612cf9565b5f828152602080822083015f19908101839055909201909255938152601090935250506040812055565b5f818152601260209081526040808320546001600160a01b038616845260119092528220549091906121d890600190612ce6565b9050808214612269576001600160a01b0384165f90815260116020526040812080548390811061220a5761220a612bdc565b905f5260205f20015490508060115f876001600160a01b03166001600160a01b031681526020019081526020015f20848154811061224a5761224a612bdc565b5f91825260208083209091019290925591825260129052604090208290555b6001600160a01b0384165f90815260116020526040902080548061228f5761228f612cf9565b5f828152602080822083015f1990810183905590920190925593815260129093525050604081205550565b5f818152600e6020526040812090600482015460ff1660038111156122e1576122e161298c565b1461236e5760048101545f906122f99060ff16612730565b82600501546123089190612c7c565b90508042101561236c5760405162461bcd60e51b815260206004820152602960248201527f4c6f636b20706572696f64206e6f74206f7665722e2043616e6e6f7420756e736044820152683a30b5b2903cb2ba1760b91b6064820152608401610621565b505b612377826118fc565b5060025481546040516323b872dd60e01b81526001600160a01b03928316926323b872dd926123b0923092909116908790600401612ca3565b5f604051808303815f87803b1580156123c7575f80fd5b505af11580156123d9573d5f803e3d5ffd5b505050506123e6826120ee565b80546123fb906001600160a01b0316836121a4565b5f828152600e6020908152604080832080546001600160a01b031916815560018101849055600281018490556003810184905560048101805460ff1916905560050192909255825491518481526001600160a01b03909216917f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f75910160405180910390a25050565b5f818152600e6020526040812080546001600160a01b03166124a757505f92915050565b600381015442908082116124bf57505f949350505050565b5f6124ca8284612ce6565b90505f8080600487015460ff1660038111156124e8576124e861298c565b146125125760048601546124fe9060ff16612730565b866005015461250d9190612c7c565b612514565b5f5b90505f600487015460ff1660038111156125305761253061298c565b146126c5578084101561265f575f81861061254b578161254d565b855b90505f85821161255d575f612567565b6125678683612ce6565b90505f600554826125789190612c5d565b60048a01549091505f9061258e9060ff1661279b565b90505f6064826006546125a19190612c46565b6125ab9190612c5d565b5f8e8152600d60205260408120549192508190036125c7575060645b5f60646125d48385612c46565b6125de9190612c5d565b6125e89086612c46565b90506125f4818a612c7c565b9850878c1115612653575f612609898e612ce6565b90505f6005548261261a9190612c5d565b90505f60648560065461262d9190612c46565b6126379190612c5d565b90506126438183612c46565b61264d908d612c7c565b9b505050505b50505050505050611d1d565b5f6005548461266e9190612c5d565b5f8a8152600d602052604081205491925081900361268a575060645b5f60648260065461269b9190612c46565b6126a59190612c5d565b90506126b18184612c46565b6126bb9086612c7c565b9450505050611d1d565b5f600554846126d49190612c5d565b5f8a8152600d60205260408120549192508190036126f0575060645b5f6064826006546127019190612c46565b61270b9190612c5d565b90506127178184612c46565b6127219086612c7c565b9b9a5050505050505050505050565b5f60018260038111156127455761274561298c565b0361275257505060075490565b60028260038111156127665761276661298c565b0361277357505060095490565b60038260038111156127875761278761298c565b03612794575050600b5490565b505f919050565b5f60018260038111156127b0576127b061298c565b036127bd57505060085490565b60028260038111156127d1576127d161298c565b036127de575050600a5490565b60038260038111156127f2576127f261298c565b036127ff575050600c5490565b506064919050565b6040518060c001604052805f6001600160a01b031681526020015f81526020015f81526020015f81526020015f60038111156128455761284561298c565b81526020015f81525090565b6001600160a01b0381168114610e03575f80fd5b5f60208284031215612875575f80fd5b813561288081612851565b9392505050565b5f60208284031215612897575f80fd5b5035919050565b5f8083601f8401126128ae575f80fd5b50813567ffffffffffffffff8111156128c5575f80fd5b6020830191508360208260051b85010111156128df575f80fd5b9250929050565b5f805f80604085870312156128f9575f80fd5b843567ffffffffffffffff80821115612910575f80fd5b61291c8883890161289e565b90965094506020870135915080821115612934575f80fd5b506129418782880161289e565b95989497509550505050565b5f806020838503121561295e575f80fd5b823567ffffffffffffffff811115612974575f80fd5b6129808582860161289e565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600481106129bc57634e487b7160e01b5f52602160045260245ffd5b9052565b602080825282518282018190525f919060409081850190868401855b82811015612a3d57815180516001600160a01b031685528681015187860152858101518686015260608082015190860152608080820151612a1f828801826129a0565b505060a0908101519085015260c090930192908501906001016129dc565b5091979650505050505050565b5f8060408385031215612a5b575f80fd5b8235612a6681612851565b946020939093013593505050565b6001600160a01b038716815260208101869052604081018590526060810184905260c08101612aa660808301856129a0565b8260a0830152979650505050505050565b5f805f805f8060c08789031215612acc575f80fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b602080825282518282018190525f9190848201906040850190845b81811015612b2d57835183529284019291840191600101612b11565b50909695505050505050565b5f60208284031215612b49575f80fd5b5051919050565b60208082526037908201527f4d75737420686f6c64206174206c656173742031204e46542066726f6d20746860408201527f6520276e6674546f486f6c642720636f6e74726163742e000000000000000000606082015260800190565b602080825260159082015274082e4e4c2f240d8cadccee8d040dad2e6dac2e8c6d605b1b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b6020808252600a90820152692737ba1039ba30b5b2b960b11b604082015260600190565b5f60208284031215612c24575f80fd5b813560048110612880575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176115cb576115cb612c32565b5f82612c7757634e487b7160e01b5f52601260045260245ffd5b500490565b808201808211156115cb576115cb612c32565b634e487b7160e01b5f52604160045260245ffd5b6001600160a01b039384168152919092166020820152604081019190915260600190565b5f60208284031215612cd7575f80fd5b81518015158114612880575f80fd5b818103818111156115cb576115cb612c32565b634e487b7160e01b5f52603160045260245ffd5b8281526040810161288060208301846129a056fea26469706673582212205b2cb41e8d904a4dd9f6b98c816b4cfebe5f9bd11c2a95eac41e989349e2f03b64736f6c634300081800330000000000000000000000003303c4350259c2b8f3c560b2ec70ad3ed87a5e72
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061023f575f3560e01c80638cd4426d11610135578063dbb7a621116100b4578063f7c618c111610079578063f7c618c114610509578063f7e455d71461051c578063fae40fa01461053c578063fb64455b14610545578063ffd2d8291461054d575f80fd5b8063dbb7a621146104b5578063dd49756e146104bd578063e64a21f3146104d0578063efdd78e1146104e3578063f2fde38b146104f6575f80fd5b8063b2040612116100fa578063b20406121461040f578063b865749d14610418578063bf4bac391461047c578063d3abfe121461048f578063d56d229d146104a2575f80fd5b80638cd4426d146103d05780638da5cb5b146103e357806399ba918d146103f45780639ce98f0e146103fd578063ae63586c14610406575f80fd5b80636f9fb98a116101c15780637f4ca1d7116101865780637f4ca1d714610363578063817b1cd214610382578063888ce4af1461038a57806388c0771b146103aa5780638aee8127146103bd575f80fd5b80636f9fb98a1461032457806370becf5d1461032c578063715018a614610335578063760edace1461033d5780637dc3db8f14610350575f80fd5b80633af7a795116102075780633af7a795146102c5578063454aa669146102d857806352f5ad77146102eb578063646e6f8b146102fe57806366e4664a14610311575f80fd5b80630dfa1e96146102435780631a658ea01461025f578063224eb1291461027457806327711b2714610287578063398612b8146102b2575b5f80fd5b61024c60095481565b6040519081526020015b60405180910390f35b61027261026d366004612865565b610556565b005b610272610282366004612887565b610580565b60045461029a906001600160a01b031681565b6040516001600160a01b039091168152602001610256565b6102726102c03660046128e6565b61058d565b6102726102d33660046128e6565b6106f3565b6102726102e6366004612887565b61077a565b6102726102f9366004612865565b610800565b61027261030c36600461294d565b61082a565b61027261031f3660046128e6565b61093c565b61024c610a49565b61024c600b5481565b610272610ab8565b61024c61034b366004612865565b610acb565b61027261035e366004612887565b610c1c565b61024c610371366004612887565b600d6020525f908152604090205481565b600f5461024c565b61039d610398366004612865565b610c29565b60405161025691906129c0565b6102726103b8366004612887565b610d7a565b6102726103cb366004612865565b610e06565b6102726103de366004612a4a565b610e30565b6001546001600160a01b031661029a565b61024c60065481565b61024c60075481565b61024c60055481565b61024c600c5481565b61046a610426366004612887565b600e6020525f90815260409020805460018201546002830154600384015460048501546005909501546001600160a01b039094169492939192909160ff9091169086565b60405161025696959493929190612a74565b61027261048a3660046128e6565b610eab565b61027261049d36600461294d565b610ff8565b60025461029a906001600160a01b031681565b610272611121565b6102726104cb366004612887565b61127f565b6102726104de36600461294d565b6113c9565b6102726104f1366004612ab7565b6114d0565b610272610504366004612865565b6114f5565b60035461029a906001600160a01b031681565b61052f61052a36600461294d565b61152f565b6040516102569190612af6565b61024c600a5481565b61039d6115d1565b61024c60085481565b61055e61170c565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b61058861170c565b600555565b610595611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156105e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106049190612b39565b1161062a5760405162461bcd60e51b815260040161062190612b50565b60405180910390fd5b8281146106495760405162461bcd60e51b815260040161062190612bad565b5f5b838110156106e3575f85858381811061066657610666612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b031633146106aa5760405162461bcd60e51b815260040161062190612bf0565b6106da818585858181106106c0576106c0612bdc565b90506020020160208101906106d59190612c14565b611790565b5060010161064b565b506106ed60015f55565b50505050565b6106fb61170c565b82811461071a5760405162461bcd60e51b815260040161062190612bad565b5f5b838110156107735782828281811061073657610736612bdc565b90506020020135600d5f87878581811061075257610752612bdc565b602090810292909201358352508101919091526040015f205560010161071c565b5050505050565b61078261170c565b804710156107d25760405162461bcd60e51b815260206004820152601960248201527f4e6f7420656e6f756768206e61746976652062616c616e6365000000000000006044820152606401610621565b604051339082156108fc029083905f818181858888f193505050501580156107fc573d5f803e3d5ffd5b5050565b61080861170c565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610832611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561087d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a19190612b39565b116108be5760405162461bcd60e51b815260040161062190612b50565b5f5b81811015610932575f8383838181106108db576108db612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b0316331461091f5760405162461bcd60e51b815260040161062190612bf0565b610928816118fc565b50506001016108c0565b506107fc60015f55565b610944611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561098f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b39190612b39565b116109d05760405162461bcd60e51b815260040161062190612b50565b8281146109ef5760405162461bcd60e51b815260040161062190612bad565b5f5b838110156106e357610a41858583818110610a0e57610a0e612bdc565b90506020020135848484818110610a2757610a27612bdc565b9050602002016020810190610a3c9190612c14565b611d28565b6001016109f1565b6003546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610a8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab39190612b39565b905090565b610ac061170c565b610ac95f611eb5565b565b6001600160a01b0381165f908152601160209081526040808320805482518185028101850190935280835284938493929190830182828015610b2a57602002820191905f5260205f20905b815481526020019060010190808311610b16575b505050505090505f5b8151811015610c13575f828281518110610b4f57610b4f612bdc565b6020908102919091018101515f818152600e90925260409091208054919250906001600160a01b03888116911614610b88575050610c0b565b5f80610b9383611f06565b915091505f8115610bbf57606483600654610bae9190612c46565b610bb89190612c5d565b9050610bc4565b506006545b5f858152600d602052604081205490819003610bde575060645b5f6064610beb8385612c46565b610bf59190612c5d565b9050610c01818b612c7c565b9950505050505050505b600101610b33565b50909392505050565b610c2461170c565b600655565b6001600160a01b0381165f90815260116020526040812080546060928167ffffffffffffffff811115610c5e57610c5e612c8f565b604051908082528060200260200182016040528015610c9757816020015b610c84612807565b815260200190600190039081610c7c5790505b5090505f5b82811015610d71575f848281548110610cb757610cb7612bdc565b5f918252602080832090910154808352600e8252604092839020835160c08101855281546001600160a01b0316815260018201549381019390935260028101549383019390935260038084015460608401526004840154919450919291608084019160ff1690811115610d2c57610d2c61298c565b6003811115610d3d57610d3d61298c565b8152602001600582015481525050838381518110610d5d57610d5d612bdc565b602090810291909101015250600101610c9c565b50949350505050565b610d8261170c565b610d8a611739565b6002546001600160a01b03166323b872dd30610dae6001546001600160a01b031690565b846040518463ffffffff1660e01b8152600401610dcd93929190612ca3565b5f604051808303815f87803b158015610de4575f80fd5b505af1158015610df6573d5f803e3d5ffd5b50505050610e0360015f55565b50565b610e0e61170c565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e3861170c565b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb906044016020604051808303815f875af1158015610e82573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ea69190612cc7565b505050565b610eb3611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610efe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f229190612b39565b11610f3f5760405162461bcd60e51b815260040161062190612b50565b828114610f5e5760405162461bcd60e51b815260040161062190612bad565b5f5b838110156106e3575f858583818110610f7b57610f7b612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b03163314610fbf5760405162461bcd60e51b815260040161062190612bf0565b610fef81858585818110610fd557610fd5612bdc565b9050602002016020810190610fea9190612c14565b611f7f565b50600101610f60565b61100061170c565b611008611739565b5f5b81811015610932575f83838381811061102557611025612bdc565b602090810292909201355f818152600e90935260409092208054929350916001600160a01b03161590506111175760025481546040516323b872dd60e01b81526001600160a01b03928316926323b872dd9261108b923092909116908790600401612ca3565b5f604051808303815f87803b1580156110a2575f80fd5b505af11580156110b4573d5f803e3d5ffd5b505050506110c1826120ee565b80546110d6906001600160a01b0316836121a4565b5f828152600e6020526040812080546001600160a01b031916815560018101829055600281018290556003810182905560048101805460ff19169055600501555b505060010161100a565b61112961170c565b611131611739565b600f541561127657600f545f9061114a90600190612ce6565b90505f600f828154811061116057611160612bdc565b5f918252602080832090910154808352600e90915260409091208054919250906001600160a01b03161561124a5760025481546040516323b872dd60e01b81526001600160a01b03928316926323b872dd926111c6923092909116908790600401612ca3565b5f604051808303815f87803b1580156111dd575f80fd5b505af11580156111ef573d5f803e3d5ffd5b5050825461120992506001600160a01b03169050836121a4565b5f828152600e6020526040812080546001600160a01b031916815560018101829055600281018290556003810182905560048101805460ff19169055600501555b600f80548061125b5761125b612cf9565b600190038181905f5260205f20015f90559055505050611131565b610ac960015f55565b611287611739565b61128f61170c565b5f81116112d15760405162461bcd60e51b815260206004820152601060248201526f043616e6e6f74206465706f73697420360841b6044820152606401610621565b6003546040516323b872dd60e01b81525f916001600160a01b0316906323b872dd9061130590339030908790600401612ca3565b6020604051808303815f875af1158015611321573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113459190612cc7565b90508061138a5760405162461bcd60e51b81526020600482015260136024820152721d1c985b9cd9995c919c9bdb4819985a5b1959606a1b6044820152606401610621565b60405182815233907f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e9060200160405180910390a250610e0360015f55565b6113d1611739565b600480546040516370a0823160e01b815233928101929092525f916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561141c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114409190612b39565b1161145d5760405162461bcd60e51b815260040161062190612b50565b5f5b81811015610932575f83838381811061147a5761147a612bdc565b602090810292909201355f818152600e909352604090922054919250506001600160a01b031633146114be5760405162461bcd60e51b815260040161062190612bf0565b6114c7816122ba565b5060010161145f565b6114d861170c565b600795909555600893909355600991909155600a55600b55600c55565b6114fd61170c565b6001600160a01b03811661152657604051631e4fbdf760e01b81525f6004820152602401610621565b610e0381611eb5565b60605f8267ffffffffffffffff81111561154b5761154b612c8f565b604051908082528060200260200182016040528015611574578160200160208202803683370190505b5090505f5b838110156115c7576115a285858381811061159657611596612bdc565b90506020020135612483565b8282815181106115b4576115b4612bdc565b6020908102919091010152600101611579565b5090505b92915050565b600f546060905f8167ffffffffffffffff8111156115f1576115f1612c8f565b60405190808252806020026020018201604052801561162a57816020015b611617612807565b81526020019060019003908161160f5790505b5090505f5b82811015611705575f600f828154811061164b5761164b612bdc565b5f918252602080832090910154808352600e8252604092839020835160c08101855281546001600160a01b0316815260018201549381019390935260028101549383019390935260038084015460608401526004840154919450919291608084019160ff16908111156116c0576116c061298c565b60038111156116d1576116d161298c565b81526020016005820154815250508383815181106116f1576116f1612bdc565b60209081029190910101525060010161162f565b5092915050565b6001546001600160a01b03163314610ac95760405163118cdaa760e01b8152336004820152602401610621565b60025f540361178a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610621565b60025f55565b5f828152600e6020526040902080546001600160a01b03166117e15760405162461bcd60e51b815260206004820152600a602482015269139bdd081cdd185ad95960b21b6044820152606401610621565b5f600482015460ff1660038111156117fb576117fb61298c565b146118725760048101545f906118139060ff16612730565b82600501546118229190612c7c565b9050804210156118705760405162461bcd60e51b815260206004820152601960248201527810dd5c9c995b9d081b1bd8dac81b9bdd08199a5b9a5cda1959603a1b6044820152606401610621565b505b61187b836118fc565b5060048101805483919060ff1916600183600381111561189d5761189d61298c565b02179055504260058201819055600382015580546040516001600160a01b03909116907f60f10efe42a59033e0f0d69d2e985d0dda173e5b56058f8aab1db6a4a8d974f3906118ef9086908690612d0d565b60405180910390a2505050565b5f818152600e602052604081206003810154429080821161192157505f949350505050565b5f61192c8284612ce6565b90505f8080600487015460ff16600381111561194a5761194a61298c565b146119745760048601546119609060ff16612730565b866005015461196f9190612c7c565b611976565b5f5b90505f600487015460ff1660038111156119925761199261298c565b14611b275780841015611ac1575f8186106119ad57816119af565b855b90505f8582116119bf575f6119c9565b6119c98683612ce6565b90505f600554826119da9190612c5d565b60048a01549091505f906119f09060ff1661279b565b90505f606482600654611a039190612c46565b611a0d9190612c5d565b5f8e8152600d6020526040812054919250819003611a29575060645b5f6064611a368385612c46565b611a409190612c5d565b611a4a9086612c46565b9050611a56818a612c7c565b9850878c1115611ab5575f611a6b898e612ce6565b90505f60055482611a7c9190612c5d565b90505f606485600654611a8f9190612c46565b611a999190612c5d565b9050611aa58183612c46565b611aaf908d612c7c565b9b505050505b50505050505050611b89565b5f60055484611ad09190612c5d565b5f8a8152600d6020526040812054919250819003611aec575060645b5f606482600654611afd9190612c46565b611b079190612c5d565b9050611b138184612c46565b611b1d9086612c7c565b9450505050611b89565b5f60055484611b369190612c5d565b5f8a8152600d6020526040812054919250819003611b52575060645b5f606482600654611b639190612c46565b611b6d9190612c5d565b9050611b798184612c46565b611b839086612c7c565b94505050505b600386018590558115611d1d576003546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015611bdc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c009190612b39565b905082811015611c5e5760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f7567682072657761726420746f6b656e7320696e20636f6e746044820152631c9858dd60e21b6064820152608401610621565b600354875460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810186905291169063a9059cbb906044016020604051808303815f875af1158015611caf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd39190612cc7565b508654604080518b8152602081018690526001600160a01b03909216917ff01da32686223933d8a18a391060918c7f11a3648639edd87ae013e2e2731743910160405180910390a2505b509695505050505050565b6002546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611d5c90339030908790600401612ca3565b5f604051808303815f87803b158015611d73575f80fd5b505af1158015611d85573d5f803e3d5ffd5b5050505f838152600e6020526040902080546001600160a01b03191633178155600180820185905542600283018190556003808401919091556004830180549394508593909260ff19909116918490811115611de357611de361298c565b02179055505f826003811115611dfb57611dfb61298c565b14611e065742611e08565b5f5b6005820155611e5483600f80545f838152601060205260408120829055600182018355919091527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020155565b335f8181526011602081815260408084208054898652601284528286208190559383526001840181558452922001859055517f8acf475137e0cd74ca7f611d16b1e6383ec9a9c71a8e5b85967781b9c7214d11906118ef9086908690612d0d565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f8080600484015460ff166003811115611f2257611f2261298c565b03611f3257506064925f92509050565b60048301545f90611f459060ff16612730565b90505f818560050154611f589190612c7c565b6004860154909150428211905f90611f729060ff1661279b565b9791965090945050505050565b5f828152600e6020526040812090600482015460ff166003811115611fa657611fa661298c565b03611ff35760405162461bcd60e51b815260206004820152601860248201527f4e4654206e6f742063757272656e746c79206c6f636b656400000000000000006044820152606401610621565b60048101545f906120069060ff16612730565b82600501546120159190612c7c565b9050804210156120635760405162461bcd60e51b815260206004820152601960248201527810dd5c9c995b9d081b1bd8dac81b9bdd08199a5b9a5cda1959603a1b6044820152606401610621565b61206c846118fc565b5060048201805484919060ff1916600183600381111561208e5761208e61298c565b02179055504260058301819055600383015581546040516001600160a01b03909116907f60f10efe42a59033e0f0d69d2e985d0dda173e5b56058f8aab1db6a4a8d974f3906120e09087908790612d0d565b60405180910390a250505050565b5f81815260106020526040812054600f5490919061210e90600190612ce6565b9050808214612169575f600f828154811061212b5761212b612bdc565b905f5260205f200154905080600f848154811061214a5761214a612bdc565b5f91825260208083209091019290925591825260109052604090208290555b600f80548061217a5761217a612cf9565b5f828152602080822083015f19908101839055909201909255938152601090935250506040812055565b5f818152601260209081526040808320546001600160a01b038616845260119092528220549091906121d890600190612ce6565b9050808214612269576001600160a01b0384165f90815260116020526040812080548390811061220a5761220a612bdc565b905f5260205f20015490508060115f876001600160a01b03166001600160a01b031681526020019081526020015f20848154811061224a5761224a612bdc565b5f91825260208083209091019290925591825260129052604090208290555b6001600160a01b0384165f90815260116020526040902080548061228f5761228f612cf9565b5f828152602080822083015f1990810183905590920190925593815260129093525050604081205550565b5f818152600e6020526040812090600482015460ff1660038111156122e1576122e161298c565b1461236e5760048101545f906122f99060ff16612730565b82600501546123089190612c7c565b90508042101561236c5760405162461bcd60e51b815260206004820152602960248201527f4c6f636b20706572696f64206e6f74206f7665722e2043616e6e6f7420756e736044820152683a30b5b2903cb2ba1760b91b6064820152608401610621565b505b612377826118fc565b5060025481546040516323b872dd60e01b81526001600160a01b03928316926323b872dd926123b0923092909116908790600401612ca3565b5f604051808303815f87803b1580156123c7575f80fd5b505af11580156123d9573d5f803e3d5ffd5b505050506123e6826120ee565b80546123fb906001600160a01b0316836121a4565b5f828152600e6020908152604080832080546001600160a01b031916815560018101849055600281018490556003810184905560048101805460ff1916905560050192909255825491518481526001600160a01b03909216917f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f75910160405180910390a25050565b5f818152600e6020526040812080546001600160a01b03166124a757505f92915050565b600381015442908082116124bf57505f949350505050565b5f6124ca8284612ce6565b90505f8080600487015460ff1660038111156124e8576124e861298c565b146125125760048601546124fe9060ff16612730565b866005015461250d9190612c7c565b612514565b5f5b90505f600487015460ff1660038111156125305761253061298c565b146126c5578084101561265f575f81861061254b578161254d565b855b90505f85821161255d575f612567565b6125678683612ce6565b90505f600554826125789190612c5d565b60048a01549091505f9061258e9060ff1661279b565b90505f6064826006546125a19190612c46565b6125ab9190612c5d565b5f8e8152600d60205260408120549192508190036125c7575060645b5f60646125d48385612c46565b6125de9190612c5d565b6125e89086612c46565b90506125f4818a612c7c565b9850878c1115612653575f612609898e612ce6565b90505f6005548261261a9190612c5d565b90505f60648560065461262d9190612c46565b6126379190612c5d565b90506126438183612c46565b61264d908d612c7c565b9b505050505b50505050505050611d1d565b5f6005548461266e9190612c5d565b5f8a8152600d602052604081205491925081900361268a575060645b5f60648260065461269b9190612c46565b6126a59190612c5d565b90506126b18184612c46565b6126bb9086612c7c565b9450505050611d1d565b5f600554846126d49190612c5d565b5f8a8152600d60205260408120549192508190036126f0575060645b5f6064826006546127019190612c46565b61270b9190612c5d565b90506127178184612c46565b6127219086612c7c565b9b9a5050505050505050505050565b5f60018260038111156127455761274561298c565b0361275257505060075490565b60028260038111156127665761276661298c565b0361277357505060095490565b60038260038111156127875761278761298c565b03612794575050600b5490565b505f919050565b5f60018260038111156127b0576127b061298c565b036127bd57505060085490565b60028260038111156127d1576127d161298c565b036127de575050600a5490565b60038260038111156127f2576127f261298c565b036127ff575050600c5490565b506064919050565b6040518060c001604052805f6001600160a01b031681526020015f81526020015f81526020015f81526020015f60038111156128455761284561298c565b81526020015f81525090565b6001600160a01b0381168114610e03575f80fd5b5f60208284031215612875575f80fd5b813561288081612851565b9392505050565b5f60208284031215612897575f80fd5b5035919050565b5f8083601f8401126128ae575f80fd5b50813567ffffffffffffffff8111156128c5575f80fd5b6020830191508360208260051b85010111156128df575f80fd5b9250929050565b5f805f80604085870312156128f9575f80fd5b843567ffffffffffffffff80821115612910575f80fd5b61291c8883890161289e565b90965094506020870135915080821115612934575f80fd5b506129418782880161289e565b95989497509550505050565b5f806020838503121561295e575f80fd5b823567ffffffffffffffff811115612974575f80fd5b6129808582860161289e565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600481106129bc57634e487b7160e01b5f52602160045260245ffd5b9052565b602080825282518282018190525f919060409081850190868401855b82811015612a3d57815180516001600160a01b031685528681015187860152858101518686015260608082015190860152608080820151612a1f828801826129a0565b505060a0908101519085015260c090930192908501906001016129dc565b5091979650505050505050565b5f8060408385031215612a5b575f80fd5b8235612a6681612851565b946020939093013593505050565b6001600160a01b038716815260208101869052604081018590526060810184905260c08101612aa660808301856129a0565b8260a0830152979650505050505050565b5f805f805f8060c08789031215612acc575f80fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b602080825282518282018190525f9190848201906040850190845b81811015612b2d57835183529284019291840191600101612b11565b50909695505050505050565b5f60208284031215612b49575f80fd5b5051919050565b60208082526037908201527f4d75737420686f6c64206174206c656173742031204e46542066726f6d20746860408201527f6520276e6674546f486f6c642720636f6e74726163742e000000000000000000606082015260800190565b602080825260159082015274082e4e4c2f240d8cadccee8d040dad2e6dac2e8c6d605b1b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b6020808252600a90820152692737ba1039ba30b5b2b960b11b604082015260600190565b5f60208284031215612c24575f80fd5b813560048110612880575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176115cb576115cb612c32565b5f82612c7757634e487b7160e01b5f52601260045260245ffd5b500490565b808201808211156115cb576115cb612c32565b634e487b7160e01b5f52604160045260245ffd5b6001600160a01b039384168152919092166020820152604081019190915260600190565b5f60208284031215612cd7575f80fd5b81518015158114612880575f80fd5b818103818111156115cb576115cb612c32565b634e487b7160e01b5f52603160045260245ffd5b8281526040810161288060208301846129a056fea26469706673582212205b2cb41e8d904a4dd9f6b98c816b4cfebe5f9bd11c2a95eac41e989349e2f03b64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003303c4350259c2b8f3c560b2ec70ad3ed87a5e72
-----Decoded View---------------
Arg [0] : _initialOwner (address): 0x3303C4350259C2B8F3C560B2ec70aD3ed87A5E72
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000003303c4350259c2b8f3c560b2ec70ad3ed87a5e72
Deployed Bytecode Sourcemap
16643:30008:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17975:39;;;;;;;;;160:25:1;;;148:2;133:18;17975:39:0;;;;;;;;21120:102;;;;;;:::i;:::-;;:::i;:::-;;21230:104;;;;;;:::i;:::-;;:::i;17323:78::-;;;;;-1:-1:-1;;;;;17323:78:0;;;;;;-1:-1:-1;;;;;981:32:1;;;963:51;;951:2;936:18;17323:78:0;802:218:1;25821:538:0;;;;;;:::i;:::-;;:::i;22403:360::-;;;;;;:::i;:::-;;:::i;22897:195::-;;;;;;:::i;:::-;;:::i;20885:110::-;;;;;;:::i;:::-;;:::i;25173:365::-;;;;;;:::i;:::-;;:::i;24187:405::-;;;;;;:::i;:::-;;:::i;23699:124::-;;;:::i;18075:39::-;;;;;;15344:103;;;:::i;27930:1203::-;;;;;;:::i;:::-;;:::i;21342:110::-;;;;;;:::i;:::-;;:::i;18308:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;39747:105;39820:17;:24;39747:105;;40243:436;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;46491:157::-;;;;;;:::i;:::-;;:::i;21003:109::-;;;;;;:::i;:::-;;:::i;23100:136::-;;;;;;:::i;:::-;;:::i;14669:87::-;14742:6;;-1:-1:-1;;;;;14742:6:0;14669:87;;17664:41;;;;;;17875:39;;;;;;17483:36;;;;;;18121:37;;;;;;19088:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19088:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;26559:533::-;;;;;;:::i;:::-;;:::i;44340:834::-;;;;;;:::i;:::-;;:::i;16895:80::-;;;;;-1:-1:-1;;;;;16895:80:0;;;45377:871;;;:::i;23376:315::-;;;;;;:::i;:::-;;:::i;24727:363::-;;;;;;:::i;:::-;;:::i;21634:541::-;;;;;;:::i;:::-;;:::i;15602:220::-;;;;;;:::i;:::-;;:::i;17076:78::-;;;;;-1:-1:-1;;;;;17076:78:0;;;27364:372;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;18021:37::-;;;;;;39860:375;;;:::i;17921:37::-;;;;;;21120:102;14555:13;:11;:13::i;:::-;21192:9:::1;:22:::0;;-1:-1:-1;;;;;;21192:22:0::1;-1:-1:-1::0;;;;;21192:22:0;;;::::1;::::0;;;::::1;::::0;;21120:102::o;21230:104::-;14555:13;:11;:13::i;:::-;21303:12:::1;:23:::0;21230:104::o;25821:538::-;11195:21;:19;:21::i;:::-;20610:9:::1;::::0;;:31:::1;::::0;-1:-1:-1;;;20610:31:0;;20630:10:::1;20610:31:::0;;::::1;963:51:1::0;;;;20644:1:0::1;::::0;-1:-1:-1;;;;;20610:9:0;;::::1;::::0;:19:::1;::::0;936:18:1;;20610:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;20588:140;;;;-1:-1:-1::0;;;20588:140:0::1;;;;;;;:::i;:::-;;;;;;;;;26032:39:::0;;::::2;26024:73;;;;-1:-1:-1::0;;;26024:73:0::2;;;;;;;:::i;:::-;26113:9;26108:244;26128:20:::0;;::::2;26108:244;;;26170:15;26188:9;;26198:1;26188:12;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;26223:19;::::0;;;:10:::2;:19:::0;;;;;;;:25;26188:12;;-1:-1:-1;;;;;;;26223:25:0::2;26252:10;26223:39;26215:62;;;;-1:-1:-1::0;;;26215:62:0::2;;;;;;;:::i;:::-;26292:48;26315:7;26324:12;;26337:1;26324:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;26292:22;:48::i;:::-;-1:-1:-1::0;26150:3:0::2;;26108:244;;;;11239:20:::0;10633:1;11759:7;:22;11576:213;11239:20;25821:538;;;;:::o;22403:360::-;14555:13;:11;:13::i;:::-;22561:39;;::::1;22553:73;;;;-1:-1:-1::0;;;22553:73:0::1;;;;;;;:::i;:::-;22642:9;22637:119;22657:20:::0;;::::1;22637:119;;;22729:12;;22742:1;22729:15;;;;;;;:::i;:::-;;;;;;;22699:13;:27;22713:9;;22723:1;22713:12;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;::::1;;22699:27:::0;;-1:-1:-1;22699:27:0;::::1;::::0;;;;;;-1:-1:-1;22699:27:0;:45;22679:3:::1;;22637:119;;;;22403:360:::0;;;;:::o;22897:195::-;14555:13;:11;:13::i;:::-;22999:7:::1;22974:21;:32;;22966:70;;;::::0;-1:-1:-1;;;22966:70:0;;9934:2:1;22966:70:0::1;::::0;::::1;9916:21:1::0;9973:2;9953:18;;;9946:30;10012:27;9992:18;;;9985:55;10057:18;;22966:70:0::1;9732:349:1::0;22966:70:0::1;23047:37;::::0;23055:10:::1;::::0;23047:37;::::1;;;::::0;23076:7;;23047:37:::1;::::0;;;23076:7;23055:10;23047:37;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;22897:195:::0;:::o;20885:110::-;14555:13;:11;:13::i;:::-;20961:11:::1;:26:::0;;-1:-1:-1;;;;;;20961:26:0::1;-1:-1:-1::0;;;;;20961:26:0;;;::::1;::::0;;;::::1;::::0;;20885:110::o;25173:365::-;11195:21;:19;:21::i;:::-;20610:9:::1;::::0;;:31:::1;::::0;-1:-1:-1;;;20610:31:0;;20630:10:::1;20610:31:::0;;::::1;963:51:1::0;;;;20644:1:0::1;::::0;-1:-1:-1;;;;;20610:9:0;;::::1;::::0;:19:::1;::::0;936:18:1;;20610:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;20588:140;;;;-1:-1:-1::0;;;20588:140:0::1;;;;;;;:::i;:::-;25318:9:::2;25313:218;25333:20:::0;;::::2;25313:218;;;25375:15;25393:9;;25403:1;25393:12;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;25428:19;::::0;;;:10:::2;:19:::0;;;;;;;:25;25393:12;;-1:-1:-1;;;;;;;25428:25:0::2;25457:10;25428:39;25420:62;;;;-1:-1:-1::0;;;25420:62:0::2;;;;;;;:::i;:::-;25497:22;25511:7;25497:13;:22::i;:::-;-1:-1:-1::0;;25355:3:0::2;;25313:218;;;;11239:20:::0;10633:1;11759:7;:22;11576:213;24187:405;11195:21;:19;:21::i;:::-;20610:9:::1;::::0;;:31:::1;::::0;-1:-1:-1;;;20610:31:0;;20630:10:::1;20610:31:::0;;::::1;963:51:1::0;;;;20644:1:0::1;::::0;-1:-1:-1;;;;;20610:9:0;;::::1;::::0;:19:::1;::::0;936:18:1;;20610:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;20588:140;;;;-1:-1:-1::0;;;20588:140:0::1;;;;;;;:::i;:::-;24390:39:::0;;::::2;24382:73;;;;-1:-1:-1::0;;;24382:73:0::2;;;;;;;:::i;:::-;24471:9;24466:119;24486:20:::0;;::::2;24466:119;;;24528:45;24543:9;;24553:1;24543:12;;;;;;;:::i;:::-;;;;;;;24557;;24570:1;24557:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;24528:14;:45::i;:::-;24508:3;;24466:119;;23699:124:::0;23779:11;;:36;;-1:-1:-1;;;23779:36:0;;23809:4;23779:36;;;963:51:1;23752:7:0;;-1:-1:-1;;;;;23779:11:0;;:21;;936:18:1;;23779:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23772:43;;23699:124;:::o;15344:103::-;14555:13;:11;:13::i;:::-;15409:30:::1;15436:1;15409:18;:30::i;:::-;15344:103::o:0;27930:1203::-;-1:-1:-1;;;;;28079:23:0;;27994:7;28079:23;;;:16;:23;;;;;;;;28051:51;;;;;;;;;;;;;;;;;27994:7;;;;28051:51;28079:23;28051:51;;;28079:23;28051:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28120:9;28115:977;28139:8;:15;28135:1;:19;28115:977;;;28176:15;28194:8;28203:1;28194:11;;;;;;;;:::i;:::-;;;;;;;;;;;;28220:22;28245:19;;;:10;:19;;;;;;;28314:10;;28194:11;;-1:-1:-1;28245:19:0;-1:-1:-1;;;;;28314:19:0;;;:10;;:19;28310:33;;28335:8;;;;28310:33;28412:22;28436:11;28451:33;28479:4;28451:27;:33::i;:::-;28411:73;;;;28499:17;28537:6;28533:293;;;28678:3;28660:14;28641:16;;:33;;;;:::i;:::-;28640:41;;;;:::i;:::-;28628:53;;28533:293;;;-1:-1:-1;28794:16:0;;28533:293;28888:15;28906:22;;;:13;:22;;;;;;;28947:12;;;28943:31;;-1:-1:-1;28971:3:0;28943:31;28991:17;29035:3;29012:19;29024:7;29012:9;:19;:::i;:::-;29011:27;;;;:::i;:::-;28991:47;-1:-1:-1;29053:27:0;28991:47;29053:27;;:::i;:::-;;;28161:931;;;;;;;28115:977;28156:3;;28115:977;;;-1:-1:-1;29111:14:0;;27930:1203;-1:-1:-1;;;27930:1203:0:o;21342:110::-;14555:13;:11;:13::i;:::-;21418:16:::1;:26:::0;21342:110::o;40243:436::-;-1:-1:-1;;;;;40368:25:0;;40339:26;40368:25;;;:16;:25;;;;;40421:15;;40308:18;;40421:15;40475:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;40447:51;;40514:9;40509:139;40533:6;40529:1;:10;40509:139;;;40561:15;40579:8;40588:1;40579:11;;;;;;;;:::i;:::-;;;;;;;;;;;;;40617:19;;;:10;:19;;;;;;;40605:31;;;;;;;;;-1:-1:-1;;;;;40605:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40579:11;;-1:-1:-1;40605:31:0;;40617:19;40605:31;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:6;40612:1;40605:9;;;;;;;;:::i;:::-;;;;;;;;;;:31;-1:-1:-1;40541:3:0;;40509:139;;;-1:-1:-1;40665:6:0;40243:436;-1:-1:-1;;;;40243:436:0:o;46491:157::-;14555:13;:11;:13::i;:::-;11195:21:::1;:19;:21::i;:::-;46582:11:::2;::::0;-1:-1:-1;;;;;46582:11:0::2;:24;46615:4;46622:7;14742:6:::0;;-1:-1:-1;;;;;14742:6:0;;14669:87;46622:7:::2;46631:8;46582:58;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;11239:20:::1;10633:1:::0;11759:7;:22;11576:213;11239:20:::1;46491:157:::0;:::o;21003:109::-;14555:13;:11;:13::i;:::-;21078:11:::1;:26:::0;;-1:-1:-1;;;;;;21078:26:0::1;-1:-1:-1::0;;;;;21078:26:0;;;::::1;::::0;;;::::1;::::0;;21003:109::o;23100:136::-;14555:13;:11;:13::i;:::-;23184:44:::1;::::0;-1:-1:-1;;;23184:44:0;;23208:10:::1;23184:44;::::0;::::1;11429:51:1::0;11496:18;;;11489:34;;;-1:-1:-1;;;;;23184:23:0;::::1;::::0;::::1;::::0;11402:18:1;;23184:44:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;23100:136:::0;;:::o;26559:533::-;11195:21;:19;:21::i;:::-;20610:9:::1;::::0;;:31:::1;::::0;-1:-1:-1;;;20610:31:0;;20630:10:::1;20610:31:::0;;::::1;963:51:1::0;;;;20644:1:0::1;::::0;-1:-1:-1;;;;;20610:9:0;;::::1;::::0;:19:::1;::::0;936:18:1;;20610:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;20588:140;;;;-1:-1:-1::0;;;20588:140:0::1;;;;;;;:::i;:::-;26766:42:::0;;::::2;26758:76;;;;-1:-1:-1::0;;;26758:76:0::2;;;;;;;:::i;:::-;26850:9;26845:240;26865:20:::0;;::::2;26845:240;;;26907:15;26925:9;;26935:1;26925:12;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;26960:19;::::0;;;:10:::2;:19:::0;;;;;;;:25;26925:12;;-1:-1:-1;;;;;;;26960:25:0::2;26989:10;26960:39;26952:62;;;;-1:-1:-1::0;;;26952:62:0::2;;;;;;;:::i;:::-;27029:44;27045:7;27054:15;;27070:1;27054:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;27029:15;:44::i;:::-;-1:-1:-1::0;26887:3:0::2;;26845:240;;44340:834:::0;14555:13;:11;:13::i;:::-;11195:21:::1;:19;:21::i;:::-;44448:9:::2;44443:724;44463:20:::0;;::::2;44443:724;;;44505:15;44523:9;;44533:1;44523:12;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;44550:22;44575:19:::0;;;:10:::2;:19:::0;;;;;;;44677:10;;44523:12;;-1:-1:-1;44575:19:0;-1:-1:-1;;;;;44677:10:0::2;:24:::0;;-1:-1:-1;44673:483:0::2;;44770:11;::::0;44810:10;;44770:60:::2;::::0;-1:-1:-1;;;44770:60:0;;-1:-1:-1;;;;;44770:11:0;;::::2;::::0;:24:::2;::::0;:60:::2;::::0;44803:4:::2;::::0;44810:10;;::::2;::::0;44822:7;;44770:60:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;44896:37;44925:7;44896:28;:37::i;:::-;45023:10:::0;;44995:48:::2;::::0;-1:-1:-1;;;;;45023:10:0::2;45035:7:::0;44995:27:::2;:48::i;:::-;45121:19;::::0;;;:10:::2;:19;::::0;;;;45114:26;;-1:-1:-1;;;;;;45114:26:0::2;::::0;;;;::::2;::::0;;;::::2;::::0;::::2;::::0;;;::::2;::::0;::::2;::::0;;;::::2;::::0;::::2;::::0;;-1:-1:-1;;45114:26:0::2;::::0;;::::2;;::::0;44673:483:::2;-1:-1:-1::0;;44485:3:0::2;;44443:724;;45377:871:::0;14555:13;:11;:13::i;:::-;11195:21:::1;:19;:21::i;:::-;45535:17:::2;:24:::0;:28;45528:713:::2;;45600:17;:24:::0;45580:17:::2;::::0;45600:28:::2;::::0;45627:1:::2;::::0;45600:28:::2;:::i;:::-;45580:48;;45643:15;45661:17;45679:9;45661:28;;;;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;;;::::2;::::0;45729:19;;;:10:::2;:19:::0;;;;;;;45769:10;;45661:28;;-1:-1:-1;45729:19:0;-1:-1:-1;;;;;45769:10:0::2;:24:::0;45765:369:::2;;45862:11;::::0;45902:10;;45862:60:::2;::::0;-1:-1:-1;;;45862:60:0;;-1:-1:-1;;;;;45862:11:0;;::::2;::::0;:24:::2;::::0;:60:::2;::::0;45895:4:::2;::::0;45902:10;;::::2;::::0;45914:7;;45862:60:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;46014:10:0;;45986:48:::2;::::0;-1:-1:-1;;;;;;46014:10:0::2;::::0;-1:-1:-1;46026:7:0;45986:27:::2;:48::i;:::-;46099:19;::::0;;;:10:::2;:19;::::0;;;;46092:26;;-1:-1:-1;;;;;;46092:26:0::2;::::0;;;;::::2;::::0;;;::::2;::::0;::::2;::::0;;;::::2;::::0;::::2;::::0;;;::::2;::::0;::::2;::::0;;-1:-1:-1;;46092:26:0::2;::::0;;::::2;;::::0;45765:369:::2;46206:17;:23;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;45565:676;;;45528:713;;;11239:20:::1;10633:1:::0;11759:7;:22;11576:213;23376:315;11195:21;:19;:21::i;:::-;14555:13:::1;:11;:13::i;:::-;23475:1:::2;23466:6;:10;23458:39;;;::::0;-1:-1:-1;;;23458:39:0;;12283:2:1;23458:39:0::2;::::0;::::2;12265:21:1::0;12322:2;12302:18;;;12295:30;-1:-1:-1;;;12341:18:1;;;12334:46;12397:18;;23458:39:0::2;12081:340:1::0;23458:39:0::2;23523:11;::::0;:59:::2;::::0;-1:-1:-1;;;23523:59:0;;23508:12:::2;::::0;-1:-1:-1;;;;;23523:11:0::2;::::0;:24:::2;::::0;:59:::2;::::0;23548:10:::2;::::0;23568:4:::2;::::0;23575:6;;23523:59:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23508:74;;23601:7;23593:39;;;::::0;-1:-1:-1;;;23593:39:0;;12628:2:1;23593:39:0::2;::::0;::::2;12610:21:1::0;12667:2;12647:18;;;12640:30;-1:-1:-1;;;12686:18:1;;;12679:49;12745:18;;23593:39:0::2;12426:343:1::0;23593:39:0::2;23648:35;::::0;160:25:1;;;23664:10:0::2;::::0;23648:35:::2;::::0;148:2:1;133:18;23648:35:0::2;;;;;;;23447:244;11239:20:::0;10633:1;11759:7;:22;11576:213;24727:363;11195:21;:19;:21::i;:::-;20610:9:::1;::::0;;:31:::1;::::0;-1:-1:-1;;;20610:31:0;;20630:10:::1;20610:31:::0;;::::1;963:51:1::0;;;;20644:1:0::1;::::0;-1:-1:-1;;;;;20610:9:0;;::::1;::::0;:19:::1;::::0;936:18:1;;20610:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:35;20588:140;;;;-1:-1:-1::0;;;20588:140:0::1;;;;;;;:::i;:::-;24867:9:::2;24862:221;24882:20:::0;;::::2;24862:221;;;24924:15;24942:9;;24952:1;24942:12;;;;;;;:::i;:::-;;::::0;;::::2;::::0;;;::::2;;24977:19;::::0;;;:10:::2;:19:::0;;;;;;;:25;24942:12;;-1:-1:-1;;;;;;;24977:25:0::2;25006:10;24977:39;24969:62;;;;-1:-1:-1::0;;;24969:62:0::2;;;;;;;:::i;:::-;25046:25;25063:7;25046:16;:25::i;:::-;-1:-1:-1::0;24904:3:0::2;;24862:221;;21634:541:::0;14555:13;:11;:13::i;:::-;21904:14:::1;:32:::0;;;;21947:16:::1;:36:::0;;;;21996:14:::1;:32:::0;;;;22039:16:::1;:36:::0;22088:14:::1;:32:::0;22131:16:::1;:36:::0;21634:541::o;15602:220::-;14555:13;:11;:13::i;:::-;-1:-1:-1;;;;;15687:22:0;::::1;15683:93;;15733:31;::::0;-1:-1:-1;;;15733:31:0;;15761:1:::1;15733:31;::::0;::::1;963:51:1::0;936:18;;15733:31:0::1;802:218:1::0;15683:93:0::1;15786:28;15805:8;15786:18;:28::i;27364:372::-:0;27478:16;27513:24;27554:9;27540:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27540:31:0;;27513:58;;27587:9;27582:122;27602:20;;;27582:122;;;27657:35;27679:9;;27689:1;27679:12;;;;;;;:::i;:::-;;;;;;;27657:21;:35::i;:::-;27644:7;27652:1;27644:10;;;;;;;;:::i;:::-;;;;;;;;;;:48;27624:3;;27582:122;;;-1:-1:-1;27721:7:0;-1:-1:-1;27364:372:0;;;;;:::o;39860:375::-;39959:17;:24;39911:18;;39942:14;39959:24;40022:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;39994:51;;40061:9;40056:148;40080:6;40076:1;:10;40056:148;;;40108:15;40126:17;40144:1;40126:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;40173:19;;;:10;:19;;;;;;;40161:31;;;;;;;;;-1:-1:-1;;;;;40161:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40126:20;;-1:-1:-1;40161:31:0;;40173:19;40161:31;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:6;40168:1;40161:9;;;;;;;;:::i;:::-;;;;;;;;;;:31;-1:-1:-1;40088:3:0;;40056:148;;;-1:-1:-1;40221:6:0;39860:375;-1:-1:-1;;39860:375:0:o;14834:166::-;14742:6;;-1:-1:-1;;;;;14742:6:0;12865:10;14894:23;14890:103;;14941:40;;-1:-1:-1;;;14941:40:0;;12865:10;14941:40;;;963:51:1;936:18;;14941:40:0;802:218:1;11275:293:0;10677:1;11409:7;;:19;11401:63;;;;-1:-1:-1;;;11401:63:0;;12976:2:1;11401:63:0;;;12958:21:1;13015:2;12995:18;;;12988:30;13054:33;13034:18;;;13027:61;13105:18;;11401:63:0;12774:355:1;11401:63:0;10677:1;11542:7;:18;11275:293::o;31230:902::-;31327:22;31352:20;;;:10;:20;;;;;31420:10;;-1:-1:-1;;;;;31420:10:0;31412:47;;;;-1:-1:-1;;;31412:47:0;;13336:2:1;31412:47:0;;;13318:21:1;13375:2;13355:18;;;13348:30;-1:-1:-1;;;13394:18:1;;;13387:40;13444:18;;31412:47:0;13134:334:1;31412:47:0;31557:15;31538;;;;;;:34;;;;;;;;:::i;:::-;;31534:218;;31645:15;;;;31589;;31628:33;;31645:15;;31628:16;:33::i;:::-;31607:4;:18;;;:54;;;;:::i;:::-;31589:72;;31703:7;31684:15;:26;;31676:64;;;;-1:-1:-1;;;31676:64:0;;13675:2:1;31676:64:0;;;13657:21:1;13714:2;13694:18;;;13687:30;-1:-1:-1;;;13733:18:1;;;13726:55;13798:18;;31676:64:0;13473:349:1;31676:64:0;31574:178;31534:218;31843:23;31857:8;31843:13;:23::i;:::-;-1:-1:-1;31904:15:0;;;:32;;31922:14;;31904:15;-1:-1:-1;;31904:32:0;;31922:14;31904:32;;;;;;;;:::i;:::-;;;;;-1:-1:-1;31968:15:0;31947:18;;;:36;;;31994:18;;;:36;32087:10;;32069:55;;-1:-1:-1;;;;;32087:10:0;;;;32069:55;;;;32099:8;;32109:14;;32069:55;:::i;:::-;;;;;;;;31316:816;31230:902;;:::o;33374:3599::-;33433:7;33478:20;;;:10;:20;;;;;33581:18;;;;33533:15;;33657:26;;;33653:67;;-1:-1:-1;33707:1:0;;33374:3599;-1:-1:-1;;;;33374:3599:0:o;33653:67::-;33732:16;33751:25;33765:11;33751;:25;:::i;:::-;33732:44;-1:-1:-1;33787:19:0;;;33874:15;;;;;;:34;;;;;;;;:::i;:::-;;33873:125;;33981:15;;;;33964:33;;33981:15;;33964:16;:33::i;:::-;33943:4;:18;;;:54;;;;:::i;:::-;33873:125;;;33925:1;33873:125;33855:143;-1:-1:-1;34105:15:0;34086;;;;;;:34;;;;;;;;:::i;:::-;;34082:2394;;34188:7;34174:11;:21;34170:1962;;;34252:24;34294:7;34280:11;:21;34279:47;;34319:7;34279:47;;;34305:11;34279:47;34252:74;;34345:18;34386:11;34367:16;:30;34366:111;;34476:1;34366:111;;;34422:30;34441:11;34422:16;:30;:::i;:::-;34345:132;;34498:18;34532:12;;34519:10;:25;;;;:::i;:::-;34603:15;;;;34498:46;;-1:-1:-1;34563:18:0;;34584:35;;34603:15;;34584:18;:35::i;:::-;34563:56;;34776:23;34836:3;34822:10;34803:16;;:29;;;;:::i;:::-;34802:37;;;;:::i;:::-;34904:15;34922:23;;;:13;:23;;;;;;34776:63;;-1:-1:-1;34968:12:0;;;34964:31;;-1:-1:-1;34992:3:0;34964:31;35104:20;35171:3;35142:25;35160:7;35142:15;:25;:::i;:::-;35141:33;;;;:::i;:::-;35127:48;;:10;:48;:::i;:::-;35104:71;-1:-1:-1;35194:27:0;35104:71;35194:27;;:::i;:::-;;;35326:7;35312:11;:21;35308:421;;;35358:20;35381:21;35395:7;35381:11;:21;:::i;:::-;35358:44;;35425:20;35463:12;;35448;:27;;;;:::i;:::-;35425:50;;35577:25;35636:3;35625:7;35606:16;;:26;;;;:::i;:::-;35605:34;;;;:::i;:::-;35577:62;-1:-1:-1;35677:32:0;35577:62;35677:12;:32;:::i;:::-;35662:47;;;;:::i;:::-;;;35335:394;;;35308:421;34197:1547;;;;;;;34082:2394;;34170:1962;35825:17;35856:12;;35845:8;:23;;;;:::i;:::-;35887:15;35905:23;;;:13;:23;;;;;;35825:43;;-1:-1:-1;35951:12:0;;;35947:31;;-1:-1:-1;35975:3:0;35947:31;35999:21;36054:3;36043:7;36024:16;;:26;;;;:::i;:::-;36023:34;;;;:::i;:::-;35999:58;-1:-1:-1;36091:25:0;35999:58;36091:9;:25;:::i;:::-;36076:40;;;;:::i;:::-;;;35750:382;;;34082:2394;;;36205:17;36236:12;;36225:8;:23;;;;:::i;:::-;36263:15;36281:23;;;:13;:23;;;;;;36205:43;;-1:-1:-1;36323:12:0;;;36319:31;;-1:-1:-1;36347:3:0;36319:31;36367:13;36414:3;36403:7;36384:16;;:26;;;;:::i;:::-;36383:34;;;;:::i;:::-;36367:50;-1:-1:-1;36447:17:0;36367:50;36447:9;:17;:::i;:::-;36432:32;;;;:::i;:::-;;;36149:327;;;34082:2394;36519:18;;;:32;;;36613:15;;36609:326;;36667:11;;:36;;-1:-1:-1;;;36667:36:0;;36697:4;36667:36;;;963:51:1;36645:19:0;;-1:-1:-1;;;;;36667:11:0;;:21;;936:18:1;;36667:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36645:58;;36741:11;36726;:26;;36718:75;;;;-1:-1:-1;;;36718:75:0;;14314:2:1;36718:75:0;;;14296:21:1;14353:2;14333:18;;;14326:30;14392:34;14372:18;;;14365:62;-1:-1:-1;;;14443:18:1;;;14436:34;14487:19;;36718:75:0;14112:400:1;36718:75:0;36808:11;;36829:10;;36808:45;;-1:-1:-1;;;36808:45:0;;-1:-1:-1;;;;;36829:10:0;;;36808:45;;;11429:51:1;11496:18;;;11489:34;;;36808:11:0;;;:20;;11402:18:1;;36808:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;36889:10:0;;36875:48;;;14691:25:1;;;14747:2;14732:18;;14725:34;;;-1:-1:-1;;;;;36889:10:0;;;;36875:48;;14664:18:1;36875:48:0;;;;;;;36630:305;36609:326;-1:-1:-1;36954:11:0;33374:3599;-1:-1:-1;;;;;;33374:3599:0:o;29324:784::-;29462:11;;:61;;-1:-1:-1;;;29462:61:0;;-1:-1:-1;;;;;29462:11:0;;;;:24;;:61;;29487:10;;29507:4;;29514:8;;29462:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;29568:22:0;29593:20;;;:10;:20;;;;;29624:23;;-1:-1:-1;;;;;;29624:23:0;29637:10;29624:23;;;;29658:12;;;:23;;;29708:15;29692:13;;;:31;;;29734:18;;;;:36;;;;29781:15;;;:29;;29593:20;;-1:-1:-1;29799:11:0;;29781:15;;-1:-1:-1;;29781:29:0;;;;29799:11;;29781:29;;;;;;;:::i;:::-;;;;;-1:-1:-1;29858:15:0;29843:11;:30;;;;;;;;:::i;:::-;;29842:54;;29881:15;29842:54;;;29877:1;29842:54;29821:18;;;:75;29953:33;29977:8;40915:17;:24;;40883:29;;;;:19;:29;;;;;:56;;;40950:32;;;;;;;;;;;;40812:178;29953:33;30020:10;41605:23;;;;:16;:23;;;;;;;;:30;;41571:31;;;:21;:31;;;;;:64;;;41646:23;;;:38;;;;;;;;;;;;;30059:41;;;;;41571:31;;30088:11;;30059:41;:::i;15982:191::-;16075:6;;;-1:-1:-1;;;;;16092:17:0;;;-1:-1:-1;;;;;;16092:17:0;;;;;;;16125:40;;16075:6;;;16092:17;16075:6;;16125:40;;16056:16;;16125:40;16045:128;15982:191;:::o;43374:570::-;43504:24;;;43569:15;;;;;;:34;;;;;;;;:::i;:::-;;43565:86;;-1:-1:-1;43628:3:0;;43633:5;;-1:-1:-1;43374:570:0;-1:-1:-1;43374:570:0:o;43565:86::-;43697:15;;;;43661:16;;43680:33;;43697:15;;43680:16;:33::i;:::-;43661:52;;43724:15;43763:8;43742:4;:18;;;:29;;;;:::i;:::-;43878:15;;;;43724:47;;-1:-1:-1;43803:15:0;:25;-1:-1:-1;43803:25:0;43782:17;;43859:35;;43878:15;;43859:18;:35::i;:::-;43840:54;43923:12;;-1:-1:-1;43374:570:0;;-1:-1:-1;;;;;43374:570:0:o;32326:801::-;32416:22;32441:20;;;:10;:20;;;;;;32534:15;;;;;;:34;;;;;;;;:::i;:::-;;32526:71;;;;-1:-1:-1;;;32526:71:0;;14972:2:1;32526:71:0;;;14954:21:1;15011:2;14991:18;;;14984:30;15050:26;15030:18;;;15023:54;15094:18;;32526:71:0;14770:348:1;32526:71:0;32700:15;;;;32644;;32683:33;;32700:15;;32683:16;:33::i;:::-;32662:4;:18;;;:54;;;;:::i;:::-;32644:72;;32754:7;32735:15;:26;;32727:64;;;;-1:-1:-1;;;32727:64:0;;13675:2:1;32727:64:0;;;13657:21:1;13714:2;13694:18;;;13687:30;-1:-1:-1;;;13733:18:1;;;13726:55;13798:18;;32727:64:0;13473:349:1;32727:64:0;32844:23;32858:8;32844:13;:23::i;:::-;-1:-1:-1;32920:15:0;;;:32;;32938:14;;32920:15;-1:-1:-1;;32920:32:0;;32938:14;32920:32;;;;;;;;:::i;:::-;;;;;-1:-1:-1;32984:15:0;32963:18;;;:36;;;33010:18;;;:36;33082:10;;33064:55;;-1:-1:-1;;;;;33082:10:0;;;;33064:55;;;;33094:8;;33104:14;;33064:55;:::i;:::-;;;;;;;;32405:722;;32326:801;;:::o;40998:480::-;41074:11;41088:29;;;:19;:29;;;;;;41148:17;:24;41088:29;;41074:11;41148:28;;41175:1;;41148:28;:::i;:::-;41128:48;;41198:9;41191:3;:16;41187:203;;41224:19;41246:17;41264:9;41246:28;;;;;;;;:::i;:::-;;;;;;;;;41224:50;;41314:11;41289:17;41307:3;41289:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;41340:32;;;:19;:32;;;;;:38;;;41187:203;41400:17;:23;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;41400:23:0;;;;;;;;;;;;41441:29;;;:19;:29;;;-1:-1:-1;;41441:29:0;;;41434:36;40998:480::o;41700:526::-;41790:11;41804:31;;;:21;:31;;;;;;;;;-1:-1:-1;;;;;41866:23:0;;;;:16;:23;;;;;:30;41804:31;;41790:11;41866:34;;41899:1;;41866:34;:::i;:::-;41846:54;;41924:9;41917:3;:16;41913:217;;-1:-1:-1;;;;;41972:23:0;;41950:19;41972:23;;;:16;:23;;;;;:34;;41996:9;;41972:34;;;;;;:::i;:::-;;;;;;;;;41950:56;;42052:11;42021:16;:23;42038:5;-1:-1:-1;;;;;42021:23:0;-1:-1:-1;;;;;42021:23:0;;;;;;;;;;;;42045:3;42021:28;;;;;;;;:::i;:::-;;;;;;;;;;;;:42;;;;42078:34;;;:21;:34;;;;;:40;;;41913:217;-1:-1:-1;;;;;42140:23:0;;;;;;:16;:23;;;;;:29;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;42140:29:0;;;;;;;;;;;;42187:31;;;:21;:31;;;-1:-1:-1;;42187:31:0;;;42180:38;-1:-1:-1;41700:526:0:o;30116:808::-;30180:22;30205:20;;;:10;:20;;;;;;30290:15;;;;;;:34;;;;;;;;:::i;:::-;;30286:234;;30397:15;;;;30341;;30380:33;;30397:15;;30380:16;:33::i;:::-;30359:4;:18;;;:54;;;;:::i;:::-;30341:72;;30455:7;30436:15;:26;;30428:80;;;;-1:-1:-1;;;30428:80:0;;15325:2:1;30428:80:0;;;15307:21:1;15364:2;15344:18;;;15337:30;15403:34;15383:18;;;15376:62;-1:-1:-1;;;15454:18:1;;;15447:39;15503:19;;30428:80:0;15123:405:1;30428:80:0;30326:194;30286:234;30572:23;30586:8;30572:13;:23::i;:::-;-1:-1:-1;30638:11:0;;30678:10;;30638:61;;-1:-1:-1;;;30638:61:0;;-1:-1:-1;;;;;30638:11:0;;;;:24;;:61;;30671:4;;30678:10;;;;30690:8;;30638:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30732:38;30761:8;30732:28;:38::i;:::-;30809:10;;30781:49;;-1:-1:-1;;;;;30809:10:0;30821:8;30781:27;:49::i;:::-;30848:20;;;;:10;:20;;;;;;;;30841:27;;-1:-1:-1;;;;;;30841:27:0;;;-1:-1:-1;30841:27:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;30841:27:0;;;;;;;;;30895:10;;30886:30;;160:25:1;;;-1:-1:-1;;;;;30895:10:0;;;;30886:30;;133:18:1;30886:30:0;;;;;;;30169:755;30116:808;:::o;37068:2528::-;37140:7;37185:20;;;:10;:20;;;;;37220:10;;-1:-1:-1;;;;;37220:10:0;37216:38;;-1:-1:-1;37253:1:0;;37068:2528;-1:-1:-1;;37068:2528:0:o;37216:38::-;37351:18;;;;37303:15;;37384:26;;;37380:40;;-1:-1:-1;37419:1:0;;37068:2528;-1:-1:-1;;;;37068:2528:0:o;37380:40::-;37433:16;37452:25;37466:11;37452;:25;:::i;:::-;37433:44;-1:-1:-1;37488:19:0;;;37543:15;;;;;;:34;;;;;;;;:::i;:::-;;37542:125;;37650:15;;;;37633:33;;37650:15;;37633:16;:33::i;:::-;37612:4;:18;;;:54;;;;:::i;:::-;37542:125;;;37594:1;37542:125;37524:143;-1:-1:-1;37703:15:0;37684;;;;;;:34;;;;;;;;:::i;:::-;;37680:1878;;37753:7;37739:11;:21;37735:1496;;;37781:24;37823:7;37809:11;:21;37808:47;;37848:7;37808:47;;;37834:11;37808:47;37781:74;;37874:18;37915:11;37896:16;:30;37895:111;;38005:1;37895:111;;;37951:30;37970:11;37951:16;:30;:::i;:::-;37874:132;;38027:18;38061:12;;38048:10;:25;;;;:::i;:::-;38132:15;;;;38027:46;;-1:-1:-1;38092:18:0;;38113:35;;38132:15;;38113:18;:35::i;:::-;38092:56;;38169:23;38229:3;38215:10;38196:16;;:29;;;;:::i;:::-;38195:37;;;;:::i;:::-;38253:15;38271:23;;;:13;:23;;;;;;38169:63;;-1:-1:-1;38317:12:0;;;38313:31;;-1:-1:-1;38341:3:0;38313:31;38365:20;38432:3;38403:25;38421:7;38403:15;:25;:::i;:::-;38402:33;;;;:::i;:::-;38388:48;;:10;:48;:::i;:::-;38365:71;-1:-1:-1;38455:27:0;38365:71;38455:27;;:::i;:::-;;;38521:7;38507:11;:21;38503:334;;;38553:20;38576:21;38590:7;38576:11;:21;:::i;:::-;38553:44;;38620:20;38658:12;;38643;:27;;;;:::i;:::-;38620:50;;38693:21;38748:3;38737:7;38718:16;;:26;;;;:::i;:::-;38717:34;;;;:::i;:::-;38693:58;-1:-1:-1;38789:28:0;38693:58;38789:12;:28;:::i;:::-;38774:43;;;;:::i;:::-;;;38530:307;;;38503:334;37762:1090;;;;;;;37680:1878;;37735:1496;38924:17;38955:12;;38944:8;:23;;;;:::i;:::-;38986:15;39004:23;;;:13;:23;;;;;;38924:43;;-1:-1:-1;39050:12:0;;;39046:31;;-1:-1:-1;39074:3:0;39046:31;39098:21;39153:3;39142:7;39123:16;;:26;;;;:::i;:::-;39122:34;;;;:::i;:::-;39098:58;-1:-1:-1;39190:25:0;39098:58;39190:9;:25;:::i;:::-;39175:40;;;;:::i;:::-;;;38858:373;;;37680:1878;;;39287:17;39318:12;;39307:8;:23;;;;:::i;:::-;39345:15;39363:23;;;:13;:23;;;;;;39287:43;;-1:-1:-1;39405:12:0;;;39401:31;;-1:-1:-1;39429:3:0;39401:31;39449:13;39496:3;39485:7;39466:16;;:26;;;;:::i;:::-;39465:34;;;;:::i;:::-;39449:50;-1:-1:-1;39529:17:0;39449:50;39529:9;:17;:::i;:::-;39514:32;;;;:::i;:::-;;39577:11;-1:-1:-1;;;;;;;;;;;37068:2528:0:o;42338:369::-;42406:7;42440:17;42430:6;:27;;;;;;;;:::i;:::-;;42426:255;;-1:-1:-1;;42481:14:0;;;42338:369::o;42426:255::-;42527:17;42517:6;:27;;;;;;;;:::i;:::-;;42513:168;;-1:-1:-1;;42568:14:0;;;42338:369::o;42513:168::-;42614:17;42604:6;:27;;;;;;;;:::i;:::-;;42600:81;;-1:-1:-1;;42655:14:0;;;42338:369::o;42600:81::-;-1:-1:-1;42698:1:0;;42338:369;-1:-1:-1;42338:369:0:o;42822:397::-;42892:7;42926:17;42916:6;:27;;;;;;;;:::i;:::-;;42912:261;;-1:-1:-1;;42967:16:0;;;42822:397::o;42912:261::-;43015:17;43005:6;:27;;;;;;;;:::i;:::-;;43001:172;;-1:-1:-1;;43056:16:0;;;42822:397::o;43001:172::-;43104:17;43094:6;:27;;;;;;;;:::i;:::-;;43090:83;;-1:-1:-1;;43145:16:0;;;42822:397::o;43090:83::-;-1:-1:-1;43190:3:0;;42822:397;-1:-1:-1;42822:397:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;196:140:1:-;-1:-1:-1;;;;;280:31:1;;270:42;;260:70;;326:1;323;316:12;341:271;415:6;468:2;456:9;447:7;443:23;439:32;436:52;;;484:1;481;474:12;436:52;523:9;510:23;542:40;576:5;542:40;:::i;:::-;601:5;341:271;-1:-1:-1;;;341:271:1:o;617:180::-;676:6;729:2;717:9;708:7;704:23;700:32;697:52;;;745:1;742;735:12;697:52;-1:-1:-1;768:23:1;;617:180;-1:-1:-1;617:180:1:o;1025:367::-;1088:8;1098:6;1152:3;1145:4;1137:6;1133:17;1129:27;1119:55;;1170:1;1167;1160:12;1119:55;-1:-1:-1;1193:20:1;;1236:18;1225:30;;1222:50;;;1268:1;1265;1258:12;1222:50;1305:4;1297:6;1293:17;1281:29;;1365:3;1358:4;1348:6;1345:1;1341:14;1333:6;1329:27;1325:38;1322:47;1319:67;;;1382:1;1379;1372:12;1319:67;1025:367;;;;;:::o;1397:787::-;1533:6;1541;1549;1557;1610:2;1598:9;1589:7;1585:23;1581:32;1578:52;;;1626:1;1623;1616:12;1578:52;1666:9;1653:23;1695:18;1736:2;1728:6;1725:14;1722:34;;;1752:1;1749;1742:12;1722:34;1791:70;1853:7;1844:6;1833:9;1829:22;1791:70;:::i;:::-;1880:8;;-1:-1:-1;1765:96:1;-1:-1:-1;1968:2:1;1953:18;;1940:32;;-1:-1:-1;1984:16:1;;;1981:36;;;2013:1;2010;2003:12;1981:36;;2052:72;2116:7;2105:8;2094:9;2090:24;2052:72;:::i;:::-;1397:787;;;;-1:-1:-1;2143:8:1;-1:-1:-1;;;;1397:787:1:o;2967:437::-;3053:6;3061;3114:2;3102:9;3093:7;3089:23;3085:32;3082:52;;;3130:1;3127;3120:12;3082:52;3170:9;3157:23;3203:18;3195:6;3192:30;3189:50;;;3235:1;3232;3225:12;3189:50;3274:70;3336:7;3327:6;3316:9;3312:22;3274:70;:::i;:::-;3363:8;;3248:96;;-1:-1:-1;2967:437:1;-1:-1:-1;;;;2967:437:1:o;3670:127::-;3731:10;3726:3;3722:20;3719:1;3712:31;3762:4;3759:1;3752:15;3786:4;3783:1;3776:15;3802:238;3884:1;3877:5;3874:12;3864:143;;3929:10;3924:3;3920:20;3917:1;3910:31;3964:4;3961:1;3954:15;3992:4;3989:1;3982:15;3864:143;4016:18;;3802:238::o;4045:1176::-;4268:2;4320:21;;;4390:13;;4293:18;;;4412:22;;;4239:4;;4268:2;4453;;4471:18;;;;4512:15;;;4239:4;4555:640;4569:6;4566:1;4563:13;4555:640;;;4628:13;;4670:9;;-1:-1:-1;;;;;4666:35:1;4654:48;;4742:11;;;4736:18;4722:12;;;4715:40;4795:11;;;4789:18;4775:12;;;4768:40;4831:4;4875:11;;;4869:18;4855:12;;;4848:40;4911:4;4954:11;;;4948:18;4979:54;5020:12;;;4948:18;4979:54;:::i;:::-;-1:-1:-1;;5056:4:1;5100:11;;;5094:18;5080:12;;;5073:40;5142:4;5133:14;;;;5170:15;;;;4591:1;4584:9;4555:640;;;-1:-1:-1;5212:3:1;;4045:1176;-1:-1:-1;;;;;;;4045:1176:1:o;5501:324::-;5569:6;5577;5630:2;5618:9;5609:7;5605:23;5601:32;5598:52;;;5646:1;5643;5636:12;5598:52;5685:9;5672:23;5704:40;5738:5;5704:40;:::i;:::-;5763:5;5815:2;5800:18;;;;5787:32;;-1:-1:-1;;;5501:324:1:o;6038:593::-;-1:-1:-1;;;;;6355:32:1;;6337:51;;6419:2;6404:18;;6397:34;;;6462:2;6447:18;;6440:34;;;6505:2;6490:18;;6483:34;;;6324:3;6309:19;;6526:55;6576:3;6561:19;;6553:6;6526:55;:::i;:::-;6618:6;6612:3;6601:9;6597:19;6590:35;6038:593;;;;;;;;;:::o;6636:523::-;6740:6;6748;6756;6764;6772;6780;6833:3;6821:9;6812:7;6808:23;6804:33;6801:53;;;6850:1;6847;6840:12;6801:53;-1:-1:-1;;6873:23:1;;;6943:2;6928:18;;6915:32;;-1:-1:-1;6994:2:1;6979:18;;6966:32;;7045:2;7030:18;;7017:32;;-1:-1:-1;7096:3:1;7081:19;;7068:33;;-1:-1:-1;7148:3:1;7133:19;7120:33;;-1:-1:-1;6636:523:1;-1:-1:-1;6636:523:1:o;7386:632::-;7557:2;7609:21;;;7679:13;;7582:18;;;7701:22;;;7528:4;;7557:2;7780:15;;;;7754:2;7739:18;;;7528:4;7823:169;7837:6;7834:1;7831:13;7823:169;;;7898:13;;7886:26;;7967:15;;;;7932:12;;;;7859:1;7852:9;7823:169;;;-1:-1:-1;8009:3:1;;7386:632;-1:-1:-1;;;;;;7386:632:1:o;8023:184::-;8093:6;8146:2;8134:9;8125:7;8121:23;8117:32;8114:52;;;8162:1;8159;8152:12;8114:52;-1:-1:-1;8185:16:1;;8023:184;-1:-1:-1;8023:184:1:o;8212:419::-;8414:2;8396:21;;;8453:2;8433:18;;;8426:30;8492:34;8487:2;8472:18;;8465:62;8563:25;8558:2;8543:18;;8536:53;8621:3;8606:19;;8212:419::o;8636:345::-;8838:2;8820:21;;;8877:2;8857:18;;;8850:30;-1:-1:-1;;;8911:2:1;8896:18;;8889:51;8972:2;8957:18;;8636:345::o;8986:127::-;9047:10;9042:3;9038:20;9035:1;9028:31;9078:4;9075:1;9068:15;9102:4;9099:1;9092:15;9118:334;9320:2;9302:21;;;9359:2;9339:18;;;9332:30;-1:-1:-1;;;9393:2:1;9378:18;;9371:40;9443:2;9428:18;;9118:334::o;9457:270::-;9530:6;9583:2;9571:9;9562:7;9558:23;9554:32;9551:52;;;9599:1;9596;9589:12;9551:52;9638:9;9625:23;9677:1;9670:5;9667:12;9657:40;;9693:1;9690;9683:12;10086:127;10147:10;10142:3;10138:20;10135:1;10128:31;10178:4;10175:1;10168:15;10202:4;10199:1;10192:15;10218:168;10291:9;;;10322;;10339:15;;;10333:22;;10319:37;10309:71;;10360:18;;:::i;10391:217::-;10431:1;10457;10447:132;;10501:10;10496:3;10492:20;10489:1;10482:31;10536:4;10533:1;10526:15;10564:4;10561:1;10554:15;10447:132;-1:-1:-1;10593:9:1;;10391:217::o;10613:125::-;10678:9;;;10699:10;;;10696:36;;;10712:18;;:::i;10743:127::-;10804:10;10799:3;10795:20;10792:1;10785:31;10835:4;10832:1;10825:15;10859:4;10856:1;10849:15;10875:375;-1:-1:-1;;;;;11133:15:1;;;11115:34;;11185:15;;;;11180:2;11165:18;;11158:43;11232:2;11217:18;;11210:34;;;;11065:2;11050:18;;10875:375::o;11534:277::-;11601:6;11654:2;11642:9;11633:7;11629:23;11625:32;11622:52;;;11670:1;11667;11660:12;11622:52;11702:9;11696:16;11755:5;11748:13;11741:21;11734:5;11731:32;11721:60;;11777:1;11774;11767:12;11816:128;11883:9;;;11904:11;;;11901:37;;;11918:18;;:::i;11949:127::-;12010:10;12005:3;12001:20;11998:1;11991:31;12041:4;12038:1;12031:15;12065:4;12062:1;12055:15;13827:280;14013:25;;;14001:2;13986:18;;14047:54;14097:2;14082:18;;14074:6;14047:54;:::i
Swarm Source
ipfs://5b2cb41e8d904a4dd9f6b98c816b4cfebe5f9bd11c2a95eac41e989349e2f03b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.