ETH Price: $3,350.29 (-3.73%)

Token

xEMRLD (xEMRLD)
 

Overview

Max Total Supply

58,674,210.083302617196800721 xEMRLD

Holders

54

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
15,500,000 xEMRLD

Value
$0.00
0x1f43092B9463a851D677ad6B4fC4885BDe4467E3
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
EMRLDStaking

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-06-04
*/

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

/// @title $EMRLD Staking
/// @author Andre Costa @ MyWeb3Startup.com


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

/**
 * @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;
    }
}

// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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);
}

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the ERC may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the ERC. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);
}

contract EMRLDStaking is Ownable, ERC20 {

    /**
     * @dev Struct to represent a staking pool with specific parameters.
     */
    struct StakingPool {
        uint256 apr; // Annual Percentage Rate for the staking pool.
        uint256 minStake; // Minimum staking amount allowed.
        uint256 maxStake; // Maximum staking amount allowed.
        uint256 totalMaxStakeAmount; // Total maximum amount that can be staked in this pool.
        uint256 totalStaked; // Total amount currently staked in this pool.
        uint256 totalStakers; // Total number of stakers in this pool.
        bool active; // Boolean to indicate if the pool is active.
    }
    mapping(uint256 => StakingPool) public stakingPools; // Mapping of staking pool IDs to their respective pools.

    /**
     * @dev Struct to represent a stake made by a user.
     */
    struct Stake {
        uint256 totalStaked;  // Total amount of ETH staked by the user.
        uint256 stakeTimestamp;  // Last timestamp the user's staking data was updated.
        bool isActive; // Boolean to indicate if the stake is currently active.
    }
    mapping(address => mapping(uint256 => Stake)) public stakes;  // Maps user addresses to their staking information.

    mapping(address => uint256) public tokensClaimed; // Mapping of user addresses to the total amount of tokens claimed.

    IERC20Metadata public EMRLD;  // ERC20 token for EMRLD.

    /**
     * @dev Enum to represent the state of the contract.
     */
    enum ContractState { OFF, OPEN }  // States of contract: OFF for not accepting stakes, OPEN for accepting stakes.
    ContractState public contractState = ContractState.OPEN;  // Initial state of the contract.

    /**
     * @dev Event emitted when a new staking pool is created.
     * @param lock The lock period for the staking pool.
     * @param apr The APR for the staking pool.
     * @param minStake The minimum stake amount for the staking pool.
     * @param maxStake The maximum stake amount for the staking pool.
     * @param totalMaxStakeAmount The total maximum stake amount for the staking pool.
     * @param active Whether the staking pool is active.
     */
    event StakingPoolCreated(uint256 lock, uint256 apr, uint256 minStake, uint256 maxStake, uint256 totalMaxStakeAmount, bool active);

    /**
     * @dev Event emitted when a user stakes tokens.
     * @param user The address of the user.
     * @param lock The ID of the staking pool.
     * @param amount The amount of tokens staked.
     */
    event Staked(address indexed user, uint256 indexed lock, uint256 amount);

    /**
     * @dev Event emitted when a user unstakes tokens.
     * @param user The address of the user.
     * @param lock The ID of the staking pool.
     * @param amount The amount of tokens unstaked.
     * @param rewards The amount of rewards earned.
     */
    event Unstaked(address indexed user, uint256 indexed lock, uint256 amount, uint256 rewards);

    /**
     * @dev Event emitted when a user restakes tokens.
     * @param user The address of the user.
     * @param lock The ID of the staking pool.
     * @param amount The amount of tokens restaked.
     * @param rewards The amount of rewards earned.
     */
    event Restaked(address indexed user, uint256 indexed lock, uint256 amount, uint256 rewards);

    /**
     * @dev Constructor to set the name and symbol for the staked tokens.
     */
    constructor() ERC20("xEMRLD", "xEMRLD") {
        EMRLD = IERC20Metadata(0xeBB1AFb0A4ddC9b1f84D9Aa72FF956cD1c1Eb4be);
    }

    /**
     * @dev Modifier to check the contract's current state before proceeding.
     * @param requiredState The state that the contract must be in.
     */
    modifier isContractState(ContractState requiredState) {
        require(contractState == requiredState, "Contract is not in the required state");
        _;
    }

    /**
     * @dev Function to stake tokens in a specific pool.
     * @param lock The ID of the staking pool.
     * @param amount The amount of tokens to stake.
     */
    function stake(uint256 lock, uint256 amount) external isContractState(ContractState.OPEN) {
        StakingPool storage pool = stakingPools[lock];
        Stake storage userStake = stakes[msg.sender][lock];

        require(pool.active, "Staking pool is not active");
        require(amount + stakes[msg.sender][lock].totalStaked >= pool.minStake, "Amount is less than minimum stake");
        require(amount + stakes[msg.sender][lock].totalStaked <= pool.maxStake, "Amount exceeds maximum stake");
        require(pool.totalStaked + amount <= pool.totalMaxStakeAmount, "Exceeds total maximum stake amount");
        require(!userStake.isActive, "User already has an active stake in this pool");

        EMRLD.transferFrom(msg.sender, address(this), amount);

        userStake.totalStaked = amount;
        userStake.stakeTimestamp = block.timestamp;
        userStake.isActive = true;

        pool.totalStaked += amount;
        pool.totalStakers++;

        _mint(msg.sender, amount);

        emit Staked(msg.sender, lock, amount);
    }

    /**
     * @dev Function to unstake tokens from a specific pool.
     * @param lock The ID of the staking pool.
     */
    function unstake(uint256 lock) external isContractState(ContractState.OPEN) {
        Stake storage userStake = stakes[msg.sender][lock];
        require(userStake.isActive, "No active stake found");
        
        StakingPool storage pool = stakingPools[lock];
        require(block.timestamp >= userStake.stakeTimestamp + lock * 86400, "Lock period has not passed");

        uint256 amountStaked = userStake.totalStaked;
        uint256 rewards = calculateReward(msg.sender, lock);
        tokensClaimed[msg.sender] += rewards;

        // Transfer the staked amount and rewards back to the user
        // EMRLD.transfer(msg.sender, rewards);
        EMRLD.transfer(msg.sender, amountStaked);

        // Update the user's stake and the pool's totals
        userStake.isActive = false;
        pool.totalStaked -= amountStaked;
        pool.totalStakers -= 1;

        _burn(msg.sender, amountStaked);

        emit Unstaked(msg.sender, lock, amountStaked, rewards);
    }

    /**
     * @dev Function to restake tokens and rewards in a specific pool.
     * @param lock The ID of the staking pool.
     */
    function restake(uint256 lock) external isContractState(ContractState.OPEN) {
        Stake storage userStake = stakes[msg.sender][lock];
        require(userStake.isActive, "No active stake found");

        StakingPool storage pool = stakingPools[lock];
        require(block.timestamp >= userStake.stakeTimestamp + lock * 86400, "Lock period has not passed");

        uint256 amountStaked = userStake.totalStaked;
        uint256 rewards = calculateReward(msg.sender, lock);

        // Ensure the total amount to be restaked doesn't exceed pool's maximum limits
        uint256 totalToRestake = amountStaked + rewards;
        require(totalToRestake >= pool.minStake, "Restake amount is less than minimum stake");
        require(totalToRestake <= pool.maxStake, "Restake amount exceeds maximum stake");
        require(pool.totalStaked + rewards <= pool.totalMaxStakeAmount, "Exceeds total maximum stake amount");

        // Update user's stake
        userStake.totalStaked = totalToRestake;
        userStake.stakeTimestamp = block.timestamp;

        // Update the pool's total staked amount (adding only rewards, as the initial staked amount is already included)
        pool.totalStaked += rewards;

        _mint(msg.sender, rewards);

        emit Restaked(msg.sender, lock, amountStaked, rewards);
    }

    /**
     * @dev Emergency function for the owner to unstake tokens for a user.
     * @param user The address of the user.
     * @param lock The ID of the staking pool.
     */
    function emergencyUnstake(address user, uint256 lock) external onlyOwner {
        Stake storage userStake = stakes[user][lock];
        require(userStake.isActive, "No active stake found");

        StakingPool storage pool = stakingPools[lock];

        uint256 amountStaked = userStake.totalStaked;

        uint256 rewards;
        if (block.timestamp >= userStake.stakeTimestamp + lock * 86400) {
            rewards = calculateReward(msg.sender, lock);
            tokensClaimed[user] += rewards;
        }

        // Transfer the staked amount and rewards back to the user
        // EMRLD.transfer(msg.sender, rewards);
        EMRLD.transfer(msg.sender, amountStaked);

        // Update the user's stake and the pool's totals
        userStake.isActive = false;
        pool.totalStaked -= amountStaked;
        pool.totalStakers -= 1;

        _burn(user, amountStaked);

        emit Unstaked(user, lock, amountStaked, rewards);
    }

    /**
     * @dev Calculates the total rewards earned by a staker based on the staked amounts and time elapsed.
     * @param staker The address of the staker.
     * @param lock The ID of the staking pool.
     * @return The total rewards earned.
     */
    function calculateReward(address staker, uint256 lock) public view returns (uint256) {
        uint256 timeStaked = block.timestamp - stakes[staker][lock].stakeTimestamp;
        return (((stakes[staker][lock].totalStaked * stakingPools[lock].apr) / 10000) * timeStaked) / (365 days);
    }

    ///
    /// SETTERS
    ///

    /**
     * @dev Function to set up a staking pool.
     * @param lock The lock period for the staking pool.
     * @param apr The APR for the staking pool.
     * @param minStake The minimum stake amount.
     * @param maxStake The maximum stake amount.
     * @param totalMaxStakeAmount The total maximum amount that can be staked in the pool.
     * @param active Boolean indicating if the pool is active.
     */
    function setStakingPool(
        uint256 lock,
        uint256 apr,
        uint256 minStake,
        uint256 maxStake,
        uint256 totalMaxStakeAmount,
        bool active
    ) public onlyOwner {
        require(apr > 0 && apr <= 10000, "APR must be between 1 and 100");
        require(minStake > 0, "Minimum stake must be greater than 0");
        require(maxStake >= minStake, "Maximum stake must be greater than or equal to minimum stake");
        require(totalMaxStakeAmount >= maxStake, "Total maximum stake amount must be greater than or equal to maximum stake");

        StakingPool storage pool = stakingPools[lock];
        pool.apr = apr;
        pool.minStake = minStake;
        pool.maxStake = maxStake;
        pool.totalMaxStakeAmount = totalMaxStakeAmount;
        pool.active = active;

        emit StakingPoolCreated(lock, apr, minStake, maxStake, totalMaxStakeAmount, active);
    }

    /**
     * @dev Sets the contract's operational state.
     * @param newState The new state to set the contract to (0 for OFF, 1 for OPEN).
     */
    function setContractState(uint256 newState) external onlyOwner {
        require(newState < 2, "Invalid State!");
        contractState = ContractState(newState);
    }

    /**
     * @dev Sets the USDB ERC20 token contract.
     * @param _EMRLD The address of the EMRLD ERC20 token contract.
     */
    function setEMRLD(address _EMRLD) external onlyOwner {
        EMRLD = IERC20Metadata(_EMRLD);
    }

    ///
    /// MISC
    ///
    
    /**
     * @notice Withdraws Ether from the contract.
     * @param recipient The address to receive the Ether.
     * @param amount The amount of Ether to withdraw.
     */
    function withdrawEther(address recipient, uint256 amount) external onlyOwner {
        require(recipient != address(0), "Invalid Address!");
        require(amount > 0 && address(this).balance >= amount, "Invalid Amount!");

        (bool sent, ) = recipient.call{value: amount}("");
        require(sent, "Failed to send Ether");
    }

    /**
     * @notice Withdraws ERC20 tokens from the contract.
     * @param recipient The address to receive the tokens.
     * @param amount The amount of tokens to withdraw.
     * @param token The address of the token contract.
     */
    function withdrawToken(address recipient, uint256 amount, address token) external onlyOwner {
        require(recipient != address(0), "Invalid Address!");
        require(amount > 0, "Invalid Amount!");
        require(token != address(0), "Invalid Token!");

        require(IERC20(token).transfer(recipient, amount), "Unsuccessful Transfer!");
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","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":true,"internalType":"uint256","name":"lock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"Restaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"lock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"apr","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minStake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxStake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMaxStakeAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"StakingPoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"lock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"EMRLD","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint256","name":"lock","type":"uint256"}],"name":"calculateReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractState","outputs":[{"internalType":"enum EMRLDStaking.ContractState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"lock","type":"uint256"}],"name":"emergencyUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lock","type":"uint256"}],"name":"restake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newState","type":"uint256"}],"name":"setContractState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_EMRLD","type":"address"}],"name":"setEMRLD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lock","type":"uint256"},{"internalType":"uint256","name":"apr","type":"uint256"},{"internalType":"uint256","name":"minStake","type":"uint256"},{"internalType":"uint256","name":"maxStake","type":"uint256"},{"internalType":"uint256","name":"totalMaxStakeAmount","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setStakingPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lock","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakes","outputs":[{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"stakeTimestamp","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakingPools","outputs":[{"internalType":"uint256","name":"apr","type":"uint256"},{"internalType":"uint256","name":"minStake","type":"uint256"},{"internalType":"uint256","name":"maxStake","type":"uint256"},{"internalType":"uint256","name":"totalMaxStakeAmount","type":"uint256"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"totalStakers","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokensClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lock","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526009805460ff60a01b1916600160a01b17905534801562000023575f80fd5b50604051806040016040528060068152602001651e115354931160d21b815250604051806040016040528060068152602001651e115354931160d21b8152506200007c62000076620000c860201b60201c565b620000cc565b60046200008a8382620001bb565b506005620000998282620001bb565b5050600980546001600160a01b03191673ebb1afb0a4ddc9b1f84d9aa72ff956cd1c1eb4be1790555062000283565b3390565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200014457607f821691505b6020821081036200016357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620001b6575f81815260208120601f850160051c81016020861015620001915750805b601f850160051c820191505b81811015620001b2578281556001016200019d565b5050505b505050565b81516001600160401b03811115620001d757620001d76200011b565b620001ef81620001e884546200012f565b8462000169565b602080601f83116001811462000225575f84156200020d5750858301515b5f19600386901b1c1916600185901b178555620001b2565b5f85815260208120601f198616915b82811015620002555788860151825594840194600190910190840162000234565b50858210156200027357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b611e4d80620002915f395ff3fe608060405234801561000f575f80fd5b50600436106101a1575f3560e01c8063624601b6116100f357806395d89b4111610093578063ca3c782c1161006e578063ca3c782c14610458578063dd62ed3e1461046b578063f2fde38b146104a3578063fb7265ff146104b6575f80fd5b806395d89b411461042a578063a9059cbb14610432578063bce1b52014610445575f80fd5b806372706a8c116100ce57806372706a8c146103bb5780637b0472f0146103e657806385209ee0146103f95780638da5cb5b1461041a575f80fd5b8063624601b61461036c57806370a082311461038b578063715018a6146103b3575f80fd5b8063313ce5671161015e578063522f681511610139578063522f6815146102685780635733c7861461027b578063584b62a11461028e5780635aad6cf0146102e7575f80fd5b8063313ce567146102335780633ccdbb28146102425780634268121e14610255575f80fd5b806306fdde03146101a5578063095ea7b3146101c357806318160ddd146101e65780631852e8d9146101f857806323b872dd1461020b5780632e17de781461021e575b5f80fd5b6101ad6104c9565b6040516101ba9190611a66565b60405180910390f35b6101d66101d1366004611acc565b610559565b60405190151581526020016101ba565b6003545b6040519081526020016101ba565b6101ea610206366004611acc565b610572565b6101d6610219366004611af4565b610611565b61023161022c366004611b2d565b610634565b005b604051601281526020016101ba565b610231610250366004611b44565b61086b565b610231610263366004611acc565b6109fe565b610231610276366004611acc565b610bbe565b610231610289366004611b7d565b610cf2565b6102ca61029c366004611acc565b600760209081525f928352604080842090915290825290208054600182015460029092015490919060ff1683565b6040805193845260208401929092521515908201526060016101ba565b6103356102f5366004611b2d565b600660208190525f918252604090912080546001820154600283015460038401546004850154600586015495909601549395929491939092919060ff1687565b604080519788526020880196909652948601939093526060850191909152608084015260a0830152151560c082015260e0016101ba565b6101ea61037a366004611b7d565b60086020525f908152604090205481565b6101ea610399366004611b7d565b6001600160a01b03165f9081526001602052604090205490565b610231610d1c565b6009546103ce906001600160a01b031681565b6040516001600160a01b0390911681526020016101ba565b6102316103f4366004611b9d565b610d2f565b60095461040d90600160a01b900460ff1681565b6040516101ba9190611bd1565b5f546001600160a01b03166103ce565b6101ad611087565b6101d6610440366004611acc565b611096565b610231610453366004611b2d565b6110a3565b610231610466366004611c04565b611320565b6101ea610479366004611c55565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205490565b6102316104b1366004611b7d565b611577565b6102316104c4366004611b2d565b6115f0565b6060600480546104d890611c86565b80601f016020809104026020016040519081016040528092919081815260200182805461050490611c86565b801561054f5780601f106105265761010080835404028352916020019161054f565b820191905f5260205f20905b81548152906001019060200180831161053257829003601f168201915b5050505050905090565b5f33610566818585611675565b60019150505b92915050565b6001600160a01b0382165f90815260076020908152604080832084845290915281206001015481906105a49042611cd2565b5f848152600660209081526040808320546001600160a01b038916845260078352818420888552909252909120549192506301e13380918391612710916105eb9190611ce5565b6105f59190611cfc565b6105ff9190611ce5565b6106099190611cfc565b949350505050565b5f3361061e858285611682565b6106298585856116fd565b506001949350505050565b600180600954600160a01b900460ff16600181111561065557610655611bbd565b1461067b5760405162461bcd60e51b815260040161067290611d1b565b60405180910390fd5b335f9081526007602090815260408083208584529091529020600281015460ff166106b85760405162461bcd60e51b815260040161067290611d60565b5f8381526006602052604090206106d28462015180611ce5565b82600101546106e19190611d8f565b4210156107305760405162461bcd60e51b815260206004820152601a60248201527f4c6f636b20706572696f6420686173206e6f74207061737365640000000000006044820152606401610672565b81545f61073d3387610572565b335f90815260086020526040812080549293508392909190610760908490611d8f565b909155505060095460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303815f875af11580156107b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d79190611da2565b5060028401805460ff191690556004830180548391905f906107fa908490611cd2565b925050819055506001836005015f8282546108159190611cd2565b909155506108259050338361175a565b6040805183815260208101839052879133917f204fccf0d92ed8d48f204adb39b2e81e92bad0dedb93f5716ca9478cfb57de0091015b60405180910390a3505050505050565b610873611792565b6001600160a01b0383166108bc5760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420416464726573732160801b6044820152606401610672565b5f82116108fd5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420416d6f756e742160881b6044820152606401610672565b6001600160a01b0381166109445760405162461bcd60e51b815260206004820152600e60248201526d496e76616c696420546f6b656e2160901b6044820152606401610672565b60405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905282169063a9059cbb906044016020604051808303815f875af1158015610990573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b49190611da2565b6109f95760405162461bcd60e51b8152602060048201526016602482015275556e7375636365737366756c205472616e736665722160501b6044820152606401610672565b505050565b610a06611792565b6001600160a01b0382165f9081526007602090815260408083208484529091529020600281015460ff16610a4c5760405162461bcd60e51b815260040161067290611d60565b5f82815260066020526040812082549091610a6a8562015180611ce5565b8460010154610a799190611d8f565b4210610abb57610a893386610572565b6001600160a01b0387165f90815260086020526040812080549293508392909190610ab5908490611d8f565b90915550505b60095460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015610b09573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2d9190611da2565b5060028401805460ff191690556004830180548391905f90610b50908490611cd2565b925050819055506001836005015f828254610b6b9190611cd2565b90915550610b7b9050868361175a565b604080518381526020810183905286916001600160a01b038916917f204fccf0d92ed8d48f204adb39b2e81e92bad0dedb93f5716ca9478cfb57de00910161085b565b610bc6611792565b6001600160a01b038216610c0f5760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420416464726573732160801b6044820152606401610672565b5f81118015610c1e5750804710155b610c5c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420416d6f756e742160881b6044820152606401610672565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610ca5576040519150601f19603f3d011682016040523d82523d5f602084013e610caa565b606091505b50509050806109f95760405162461bcd60e51b81526020600482015260146024820152732330b4b632b2103a379039b2b7321022ba3432b960611b6044820152606401610672565b610cfa611792565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b610d24611792565b610d2d5f6117eb565b565b600180600954600160a01b900460ff166001811115610d5057610d50611bbd565b14610d6d5760405162461bcd60e51b815260040161067290611d1b565b5f838152600660208181526040808420338552600783528185208886529092529092209082015460ff16610de35760405162461bcd60e51b815260206004820152601a60248201527f5374616b696e6720706f6f6c206973206e6f74206163746976650000000000006044820152606401610672565b6001820154335f908152600760209081526040808320898452909152902054610e0c9086611d8f565b1015610e645760405162461bcd60e51b815260206004820152602160248201527f416d6f756e74206973206c657373207468616e206d696e696d756d207374616b6044820152606560f81b6064820152608401610672565b6002820154335f908152600760209081526040808320898452909152902054610e8d9086611d8f565b1115610edb5760405162461bcd60e51b815260206004820152601c60248201527f416d6f756e742065786365656473206d6178696d756d207374616b65000000006044820152606401610672565b8160030154848360040154610ef09190611d8f565b1115610f0e5760405162461bcd60e51b815260040161067290611dbd565b600281015460ff1615610f795760405162461bcd60e51b815260206004820152602d60248201527f5573657220616c72656164792068617320616e20616374697665207374616b6560448201526c081a5b881d1a1a5cc81c1bdbdb609a1b6064820152608401610672565b6009546040516323b872dd60e01b8152336004820152306024820152604481018690526001600160a01b03909116906323b872dd906064016020604051808303815f875af1158015610fcd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ff19190611da2565b508381554260018083019190915560028201805460ff191690911790556004820180548591905f90611024908490611d8f565b9091555050600582018054905f61103a83611dff565b9190505550611049338561183a565b604051848152859033907f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909060200160405180910390a35050505050565b6060600580546104d890611c86565b5f336105668185856116fd565b600180600954600160a01b900460ff1660018111156110c4576110c4611bbd565b146110e15760405162461bcd60e51b815260040161067290611d1b565b335f9081526007602090815260408083208584529091529020600281015460ff1661111e5760405162461bcd60e51b815260040161067290611d60565b5f8381526006602052604090206111388462015180611ce5565b82600101546111479190611d8f565b4210156111965760405162461bcd60e51b815260206004820152601a60248201527f4c6f636b20706572696f6420686173206e6f74207061737365640000000000006044820152606401610672565b81545f6111a33387610572565b90505f6111b08284611d8f565b905083600101548110156112185760405162461bcd60e51b815260206004820152602960248201527f52657374616b6520616d6f756e74206973206c657373207468616e206d696e696044820152686d756d207374616b6560b81b6064820152608401610672565b83600201548111156112785760405162461bcd60e51b8152602060048201526024808201527f52657374616b6520616d6f756e742065786365656473206d6178696d756d207360448201526374616b6560e01b6064820152608401610672565b836003015482856004015461128d9190611d8f565b11156112ab5760405162461bcd60e51b815260040161067290611dbd565b8085554260018601556004840180548391905f906112ca908490611d8f565b909155506112da9050338361183a565b6040805184815260208101849052889133917f63acdca311ce77b458c1dde8cdea3e282508af05da37a4f52a915b7784c37c48910160405180910390a350505050505050565b611328611792565b5f8511801561133957506127108511155b6113855760405162461bcd60e51b815260206004820152601d60248201527f415052206d757374206265206265747765656e203120616e64203130300000006044820152606401610672565b5f84116113e05760405162461bcd60e51b8152602060048201526024808201527f4d696e696d756d207374616b65206d75737420626520677265617465722074686044820152630616e20360e41b6064820152608401610672565b838310156114565760405162461bcd60e51b815260206004820152603c60248201527f4d6178696d756d207374616b65206d757374206265206772656174657220746860448201527f616e206f7220657175616c20746f206d696e696d756d207374616b65000000006064820152608401610672565b828210156114de5760405162461bcd60e51b815260206004820152604960248201527f546f74616c206d6178696d756d207374616b6520616d6f756e74206d7573742060448201527f62652067726561746572207468616e206f7220657175616c20746f206d6178696064820152686d756d207374616b6560b81b608482015260a401610672565b5f86815260066020818152604092839020888155600181018890556002810187905560038101869055918201805460ff191685151590811790915583518a8152918201899052928101879052606081018690526080810185905260a0810192909252907f497768b3d65a26bbe0117804b6c1f7dbfd9bfd4e4a4d9af2aec5f9f64b2681019060c00160405180910390a150505050505050565b61157f611792565b6001600160a01b0381166115e45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610672565b6115ed816117eb565b50565b6115f8611792565b600281106116395760405162461bcd60e51b815260206004820152600e60248201526d496e76616c69642053746174652160901b6044820152606401610672565b80600181111561164b5761164b611bbd565b6009805460ff60a01b1916600160a01b83600181111561166d5761166d611bbd565b021790555050565b6109f9838383600161186e565b6001600160a01b038381165f908152600260209081526040808320938616835292905220545f1981146116f757818110156116e957604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610672565b6116f784848484035f61186e565b50505050565b6001600160a01b03831661172657604051634b637e8f60e11b81525f6004820152602401610672565b6001600160a01b03821661174f5760405163ec442f0560e01b81525f6004820152602401610672565b6109f9838383611940565b6001600160a01b03821661178357604051634b637e8f60e11b81525f6004820152602401610672565b61178e825f83611940565b5050565b5f546001600160a01b03163314610d2d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610672565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382166118635760405163ec442f0560e01b81525f6004820152602401610672565b61178e5f8383611940565b6001600160a01b0384166118975760405163e602df0560e01b81525f6004820152602401610672565b6001600160a01b0383166118c057604051634a1406b160e11b81525f6004820152602401610672565b6001600160a01b038085165f90815260026020908152604080832093871683529290522082905580156116f757826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161193291815260200190565b60405180910390a350505050565b6001600160a01b03831661196a578060035f82825461195f9190611d8f565b909155506119da9050565b6001600160a01b0383165f90815260016020526040902054818110156119bc5760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610672565b6001600160a01b0384165f9081526001602052604090209082900390555b6001600160a01b0382166119f657600380548290039055611a14565b6001600160a01b0382165f9081526001602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611a5991815260200190565b60405180910390a3505050565b5f6020808352835180828501525f5b81811015611a9157858101830151858201604001528201611a75565b505f604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114611ac7575f80fd5b919050565b5f8060408385031215611add575f80fd5b611ae683611ab1565b946020939093013593505050565b5f805f60608486031215611b06575f80fd5b611b0f84611ab1565b9250611b1d60208501611ab1565b9150604084013590509250925092565b5f60208284031215611b3d575f80fd5b5035919050565b5f805f60608486031215611b56575f80fd5b611b5f84611ab1565b925060208401359150611b7460408501611ab1565b90509250925092565b5f60208284031215611b8d575f80fd5b611b9682611ab1565b9392505050565b5f8060408385031215611bae575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310611bf157634e487b7160e01b5f52602160045260245ffd5b91905290565b80151581146115ed575f80fd5b5f805f805f8060c08789031215611c19575f80fd5b863595506020870135945060408701359350606087013592506080870135915060a0870135611c4781611bf7565b809150509295509295509295565b5f8060408385031215611c66575f80fd5b611c6f83611ab1565b9150611c7d60208401611ab1565b90509250929050565b600181811c90821680611c9a57607f821691505b602082108103611cb857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561056c5761056c611cbe565b808202811582820484141761056c5761056c611cbe565b5f82611d1657634e487b7160e01b5f52601260045260245ffd5b500490565b60208082526025908201527f436f6e7472616374206973206e6f7420696e2074686520726571756972656420604082015264737461746560d81b606082015260800190565b602080825260159082015274139bc81858dd1a5d99481cdd185ad948199bdd5b99605a1b604082015260600190565b8082018082111561056c5761056c611cbe565b5f60208284031215611db2575f80fd5b8151611b9681611bf7565b60208082526022908201527f4578636565647320746f74616c206d6178696d756d207374616b6520616d6f756040820152611b9d60f21b606082015260800190565b5f60018201611e1057611e10611cbe565b506001019056fea2646970667358221220cbf9715f334991d3b8316512d9b2bdb409ab5f70d96d682737399fc6ee0e7a2764736f6c63430008140033

Deployed Bytecode

0x608060405234801561000f575f80fd5b50600436106101a1575f3560e01c8063624601b6116100f357806395d89b4111610093578063ca3c782c1161006e578063ca3c782c14610458578063dd62ed3e1461046b578063f2fde38b146104a3578063fb7265ff146104b6575f80fd5b806395d89b411461042a578063a9059cbb14610432578063bce1b52014610445575f80fd5b806372706a8c116100ce57806372706a8c146103bb5780637b0472f0146103e657806385209ee0146103f95780638da5cb5b1461041a575f80fd5b8063624601b61461036c57806370a082311461038b578063715018a6146103b3575f80fd5b8063313ce5671161015e578063522f681511610139578063522f6815146102685780635733c7861461027b578063584b62a11461028e5780635aad6cf0146102e7575f80fd5b8063313ce567146102335780633ccdbb28146102425780634268121e14610255575f80fd5b806306fdde03146101a5578063095ea7b3146101c357806318160ddd146101e65780631852e8d9146101f857806323b872dd1461020b5780632e17de781461021e575b5f80fd5b6101ad6104c9565b6040516101ba9190611a66565b60405180910390f35b6101d66101d1366004611acc565b610559565b60405190151581526020016101ba565b6003545b6040519081526020016101ba565b6101ea610206366004611acc565b610572565b6101d6610219366004611af4565b610611565b61023161022c366004611b2d565b610634565b005b604051601281526020016101ba565b610231610250366004611b44565b61086b565b610231610263366004611acc565b6109fe565b610231610276366004611acc565b610bbe565b610231610289366004611b7d565b610cf2565b6102ca61029c366004611acc565b600760209081525f928352604080842090915290825290208054600182015460029092015490919060ff1683565b6040805193845260208401929092521515908201526060016101ba565b6103356102f5366004611b2d565b600660208190525f918252604090912080546001820154600283015460038401546004850154600586015495909601549395929491939092919060ff1687565b604080519788526020880196909652948601939093526060850191909152608084015260a0830152151560c082015260e0016101ba565b6101ea61037a366004611b7d565b60086020525f908152604090205481565b6101ea610399366004611b7d565b6001600160a01b03165f9081526001602052604090205490565b610231610d1c565b6009546103ce906001600160a01b031681565b6040516001600160a01b0390911681526020016101ba565b6102316103f4366004611b9d565b610d2f565b60095461040d90600160a01b900460ff1681565b6040516101ba9190611bd1565b5f546001600160a01b03166103ce565b6101ad611087565b6101d6610440366004611acc565b611096565b610231610453366004611b2d565b6110a3565b610231610466366004611c04565b611320565b6101ea610479366004611c55565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205490565b6102316104b1366004611b7d565b611577565b6102316104c4366004611b2d565b6115f0565b6060600480546104d890611c86565b80601f016020809104026020016040519081016040528092919081815260200182805461050490611c86565b801561054f5780601f106105265761010080835404028352916020019161054f565b820191905f5260205f20905b81548152906001019060200180831161053257829003601f168201915b5050505050905090565b5f33610566818585611675565b60019150505b92915050565b6001600160a01b0382165f90815260076020908152604080832084845290915281206001015481906105a49042611cd2565b5f848152600660209081526040808320546001600160a01b038916845260078352818420888552909252909120549192506301e13380918391612710916105eb9190611ce5565b6105f59190611cfc565b6105ff9190611ce5565b6106099190611cfc565b949350505050565b5f3361061e858285611682565b6106298585856116fd565b506001949350505050565b600180600954600160a01b900460ff16600181111561065557610655611bbd565b1461067b5760405162461bcd60e51b815260040161067290611d1b565b60405180910390fd5b335f9081526007602090815260408083208584529091529020600281015460ff166106b85760405162461bcd60e51b815260040161067290611d60565b5f8381526006602052604090206106d28462015180611ce5565b82600101546106e19190611d8f565b4210156107305760405162461bcd60e51b815260206004820152601a60248201527f4c6f636b20706572696f6420686173206e6f74207061737365640000000000006044820152606401610672565b81545f61073d3387610572565b335f90815260086020526040812080549293508392909190610760908490611d8f565b909155505060095460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303815f875af11580156107b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d79190611da2565b5060028401805460ff191690556004830180548391905f906107fa908490611cd2565b925050819055506001836005015f8282546108159190611cd2565b909155506108259050338361175a565b6040805183815260208101839052879133917f204fccf0d92ed8d48f204adb39b2e81e92bad0dedb93f5716ca9478cfb57de0091015b60405180910390a3505050505050565b610873611792565b6001600160a01b0383166108bc5760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420416464726573732160801b6044820152606401610672565b5f82116108fd5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420416d6f756e742160881b6044820152606401610672565b6001600160a01b0381166109445760405162461bcd60e51b815260206004820152600e60248201526d496e76616c696420546f6b656e2160901b6044820152606401610672565b60405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905282169063a9059cbb906044016020604051808303815f875af1158015610990573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b49190611da2565b6109f95760405162461bcd60e51b8152602060048201526016602482015275556e7375636365737366756c205472616e736665722160501b6044820152606401610672565b505050565b610a06611792565b6001600160a01b0382165f9081526007602090815260408083208484529091529020600281015460ff16610a4c5760405162461bcd60e51b815260040161067290611d60565b5f82815260066020526040812082549091610a6a8562015180611ce5565b8460010154610a799190611d8f565b4210610abb57610a893386610572565b6001600160a01b0387165f90815260086020526040812080549293508392909190610ab5908490611d8f565b90915550505b60095460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015610b09573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2d9190611da2565b5060028401805460ff191690556004830180548391905f90610b50908490611cd2565b925050819055506001836005015f828254610b6b9190611cd2565b90915550610b7b9050868361175a565b604080518381526020810183905286916001600160a01b038916917f204fccf0d92ed8d48f204adb39b2e81e92bad0dedb93f5716ca9478cfb57de00910161085b565b610bc6611792565b6001600160a01b038216610c0f5760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420416464726573732160801b6044820152606401610672565b5f81118015610c1e5750804710155b610c5c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420416d6f756e742160881b6044820152606401610672565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610ca5576040519150601f19603f3d011682016040523d82523d5f602084013e610caa565b606091505b50509050806109f95760405162461bcd60e51b81526020600482015260146024820152732330b4b632b2103a379039b2b7321022ba3432b960611b6044820152606401610672565b610cfa611792565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b610d24611792565b610d2d5f6117eb565b565b600180600954600160a01b900460ff166001811115610d5057610d50611bbd565b14610d6d5760405162461bcd60e51b815260040161067290611d1b565b5f838152600660208181526040808420338552600783528185208886529092529092209082015460ff16610de35760405162461bcd60e51b815260206004820152601a60248201527f5374616b696e6720706f6f6c206973206e6f74206163746976650000000000006044820152606401610672565b6001820154335f908152600760209081526040808320898452909152902054610e0c9086611d8f565b1015610e645760405162461bcd60e51b815260206004820152602160248201527f416d6f756e74206973206c657373207468616e206d696e696d756d207374616b6044820152606560f81b6064820152608401610672565b6002820154335f908152600760209081526040808320898452909152902054610e8d9086611d8f565b1115610edb5760405162461bcd60e51b815260206004820152601c60248201527f416d6f756e742065786365656473206d6178696d756d207374616b65000000006044820152606401610672565b8160030154848360040154610ef09190611d8f565b1115610f0e5760405162461bcd60e51b815260040161067290611dbd565b600281015460ff1615610f795760405162461bcd60e51b815260206004820152602d60248201527f5573657220616c72656164792068617320616e20616374697665207374616b6560448201526c081a5b881d1a1a5cc81c1bdbdb609a1b6064820152608401610672565b6009546040516323b872dd60e01b8152336004820152306024820152604481018690526001600160a01b03909116906323b872dd906064016020604051808303815f875af1158015610fcd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ff19190611da2565b508381554260018083019190915560028201805460ff191690911790556004820180548591905f90611024908490611d8f565b9091555050600582018054905f61103a83611dff565b9190505550611049338561183a565b604051848152859033907f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee909060200160405180910390a35050505050565b6060600580546104d890611c86565b5f336105668185856116fd565b600180600954600160a01b900460ff1660018111156110c4576110c4611bbd565b146110e15760405162461bcd60e51b815260040161067290611d1b565b335f9081526007602090815260408083208584529091529020600281015460ff1661111e5760405162461bcd60e51b815260040161067290611d60565b5f8381526006602052604090206111388462015180611ce5565b82600101546111479190611d8f565b4210156111965760405162461bcd60e51b815260206004820152601a60248201527f4c6f636b20706572696f6420686173206e6f74207061737365640000000000006044820152606401610672565b81545f6111a33387610572565b90505f6111b08284611d8f565b905083600101548110156112185760405162461bcd60e51b815260206004820152602960248201527f52657374616b6520616d6f756e74206973206c657373207468616e206d696e696044820152686d756d207374616b6560b81b6064820152608401610672565b83600201548111156112785760405162461bcd60e51b8152602060048201526024808201527f52657374616b6520616d6f756e742065786365656473206d6178696d756d207360448201526374616b6560e01b6064820152608401610672565b836003015482856004015461128d9190611d8f565b11156112ab5760405162461bcd60e51b815260040161067290611dbd565b8085554260018601556004840180548391905f906112ca908490611d8f565b909155506112da9050338361183a565b6040805184815260208101849052889133917f63acdca311ce77b458c1dde8cdea3e282508af05da37a4f52a915b7784c37c48910160405180910390a350505050505050565b611328611792565b5f8511801561133957506127108511155b6113855760405162461bcd60e51b815260206004820152601d60248201527f415052206d757374206265206265747765656e203120616e64203130300000006044820152606401610672565b5f84116113e05760405162461bcd60e51b8152602060048201526024808201527f4d696e696d756d207374616b65206d75737420626520677265617465722074686044820152630616e20360e41b6064820152608401610672565b838310156114565760405162461bcd60e51b815260206004820152603c60248201527f4d6178696d756d207374616b65206d757374206265206772656174657220746860448201527f616e206f7220657175616c20746f206d696e696d756d207374616b65000000006064820152608401610672565b828210156114de5760405162461bcd60e51b815260206004820152604960248201527f546f74616c206d6178696d756d207374616b6520616d6f756e74206d7573742060448201527f62652067726561746572207468616e206f7220657175616c20746f206d6178696064820152686d756d207374616b6560b81b608482015260a401610672565b5f86815260066020818152604092839020888155600181018890556002810187905560038101869055918201805460ff191685151590811790915583518a8152918201899052928101879052606081018690526080810185905260a0810192909252907f497768b3d65a26bbe0117804b6c1f7dbfd9bfd4e4a4d9af2aec5f9f64b2681019060c00160405180910390a150505050505050565b61157f611792565b6001600160a01b0381166115e45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610672565b6115ed816117eb565b50565b6115f8611792565b600281106116395760405162461bcd60e51b815260206004820152600e60248201526d496e76616c69642053746174652160901b6044820152606401610672565b80600181111561164b5761164b611bbd565b6009805460ff60a01b1916600160a01b83600181111561166d5761166d611bbd565b021790555050565b6109f9838383600161186e565b6001600160a01b038381165f908152600260209081526040808320938616835292905220545f1981146116f757818110156116e957604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610672565b6116f784848484035f61186e565b50505050565b6001600160a01b03831661172657604051634b637e8f60e11b81525f6004820152602401610672565b6001600160a01b03821661174f5760405163ec442f0560e01b81525f6004820152602401610672565b6109f9838383611940565b6001600160a01b03821661178357604051634b637e8f60e11b81525f6004820152602401610672565b61178e825f83611940565b5050565b5f546001600160a01b03163314610d2d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610672565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382166118635760405163ec442f0560e01b81525f6004820152602401610672565b61178e5f8383611940565b6001600160a01b0384166118975760405163e602df0560e01b81525f6004820152602401610672565b6001600160a01b0383166118c057604051634a1406b160e11b81525f6004820152602401610672565b6001600160a01b038085165f90815260026020908152604080832093871683529290522082905580156116f757826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161193291815260200190565b60405180910390a350505050565b6001600160a01b03831661196a578060035f82825461195f9190611d8f565b909155506119da9050565b6001600160a01b0383165f90815260016020526040902054818110156119bc5760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610672565b6001600160a01b0384165f9081526001602052604090209082900390555b6001600160a01b0382166119f657600380548290039055611a14565b6001600160a01b0382165f9081526001602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611a5991815260200190565b60405180910390a3505050565b5f6020808352835180828501525f5b81811015611a9157858101830151858201604001528201611a75565b505f604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114611ac7575f80fd5b919050565b5f8060408385031215611add575f80fd5b611ae683611ab1565b946020939093013593505050565b5f805f60608486031215611b06575f80fd5b611b0f84611ab1565b9250611b1d60208501611ab1565b9150604084013590509250925092565b5f60208284031215611b3d575f80fd5b5035919050565b5f805f60608486031215611b56575f80fd5b611b5f84611ab1565b925060208401359150611b7460408501611ab1565b90509250925092565b5f60208284031215611b8d575f80fd5b611b9682611ab1565b9392505050565b5f8060408385031215611bae575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310611bf157634e487b7160e01b5f52602160045260245ffd5b91905290565b80151581146115ed575f80fd5b5f805f805f8060c08789031215611c19575f80fd5b863595506020870135945060408701359350606087013592506080870135915060a0870135611c4781611bf7565b809150509295509295509295565b5f8060408385031215611c66575f80fd5b611c6f83611ab1565b9150611c7d60208401611ab1565b90509250929050565b600181811c90821680611c9a57607f821691505b602082108103611cb857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561056c5761056c611cbe565b808202811582820484141761056c5761056c611cbe565b5f82611d1657634e487b7160e01b5f52601260045260245ffd5b500490565b60208082526025908201527f436f6e7472616374206973206e6f7420696e2074686520726571756972656420604082015264737461746560d81b606082015260800190565b602080825260159082015274139bc81858dd1a5d99481cdd185ad948199bdd5b99605a1b604082015260600190565b8082018082111561056c5761056c611cbe565b5f60208284031215611db2575f80fd5b8151611b9681611bf7565b60208082526022908201527f4578636565647320746f74616c206d6178696d756d207374616b6520616d6f756040820152611b9d60f21b606082015260800190565b5f60018201611e1057611e10611cbe565b506001019056fea2646970667358221220cbf9715f334991d3b8316512d9b2bdb409ab5f70d96d682737399fc6ee0e7a2764736f6c63430008140033

Deployed Bytecode Sourcemap

25662:12748:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10527:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12820:190;;;;;;:::i;:::-;;:::i;:::-;;;1169:14:1;;1162:22;1144:41;;1132:2;1117:18;12820:190:0;1004:187:1;11629:99:0;11708:12;;11629:99;;;1342:25:1;;;1330:2;1315:18;11629:99:0;1196:177:1;34942:293:0;;;;;;:::i;:::-;;:::i;13588:249::-;;;;;;:::i;:::-;;:::i;31010:1002::-;;;;;;:::i;:::-;;:::i;:::-;;11480:84;;;11554:2;2038:36:1;;2026:2;2011:18;11480:84:0;1896:184:1;38049:358:0;;;;;;:::i;:::-;;:::i;33697:973::-;;;;;;:::i;:::-;;:::i;37451:342::-;;;;;;:::i;:::-;;:::i;37120:102::-;;;;;;:::i;:::-;;:::i;26806:59::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2805:25:1;;;2861:2;2846:18;;2839:34;;;;2916:14;2909:22;2889:18;;;2882:50;2793:2;2778:18;26806:59:0;2609:329:1;26342:51:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3252:25:1;;;3308:2;3293:18;;3286:34;;;;3336:18;;;3329:34;;;;3394:2;3379:18;;3372:34;;;;3437:3;3422:19;;3415:35;3481:3;3466:19;;3459:35;3538:14;3531:22;3525:3;3510:19;;3503:51;3239:3;3224:19;26342:51:0;2943:617:1;26928:48:0;;;;;;:::i;:::-;;;;;;;;;;;;;;11791:118;;;;;;:::i;:::-;-1:-1:-1;;;;;11883:18:0;11856:7;11883:18;;;:9;:18;;;;;;;11791:118;2743:103;;;:::i;27053:27::-;;;;;-1:-1:-1;;;;;27053:27:0;;;;;;-1:-1:-1;;;;;3751:32:1;;;3733:51;;3721:2;3706:18;27053:27:0;3565:225:1;29809:1065:0;;;;;;:::i;:::-;;:::i;27311:55::-;;;;;-1:-1:-1;;;27311:55:0;;;;;;;;;;;;;:::i;2095:87::-;2141:7;2168:6;-1:-1:-1;;;;;2168:6:0;2095:87;;10737:95;;;:::i;12114:182::-;;;;;;:::i;:::-;;:::i;32158:1344::-;;;;;;:::i;:::-;;:::i;35709:932::-;;;;;;:::i;:::-;;:::i;12359:142::-;;;;;;:::i;:::-;-1:-1:-1;;;;;12466:18:0;;;12439:7;12466:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;12359:142;3001:201;;;;;;:::i;:::-;;:::i;36805:171::-;;;;;;:::i;:::-;;:::i;10527:91::-;10572:13;10605:5;10598:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10527:91;:::o;12820:190::-;12893:4;812:10;12949:31;812:10;12965:7;12974:5;12949:8;:31::i;:::-;12998:4;12991:11;;;12820:190;;;;;:::o;34942:293::-;-1:-1:-1;;;;;35077:14:0;;35018:7;35077:14;;;:6;:14;;;;;;;;:20;;;;;;;;:35;;;35018:7;;35059:53;;:15;:53;:::i;:::-;35168:18;;;;:12;:18;;;;;;;;:22;-1:-1:-1;;;;;35133:14:0;;;;:6;:14;;;;;:20;;;;;;;;;:32;35038:74;;-1:-1:-1;35218:8:0;;35038:74;;35194:5;;35133:57;;35168:22;35133:57;:::i;:::-;35132:67;;;;:::i;:::-;35131:82;;;;:::i;:::-;35130:97;;;;:::i;:::-;35123:104;34942:293;-1:-1:-1;;;;34942:293:0:o;13588:249::-;13675:4;812:10;13733:37;13749:4;812:10;13764:5;13733:15;:37::i;:::-;13781:26;13791:4;13797:2;13801:5;13781:9;:26::i;:::-;-1:-1:-1;13825:4:0;;13588:249;-1:-1:-1;;;;13588:249:0:o;31010:1002::-;31066:18;;29532:13;;-1:-1:-1;;;29532:13:0;;;;:30;;;;;;;;:::i;:::-;;29524:80;;;;-1:-1:-1;;;29524:80:0;;;;;;;:::i;:::-;;;;;;;;;31130:10:::1;31097:23;31123:18:::0;;;:6:::1;:18;::::0;;;;;;;:24;;;;;;;;31166:18:::1;::::0;::::1;::::0;::::1;;31158:52;;;;-1:-1:-1::0;;;31158:52:0::1;;;;;;;:::i;:::-;31231:24;31258:18:::0;;;:12:::1;:18;::::0;;;;31341:12:::1;31271:4:::0;31348:5:::1;31341:12;:::i;:::-;31314:9;:24;;;:39;;;;:::i;:::-;31295:15;:58;;31287:97;;;::::0;-1:-1:-1;;;31287:97:0;;7848:2:1;31287:97:0::1;::::0;::::1;7830:21:1::0;7887:2;7867:18;;;7860:30;7926:28;7906:18;;;7899:56;7972:18;;31287:97:0::1;7646:350:1::0;31287:97:0::1;31420:21:::0;;31397:20:::1;31470:33;31486:10;31498:4:::0;31470:15:::1;:33::i;:::-;31528:10;31514:25;::::0;;;:13:::1;:25;::::0;;;;:36;;31452:51;;-1:-1:-1;31452:51:0;;31514:25;;;:36:::1;::::0;31452:51;;31514:36:::1;:::i;:::-;::::0;;;-1:-1:-1;;31680:5:0::1;::::0;:40:::1;::::0;-1:-1:-1;;;31680:40:0;;31695:10:::1;31680:40;::::0;::::1;8175:51:1::0;8242:18;;;8235:34;;;-1:-1:-1;;;;;31680:5:0;;::::1;::::0;:14:::1;::::0;8148:18:1;;31680:40:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;31791:18:0::1;::::0;::::1;:26:::0;;-1:-1:-1;;31791:26:0::1;::::0;;31828:16:::1;::::0;::::1;:32:::0;;31848:12;;31828:16;31812:5:::1;::::0;31828:32:::1;::::0;31848:12;;31828:32:::1;:::i;:::-;;;;;;;;31892:1;31871:4;:17;;;:22;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;31906:31:0::1;::::0;-1:-1:-1;31912:10:0::1;31924:12:::0;31906:5:::1;:31::i;:::-;31955:49;::::0;;8704:25:1;;;8760:2;8745:18;;8738:34;;;31976:4:0;;31964:10:::1;::::0;31955:49:::1;::::0;8677:18:1;31955:49:0::1;;;;;;;;31086:926;;;;31010:1002:::0;;:::o;38049:358::-;1981:13;:11;:13::i;:::-;-1:-1:-1;;;;;38160:23:0;::::1;38152:52;;;::::0;-1:-1:-1;;;38152:52:0;;8985:2:1;38152:52:0::1;::::0;::::1;8967:21:1::0;9024:2;9004:18;;;8997:30;-1:-1:-1;;;9043:18:1;;;9036:46;9099:18;;38152:52:0::1;8783:340:1::0;38152:52:0::1;38232:1;38223:6;:10;38215:38;;;::::0;-1:-1:-1;;;38215:38:0;;9330:2:1;38215:38:0::1;::::0;::::1;9312:21:1::0;9369:2;9349:18;;;9342:30;-1:-1:-1;;;9388:18:1;;;9381:45;9443:18;;38215:38:0::1;9128:339:1::0;38215:38:0::1;-1:-1:-1::0;;;;;38272:19:0;::::1;38264:46;;;::::0;-1:-1:-1;;;38264:46:0;;9674:2:1;38264:46:0::1;::::0;::::1;9656:21:1::0;9713:2;9693:18;;;9686:30;-1:-1:-1;;;9732:18:1;;;9725:44;9786:18;;38264:46:0::1;9472:338:1::0;38264:46:0::1;38331:41;::::0;-1:-1:-1;;;38331:41:0;;-1:-1:-1;;;;;8193:32:1;;;38331:41:0::1;::::0;::::1;8175:51:1::0;8242:18;;;8235:34;;;38331:22:0;::::1;::::0;::::1;::::0;8148:18:1;;38331:41:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38323:76;;;::::0;-1:-1:-1;;;38323:76:0;;10017:2:1;38323:76:0::1;::::0;::::1;9999:21:1::0;10056:2;10036:18;;;10029:30;-1:-1:-1;;;10075:18:1;;;10068:52;10137:18;;38323:76:0::1;9815:346:1::0;38323:76:0::1;38049:358:::0;;;:::o;33697:973::-;1981:13;:11;:13::i;:::-;-1:-1:-1;;;;;33807:12:0;::::1;33781:23;33807:12:::0;;;:6:::1;:12;::::0;;;;;;;:18;;;;;;;;33844::::1;::::0;::::1;::::0;::::1;;33836:52;;;;-1:-1:-1::0;;;33836:52:0::1;;;;;;;:::i;:::-;33901:24;33928:18:::0;;;:12:::1;:18;::::0;;;;33982:21;;33928:18;;34092:12:::1;33941:4:::0;34099:5:::1;34092:12;:::i;:::-;34065:9;:24;;;:39;;;;:::i;:::-;34046:15;:58;34042:179;;34131:33;34147:10;34159:4;34131:15;:33::i;:::-;-1:-1:-1::0;;;;;34179:19:0;::::1;;::::0;;;:13:::1;:19;::::0;;;;:30;;34121:43;;-1:-1:-1;34121:43:0;;34179:19;;;:30:::1;::::0;34121:43;;34179:30:::1;:::i;:::-;::::0;;;-1:-1:-1;;34042:179:0::1;34350:5;::::0;:40:::1;::::0;-1:-1:-1;;;34350:40:0;;34365:10:::1;34350:40;::::0;::::1;8175:51:1::0;8242:18;;;8235:34;;;-1:-1:-1;;;;;34350:5:0;;::::1;::::0;:14:::1;::::0;8148:18:1;;34350:40:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;34461:18:0::1;::::0;::::1;:26:::0;;-1:-1:-1;;34461:26:0::1;::::0;;34498:16:::1;::::0;::::1;:32:::0;;34518:12;;34498:16;34482:5:::1;::::0;34498:32:::1;::::0;34518:12;;34498:32:::1;:::i;:::-;;;;;;;;34562:1;34541:4;:17;;;:22;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;34576:25:0::1;::::0;-1:-1:-1;34582:4:0;34588:12;34576:5:::1;:25::i;:::-;34619:43;::::0;;8704:25:1;;;8760:2;8745:18;;8738:34;;;34634:4:0;;-1:-1:-1;;;;;34619:43:0;::::1;::::0;::::1;::::0;8677:18:1;34619:43:0::1;8530:248:1::0;37451:342:0;1981:13;:11;:13::i;:::-;-1:-1:-1;;;;;37547:23:0;::::1;37539:52;;;::::0;-1:-1:-1;;;37539:52:0;;8985:2:1;37539:52:0::1;::::0;::::1;8967:21:1::0;9024:2;9004:18;;;8997:30;-1:-1:-1;;;9043:18:1;;;9036:46;9099:18;;37539:52:0::1;8783:340:1::0;37539:52:0::1;37619:1;37610:6;:10;:45;;;;;37649:6;37624:21;:31;;37610:45;37602:73;;;::::0;-1:-1:-1;;;37602:73:0;;9330:2:1;37602:73:0::1;::::0;::::1;9312:21:1::0;9369:2;9349:18;;;9342:30;-1:-1:-1;;;9388:18:1;;;9381:45;9443:18;;37602:73:0::1;9128:339:1::0;37602:73:0::1;37689:9;37704;-1:-1:-1::0;;;;;37704:14:0::1;37726:6;37704:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37688:49;;;37756:4;37748:37;;;::::0;-1:-1:-1;;;37748:37:0;;10578:2:1;37748:37:0::1;::::0;::::1;10560:21:1::0;10617:2;10597:18;;;10590:30;-1:-1:-1;;;10636:18:1;;;10629:50;10696:18;;37748:37:0::1;10376:344:1::0;37120:102:0;1981:13;:11;:13::i;:::-;37184:5:::1;:30:::0;;-1:-1:-1;;;;;;37184:30:0::1;-1:-1:-1::0;;;;;37184:30:0;;;::::1;::::0;;;::::1;::::0;;37120:102::o;2743:103::-;1981:13;:11;:13::i;:::-;2808:30:::1;2835:1;2808:18;:30::i;:::-;2743:103::o:0;29809:1065::-;29879:18;;29532:13;;-1:-1:-1;;;29532:13:0;;;;:30;;;;;;;;:::i;:::-;;29524:80;;;;-1:-1:-1;;;29524:80:0;;;;;;;:::i;:::-;29910:24:::1;29937:18:::0;;;:12:::1;:18;::::0;;;;;;;29999:10:::1;29992:18:::0;;:6:::1;:18:::0;;;;;:24;;;;;;;;;30037:11;;::::1;::::0;::::1;;30029:50;;;::::0;-1:-1:-1;;;30029:50:0;;10927:2:1;30029:50:0::1;::::0;::::1;10909:21:1::0;10966:2;10946:18;;;10939:30;11005:28;10985:18;;;10978:56;11051:18;;30029:50:0::1;10725:350:1::0;30029:50:0::1;30147:13;::::0;::::1;::::0;30114:10:::1;30107:18;::::0;;;:6:::1;:18;::::0;;;;;;;:24;;;;;;;;:36;30098:45:::1;::::0;:6;:45:::1;:::i;:::-;:62;;30090:108;;;::::0;-1:-1:-1;;;30090:108:0;;11282:2:1;30090:108:0::1;::::0;::::1;11264:21:1::0;11321:2;11301:18;;;11294:30;11360:34;11340:18;;;11333:62;-1:-1:-1;;;11411:18:1;;;11404:31;11452:19;;30090:108:0::1;11080:397:1::0;30090:108:0::1;30266:13;::::0;::::1;::::0;30233:10:::1;30226:18;::::0;;;:6:::1;:18;::::0;;;;;;;:24;;;;;;;;:36;30217:45:::1;::::0;:6;:45:::1;:::i;:::-;:62;;30209:103;;;::::0;-1:-1:-1;;;30209:103:0;;11684:2:1;30209:103:0::1;::::0;::::1;11666:21:1::0;11723:2;11703:18;;;11696:30;11762;11742:18;;;11735:58;11810:18;;30209:103:0::1;11482:352:1::0;30209:103:0::1;30360:4;:24;;;30350:6;30331:4;:16;;;:25;;;;:::i;:::-;:53;;30323:100;;;;-1:-1:-1::0;;;30323:100:0::1;;;;;;;:::i;:::-;30443:18;::::0;::::1;::::0;::::1;;30442:19;30434:77;;;::::0;-1:-1:-1;;;30434:77:0;;12444:2:1;30434:77:0::1;::::0;::::1;12426:21:1::0;12483:2;12463:18;;;12456:30;12522:34;12502:18;;;12495:62;-1:-1:-1;;;12573:18:1;;;12566:43;12626:19;;30434:77:0::1;12242:409:1::0;30434:77:0::1;30524:5;::::0;:53:::1;::::0;-1:-1:-1;;;30524:53:0;;30543:10:::1;30524:53;::::0;::::1;12896:34:1::0;30563:4:0::1;12946:18:1::0;;;12939:43;12998:18;;;12991:34;;;-1:-1:-1;;;;;30524:5:0;;::::1;::::0;:18:::1;::::0;12831::1;;30524:53:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;30590:30:0;;;30658:15:::1;30631:24;::::0;;::::1;:42:::0;;;;30684:18:::1;::::0;::::1;:25:::0;;-1:-1:-1;;30684:25:0::1;::::0;;::::1;::::0;;30722:16:::1;::::0;::::1;:26:::0;;30614:6;;30722:16;30590:21:::1;::::0;30722:26:::1;::::0;30614:6;;30722:26:::1;:::i;:::-;::::0;;;-1:-1:-1;;30759:17:0::1;::::0;::::1;:19:::0;;;:17:::1;:19;::::0;::::1;:::i;:::-;;;;;;30791:25;30797:10;30809:6;30791:5;:25::i;:::-;30834:32;::::0;1342:25:1;;;30853:4:0;;30841:10:::1;::::0;30834:32:::1;::::0;1330:2:1;1315:18;30834:32:0::1;;;;;;;29899:975;;29809:1065:::0;;;:::o;10737:95::-;10784:13;10817:7;10810:14;;;;;:::i;12114:182::-;12183:4;812:10;12239:27;812:10;12256:2;12260:5;12239:9;:27::i;32158:1344::-;32214:18;;29532:13;;-1:-1:-1;;;29532:13:0;;;;:30;;;;;;;;:::i;:::-;;29524:80;;;;-1:-1:-1;;;29524:80:0;;;;;;;:::i;:::-;32278:10:::1;32245:23;32271:18:::0;;;:6:::1;:18;::::0;;;;;;;:24;;;;;;;;32314:18:::1;::::0;::::1;::::0;::::1;;32306:52;;;;-1:-1:-1::0;;;32306:52:0::1;;;;;;;:::i;:::-;32371:24;32398:18:::0;;;:12:::1;:18;::::0;;;;32481:12:::1;32411:4:::0;32488:5:::1;32481:12;:::i;:::-;32454:9;:24;;;:39;;;;:::i;:::-;32435:15;:58;;32427:97;;;::::0;-1:-1:-1;;;32427:97:0;;7848:2:1;32427:97:0::1;::::0;::::1;7830:21:1::0;7887:2;7867:18;;;7860:30;7926:28;7906:18;;;7899:56;7972:18;;32427:97:0::1;7646:350:1::0;32427:97:0::1;32560:21:::0;;32537:20:::1;32610:33;32626:10;32638:4:::0;32610:15:::1;:33::i;:::-;32592:51:::0;-1:-1:-1;32744:22:0::1;32769;32592:51:::0;32769:12;:22:::1;:::i;:::-;32744:47;;32828:4;:13;;;32810:14;:31;;32802:85;;;::::0;-1:-1:-1;;;32802:85:0;;13378:2:1;32802:85:0::1;::::0;::::1;13360:21:1::0;13417:2;13397:18;;;13390:30;13456:34;13436:18;;;13429:62;-1:-1:-1;;;13507:18:1;;;13500:39;13556:19;;32802:85:0::1;13176:405:1::0;32802:85:0::1;32924:4;:13;;;32906:14;:31;;32898:80;;;::::0;-1:-1:-1;;;32898:80:0;;13788:2:1;32898:80:0::1;::::0;::::1;13770:21:1::0;13827:2;13807:18;;;13800:30;13866:34;13846:18;;;13839:62;-1:-1:-1;;;13917:18:1;;;13910:34;13961:19;;32898:80:0::1;13586:400:1::0;32898:80:0::1;33027:4;:24;;;33016:7;32997:4;:16;;;:26;;;;:::i;:::-;:54;;32989:101;;;;-1:-1:-1::0;;;32989:101:0::1;;;;;;;:::i;:::-;33135:38:::0;;;33211:15:::1;33184:24;::::0;::::1;:42:::0;33361:16:::1;::::0;::::1;:27:::0;;33381:7;;33361:16;33135:21:::1;::::0;33361:27:::1;::::0;33381:7;;33361:27:::1;:::i;:::-;::::0;;;-1:-1:-1;33401:26:0::1;::::0;-1:-1:-1;33407:10:0::1;33419:7:::0;33401:5:::1;:26::i;:::-;33445:49;::::0;;8704:25:1;;;8760:2;8745:18;;8738:34;;;33466:4:0;;33454:10:::1;::::0;33445:49:::1;::::0;8677:18:1;33445:49:0::1;;;;;;;32234:1268;;;;;32158:1344:::0;;:::o;35709:932::-;1981:13;:11;:13::i;:::-;35941:1:::1;35935:3;:7;:23;;;;;35953:5;35946:3;:12;;35935:23;35927:65;;;::::0;-1:-1:-1;;;35927:65:0;;14193:2:1;35927:65:0::1;::::0;::::1;14175:21:1::0;14232:2;14212:18;;;14205:30;14271:31;14251:18;;;14244:59;14320:18;;35927:65:0::1;13991:353:1::0;35927:65:0::1;36022:1;36011:8;:12;36003:61;;;::::0;-1:-1:-1;;;36003:61:0;;14551:2:1;36003:61:0::1;::::0;::::1;14533:21:1::0;14590:2;14570:18;;;14563:30;14629:34;14609:18;;;14602:62;-1:-1:-1;;;14680:18:1;;;14673:34;14724:19;;36003:61:0::1;14349:400:1::0;36003:61:0::1;36095:8;36083;:20;;36075:93;;;::::0;-1:-1:-1;;;36075:93:0;;14956:2:1;36075:93:0::1;::::0;::::1;14938:21:1::0;14995:2;14975:18;;;14968:30;15034:34;15014:18;;;15007:62;15105:30;15085:18;;;15078:58;15153:19;;36075:93:0::1;14754:424:1::0;36075:93:0::1;36210:8;36187:19;:31;;36179:117;;;::::0;-1:-1:-1;;;36179:117:0;;15385:2:1;36179:117:0::1;::::0;::::1;15367:21:1::0;15424:2;15404:18;;;15397:30;15463:34;15443:18;;;15436:62;15534:34;15514:18;;;15507:62;-1:-1:-1;;;15585:19:1;;;15578:40;15635:19;;36179:117:0::1;15183:477:1::0;36179:117:0::1;36309:24;36336:18:::0;;;:12:::1;:18;::::0;;;;;;;;36365:14;;;36390:13:::1;::::0;::::1;:24:::0;;;36425:13:::1;::::0;::::1;:24:::0;;;36460::::1;::::0;::::1;:46:::0;;;36517:11;;::::1;:20:::0;;-1:-1:-1;;36517:20:0::1;::::0;::::1;;::::0;;::::1;::::0;;;36555:78;;15946:25:1;;;15987:18;;;15980:34;;;16030:18;;;16023:34;;;16088:2;16073:18;;16066:34;;;16131:3;16116:19;;16109:35;;;16175:3;16160:19;;16153:51;;;;36336:18:0;36555:78:::1;::::0;15933:3:1;15918:19;36555:78:0::1;;;;;;;35916:725;35709:932:::0;;;;;;:::o;3001:201::-;1981:13;:11;:13::i;:::-;-1:-1:-1;;;;;3090:22:0;::::1;3082:73;;;::::0;-1:-1:-1;;;3082:73:0;;16417:2:1;3082:73:0::1;::::0;::::1;16399:21:1::0;16456:2;16436:18;;;16429:30;16495:34;16475:18;;;16468:62;-1:-1:-1;;;16546:18:1;;;16539:36;16592:19;;3082:73:0::1;16215:402:1::0;3082:73:0::1;3166:28;3185:8;3166:18;:28::i;:::-;3001:201:::0;:::o;36805:171::-;1981:13;:11;:13::i;:::-;36898:1:::1;36887:8;:12;36879:39;;;::::0;-1:-1:-1;;;36879:39:0;;16824:2:1;36879:39:0::1;::::0;::::1;16806:21:1::0;16863:2;16843:18;;;16836:30;-1:-1:-1;;;16882:18:1;;;16875:44;16936:18;;36879:39:0::1;16622:338:1::0;36879:39:0::1;36959:8;36945:23;;;;;;;;:::i;:::-;36929:13;:39:::0;;-1:-1:-1;;;;36929:39:0::1;-1:-1:-1::0;;;36929:39:0;::::1;::::0;::::1;;;;;;:::i;:::-;;;;;;36805:171:::0;:::o;17655:130::-;17740:37;17749:5;17756:7;17765:5;17772:4;17740:8;:37::i;19371:487::-;-1:-1:-1;;;;;12466:18:0;;;19471:24;12466:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;-1:-1:-1;;19538:37:0;;19534:317;;19615:5;19596:16;:24;19592:132;;;19648:60;;-1:-1:-1;;;19648:60:0;;-1:-1:-1;;;;;17185:32:1;;19648:60:0;;;17167:51:1;17234:18;;;17227:34;;;17277:18;;;17270:34;;;17140:18;;19648:60:0;16965:345:1;19592:132:0;19767:57;19776:5;19783:7;19811:5;19792:16;:24;19818:5;19767:8;:57::i;:::-;19460:398;19371:487;;;:::o;14222:316::-;-1:-1:-1;;;;;14314:18:0;;14310:88;;14356:30;;-1:-1:-1;;;14356:30:0;;14383:1;14356:30;;;3733:51:1;3706:18;;14356:30:0;3565:225:1;14310:88:0;-1:-1:-1;;;;;14412:16:0;;14408:88;;14452:32;;-1:-1:-1;;;14452:32:0;;14481:1;14452:32;;;3733:51:1;3706:18;;14452:32:0;3565:225:1;14408:88:0;14506:24;14514:4;14520:2;14524:5;14506:7;:24::i;16891:211::-;-1:-1:-1;;;;;16962:21:0;;16958:91;;17007:30;;-1:-1:-1;;;17007:30:0;;17034:1;17007:30;;;3733:51:1;3706:18;;17007:30:0;3565:225:1;16958:91:0;17059:35;17067:7;17084:1;17088:5;17059:7;:35::i;:::-;16891:211;;:::o;2260:132::-;2141:7;2168:6;-1:-1:-1;;;;;2168:6:0;812:10;2324:23;2316:68;;;;-1:-1:-1;;;2316:68:0;;17517:2:1;2316:68:0;;;17499:21:1;;;17536:18;;;17529:30;17595:34;17575:18;;;17568:62;17647:18;;2316:68:0;17315:356:1;3362:191:0;3436:16;3455:6;;-1:-1:-1;;;;;3472:17:0;;;-1:-1:-1;;;;;;3472:17:0;;;;;;3505:40;;3455:6;;;;;;;3505:40;;3436:16;3505:40;3425:128;3362:191;:::o;16350:213::-;-1:-1:-1;;;;;16421:21:0;;16417:93;;16466:32;;-1:-1:-1;;;16466:32:0;;16495:1;16466:32;;;3733:51:1;3706:18;;16466:32:0;3565:225:1;16417:93:0;16520:35;16536:1;16540:7;16549:5;16520:7;:35::i;18636:443::-;-1:-1:-1;;;;;18749:19:0;;18745:91;;18792:32;;-1:-1:-1;;;18792:32:0;;18821:1;18792:32;;;3733:51:1;3706:18;;18792:32:0;3565:225:1;18745:91:0;-1:-1:-1;;;;;18850:21:0;;18846:92;;18895:31;;-1:-1:-1;;;18895:31:0;;18923:1;18895:31;;;3733:51:1;3706:18;;18895:31:0;3565:225:1;18846:92:0;-1:-1:-1;;;;;18948:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;18994:78;;;;19045:7;-1:-1:-1;;;;;19029:31:0;19038:5;-1:-1:-1;;;;;19029:31:0;;19054:5;19029:31;;;;1342:25:1;;1330:2;1315:18;;1196:177;19029:31:0;;;;;;;;18636:443;;;;:::o;14862:1135::-;-1:-1:-1;;;;;14952:18:0;;14948:552;;15106:5;15090:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;14948:552:0;;-1:-1:-1;14948:552:0;;-1:-1:-1;;;;;15166:15:0;;15144:19;15166:15;;;:9;:15;;;;;;15200:19;;;15196:117;;;15247:50;;-1:-1:-1;;;15247:50:0;;-1:-1:-1;;;;;17185:32:1;;15247:50:0;;;17167:51:1;17234:18;;;17227:34;;;17277:18;;;17270:34;;;17140:18;;15247:50:0;16965:345:1;15196:117:0;-1:-1:-1;;;;;15436:15:0;;;;;;:9;:15;;;;;15454:19;;;;15436:37;;14948:552;-1:-1:-1;;;;;15516:16:0;;15512:435;;15682:12;:21;;;;;;;15512:435;;;-1:-1:-1;;;;;15898:13:0;;;;;;:9;:13;;;;;:22;;;;;;15512:435;15979:2;-1:-1:-1;;;;;15964:25:0;15973:4;-1:-1:-1;;;;;15964:25:0;;15983:5;15964:25;;;;1342::1;;1330:2;1315:18;;1196:177;15964:25:0;;;;;;;;14862:1135;;;:::o;14:548:1:-;126:4;155:2;184;173:9;166:21;216:6;210:13;259:6;254:2;243:9;239:18;232:34;284:1;294:140;308:6;305:1;302:13;294:140;;;403:14;;;399:23;;393:30;369:17;;;388:2;365:26;358:66;323:10;;294:140;;;298:3;483:1;478:2;469:6;458:9;454:22;450:31;443:42;553:2;546;542:7;537:2;529:6;525:15;521:29;510:9;506:45;502:54;494:62;;;;14:548;;;;:::o;567:173::-;635:20;;-1:-1:-1;;;;;684:31:1;;674:42;;664:70;;730:1;727;720:12;664:70;567:173;;;:::o;745:254::-;813:6;821;874:2;862:9;853:7;849:23;845:32;842:52;;;890:1;887;880:12;842:52;913:29;932:9;913:29;:::i;:::-;903:39;989:2;974:18;;;;961:32;;-1:-1:-1;;;745:254:1:o;1378:328::-;1455:6;1463;1471;1524:2;1512:9;1503:7;1499:23;1495:32;1492:52;;;1540:1;1537;1530:12;1492:52;1563:29;1582:9;1563:29;:::i;:::-;1553:39;;1611:38;1645:2;1634:9;1630:18;1611:38;:::i;:::-;1601:48;;1696:2;1685:9;1681:18;1668:32;1658:42;;1378:328;;;;;:::o;1711:180::-;1770:6;1823:2;1811:9;1802:7;1798:23;1794:32;1791:52;;;1839:1;1836;1829:12;1791:52;-1:-1:-1;1862:23:1;;1711:180;-1:-1:-1;1711:180:1:o;2085:328::-;2162:6;2170;2178;2231:2;2219:9;2210:7;2206:23;2202:32;2199:52;;;2247:1;2244;2237:12;2199:52;2270:29;2289:9;2270:29;:::i;:::-;2260:39;;2346:2;2335:9;2331:18;2318:32;2308:42;;2369:38;2403:2;2392:9;2388:18;2369:38;:::i;:::-;2359:48;;2085:328;;;;;:::o;2418:186::-;2477:6;2530:2;2518:9;2509:7;2505:23;2501:32;2498:52;;;2546:1;2543;2536:12;2498:52;2569:29;2588:9;2569:29;:::i;:::-;2559:39;2418:186;-1:-1:-1;;;2418:186:1:o;3795:248::-;3863:6;3871;3924:2;3912:9;3903:7;3899:23;3895:32;3892:52;;;3940:1;3937;3930:12;3892:52;-1:-1:-1;;3963:23:1;;;4033:2;4018:18;;;4005:32;;-1:-1:-1;3795:248:1:o;4048:127::-;4109:10;4104:3;4100:20;4097:1;4090:31;4140:4;4137:1;4130:15;4164:4;4161:1;4154:15;4180:345;4329:2;4314:18;;4362:1;4351:13;;4341:144;;4407:10;4402:3;4398:20;4395:1;4388:31;4442:4;4439:1;4432:15;4470:4;4467:1;4460:15;4341:144;4494:25;;;4180:345;:::o;4738:118::-;4824:5;4817:13;4810:21;4803:5;4800:32;4790:60;;4846:1;4843;4836:12;4861:584;4962:6;4970;4978;4986;4994;5002;5055:3;5043:9;5034:7;5030:23;5026:33;5023:53;;;5072:1;5069;5062:12;5023:53;5108:9;5095:23;5085:33;;5165:2;5154:9;5150:18;5137:32;5127:42;;5216:2;5205:9;5201:18;5188:32;5178:42;;5267:2;5256:9;5252:18;5239:32;5229:42;;5318:3;5307:9;5303:19;5290:33;5280:43;;5373:3;5362:9;5358:19;5345:33;5387:28;5409:5;5387:28;:::i;:::-;5434:5;5424:15;;;4861:584;;;;;;;;:::o;5450:260::-;5518:6;5526;5579:2;5567:9;5558:7;5554:23;5550:32;5547:52;;;5595:1;5592;5585:12;5547:52;5618:29;5637:9;5618:29;:::i;:::-;5608:39;;5666:38;5700:2;5689:9;5685:18;5666:38;:::i;:::-;5656:48;;5450:260;;;;;:::o;5715:380::-;5794:1;5790:12;;;;5837;;;5858:61;;5912:4;5904:6;5900:17;5890:27;;5858:61;5965:2;5957:6;5954:14;5934:18;5931:38;5928:161;;6011:10;6006:3;6002:20;5999:1;5992:31;6046:4;6043:1;6036:15;6074:4;6071:1;6064:15;5928:161;;5715:380;;;:::o;6100:127::-;6161:10;6156:3;6152:20;6149:1;6142:31;6192:4;6189:1;6182:15;6216:4;6213:1;6206:15;6232:128;6299:9;;;6320:11;;;6317:37;;;6334:18;;:::i;6365:168::-;6438:9;;;6469;;6486:15;;;6480:22;;6466:37;6456:71;;6507:18;;:::i;6538:217::-;6578:1;6604;6594:132;;6648:10;6643:3;6639:20;6636:1;6629:31;6683:4;6680:1;6673:15;6711:4;6708:1;6701:15;6594:132;-1:-1:-1;6740:9:1;;6538:217::o;6760:401::-;6962:2;6944:21;;;7001:2;6981:18;;;6974:30;7040:34;7035:2;7020:18;;7013:62;-1:-1:-1;;;7106:2:1;7091:18;;7084:35;7151:3;7136:19;;6760:401::o;7166:345::-;7368:2;7350:21;;;7407:2;7387:18;;;7380:30;-1:-1:-1;;;7441:2:1;7426:18;;7419:51;7502:2;7487:18;;7166:345::o;7516:125::-;7581:9;;;7602:10;;;7599:36;;;7615:18;;:::i;8280:245::-;8347:6;8400:2;8388:9;8379:7;8375:23;8371:32;8368:52;;;8416:1;8413;8406:12;8368:52;8448:9;8442:16;8467:28;8489:5;8467:28;:::i;11839:398::-;12041:2;12023:21;;;12080:2;12060:18;;;12053:30;12119:34;12114:2;12099:18;;12092:62;-1:-1:-1;;;12185:2:1;12170:18;;12163:32;12227:3;12212:19;;11839:398::o;13036:135::-;13075:3;13096:17;;;13093:43;;13116:18;;:::i;:::-;-1:-1:-1;13163:1:1;13152:13;;13036:135::o

Swarm Source

ipfs://cbf9715f334991d3b8316512d9b2bdb409ab5f70d96d682737399fc6ee0e7a27
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.