ETH Price: $2,640.96 (-2.77%)

Token

Staked PIKA (stPIKA)
 

Overview

Max Total Supply

2,341,653,719,727.623233460907463901 stPIKA

Holders

201

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
845,272,840.650697584032922162 stPIKA

Value
$0.00
0x3a3a8674ecc3b85968b0d11b8aebffce46c390e4
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:
Staking

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity Multiple files format)

File 16 of 17: Staking.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.4;

import "./IERC20.sol";
import "./draft-IERC20Permit.sol";

import "./ERC20Snapshot.sol";
import "./AccessControlEnumerable.sol";

import {SafeMathInt, SafeMathUint} from "./SafeMath.sol";

interface Token is IERC20Permit, IERC20 {}

/// @title Staking contract for ERC20 tokens
/// @author Daniel Gretzke
/// @notice Allows users to stake an underlying ERC20 token and receive a new ERC20 token in return which tracks their stake in the pool
/// @notice Rewards in form of the underlying ERC20 token are distributed proportionally across all staking participants
/// @notice Rewards in ETH are distributed proportionally across all staking participants
contract Staking is ERC20Snapshot, AccessControlEnumerable {
    using SafeMathUint for uint256;
    using SafeMathInt for int256;

    uint256 private constant MAX_UINT256 = type(uint256).max;
    // allows to distribute small amounts of ETH correctly
    uint256 internal constant MAGNITUDE = 10**40;
    bytes32 public constant SNAPSHOTTER_ROLE = keccak256("SNAPSHOTTER");

    Token token;
    uint256 internal magnifiedRewardPerShare;
    mapping(address => int256) internal magnifiedRewardCorrections;
    mapping(address => uint256) public claimedRewards;

    event RewardsReceived(address indexed from, uint256 amount);
    event Deposit(address indexed user, uint256 underlyingToken, uint256 overlyingToken);
    event Withdraw(address indexed user, uint256 underlyingToken, uint256 overlyingToken);
    event RewardClaimed(address indexed user, address indexed to, uint256 amount);
    event SnapshotterUpdated(address snapshotter, bool isSnapshotter);

    constructor(
        string memory _name,
        string memory _symbol,
        address _token
    ) ERC20(_name, _symbol) {
        token = Token(_token);
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    /// @notice when the smart contract receives ETH, register payment
    /// @dev can only receive ETH when tokens are staked
    receive() external payable {
        require(totalSupply() > 0, "NO_TOKENS_STAKED");
        if (msg.value > 0) {
            magnifiedRewardPerShare += (msg.value * MAGNITUDE) / totalSupply();
            emit RewardsReceived(_msgSender(), msg.value);
        }
    }

    /// @notice creates a snapshot of the current balances, used to calculate random NFT rewards
    /// @dev only parties with snapshotter role can call this function
    /// @return id of the taken snapshot
    function takeSnapshot() external onlyRole(SNAPSHOTTER_ROLE) returns (uint256) {
        return _snapshot();
    }

    /// @notice allows to deposit tokens without an approve transaction by using the EIP2612 permit standard
    /// @param _amount amount of underlying token to deposit
    /// @param _deadline until the signature is valid
    /// @param _signature permit signature
    function depositWithPermit(
        uint256 _amount,
        uint256 _deadline,
        bytes memory _signature
    ) external {
        require(_signature.length == 65);
        bytes32 r;
        bytes32 s;
        uint8 v;

        assembly {
            r := mload(add(_signature, 32))
            s := mload(add(_signature, 64))
            v := byte(0, mload(add(_signature, 96)))
        }

        token.permit(_msgSender(), address(this), type(uint256).max, _deadline, v, r, s);
        deposit(_amount);
    }

    /// @notice allows to deposit the underlying token into the staking contract
    /// @dev mints an amount of overlying tokens according to the stake in the pool
    /// @param _amount amount of underlying token to deposit
    function deposit(uint256 _amount) public {
        uint256 share = 0;
        if (totalSupply() > 0) {
            share = (totalSupply() * _amount) / token.balanceOf(address(this));
        } else {
            share = _amount;
        }
        token.transferFrom(_msgSender(), address(this), _amount);
        _mint(_msgSender(), share);
        emit Deposit(_msgSender(), _amount, share);
    }

    /// @notice allows to withdraw the underlying token from the staking contract
    /// @param _amount of overlying tokens to withdraw
    /// @param _claim whether or not to claim ETH rewards
    /// @return amount of underlying tokens withdrawn
    function withdraw(uint256 _amount, bool _claim) external returns (uint256) {
        if (_claim) {
            claimRewards(_msgSender());
        }
        uint256 withdrawnTokens = (_amount * token.balanceOf(address(this))) / totalSupply();
        _burn(_msgSender(), _amount);
        token.transfer(_msgSender(), withdrawnTokens);
        emit Withdraw(_msgSender(), withdrawnTokens, _amount);
        return withdrawnTokens;
    }

    /// @notice allows to claim accumulated ETH rewards
    /// @param _to address to send rewards to
    function claimRewards(address _to) public {
        uint256 claimableRewards = claimableRewardsOf(_msgSender());
        if (claimableRewards > 0) {
            claimedRewards[_msgSender()] += claimableRewards;
            (bool success, ) = _to.call{value: claimableRewards}("");
            require(success, "ETH_TRANSFER_FAILED");
            emit RewardClaimed(_msgSender(), _to, claimableRewards);
        }
    }

    /// @dev on mint, burn and transfer adjust corrections so that ETH rewards don't change on these events
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        if (from == address(0)) {
            // mint
            magnifiedRewardCorrections[to] -= (magnifiedRewardPerShare * amount).toInt256Safe();
        } else if (to == address(0)) {
            // burn
            magnifiedRewardCorrections[from] += (magnifiedRewardPerShare * amount).toInt256Safe();
        } else {
            // transfer
            int256 magnifiedCorrection = (magnifiedRewardPerShare * amount).toInt256Safe();
            magnifiedRewardCorrections[from] += (magnifiedCorrection);
            magnifiedRewardCorrections[to] -= (magnifiedCorrection);
        }
    }

    /// @return accumulated underlying token balance that can be withdrawn by the user
    function tokenBalance(address _user) public view returns (uint256) {
        if (totalSupply() == 0) {
            return 0;
        }
        return (balanceOf(_user) * token.balanceOf(address(this))) / totalSupply();
    }

    /// @return total amount of ETH rewards earned by user
    function totalRewardsEarned(address _user) public view returns (uint256) {
        int256 magnifiedRewards = (magnifiedRewardPerShare * balanceOf(_user)).toInt256Safe();
        uint256 correctedRewards = (magnifiedRewards + magnifiedRewardCorrections[_user]).toUint256Safe();
        return correctedRewards / MAGNITUDE;
    }

    /// @return amount of ETH rewards that can be claimed by user
    function claimableRewardsOf(address _user) public view returns (uint256) {
        return totalRewardsEarned(_user) - claimedRewards[_user];
    }
}

File 1 of 17: AccessControl.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Context.sol";
import "./Strings.sol";
import "./ERC165.sol";

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    function hasRole(bytes32 role, address account) external view returns (bool);

    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    function grantRole(bytes32 role, address account) external;

    function revokeRole(bytes32 role, address account) external;

    function renounceRole(bytes32 role, address account) external;
}

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);
        _roles[role].adminRole = adminRole;
    }

    function _grantRole(bytes32 role, address account) private {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 2 of 17: AccessControlEnumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./AccessControl.sol";
import "./EnumerableSet.sol";

/**
 * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
 */
interface IAccessControlEnumerable {
    function getRoleMember(bytes32 role, uint256 index) external view returns (address);

    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

/**
 * @dev Extension of {AccessControl} that allows enumerating the members of each role.
 */
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
    using EnumerableSet for EnumerableSet.AddressSet;

    mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
        return _roleMembers[role].at(index);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
        return _roleMembers[role].length();
    }

    /**
     * @dev Overload {grantRole} to track enumerable memberships
     */
    function grantRole(bytes32 role, address account) public virtual override {
        super.grantRole(role, account);
        _roleMembers[role].add(account);
    }

    /**
     * @dev Overload {revokeRole} to track enumerable memberships
     */
    function revokeRole(bytes32 role, address account) public virtual override {
        super.revokeRole(role, account);
        _roleMembers[role].remove(account);
    }

    /**
     * @dev Overload {renounceRole} to track enumerable memberships
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        super.renounceRole(role, account);
        _roleMembers[role].remove(account);
    }

    /**
     * @dev Overload {_setupRole} to track enumerable memberships
     */
    function _setupRole(bytes32 role, address account) internal virtual override {
        super._setupRole(role, account);
        _roleMembers[role].add(account);
    }
}

File 3 of 17: Arrays.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Math.sol";

/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
    /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * `array` is expected to be sorted in ascending order, and to contain no
     * repeated elements.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (array[mid] > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && array[low - 1] == element) {
            return low - 1;
        } else {
            return low;
        }
    }
}

File 4 of 17: Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 5 of 17: Counters.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 6 of 17: draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 7 of 17: EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastvalue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastvalue;
                // Update the index for the moved value
                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 8 of 17: ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 9 of 17: ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./IERC20Metadata.sol";
import "./Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

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

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

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

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 10 of 17: ERC20Snapshot.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC20.sol";
import "./Arrays.sol";
import "./Counters.sol";

/**
 * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and
 * total supply at the time are recorded for later access.
 *
 * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting.
 * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different
 * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be
 * used to create an efficient ERC20 forking mechanism.
 *
 * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a
 * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot
 * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id
 * and the account address.
 *
 * NOTE: Snapshot policy can be customized by overriding the {_getCurrentSnapshotId} method. For example, having it
 * return `block.number` will trigger the creation of snapshot at the begining of each new block. When overridding this
 * function, be careful about the monotonicity of its result. Non-monotonic snapshot ids will break the contract.
 *
 * Implementing snapshots for every block using this method will incur significant gas costs. For a gas-efficient
 * alternative consider {ERC20Votes}.
 *
 * ==== Gas Costs
 *
 * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log
 * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much
 * smaller since identical balances in subsequent snapshots are stored as a single entry.
 *
 * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is
 * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent
 * transfers will have normal cost until the next snapshot, and so on.
 */

abstract contract ERC20Snapshot is ERC20 {
    // Inspired by Jordi Baylina's MiniMeToken to record historical balances:
    // https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol

    using Arrays for uint256[];
    using Counters for Counters.Counter;

    // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a
    // Snapshot struct, but that would impede usage of functions that work on an array.
    struct Snapshots {
        uint256[] ids;
        uint256[] values;
    }

    mapping(address => Snapshots) private _accountBalanceSnapshots;
    Snapshots private _totalSupplySnapshots;

    // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
    Counters.Counter private _currentSnapshotId;

    /**
     * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created.
     */
    event Snapshot(uint256 id);

    /**
     * @dev Creates a new snapshot and returns its snapshot id.
     *
     * Emits a {Snapshot} event that contains the same id.
     *
     * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a
     * set of accounts, for example using {AccessControl}, or it may be open to the public.
     *
     * [WARNING]
     * ====
     * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking,
     * you must consider that it can potentially be used by attackers in two ways.
     *
     * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow
     * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target
     * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs
     * section above.
     *
     * We haven't measured the actual numbers; if this is something you're interested in please reach out to us.
     * ====
     */
    function _snapshot() internal virtual returns (uint256) {
        _currentSnapshotId.increment();

        uint256 currentId = _getCurrentSnapshotId();
        emit Snapshot(currentId);
        return currentId;
    }

    /**
     * @dev Get the current snapshotId
     */
    function _getCurrentSnapshotId() internal view virtual returns (uint256) {
        return _currentSnapshotId.current();
    }

    /**
     * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
     */
    function balanceOfAt(address account, uint256 snapshotId) public view virtual returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);

        return snapshotted ? value : balanceOf(account);
    }

    /**
     * @dev Retrieves the total supply at the time `snapshotId` was created.
     */
    function totalSupplyAt(uint256 snapshotId) public view virtual returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);

        return snapshotted ? value : totalSupply();
    }

    // Update balance and/or total supply snapshots before the values are modified. This is implemented
    // in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations.
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        if (from == address(0)) {
            // mint
            _updateAccountSnapshot(to);
            _updateTotalSupplySnapshot();
        } else if (to == address(0)) {
            // burn
            _updateAccountSnapshot(from);
            _updateTotalSupplySnapshot();
        } else {
            // transfer
            _updateAccountSnapshot(from);
            _updateAccountSnapshot(to);
        }
    }

    function _valueAt(uint256 snapshotId, Snapshots storage snapshots) private view returns (bool, uint256) {
        require(snapshotId > 0, "ERC20Snapshot: id is 0");
        require(snapshotId <= _getCurrentSnapshotId(), "ERC20Snapshot: nonexistent id");

        // When a valid snapshot is queried, there are three possibilities:
        //  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
        //  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
        //  to this id is the current one.
        //  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
        //  requested id, and its value is the one to return.
        //  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
        //  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
        //  larger than the requested one.
        //
        // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
        // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
        // exactly this.

        uint256 index = snapshots.ids.findUpperBound(snapshotId);

        if (index == snapshots.ids.length) {
            return (false, 0);
        } else {
            return (true, snapshots.values[index]);
        }
    }

    function _updateAccountSnapshot(address account) private {
        _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
    }

    function _updateTotalSupplySnapshot() private {
        _updateSnapshot(_totalSupplySnapshots, totalSupply());
    }

    function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
        uint256 currentId = _getCurrentSnapshotId();
        if (_lastSnapshotId(snapshots.ids) < currentId) {
            snapshots.ids.push(currentId);
            snapshots.values.push(currentValue);
        }
    }

    function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
        if (ids.length == 0) {
            return 0;
        } else {
            return ids[ids.length - 1];
        }
    }
}

File 11 of 17: IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

File 12 of 17: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 13 of 17: IERC20Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

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

File 14 of 17: Math.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute.
        return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2);
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a / b + (a % b == 0 ? 0 : 1);
    }
}

File 15 of 17: SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

library SafeMathInt {
    function toUint256Safe(int256 a) internal pure returns (uint256) {
        require(a >= 0);
        return uint256(a);
    }
}

library SafeMathUint {
    function toInt256Safe(uint256 a) internal pure returns (int256) {
        int256 b = int256(a);
        require(b >= 0);
        return b;
    }
}

File 17 of 17: Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"underlyingToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"overlyingToken","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Snapshot","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"snapshotter","type":"address"},{"indexed":false,"internalType":"bool","name":"isSnapshotter","type":"bool"}],"name":"SnapshotterUpdated","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":false,"internalType":"uint256","name":"underlyingToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"overlyingToken","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SNAPSHOTTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"amount","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":"account","type":"address"},{"internalType":"uint256","name":"snapshotId","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"claimableRewardsOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"depositWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"takeSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"totalRewardsEarned","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":"uint256","name":"snapshotId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_claim","type":"bool"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b5060405162002fc338038062002fc3833981016040819052620000349162000359565b8251839083906200004d90600390602085019062000200565b5080516200006390600490602084019062000200565b5050600b80546001600160a01b0319166001600160a01b038416179055506200008e60003362000097565b50505062000435565b620000ae8282620000da60201b6200129d1760201c565b6000828152600a60209081526040909120620000d5918390620012a7620000ea821b17901c565b505050565b620000e682826200010a565b5050565b600062000101836001600160a01b038416620001ae565b90505b92915050565b60008281526009602090815260408083206001600160a01b038516845290915290205460ff16620000e65760008281526009602090815260408083206001600160a01b03851684529091529020805460ff191660011790556200016a3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000818152600183016020526040812054620001f75750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000104565b50600062000104565b8280546200020e90620003e2565b90600052602060002090601f0160209004810192826200023257600085556200027d565b82601f106200024d57805160ff19168380011785556200027d565b828001600101855582156200027d579182015b828111156200027d57825182559160200191906001019062000260565b506200028b9291506200028f565b5090565b5b808211156200028b576000815560010162000290565b600082601f830112620002b7578081fd5b81516001600160401b0380821115620002d457620002d46200041f565b604051601f8301601f19908116603f01168101908282118183101715620002ff57620002ff6200041f565b816040528381526020925086838588010111156200031b578485fd5b8491505b838210156200033e57858201830151818301840152908201906200031f565b838211156200034f57848385830101525b9695505050505050565b6000806000606084860312156200036e578283fd5b83516001600160401b038082111562000385578485fd5b6200039387838801620002a6565b94506020860151915080821115620003a9578384fd5b50620003b886828701620002a6565b604086015190935090506001600160a01b0381168114620003d7578182fd5b809150509250925092565b600181811c90821680620003f757607f821691505b602082108114156200041957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b612b7e80620004456000396000f3fe6080604052600436106101e75760003560e01c806391d1485411610102578063bd83434511610095578063dd62ed3e11610064578063dd62ed3e146106c0578063e4f24cb014610706578063eedc966a14610726578063ef5cfb8c1461074657600080fd5b8063bd8343451461061f578063ca15c8731461064c578063cb2db4371461066c578063d547741f146106a057600080fd5b8063a457c2d7116100d1578063a457c2d7146105aa578063a9059cbb146105ca578063b3d3d37e146105ea578063b6b55f25146105ff57600080fd5b806391d148541461051a57806395d89b4114610560578063981b24d014610575578063a217fddf1461059557600080fd5b806336568abe1161017a57806370a082311161014957806370a082311461046c57806385d2015c146104a25780639010d07c146104c257806391cc5961146104fa57600080fd5b806336568abe146103ec57806338d074361461040c578063395093511461042c5780634ee2cd7e1461044c57600080fd5b806323b872dd116101b657806323b872dd14610360578063248a9ca3146103805780632f2ff15d146103b0578063313ce567146103d057600080fd5b806301ffc9a7146102ca57806306fdde03146102ff578063095ea7b31461032157806318160ddd1461034157600080fd5b366102c55760006101f760025490565b116102495760405162461bcd60e51b815260206004820152601060248201527f4e4f5f544f4b454e535f5354414b45440000000000000000000000000000000060448201526064015b60405180910390fd5b34156102c35760025461026d701d6329f1c35ca4bfabb9f561000000000034612980565b610277919061296c565b600c60008282546102889190612954565b909155505060405134815233907f577e40010b42fd80bafa850999e7cec91750c749202445266b373708c59294209060200160405180910390a25b005b600080fd5b3480156102d657600080fd5b506102ea6102e53660046126aa565b610766565b60405190151581526020015b60405180910390f35b34801561030b57600080fd5b506103146107c2565b6040516102f6919061288f565b34801561032d57600080fd5b506102ea61033c36600461260a565b610854565b34801561034d57600080fd5b506002545b6040519081526020016102f6565b34801561036c57600080fd5b506102ea61037b3660046125cf565b61086a565b34801561038c57600080fd5b5061035261039b36600461264f565b60009081526009602052604090206001015490565b3480156103bc57600080fd5b506102c36103cb366004612667565b610929565b3480156103dc57600080fd5b50604051601281526020016102f6565b3480156103f857600080fd5b506102c3610407366004612667565b610950565b34801561041857600080fd5b50610352610427366004612702565b610972565b34801561043857600080fd5b506102ea61044736600461260a565b610b2f565b34801561045857600080fd5b5061035261046736600461260a565b610b6b565b34801561047857600080fd5b50610352610487366004612583565b6001600160a01b031660009081526020819052604090205490565b3480156104ae57600080fd5b506103526104bd366004612583565b610bc4565b3480156104ce57600080fd5b506104e26104dd366004612689565b610bf0565b6040516001600160a01b0390911681526020016102f6565b34801561050657600080fd5b506102c3610515366004612731565b610c0f565b34801561052657600080fd5b506102ea610535366004612667565b60009182526009602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561056c57600080fd5b50610314610d03565b34801561058157600080fd5b5061035261059036600461264f565b610d12565b3480156105a157600080fd5b50610352600081565b3480156105b657600080fd5b506102ea6105c536600461260a565b610d3d565b3480156105d657600080fd5b506102ea6105e536600461260a565b610dee565b3480156105f657600080fd5b50610352610dfb565b34801561060b57600080fd5b506102c361061a36600461264f565b610e36565b34801561062b57600080fd5b5061035261063a366004612583565b600e6020526000908152604090205481565b34801561065857600080fd5b5061035261066736600461264f565b610ffe565b34801561067857600080fd5b506103527f448f811bab0a96b12a5a67c73e96871dba861330a24a3040e1baeb42bb606d3181565b3480156106ac57600080fd5b506102c36106bb366004612667565b611015565b3480156106cc57600080fd5b506103526106db36600461259d565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b34801561071257600080fd5b50610352610721366004612583565b61101f565b34801561073257600080fd5b50610352610741366004612583565b6110a3565b34801561075257600080fd5b506102c3610761366004612583565b61117e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f0000000000000000000000000000000000000000000000000000000014806107bc57506107bc826112bc565b92915050565b6060600380546107d190612aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546107fd90612aa9565b801561084a5780601f1061081f5761010080835404028352916020019161084a565b820191906000526020600020905b81548152906001019060200180831161082d57829003601f168201915b5050505050905090565b6000610861338484611353565b50600192915050565b60006108778484846114a3565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156109115760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e63650000000000000000000000000000000000000000000000006064820152608401610240565b61091e8533858403611353565b506001949350505050565b61093382826116c7565b6000828152600a6020526040902061094b90826112a7565b505050565b61095a82826116ed565b6000828152600a6020526040902061094b9082611775565b60008115610983576109833361117e565b600061098e60025490565b600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b1580156109ea57600080fd5b505afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2291906126ea565b610a2c9086612980565b610a36919061296c565b9050610a42338561178a565b600b546001600160a01b031663a9059cbb336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b158015610ab457600080fd5b505af1158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190612633565b50604080518281526020810186905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a29392505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610861918590610b66908690612954565b611353565b6001600160a01b038216600090815260056020526040812081908190610b9290859061191b565b9150915081610bb9576001600160a01b038516600090815260208190526040902054610bbb565b805b95945050505050565b6001600160a01b0381166000908152600e6020526040812054610be68361101f565b6107bc9190612a31565b6000828152600a60205260408120610c089083611a27565b9392505050565b8051604114610c1d57600080fd5b60208101516040808301516060840151600b5483517fd505accf0000000000000000000000000000000000000000000000000000000081523360048201523060248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff604482015260648101889052600092831a6084820181905260a4820187905260c4820185905294519394936001600160a01b039092169263d505accf9260e48084019382900301818387803b158015610cda57600080fd5b505af1158015610cee573d6000803e3d6000fd5b50505050610cfb86610e36565b505050505050565b6060600480546107d190612aa9565b6000806000610d2284600661191b565b9150915081610d3357600254610d35565b805b949350505050565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610dd75760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610240565b610de43385858403611353565b5060019392505050565b60006108613384846114a3565b60007f448f811bab0a96b12a5a67c73e96871dba861330a24a3040e1baeb42bb606d31610e288133611a33565b610e30611ad1565b91505090565b600080610e4260025490565b1115610f0157600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610ea457600080fd5b505afa158015610eb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edc91906126ea565b82610ee660025490565b610ef09190612980565b610efa919061296c565b9050610f04565b50805b600b546001600160a01b03166323b872dd336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015230602482015260448101859052606401602060405180830381600087803b158015610f7c57600080fd5b505af1158015610f90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb49190612633565b50610fbf3382611b2b565b604080518381526020810183905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a25050565b6000818152600a602052604081206107bc90611c16565b61095a8282611c20565b600080611056611044846001600160a01b031660009081526020819052604090205490565b600c546110519190612980565b611c46565b6001600160a01b0384166000908152600d6020526040812054919250906110869061108190846128e0565b611c56565b9050610d35701d6329f1c35ca4bfabb9f56100000000008261296c565b60006110ae60025490565b6110ba57506000919050565b600254600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561111957600080fd5b505afa15801561112d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115191906126ea565b6001600160a01b0384166000908152602081905260409020546111749190612980565b6107bc919061296c565b600061118933610bc4565b9050801561129957336000908152600e6020526040812080548392906111b0908490612954565b90915550506040516000906001600160a01b0384169083908381818185875af1925050503d8060008114611200576040519150601f19603f3d011682016040523d82523d6000602084013e611205565b606091505b50509050806112565760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610240565b6040518281526001600160a01b0384169033907f0aa4d283470c904c551d18bb894d37e17674920f3261a7f854be501e25f421b7906020015b60405180910390a3505b5050565b6112998282611c69565b6000610c08836001600160a01b038416611d29565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107bc57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107bc565b6001600160a01b0383166113ce5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b03821661144a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910161128f565b6001600160a01b03831661151f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b03821661159b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610240565b6115a6838383611d78565b6001600160a01b038316600090815260208190526040902054818110156116355760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061166c908490612954565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516116b891815260200190565b60405180910390a35b50505050565b6000828152600960205260409020600101546116e38133611a33565b61094b8383611c69565b6001600160a01b038116331461176b5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610240565b6112998282611e94565b6000610c08836001600160a01b038416611f35565b6001600160a01b0382166118065760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610240565b61181282600083611d78565b6001600160a01b038216600090815260208190526040902054818110156118a15760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b03831660009081526020819052604081208383039055600280548492906118d0908490612a31565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6000806000841161196e5760405162461bcd60e51b815260206004820152601660248201527f4552433230536e617073686f743a2069642069732030000000000000000000006044820152606401610240565b611976612052565b8411156119c55760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e742069640000006044820152606401610240565b60006119d18486612062565b84549091508114156119ea576000809250925050611a20565b6001846001018281548110611a0f57634e487b7160e01b600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b6000610c088383612141565b60008281526009602090815260408083206001600160a01b038516845290915290205460ff1661129957611a71816001600160a01b03166014612179565b611a7c836020612179565b604051602001611a8d92919061280e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262461bcd60e51b82526102409160040161288f565b6000611ae1600880546001019055565b6000611aeb612052565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611b1e91815260200190565b60405180910390a1919050565b6001600160a01b038216611b815760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610240565b611b8d60008383611d78565b8060026000828254611b9f9190612954565b90915550506001600160a01b03821660009081526020819052604081208054839290611bcc908490612954565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60006107bc825490565b600082815260096020526040902060010154611c3c8133611a33565b61094b8383611e94565b600081818112156107bc57600080fd5b600080821215611c6557600080fd5b5090565b60008281526009602090815260408083206001600160a01b038516845290915290205460ff166112995760008281526009602090815260408083206001600160a01b0385168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611ce53390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000818152600183016020526040812054611d70575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107bc565b5060006107bc565b611d838383836123e8565b6001600160a01b038316611dd557611da281600c546110519190612980565b6001600160a01b0383166000908152600d602052604081208054909190611dca9084906129bd565b9091555061094b9050565b6001600160a01b038216611e1c57611df481600c546110519190612980565b6001600160a01b0384166000908152600d602052604081208054909190611dca9084906128e0565b6000611e2f82600c546110519190612980565b6001600160a01b0385166000908152600d6020526040812080549293508392909190611e5c9084906128e0565b90915550506001600160a01b0383166000908152600d602052604081208054839290611e899084906129bd565b909155505050505050565b60008281526009602090815260408083206001600160a01b038516845290915290205460ff16156112995760008281526009602090815260408083206001600160a01b038516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008181526001830160205260408120548015612048576000611f59600183612a31565b8554909150600090611f6d90600190612a31565b9050818114611fee576000866000018281548110611f9b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905080876000018481548110611fcc57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061200d57634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107bc565b60009150506107bc565b600061205d60085490565b905090565b8154600090612073575060006107bc565b82546000905b808210156120dd57600061208d8383612430565b9050848682815481106120b057634e487b7160e01b600052603260045260246000fd5b906000526020600020015411156120c9578091506120d7565b6120d4816001612954565b92505b50612079565b600082118015612120575083856120f5600185612a31565b8154811061211357634e487b7160e01b600052603260045260246000fd5b9060005260206000200154145b1561213957612130600183612a31565b925050506107bc565b5090506107bc565b600082600001828154811061216657634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000612188836002612980565b612193906002612954565b67ffffffffffffffff8111156121b957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156121e3576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061222857634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061229957634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006122d5846002612980565b6122e0906001612954565b90505b6001811115612399577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061232f57634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061235357634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361239281612a74565b90506122e3565b508315610c085760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610240565b6001600160a01b038316612407576123ff82612487565b61094b6124bc565b6001600160a01b03821661241e576123ff83612487565b61242783612487565b61094b82612487565b6000600261243e8184612ae4565b612449600286612ae4565b6124539190612954565b61245d919061296c565b61246860028461296c565b61247360028661296c565b61247d9190612954565b610c089190612954565b6001600160a01b038116600090815260056020908152604080832091839052909120546124b991906124cc565b6124cc565b50565b6124ca60066124b460025490565b565b60006124d6612052565b9050806124e284612516565b101561094b578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b805460009061252757506000919050565b8154829061253790600190612a31565b8154811061255557634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b919050565b80356001600160a01b038116811461256757600080fd5b600060208284031215612594578081fd5b610c088261256c565b600080604083850312156125af578081fd5b6125b88361256c565b91506125c66020840161256c565b90509250929050565b6000806000606084860312156125e3578081fd5b6125ec8461256c565b92506125fa6020850161256c565b9150604084013590509250925092565b6000806040838503121561261c578182fd5b6126258361256c565b946020939093013593505050565b600060208284031215612644578081fd5b8151610c0881612b3a565b600060208284031215612660578081fd5b5035919050565b60008060408385031215612679578182fd5b823591506125c66020840161256c565b6000806040838503121561269b578182fd5b50508035926020909101359150565b6000602082840312156126bb578081fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610c08578182fd5b6000602082840312156126fb578081fd5b5051919050565b60008060408385031215612714578182fd5b82359150602083013561272681612b3a565b809150509250929050565b600080600060608486031215612745578283fd5b8335925060208401359150604084013567ffffffffffffffff8082111561276a578283fd5b818601915086601f83011261277d578283fd5b81358181111561278f5761278f612b24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156127d5576127d5612b24565b816040528281528960208487010111156127ed578586fd5b82602086016020830137856020848301015280955050505050509250925092565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612846816017850160208801612a48565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612883816028840160208801612a48565b01602801949350505050565b60208152600082518060208401526128ae816040850160208701612a48565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561291a5761291a612af8565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561294e5761294e612af8565b50500190565b6000821982111561296757612967612af8565b500190565b60008261297b5761297b612b0e565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156129b8576129b8612af8565b500290565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156129f7576129f7612af8565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615612a2b57612a2b612af8565b50500390565b600082821015612a4357612a43612af8565b500390565b60005b83811015612a63578181015183820152602001612a4b565b838111156116c15750506000910152565b600081612a8357612a83612af8565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600181811c90821680612abd57607f821691505b60208210811415612ade57634e487b7160e01b600052602260045260246000fd5b50919050565b600082612af357612af3612b0e565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b80151581146124b957600080fdfea2646970667358221220b8c8005c5c8e032159a7cb883636a57d39c3f5528a010572cd6bf4b33158d8f264736f6c63430008040033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000060f5672a271c7e39e787427a18353ba59a4a3578000000000000000000000000000000000000000000000000000000000000000b5374616b65642050494b410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006737450494b410000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101e75760003560e01c806391d1485411610102578063bd83434511610095578063dd62ed3e11610064578063dd62ed3e146106c0578063e4f24cb014610706578063eedc966a14610726578063ef5cfb8c1461074657600080fd5b8063bd8343451461061f578063ca15c8731461064c578063cb2db4371461066c578063d547741f146106a057600080fd5b8063a457c2d7116100d1578063a457c2d7146105aa578063a9059cbb146105ca578063b3d3d37e146105ea578063b6b55f25146105ff57600080fd5b806391d148541461051a57806395d89b4114610560578063981b24d014610575578063a217fddf1461059557600080fd5b806336568abe1161017a57806370a082311161014957806370a082311461046c57806385d2015c146104a25780639010d07c146104c257806391cc5961146104fa57600080fd5b806336568abe146103ec57806338d074361461040c578063395093511461042c5780634ee2cd7e1461044c57600080fd5b806323b872dd116101b657806323b872dd14610360578063248a9ca3146103805780632f2ff15d146103b0578063313ce567146103d057600080fd5b806301ffc9a7146102ca57806306fdde03146102ff578063095ea7b31461032157806318160ddd1461034157600080fd5b366102c55760006101f760025490565b116102495760405162461bcd60e51b815260206004820152601060248201527f4e4f5f544f4b454e535f5354414b45440000000000000000000000000000000060448201526064015b60405180910390fd5b34156102c35760025461026d701d6329f1c35ca4bfabb9f561000000000034612980565b610277919061296c565b600c60008282546102889190612954565b909155505060405134815233907f577e40010b42fd80bafa850999e7cec91750c749202445266b373708c59294209060200160405180910390a25b005b600080fd5b3480156102d657600080fd5b506102ea6102e53660046126aa565b610766565b60405190151581526020015b60405180910390f35b34801561030b57600080fd5b506103146107c2565b6040516102f6919061288f565b34801561032d57600080fd5b506102ea61033c36600461260a565b610854565b34801561034d57600080fd5b506002545b6040519081526020016102f6565b34801561036c57600080fd5b506102ea61037b3660046125cf565b61086a565b34801561038c57600080fd5b5061035261039b36600461264f565b60009081526009602052604090206001015490565b3480156103bc57600080fd5b506102c36103cb366004612667565b610929565b3480156103dc57600080fd5b50604051601281526020016102f6565b3480156103f857600080fd5b506102c3610407366004612667565b610950565b34801561041857600080fd5b50610352610427366004612702565b610972565b34801561043857600080fd5b506102ea61044736600461260a565b610b2f565b34801561045857600080fd5b5061035261046736600461260a565b610b6b565b34801561047857600080fd5b50610352610487366004612583565b6001600160a01b031660009081526020819052604090205490565b3480156104ae57600080fd5b506103526104bd366004612583565b610bc4565b3480156104ce57600080fd5b506104e26104dd366004612689565b610bf0565b6040516001600160a01b0390911681526020016102f6565b34801561050657600080fd5b506102c3610515366004612731565b610c0f565b34801561052657600080fd5b506102ea610535366004612667565b60009182526009602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561056c57600080fd5b50610314610d03565b34801561058157600080fd5b5061035261059036600461264f565b610d12565b3480156105a157600080fd5b50610352600081565b3480156105b657600080fd5b506102ea6105c536600461260a565b610d3d565b3480156105d657600080fd5b506102ea6105e536600461260a565b610dee565b3480156105f657600080fd5b50610352610dfb565b34801561060b57600080fd5b506102c361061a36600461264f565b610e36565b34801561062b57600080fd5b5061035261063a366004612583565b600e6020526000908152604090205481565b34801561065857600080fd5b5061035261066736600461264f565b610ffe565b34801561067857600080fd5b506103527f448f811bab0a96b12a5a67c73e96871dba861330a24a3040e1baeb42bb606d3181565b3480156106ac57600080fd5b506102c36106bb366004612667565b611015565b3480156106cc57600080fd5b506103526106db36600461259d565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b34801561071257600080fd5b50610352610721366004612583565b61101f565b34801561073257600080fd5b50610352610741366004612583565b6110a3565b34801561075257600080fd5b506102c3610761366004612583565b61117e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f0000000000000000000000000000000000000000000000000000000014806107bc57506107bc826112bc565b92915050565b6060600380546107d190612aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546107fd90612aa9565b801561084a5780601f1061081f5761010080835404028352916020019161084a565b820191906000526020600020905b81548152906001019060200180831161082d57829003601f168201915b5050505050905090565b6000610861338484611353565b50600192915050565b60006108778484846114a3565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156109115760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e63650000000000000000000000000000000000000000000000006064820152608401610240565b61091e8533858403611353565b506001949350505050565b61093382826116c7565b6000828152600a6020526040902061094b90826112a7565b505050565b61095a82826116ed565b6000828152600a6020526040902061094b9082611775565b60008115610983576109833361117e565b600061098e60025490565b600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b1580156109ea57600080fd5b505afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2291906126ea565b610a2c9086612980565b610a36919061296c565b9050610a42338561178a565b600b546001600160a01b031663a9059cbb336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b158015610ab457600080fd5b505af1158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec9190612633565b50604080518281526020810186905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a29392505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610861918590610b66908690612954565b611353565b6001600160a01b038216600090815260056020526040812081908190610b9290859061191b565b9150915081610bb9576001600160a01b038516600090815260208190526040902054610bbb565b805b95945050505050565b6001600160a01b0381166000908152600e6020526040812054610be68361101f565b6107bc9190612a31565b6000828152600a60205260408120610c089083611a27565b9392505050565b8051604114610c1d57600080fd5b60208101516040808301516060840151600b5483517fd505accf0000000000000000000000000000000000000000000000000000000081523360048201523060248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff604482015260648101889052600092831a6084820181905260a4820187905260c4820185905294519394936001600160a01b039092169263d505accf9260e48084019382900301818387803b158015610cda57600080fd5b505af1158015610cee573d6000803e3d6000fd5b50505050610cfb86610e36565b505050505050565b6060600480546107d190612aa9565b6000806000610d2284600661191b565b9150915081610d3357600254610d35565b805b949350505050565b3360009081526001602090815260408083206001600160a01b038616845290915281205482811015610dd75760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610240565b610de43385858403611353565b5060019392505050565b60006108613384846114a3565b60007f448f811bab0a96b12a5a67c73e96871dba861330a24a3040e1baeb42bb606d31610e288133611a33565b610e30611ad1565b91505090565b600080610e4260025490565b1115610f0157600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610ea457600080fd5b505afa158015610eb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edc91906126ea565b82610ee660025490565b610ef09190612980565b610efa919061296c565b9050610f04565b50805b600b546001600160a01b03166323b872dd336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015230602482015260448101859052606401602060405180830381600087803b158015610f7c57600080fd5b505af1158015610f90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb49190612633565b50610fbf3382611b2b565b604080518381526020810183905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a25050565b6000818152600a602052604081206107bc90611c16565b61095a8282611c20565b600080611056611044846001600160a01b031660009081526020819052604090205490565b600c546110519190612980565b611c46565b6001600160a01b0384166000908152600d6020526040812054919250906110869061108190846128e0565b611c56565b9050610d35701d6329f1c35ca4bfabb9f56100000000008261296c565b60006110ae60025490565b6110ba57506000919050565b600254600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561111957600080fd5b505afa15801561112d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115191906126ea565b6001600160a01b0384166000908152602081905260409020546111749190612980565b6107bc919061296c565b600061118933610bc4565b9050801561129957336000908152600e6020526040812080548392906111b0908490612954565b90915550506040516000906001600160a01b0384169083908381818185875af1925050503d8060008114611200576040519150601f19603f3d011682016040523d82523d6000602084013e611205565b606091505b50509050806112565760405162461bcd60e51b815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610240565b6040518281526001600160a01b0384169033907f0aa4d283470c904c551d18bb894d37e17674920f3261a7f854be501e25f421b7906020015b60405180910390a3505b5050565b6112998282611c69565b6000610c08836001600160a01b038416611d29565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107bc57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107bc565b6001600160a01b0383166113ce5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b03821661144a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910161128f565b6001600160a01b03831661151f5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b03821661159b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610240565b6115a6838383611d78565b6001600160a01b038316600090815260208190526040902054818110156116355760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061166c908490612954565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516116b891815260200190565b60405180910390a35b50505050565b6000828152600960205260409020600101546116e38133611a33565b61094b8383611c69565b6001600160a01b038116331461176b5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610240565b6112998282611e94565b6000610c08836001600160a01b038416611f35565b6001600160a01b0382166118065760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610240565b61181282600083611d78565b6001600160a01b038216600090815260208190526040902054818110156118a15760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610240565b6001600160a01b03831660009081526020819052604081208383039055600280548492906118d0908490612a31565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6000806000841161196e5760405162461bcd60e51b815260206004820152601660248201527f4552433230536e617073686f743a2069642069732030000000000000000000006044820152606401610240565b611976612052565b8411156119c55760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e742069640000006044820152606401610240565b60006119d18486612062565b84549091508114156119ea576000809250925050611a20565b6001846001018281548110611a0f57634e487b7160e01b600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b6000610c088383612141565b60008281526009602090815260408083206001600160a01b038516845290915290205460ff1661129957611a71816001600160a01b03166014612179565b611a7c836020612179565b604051602001611a8d92919061280e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262461bcd60e51b82526102409160040161288f565b6000611ae1600880546001019055565b6000611aeb612052565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb6781604051611b1e91815260200190565b60405180910390a1919050565b6001600160a01b038216611b815760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610240565b611b8d60008383611d78565b8060026000828254611b9f9190612954565b90915550506001600160a01b03821660009081526020819052604081208054839290611bcc908490612954565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60006107bc825490565b600082815260096020526040902060010154611c3c8133611a33565b61094b8383611e94565b600081818112156107bc57600080fd5b600080821215611c6557600080fd5b5090565b60008281526009602090815260408083206001600160a01b038516845290915290205460ff166112995760008281526009602090815260408083206001600160a01b0385168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611ce53390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000818152600183016020526040812054611d70575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107bc565b5060006107bc565b611d838383836123e8565b6001600160a01b038316611dd557611da281600c546110519190612980565b6001600160a01b0383166000908152600d602052604081208054909190611dca9084906129bd565b9091555061094b9050565b6001600160a01b038216611e1c57611df481600c546110519190612980565b6001600160a01b0384166000908152600d602052604081208054909190611dca9084906128e0565b6000611e2f82600c546110519190612980565b6001600160a01b0385166000908152600d6020526040812080549293508392909190611e5c9084906128e0565b90915550506001600160a01b0383166000908152600d602052604081208054839290611e899084906129bd565b909155505050505050565b60008281526009602090815260408083206001600160a01b038516845290915290205460ff16156112995760008281526009602090815260408083206001600160a01b038516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008181526001830160205260408120548015612048576000611f59600183612a31565b8554909150600090611f6d90600190612a31565b9050818114611fee576000866000018281548110611f9b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905080876000018481548110611fcc57634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061200d57634e487b7160e01b600052603160045260246000fd5b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107bc565b60009150506107bc565b600061205d60085490565b905090565b8154600090612073575060006107bc565b82546000905b808210156120dd57600061208d8383612430565b9050848682815481106120b057634e487b7160e01b600052603260045260246000fd5b906000526020600020015411156120c9578091506120d7565b6120d4816001612954565b92505b50612079565b600082118015612120575083856120f5600185612a31565b8154811061211357634e487b7160e01b600052603260045260246000fd5b9060005260206000200154145b1561213957612130600183612a31565b925050506107bc565b5090506107bc565b600082600001828154811061216657634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000612188836002612980565b612193906002612954565b67ffffffffffffffff8111156121b957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156121e3576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061222857634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061229957634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006122d5846002612980565b6122e0906001612954565b90505b6001811115612399577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061232f57634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061235357634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361239281612a74565b90506122e3565b508315610c085760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610240565b6001600160a01b038316612407576123ff82612487565b61094b6124bc565b6001600160a01b03821661241e576123ff83612487565b61242783612487565b61094b82612487565b6000600261243e8184612ae4565b612449600286612ae4565b6124539190612954565b61245d919061296c565b61246860028461296c565b61247360028661296c565b61247d9190612954565b610c089190612954565b6001600160a01b038116600090815260056020908152604080832091839052909120546124b991906124cc565b6124cc565b50565b6124ca60066124b460025490565b565b60006124d6612052565b9050806124e284612516565b101561094b578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b805460009061252757506000919050565b8154829061253790600190612a31565b8154811061255557634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b919050565b80356001600160a01b038116811461256757600080fd5b600060208284031215612594578081fd5b610c088261256c565b600080604083850312156125af578081fd5b6125b88361256c565b91506125c66020840161256c565b90509250929050565b6000806000606084860312156125e3578081fd5b6125ec8461256c565b92506125fa6020850161256c565b9150604084013590509250925092565b6000806040838503121561261c578182fd5b6126258361256c565b946020939093013593505050565b600060208284031215612644578081fd5b8151610c0881612b3a565b600060208284031215612660578081fd5b5035919050565b60008060408385031215612679578182fd5b823591506125c66020840161256c565b6000806040838503121561269b578182fd5b50508035926020909101359150565b6000602082840312156126bb578081fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610c08578182fd5b6000602082840312156126fb578081fd5b5051919050565b60008060408385031215612714578182fd5b82359150602083013561272681612b3a565b809150509250929050565b600080600060608486031215612745578283fd5b8335925060208401359150604084013567ffffffffffffffff8082111561276a578283fd5b818601915086601f83011261277d578283fd5b81358181111561278f5761278f612b24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156127d5576127d5612b24565b816040528281528960208487010111156127ed578586fd5b82602086016020830137856020848301015280955050505050509250925092565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351612846816017850160208801612a48565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351612883816028840160208801612a48565b01602801949350505050565b60208152600082518060208401526128ae816040850160208701612a48565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561291a5761291a612af8565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561294e5761294e612af8565b50500190565b6000821982111561296757612967612af8565b500190565b60008261297b5761297b612b0e565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156129b8576129b8612af8565b500290565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156129f7576129f7612af8565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615612a2b57612a2b612af8565b50500390565b600082821015612a4357612a43612af8565b500390565b60005b83811015612a63578181015183820152602001612a4b565b838111156116c15750506000910152565b600081612a8357612a83612af8565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600181811c90821680612abd57607f821691505b60208210811415612ade57634e487b7160e01b600052602260045260246000fd5b50919050565b600082612af357612af3612b0e565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b80151581146124b957600080fdfea2646970667358221220b8c8005c5c8e032159a7cb883636a57d39c3f5528a010572cd6bf4b33158d8f264736f6c63430008040033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000060f5672a271c7e39e787427a18353ba59a4a3578000000000000000000000000000000000000000000000000000000000000000b5374616b65642050494b410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006737450494b410000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Staked PIKA
Arg [1] : _symbol (string): stPIKA
Arg [2] : _token (address): 0x60F5672A271C7E39E787427A18353ba59A4A3578

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 00000000000000000000000060f5672a271c7e39e787427a18353ba59a4a3578
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [4] : 5374616b65642050494b41000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [6] : 737450494b410000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

719:6377:14:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2097:1;2081:13;3228:12:6;;;3141:106;2081:13:14;:17;2073:46;;;;-1:-1:-1;;;2073:46:14;;9312:2:17;2073:46:14;;;9294:21:17;9351:2;9331:18;;;9324:30;9390:18;9370;;;9363:46;9426:18;;2073:46:14;;;;;;;;;2133:9;:13;2129:169;;3228:12:6;;2190:21:14;1014:6;2190:9;:21;:::i;:::-;2189:39;;;;:::i;:::-;2162:23;;:66;;;;;;;:::i;:::-;;;;-1:-1:-1;;2247:40:14;;2277:9;7504:25:17;;665:10:3;;2247:40:14;;7492:2:17;7477:18;2247:40:14;;;;;;;2129:169;719:6377;;;;;802:212:1;;;;;;;;;;-1:-1:-1;802:212:1;;;;;:::i;:::-;;:::i;:::-;;;7331:14:17;;7324:22;7306:41;;7294:2;7279:18;802:212:1;;;;;;;;2053:98:6;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4150:166::-;;;;;;;;;;-1:-1:-1;4150:166:6;;;;;:::i;:::-;;:::i;3141:106::-;;;;;;;;;;-1:-1:-1;3228:12:6;;3141:106;;;7504:25:17;;;7492:2;7477:18;3141:106:6;7459:76:17;4783:478:6;;;;;;;;;;-1:-1:-1;4783:478:6;;;;;:::i;:::-;;:::i;5412:121:0:-;;;;;;;;;;-1:-1:-1;5412:121:0;;;;;:::i;:::-;5478:7;5504:12;;;:6;:12;;;;;:22;;;;5412:121;2129:162:1;;;;;;;;;;-1:-1:-1;2129:162:1;;;;;:::i;:::-;;:::i;2990:91:6:-;;;;;;;;;;-1:-1:-1;2990:91:6;;3072:2;14748:36:17;;14736:2;14721:18;2990:91:6;14703:87:17;2636:171:1;;;;;;;;;;-1:-1:-1;2636:171:1;;;;;:::i;:::-;;:::i;4309:436:14:-;;;;;;;;;;-1:-1:-1;4309:436:14;;;;;:::i;:::-;;:::i;5656:212:6:-;;;;;;;;;;-1:-1:-1;5656:212:6;;;;;:::i;:::-;;:::i;4880:262:7:-;;;;;;;;;;-1:-1:-1;4880:262:7;;;;;:::i;:::-;;:::i;3305:125:6:-;;;;;;;;;;-1:-1:-1;3305:125:6;;;;;:::i;:::-;-1:-1:-1;;;;;3405:18:6;3379:7;3405:18;;;;;;;;;;;;3305:125;6948:146:14;;;;;;;;;;-1:-1:-1;6948:146:14;;;;;:::i;:::-;;:::i;1599:143:1:-;;;;;;;;;;-1:-1:-1;1599:143:1;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;5696:55:17;;;5678:74;;5666:2;5651:18;1599:143:1;5633:125:17;2905:519:14;;;;;;;;;;-1:-1:-1;2905:519:14;;;;;:::i;:::-;;:::i;4329:137:0:-;;;;;;;;;;-1:-1:-1;4329:137:0;;;;;:::i;:::-;4407:4;4430:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;4430:29:0;;;;;;;;;;;;;;;4329:137;2264:102:6;;;;;;;;;;;;;:::i;5241:230:7:-;;;;;;;;;;-1:-1:-1;5241:230:7;;;;;:::i;:::-;;:::i;2361:49:0:-;;;;;;;;;;-1:-1:-1;2361:49:0;2406:4;2361:49;;6355:405:6;;;;;;;;;;-1:-1:-1;6355:405:6;;;;;:::i;:::-;;:::i;3633:172::-;;;;;;;;;;-1:-1:-1;3633:172:6;;;;;:::i;:::-;;:::i;2519:113:14:-;;;;;;;;;;;;;:::i;3656:398::-;;;;;;;;;;-1:-1:-1;3656:398:14;;;;;:::i;:::-;;:::i;1231:49::-;;;;;;;;;;-1:-1:-1;1231:49:14;;;;;:::i;:::-;;;;;;;;;;;;;;1910:132:1;;;;;;;;;;-1:-1:-1;1910:132:1;;;;;:::i;:::-;;:::i;1026:67:14:-;;;;;;;;;;;;1069:24;1026:67;;2379:167:1;;;;;;;;;;-1:-1:-1;2379:167:1;;;;;:::i;:::-;;:::i;3863:149:6:-;;;;;;;;;;-1:-1:-1;3863:149:6;;;;;:::i;:::-;-1:-1:-1;;;;;3978:18:6;;;3952:7;3978:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3863:149;6549:327:14;;;;;;;;;;-1:-1:-1;6549:327:14;;;;;:::i;:::-;;:::i;6260:224::-;;;;;;;;;;-1:-1:-1;6260:224:14;;;;;:::i;:::-;;:::i;4853:418::-;;;;;;;;;;-1:-1:-1;4853:418:14;;;;;:::i;:::-;;:::i;802:212:1:-;887:4;910:57;;;925:42;910:57;;:97;;;971:36;995:11;971:23;:36::i;:::-;903:104;802:212;-1:-1:-1;;802:212:1:o;2053:98:6:-;2107:13;2139:5;2132:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2053:98;:::o;4150:166::-;4233:4;4249:39;665:10:3;4272:7:6;4281:6;4249:8;:39::i;:::-;-1:-1:-1;4305:4:6;4150:166;;;;:::o;4783:478::-;4919:4;4935:36;4945:6;4953:9;4964:6;4935:9;:36::i;:::-;-1:-1:-1;;;;;5009:19:6;;4982:24;5009:19;;;:11;:19;;;;;;;;665:10:3;5009:33:6;;;;;;;;5060:26;;;;5052:79;;;;-1:-1:-1;;;5052:79:6;;10870:2:17;5052:79:6;;;10852:21:17;10909:2;10889:18;;;10882:30;10948:34;10928:18;;;10921:62;11019:10;10999:18;;;10992:38;11047:19;;5052:79:6;10842:230:17;5052:79:6;5165:57;5174:6;665:10:3;5215:6:6;5196:16;:25;5165:8;:57::i;:::-;-1:-1:-1;5250:4:6;;4783:478;-1:-1:-1;;;;4783:478:6:o;2129:162:1:-;2213:30;2229:4;2235:7;2213:15;:30::i;:::-;2253:18;;;;:12;:18;;;;;:31;;2276:7;2253:22;:31::i;:::-;;2129:162;;:::o;2636:171::-;2723:33;2742:4;2748:7;2723:18;:33::i;:::-;2766:18;;;;:12;:18;;;;;:34;;2792:7;2766:25;:34::i;4309:436:14:-;4375:7;4398:6;4394:63;;;4420:26;665:10:3;4853:418:14;:::i;4420:26::-;4466:23;4537:13;3228:12:6;;;3141:106;4537:13:14;4503:5;;:30;;;;;4527:4;4503:30;;;5678:74:17;-1:-1:-1;;;;;4503:5:14;;;;:15;;5651:18:17;;4503:30:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4493:40;;:7;:40;:::i;:::-;4492:58;;;;:::i;:::-;4466:84;-1:-1:-1;4560:28:14;665:10:3;4580:7:14;4560:5;:28::i;:::-;4598:5;;-1:-1:-1;;;;;4598:5:14;:14;665:10:3;4598:45:14;;;;;;;;;;-1:-1:-1;;;;;7056:55:17;;;4598:45:14;;;7038:74:17;7128:18;;;7121:34;;;7011:18;;4598:45:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;4658:48:14;;;14527:25:17;;;14583:2;14568:18;;14561:34;;;665:10:3;;4658:48:14;;14500:18:17;4658:48:14;;;;;;;4723:15;4309:436;-1:-1:-1;;;4309:436:14:o;5656:212:6:-;665:10:3;5744:4:6;5792:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;5792:34:6;;;;;;;;;;5744:4;;5760:80;;5783:7;;5792:47;;5829:10;;5792:47;:::i;:::-;5760:8;:80::i;4880:262:7:-;-1:-1:-1;;;;;5043:33:7;;4967:7;5043:33;;;:24;:33;;;;;4967:7;;;;5022:55;;5031:10;;5022:8;:55::i;:::-;4986:91;;;;5095:11;:40;;-1:-1:-1;;;;;3405:18:6;;3379:7;3405:18;;;;;;;;;;;5095:40:7;;;5109:5;5095:40;5088:47;4880:262;-1:-1:-1;;;;;4880:262:7:o;6948:146:14:-;-1:-1:-1;;;;;7066:21:14;;7012:7;7066:21;;;:14;:21;;;;;;7038:25;7081:5;7038:18;:25::i;:::-;:49;;;;:::i;1599:143:1:-;1681:7;1707:18;;;:12;:18;;;;;:28;;1729:5;1707:21;:28::i;:::-;1700:35;1599:143;-1:-1:-1;;;1599:143:1:o;2905:519:14:-;3050:10;:17;3071:2;3050:23;3042:32;;;;;;3190:2;3174:19;;3168:26;3234:2;3218:19;;;3212:26;3286:2;3270:19;;3264:26;3311:5;;:80;;;;;665:10:3;3311:80:14;;;6538:34:17;3346:4:14;6588:18:17;;;6581:43;3353:17:14;6640:18:17;;;6633:34;6683:18;;;6676:34;;;3084:9:14;3256:35;;;6726:19:17;;;6719:46;;;6781:19;;;6774:35;;;6825:19;;;6818:35;;;3311:80:14;;3212:26;;3256:35;-1:-1:-1;;;;;3311:5:14;;;;:12;;6449:19:17;;;;;3311:80:14;;;;;3084:9;3311:5;:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3401:16;3409:7;3401;:16::i;:::-;2905:519;;;;;;:::o;2264:102:6:-;2320:13;2352:7;2345:14;;;;;:::i;5241:230:7:-;5313:7;5333:16;5351:13;5368:43;5377:10;5389:21;5368:8;:43::i;:::-;5332:79;;;;5429:11;:35;;3228:12:6;;5429:35:7;;;5443:5;5429:35;5422:42;5241:230;-1:-1:-1;;;;5241:230:7:o;6355:405:6:-;665:10:3;6448:4:6;6491:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;6491:34:6;;;;;;;;;;6543:35;;;;6535:85;;;;-1:-1:-1;;;6535:85:6;;13191:2:17;6535:85:6;;;13173:21:17;13230:2;13210:18;;;13203:30;13269:34;13249:18;;;13242:62;13340:7;13320:18;;;13313:35;13365:19;;6535:85:6;13163:227:17;6535:85:6;6654:67;665:10:3;6677:7:6;6705:15;6686:16;:34;6654:8;:67::i;:::-;-1:-1:-1;6749:4:6;;6355:405;-1:-1:-1;;;6355:405:6:o;3633:172::-;3719:4;3735:42;665:10:3;3759:9:6;3770:6;3735:9;:42::i;2519:113:14:-;2588:7;1069:24;3925:30:0;1069:24:14;665:10:3;3925::0;:30::i;:::-;2614:11:14::1;:9;:11::i;:::-;2607:18;;2519:113:::0;;:::o;3656:398::-;3707:13;3754:1;3738:13;3228:12:6;;;3141:106;3738:13:14;:17;3734:160;;;3807:5;;:30;;;;;3831:4;3807:30;;;5678:74:17;-1:-1:-1;;;;;3807:5:14;;;;:15;;5651:18:17;;3807:30:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3796:7;3780:13;3228:12:6;;;3141:106;3780:13:14;:23;;;;:::i;:::-;3779:58;;;;:::i;:::-;3771:66;;3734:160;;;-1:-1:-1;3876:7:14;3734:160;3903:5;;-1:-1:-1;;;;;3903:5:14;:18;665:10:3;3903:56:14;;;;;;;;;;-1:-1:-1;;;;;6044:15:17;;;3903:56:14;;;6026:34:17;3944:4:14;6076:18:17;;;6069:43;6128:18;;;6121:34;;;5938:18;;3903:56:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;3969:26:14;665:10:3;3989:5:14;3969;:26::i;:::-;4010:37;;;14527:25:17;;;14583:2;14568:18;;14561:34;;;665:10:3;;4010:37:14;;14500:18:17;4010:37:14;;;;;;;3656:398;;:::o;1910:132:1:-;1982:7;2008:18;;;:12;:18;;;;;:27;;:25;:27::i;2379:167::-;2464:31;2481:4;2487:7;2464:16;:31::i;6549:327:14:-;6613:7;6632:23;6658:59;6685:16;6695:5;-1:-1:-1;;;;;3405:18:6;3379:7;3405:18;;;;;;;;;;;;3305:125;6685:16:14;6659:23;;:42;;;;:::i;:::-;6658:57;:59::i;:::-;-1:-1:-1;;;;;6774:33:14;;6727:24;6774:33;;;:26;:33;;;;;;6632:85;;-1:-1:-1;6727:24:14;6754:70;;6755:52;;6632:85;6755:52;:::i;:::-;6754:68;:70::i;:::-;6727:97;-1:-1:-1;6841:28:14;1014:6;6727:97;6841:28;:::i;6260:224::-;6318:7;6341:13;3228:12:6;;;3141:106;6341:13:14;6337:57;;-1:-1:-1;6382:1:14;;6260:224;-1:-1:-1;6260:224:14:o;6337:57::-;3228:12:6;;6430:5:14;;:30;;;;;6454:4;6430:30;;;5678:74:17;-1:-1:-1;;;;;6430:5:14;;;;:15;;5651:18:17;;6430:30:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;3405:18:6;;3379:7;3405:18;;;;;;;;;;;6411:49:14;;;;:::i;:::-;6410:67;;;;:::i;4853:418::-;4905:24;4932:32;665:10:3;6948:146:14;:::i;4932:32::-;4905:59;-1:-1:-1;4978:20:14;;4974:291;;665:10:3;5014:28:14;;;;:14;:28;;;;;:48;;5046:16;;5014:28;:48;;5046:16;;5014:48;:::i;:::-;;;;-1:-1:-1;;5095:37:14;;5077:12;;-1:-1:-1;;;;;5095:8:14;;;5111:16;;5077:12;5095:37;5077:12;5095:37;5111:16;5095:8;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5076:56;;;5154:7;5146:39;;;;-1:-1:-1;;;5146:39:14;;12492:2:17;5146:39:14;;;12474:21:17;12531:2;12511:18;;;12504:30;12570:21;12550:18;;;12543:49;12609:18;;5146:39:14;12464:169:17;5146:39:14;5204:50;;7504:25:17;;;-1:-1:-1;;;;;5204:50:14;;;665:10:3;;5204:50:14;;7492:2:17;7477:18;5204:50:14;;;;;;;;4974:291;;4853:418;;:::o;7579:110:0:-;7657:25;7668:4;7674:7;7657:10;:25::i;6232:150:8:-;6302:4;6325:50;6330:3;-1:-1:-1;;;;;6350:23:8;;6325:4;:50::i;4040:202:0:-;4125:4;4148:47;;;4163:32;4148:47;;:87;;-1:-1:-1;886:25:5;871:40;;;;4199:36:0;763:155:5;9931:370:6;-1:-1:-1;;;;;10062:19:6;;10054:68;;;;-1:-1:-1;;;10054:68:6;;12087:2:17;10054:68:6;;;12069:21:17;12126:2;12106:18;;;12099:30;12165:34;12145:18;;;12138:62;12236:6;12216:18;;;12209:34;12260:19;;10054:68:6;12059:226:17;10054:68:6;-1:-1:-1;;;;;10140:21:6;;10132:68;;;;-1:-1:-1;;;10132:68:6;;10060:2:17;10132:68:6;;;10042:21:17;10099:2;10079:18;;;10072:30;10138:34;10118:18;;;10111:62;10209:4;10189:18;;;10182:32;10231:19;;10132:68:6;10032:224:17;10132:68:6;-1:-1:-1;;;;;10211:18:6;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;10262:32;;7504:25:17;;;10262:32:6;;7477:18:17;10262:32:6;7459:76:17;7234:713:6;-1:-1:-1;;;;;7369:20:6;;7361:70;;;;-1:-1:-1;;;7361:70:6;;11681:2:17;7361:70:6;;;11663:21:17;11720:2;11700:18;;;11693:30;11759:34;11739:18;;;11732:62;11830:7;11810:18;;;11803:35;11855:19;;7361:70:6;11653:227:17;7361:70:6;-1:-1:-1;;;;;7449:23:6;;7441:71;;;;-1:-1:-1;;;7441:71:6;;8908:2:17;7441:71:6;;;8890:21:17;8947:2;8927:18;;;8920:30;8986:34;8966:18;;;8959:62;9057:5;9037:18;;;9030:33;9080:19;;7441:71:6;8880:225:17;7441:71:6;7523:47;7544:6;7552:9;7563:6;7523:20;:47::i;:::-;-1:-1:-1;;;;;7605:17:6;;7581:21;7605:17;;;;;;;;;;;7640:23;;;;7632:74;;;;-1:-1:-1;;;7632:74:6;;10463:2:17;7632:74:6;;;10445:21:17;10502:2;10482:18;;;10475:30;10541:34;10521:18;;;10514:62;10612:8;10592:18;;;10585:36;10638:19;;7632:74:6;10435:228:17;7632:74:6;-1:-1:-1;;;;;7740:17:6;;;:9;:17;;;;;;;;;;;7760:22;;;7740:42;;7802:20;;;;;;;;:30;;7776:6;;7740:9;7802:30;;7776:6;;7802:30;:::i;:::-;;;;;;;;7865:9;-1:-1:-1;;;;;7848:35:6;7857:6;-1:-1:-1;;;;;7848:35:6;;7876:6;7848:35;;;;7504:25:17;;7492:2;7477:18;;7459:76;7848:35:6;;;;;;;;7894:46;7234:713;;;;:::o;5783:145:0:-;5478:7;5504:12;;;:6;:12;;;;;:22;;;3925:30;3936:4;665:10:3;3925::0;:30::i;:::-;5896:25:::1;5907:4;5913:7;5896:10;:25::i;6800:214::-:0;-1:-1:-1;;;;;6895:23:0;;665:10:3;6895:23:0;6887:83;;;;-1:-1:-1;;;6887:83:0;;13597:2:17;6887:83:0;;;13579:21:17;13636:2;13616:18;;;13609:30;13675:34;13655:18;;;13648:62;13746:17;13726:18;;;13719:45;13781:19;;6887:83:0;13569:237:17;6887:83:0;6981:26;6993:4;6999:7;6981:11;:26::i;6550:156:8:-;6623:4;6646:53;6654:3;-1:-1:-1;;;;;6674:23:8;;6646:7;:53::i;8932:576:6:-;-1:-1:-1;;;;;9015:21:6;;9007:67;;;;-1:-1:-1;;;9007:67:6;;11279:2:17;9007:67:6;;;11261:21:17;11318:2;11298:18;;;11291:30;11357:34;11337:18;;;11330:62;11428:3;11408:18;;;11401:31;11449:19;;9007:67:6;11251:223:17;9007:67:6;9085:49;9106:7;9123:1;9127:6;9085:20;:49::i;:::-;-1:-1:-1;;;;;9170:18:6;;9145:22;9170:18;;;;;;;;;;;9206:24;;;;9198:71;;;;-1:-1:-1;;;9198:71:6;;9657:2:17;9198:71:6;;;9639:21:17;9696:2;9676:18;;;9669:30;9735:34;9715:18;;;9708:62;9806:4;9786:18;;;9779:32;9828:19;;9198:71:6;9629:224:17;9198:71:6;-1:-1:-1;;;;;9303:18:6;;:9;:18;;;;;;;;;;9324:23;;;9303:44;;9367:12;:22;;9341:6;;9303:9;9367:22;;9341:6;;9367:22;:::i;:::-;;;;-1:-1:-1;;9405:37:6;;7504:25:17;;;9431:1:6;;-1:-1:-1;;;;;9405:37:6;;;;;7492:2:17;7477:18;9405:37:6;;;;;;;2253:31:1;2129:162;;:::o;6292:1594:7:-;6381:4;6387:7;6427:1;6414:10;:14;6406:49;;;;-1:-1:-1;;;6406:49:7;;12840:2:17;6406:49:7;;;12822:21:17;12879:2;12859:18;;;12852:30;12918:24;12898:18;;;12891:52;12960:18;;6406:49:7;12812:172:17;6406:49:7;6487:23;:21;:23::i;:::-;6473:10;:37;;6465:79;;;;-1:-1:-1;;;6465:79:7;;8189:2:17;6465:79:7;;;8171:21:17;8228:2;8208:18;;;8201:30;8267:31;8247:18;;;8240:59;8316:18;;6465:79:7;8161:179:17;6465:79:7;7667:13;7683:40;:9;7712:10;7683:28;:40::i;:::-;7747:20;;7667:56;;-1:-1:-1;7738:29:7;;7734:146;;;7791:5;7798:1;7783:17;;;;;;;7734:146;7839:4;7845:9;:16;;7862:5;7845:23;;;;;;-1:-1:-1;;;7845:23:7;;;;;;;;;;;;;;;;;7831:38;;;;;6292:1594;;;;;;:::o;7490:156:8:-;7564:7;7614:22;7618:3;7630:5;7614:3;:22::i;4747:484:0:-;4407:4;4430:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;4430:29:0;;;;;;;;;;;;4822:403;;5010:41;5038:7;-1:-1:-1;;;;;5010:41:0;5048:2;5010:19;:41::i;:::-;5122:38;5150:4;5157:2;5122:19;:38::i;:::-;4917:265;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;-1:-1:-1;;;4865:349:0;;;;;;;:::i;4370:217:7:-;4417:7;4436:30;:18;978:19:4;;996:1;978:19;;;891:123;4436:30:7;4477:17;4497:23;:21;:23::i;:::-;4477:43;;4535:19;4544:9;4535:19;;;;7504:25:17;;7492:2;7477:18;;7459:76;4535:19:7;;;;;;;;4571:9;4370:217;-1:-1:-1;4370:217:7:o;8223:389:6:-;-1:-1:-1;;;;;8306:21:6;;8298:65;;;;-1:-1:-1;;;8298:65:6;;14013:2:17;8298:65:6;;;13995:21:17;14052:2;14032:18;;;14025:30;14091:33;14071:18;;;14064:61;14142:18;;8298:65:6;13985:181:17;8298:65:6;8374:49;8403:1;8407:7;8416:6;8374:20;:49::i;:::-;8450:6;8434:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;8466:18:6;;:9;:18;;;;;;;;;;:28;;8488:6;;8466:9;:28;;8488:6;;8466:28;:::i;:::-;;;;-1:-1:-1;;8509:37:6;;7504:25:17;;;-1:-1:-1;;;;;8509:37:6;;;8526:1;;8509:37;;7492:2:17;7477:18;8509:37:6;;;;;;;4853:418:14;;:::o;7033:115:8:-;7096:7;7122:19;7130:3;3961:18;;3879:107;6162:147:0;5478:7;5504:12;;;:6;:12;;;;;:22;;;3925:30;3936:4;665:10:3;3925::0;:30::i;:::-;6276:26:::1;6288:4;6294:7;6276:11;:26::i;237:144:13:-:0;293:6;329:1;349:6;;;;341:15;;;;;82:124;138:7;170:1;165;:6;;157:15;;;;;;-1:-1:-1;197:1:13;82:124::o;8012:224:0:-;4407:4;4430:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;4430:29:0;;;;;;;;;;;;8081:149;;8124:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;8124:29:0;;;;;;;;;:36;;;;8156:4;8124:36;;;8206:12;665:10:3;;586:96;8206:12:0;-1:-1:-1;;;;;8179:40:0;8197:7;-1:-1:-1;;;;;8179:40:0;8191:4;8179:40;;;;;;;;;;8012:224;;:::o;1630:404:8:-;1693:4;3767:19;;;:12;;;:19;;;;;;1709:319;;-1:-1:-1;1751:23:8;;;;;;;;:11;:23;;;;;;;;;;;;;1931:18;;1909:19;;;:12;;;:19;;;;;;:40;;;;1963:11;;1709:319;-1:-1:-1;2012:5:8;2005:12;;5385:782:14;5523:44;5550:4;5556:2;5560:6;5523:26;:44::i;:::-;-1:-1:-1;;;;;5582:18:14;;5578:583;;5670:49;5697:6;5671:23;;:32;;;;:::i;5670:49::-;-1:-1:-1;;;;;5636:30:14;;;;;;:26;:30;;;;;:83;;:30;;;:83;;;;;:::i;:::-;;;;-1:-1:-1;5578:583:14;;-1:-1:-1;5578:583:14;;-1:-1:-1;;;;;5740:16:14;;5736:425;;5828:49;5855:6;5829:23;;:32;;;;:::i;5828:49::-;-1:-1:-1;;;;;5792:32:14;;;;;;:26;:32;;;;;:85;;:32;;;:85;;;;;:::i;5736:425::-;5932:26;5961:49;5988:6;5962:23;;:32;;;;:::i;5961:49::-;-1:-1:-1;;;;;6024:32:14;;;;;;:26;:32;;;;;:57;;5932:78;;-1:-1:-1;5932:78:14;;6024:32;;;:57;;5932:78;;6024:57;:::i;:::-;;;;-1:-1:-1;;;;;;;6095:30:14;;;;;;:26;:30;;;;;:55;;6130:19;;6095:30;:55;;6130:19;;6095:55;:::i;:::-;;;;-1:-1:-1;;;5385:782:14;;;:::o;8242:225:0:-;4407:4;4430:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;4430:29:0;;;;;;;;;;;;8312:149;;;8386:5;8354:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;8354:29:0;;;;;;;;;;:37;;;;;;8410:40;665:10:3;;8354:12:0;;8410:40;;8386:5;8410:40;8242:225;;:::o;2202:1388:8:-;2268:4;2405:19;;;:12;;;:19;;;;;;2439:15;;2435:1149;;2808:21;2832:14;2845:1;2832:10;:14;:::i;:::-;2880:18;;2808:38;;-1:-1:-1;2860:17:8;;2880:22;;2901:1;;2880:22;:::i;:::-;2860:42;;2934:13;2921:9;:26;2917:398;;2967:17;2987:3;:11;;2999:9;2987:22;;;;;;-1:-1:-1;;;2987:22:8;;;;;;;;;;;;;;;;;2967:42;;3138:9;3109:3;:11;;3121:13;3109:26;;;;;;-1:-1:-1;;;3109:26:8;;;;;;;;;;;;;;;;;;;;:38;;;;3221:23;;;:12;;;:23;;;;;:36;;;2917:398;3393:17;;:3;;:17;;;-1:-1:-1;;;3393:17:8;;;;;;;;;;;;;;;;;;;;;;;;;;3485:3;:12;;:19;3498:5;3485:19;;;;;;;;;;;3478:26;;;3526:4;3519:11;;;;;;;2435:1149;3568:5;3561:12;;;;;4648:125:7;4712:7;4738:28;:18;864:14:4;;773:112;4738:28:7;4731:35;;4648:125;:::o;577:892:2:-;689:12;;666:7;;685:56;;-1:-1:-1;729:1:2;722:8;;685:56;791:12;;751:11;;814:414;827:4;821:3;:10;814:414;;;847:11;861:23;874:3;879:4;861:12;:23::i;:::-;847:37;;1114:7;1101:5;1107:3;1101:10;;;;;;-1:-1:-1;;;1101:10:2;;;;;;;;;;;;;;;;;:20;1097:121;;;1148:3;1141:10;;1097:121;;;1196:7;:3;1202:1;1196:7;:::i;:::-;1190:13;;1097:121;814:414;;;;1351:1;1345:3;:7;:36;;;;-1:-1:-1;1374:7:2;1356:5;1362:7;1368:1;1362:3;:7;:::i;:::-;1356:14;;;;;;-1:-1:-1;;;1356:14:2;;;;;;;;;;;;;;;;;:25;1345:36;1341:122;;;1404:7;1410:1;1404:3;:7;:::i;:::-;1397:14;;;;;;1341:122;-1:-1:-1;1449:3:2;-1:-1:-1;1442:10:2;;4328:118:8;4395:7;4421:3;:11;;4433:5;4421:18;;;;;;-1:-1:-1;;;4421:18:8;;;;;;;;;;;;;;;;;4414:25;;4328:118;;;;:::o;1535:441:15:-;1610:13;1635:19;1667:10;1671:6;1667:1;:10;:::i;:::-;:14;;1680:1;1667:14;:::i;:::-;1657:25;;;;;;-1:-1:-1;;;1657:25:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1657:25:15;;1635:47;;1692:15;:6;1699:1;1692:9;;;;;;-1:-1:-1;;;1692:9:15;;;;;;;;;;;;:15;;;;;;;;;;;1717;:6;1724:1;1717:9;;;;;;-1:-1:-1;;;1717:9:15;;;;;;;;;;;;:15;;;;;;;;;;-1:-1:-1;1747:9:15;1759:10;1763:6;1759:1;:10;:::i;:::-;:14;;1772:1;1759:14;:::i;:::-;1747:26;;1742:132;1779:1;1775;:5;1742:132;;;1813:12;1826:5;1834:3;1826:11;1813:25;;;;;-1:-1:-1;;;1813:25:15;;;;;;;;;;;;1801:6;1808:1;1801:9;;;;;;-1:-1:-1;;;1801:9:15;;;;;;;;;;;;:37;;;;;;;;;;-1:-1:-1;1862:1:15;1852:11;;;;;1782:3;;;:::i;:::-;;;1742:132;;;-1:-1:-1;1891:10:15;;1883:55;;;;-1:-1:-1;;;1883:55:15;;8547:2:17;1883:55:15;;;8529:21:17;;;8566:18;;;8559:30;8625:34;8605:18;;;8598:62;8677:18;;1883:55:15;8519:182:17;5684:602:7;-1:-1:-1;;;;;5881:18:7;;5877:403;;5935:26;5958:2;5935:22;:26::i;:::-;5975:28;:26;:28::i;5877:403::-;-1:-1:-1;;;;;6024:16:7;;6020:260;;6076:28;6099:4;6076:22;:28::i;6020:260::-;6201:28;6224:4;6201:22;:28::i;:::-;6243:26;6266:2;6243:22;:26::i;608:195:12:-;670:7;794:1;784:5;794:1;784;:5;:::i;:::-;774;778:1;774;:5;:::i;:::-;773:17;;;;:::i;:::-;772:23;;;;:::i;:::-;762:5;766:1;762;:5;:::i;:::-;752;756:1;752;:5;:::i;:::-;751:17;;;;:::i;:::-;:45;;;;:::i;7892:144:7:-;-1:-1:-1;;;;;7975:33:7;;;;;;:24;:33;;;;;;;;3405:18:6;;;;;;;;7959:70:7;;7975:33;7959:15;:70::i;8010:18::-;7959:15;:70::i;:::-;7892:144;:::o;8042:116::-;8098:53;8114:21;8137:13;3228:12:6;;;3141:106;8098:53:7;8042:116::o;8164:304::-;8258:17;8278:23;:21;:23::i;:::-;8258:43;-1:-1:-1;8258:43:7;8315:30;8331:9;8315:15;:30::i;:::-;:42;8311:151;;;8373:29;;;;;;;;-1:-1:-1;8373:29:7;;;;;;;;;;;;;;8416:16;;;:35;;;;;;;;;;;;;;;8164:304::o;8474:206::-;8567:10;;8544:7;;8563:111;;-1:-1:-1;8605:1:7;;8474:206;-1:-1:-1;8474:206:7:o;8563:111::-;8648:10;;8644:3;;8648:14;;8661:1;;8648:14;:::i;:::-;8644:19;;;;;;-1:-1:-1;;;8644:19:7;;;;;;;;;;;;;;;;;8637:26;;8474:206;;;:::o;8563:111::-;8474:206;;;:::o;14:196:17:-;82:20;;-1:-1:-1;;;;;131:54:17;;121:65;;111:2;;200:1;197;190:12;215:196;274:6;327:2;315:9;306:7;302:23;298:32;295:2;;;348:6;340;333:22;295:2;376:29;395:9;376:29;:::i;416:270::-;484:6;492;545:2;533:9;524:7;520:23;516:32;513:2;;;566:6;558;551:22;513:2;594:29;613:9;594:29;:::i;:::-;584:39;;642:38;676:2;665:9;661:18;642:38;:::i;:::-;632:48;;503:183;;;;;:::o;691:338::-;768:6;776;784;837:2;825:9;816:7;812:23;808:32;805:2;;;858:6;850;843:22;805:2;886:29;905:9;886:29;:::i;:::-;876:39;;934:38;968:2;957:9;953:18;934:38;:::i;:::-;924:48;;1019:2;1008:9;1004:18;991:32;981:42;;795:234;;;;;:::o;1034:264::-;1102:6;1110;1163:2;1151:9;1142:7;1138:23;1134:32;1131:2;;;1184:6;1176;1169:22;1131:2;1212:29;1231:9;1212:29;:::i;:::-;1202:39;1288:2;1273:18;;;;1260:32;;-1:-1:-1;;;1121:177:17:o;1303:255::-;1370:6;1423:2;1411:9;1402:7;1398:23;1394:32;1391:2;;;1444:6;1436;1429:22;1391:2;1481:9;1475:16;1500:28;1522:5;1500:28;:::i;1563:190::-;1622:6;1675:2;1663:9;1654:7;1650:23;1646:32;1643:2;;;1696:6;1688;1681:22;1643:2;-1:-1:-1;1724:23:17;;1633:120;-1:-1:-1;1633:120:17:o;1758:264::-;1826:6;1834;1887:2;1875:9;1866:7;1862:23;1858:32;1855:2;;;1908:6;1900;1893:22;1855:2;1949:9;1936:23;1926:33;;1978:38;2012:2;2001:9;1997:18;1978:38;:::i;2027:258::-;2095:6;2103;2156:2;2144:9;2135:7;2131:23;2127:32;2124:2;;;2177:6;2169;2162:22;2124:2;-1:-1:-1;;2205:23:17;;;2275:2;2260:18;;;2247:32;;-1:-1:-1;2114:171:17:o;2290:352::-;2348:6;2401:2;2389:9;2380:7;2376:23;2372:32;2369:2;;;2422:6;2414;2407:22;2369:2;2466:9;2453:23;2516:66;2509:5;2505:78;2498:5;2495:89;2485:2;;2603:6;2595;2588:22;2842:194;2912:6;2965:2;2953:9;2944:7;2940:23;2936:32;2933:2;;;2986:6;2978;2971:22;2933:2;-1:-1:-1;3014:16:17;;2923:113;-1:-1:-1;2923:113:17:o;3041:319::-;3106:6;3114;3167:2;3155:9;3146:7;3142:23;3138:32;3135:2;;;3188:6;3180;3173:22;3135:2;3229:9;3216:23;3206:33;;3289:2;3278:9;3274:18;3261:32;3302:28;3324:5;3302:28;:::i;:::-;3349:5;3339:15;;;3125:235;;;;;:::o;3365:1161::-;3451:6;3459;3467;3520:2;3508:9;3499:7;3495:23;3491:32;3488:2;;;3541:6;3533;3526:22;3488:2;3582:9;3569:23;3559:33;;3639:2;3628:9;3624:18;3611:32;3601:42;;3694:2;3683:9;3679:18;3666:32;3717:18;3758:2;3750:6;3747:14;3744:2;;;3779:6;3771;3764:22;3744:2;3822:6;3811:9;3807:22;3797:32;;3867:7;3860:4;3856:2;3852:13;3848:27;3838:2;;3894:6;3886;3879:22;3838:2;3935;3922:16;3957:2;3953;3950:10;3947:2;;;3963:18;;:::i;:::-;4097:2;4091:9;4159:4;4151:13;;4002:66;4147:22;;;4171:2;4143:31;4139:40;4127:53;;;4195:18;;;4215:22;;;4192:46;4189:2;;;4241:18;;:::i;:::-;4281:10;4277:2;4270:22;4316:2;4308:6;4301:18;4356:7;4351:2;4346;4342;4338:11;4334:20;4331:33;4328:2;;;4382:6;4374;4367:22;4328:2;4443;4438;4434;4430:11;4425:2;4417:6;4413:15;4400:46;4488:6;4483:2;4478;4470:6;4466:15;4462:24;4455:40;4514:6;4504:16;;;;;;;3478:1048;;;;;:::o;4741:786::-;5152:25;5147:3;5140:38;5122:3;5207:6;5201:13;5223:62;5278:6;5273:2;5268:3;5264:12;5257:4;5249:6;5245:17;5223:62;:::i;:::-;5349:19;5344:2;5304:16;;;5336:11;;;5329:40;5394:13;;5416:63;5394:13;5465:2;5457:11;;5450:4;5438:17;;5416:63;:::i;:::-;5499:17;5518:2;5495:26;;5130:397;-1:-1:-1;;;;5130:397:17:o;7540:442::-;7689:2;7678:9;7671:21;7652:4;7721:6;7715:13;7764:6;7759:2;7748:9;7744:18;7737:34;7780:66;7839:6;7834:2;7823:9;7819:18;7814:2;7806:6;7802:15;7780:66;:::i;:::-;7898:2;7886:15;7903:66;7882:88;7867:104;;;;7973:2;7863:113;;7661:321;-1:-1:-1;;7661:321:17:o;14795:369::-;14834:3;14869;14866:1;14862:11;14980:1;14912:66;14908:74;14905:1;14901:82;14896:2;14889:10;14885:99;14882:2;;;14987:18;;:::i;:::-;15106:1;15038:66;15034:74;15031:1;15027:82;15023:2;15019:91;15016:2;;;15113:18;;:::i;:::-;-1:-1:-1;;15149:9:17;;14842:322::o;15169:128::-;15209:3;15240:1;15236:6;15233:1;15230:13;15227:2;;;15246:18;;:::i;:::-;-1:-1:-1;15282:9:17;;15217:80::o;15302:120::-;15342:1;15368;15358:2;;15373:18;;:::i;:::-;-1:-1:-1;15407:9:17;;15348:74::o;15427:228::-;15467:7;15593:1;15525:66;15521:74;15518:1;15515:81;15510:1;15503:9;15496:17;15492:105;15489:2;;;15600:18;;:::i;:::-;-1:-1:-1;15640:9:17;;15479:176::o;15660:372::-;15699:4;15735;15732:1;15728:12;15847:1;15779:66;15775:74;15772:1;15768:82;15763:2;15756:10;15752:99;15749:2;;;15854:18;;:::i;:::-;15973:1;15905:66;15901:74;15898:1;15894:82;15890:2;15886:91;15883:2;;;15980:18;;:::i;:::-;-1:-1:-1;;16017:9:17;;15708:324::o;16037:125::-;16077:4;16105:1;16102;16099:8;16096:2;;;16110:18;;:::i;:::-;-1:-1:-1;16147:9:17;;16086:76::o;16167:258::-;16239:1;16249:113;16263:6;16260:1;16257:13;16249:113;;;16339:11;;;16333:18;16320:11;;;16313:39;16285:2;16278:10;16249:113;;;16380:6;16377:1;16374:13;16371:2;;;-1:-1:-1;;16415:1:17;16397:16;;16390:27;16220:205::o;16430:196::-;16469:3;16497:5;16487:2;;16506:18;;:::i;:::-;-1:-1:-1;16553:66:17;16542:78;;16477:149::o;16631:437::-;16710:1;16706:12;;;;16753;;;16774:2;;16828:4;16820:6;16816:17;16806:27;;16774:2;16881;16873:6;16870:14;16850:18;16847:38;16844:2;;;-1:-1:-1;;;16915:1:17;16908:88;17019:4;17016:1;17009:15;17047:4;17044:1;17037:15;16844:2;;16686:382;;;:::o;17073:112::-;17105:1;17131;17121:2;;17136:18;;:::i;:::-;-1:-1:-1;17170:9:17;;17111:74::o;17190:184::-;-1:-1:-1;;;17239:1:17;17232:88;17339:4;17336:1;17329:15;17363:4;17360:1;17353:15;17379:184;-1:-1:-1;;;17428:1:17;17421:88;17528:4;17525:1;17518:15;17552:4;17549:1;17542:15;17568:184;-1:-1:-1;;;17617:1:17;17610:88;17717:4;17714:1;17707:15;17741:4;17738:1;17731:15;17757:118;17843:5;17836:13;17829:21;17822:5;17819:32;17809:2;;17865:1;17862;17855:12

Swarm Source

ipfs://b8c8005c5c8e032159a7cb883636a57d39c3f5528a010572cd6bf4b33158d8f2
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.