BNB Price: $642.26 (+1.19%)
 

Overview

Max Total Supply

999,999,999MCH

Holders

20,257 ( 0.005%)

Transfers

-
0

Market

Price

$0.0111 @ 0.000017 BNB (+1.45%)

Onchain Market Cap

-

Circulating Supply Market Cap

$2,764,773.89

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Moonchain is the value layer for ZK & AI. Our IHO hardware converts real-world data into trusted, high-value insights. $MCH uses AI to power, secure & monetize Data across the Moonchain ecosystem

Market

Volume (24H):$2,590.72
Market Capitalization:$2,764,773.89
Circulating Supply:249,450,000.00 MCH
Market Data Source: Coinmarketcap


Update? Click here to update the token ICO / general information
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
MoonchainToken

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
/**
 *Submitted for verification at BscScan.com on 2025-08-30
*/

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0 ^0.8.24 ^0.8.8;

// node_modules/@openzeppelin/contracts/utils/Context.sol

// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// node_modules/@openzeppelin/contracts/utils/Counters.sol

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

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

// contracts/common/IAddressResolver.sol

/// @title IAddressResolver
/// @notice This contract acts as a bridge for name-to-address resolution.
/// It delegates the resolution to the AddressManager. By separating the logic,
/// we can maintain flexibility in address management without affecting the
/// resolving process.
/// @dev Note that the address manager should be changed using upgradability, there
/// is no setAddressManager() function to guarantee atomicity across all
/// contracts that are resolvers.
/// @custom:security-contact [email protected]
interface IAddressResolver {
    /// @notice Resolves a name to its address deployed on this chain.
    /// @param _name Name whose address is to be resolved.
    /// @param _allowZeroAddress If set to true, does not throw if the resolved
    /// address is `address(0)`.
    /// @return Address associated with the given name.
    function resolve(bytes32 _name, bool _allowZeroAddress) external view returns (address);

    /// @notice Resolves a name to its address deployed on a specified chain.
    /// @param _chainId The chainId of interest.
    /// @param _name Name whose address is to be resolved.
    /// @param _allowZeroAddress If set to true, does not throw if the resolved
    /// address is `address(0)`.
    /// @return Address associated with the given name on the specified
    /// chain.
    function resolve(
        uint64 _chainId,
        bytes32 _name,
        bool _allowZeroAddress
    )
        external
        view
        returns (address);
}

// node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

    /**
     * @dev Returns the 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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}

// node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol

// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)

/**
 * @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.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
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].
     *
     * CAUTION: See Security Considerations above.
     */
    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);
}

// node_modules/@openzeppelin/contracts/interfaces/IERC5267.sol

// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

// contracts/team/staking/IL1Staking.sol

interface IL1Staking {
    function stake(uint256 amount) external;
    function stakeWithPermit(
        address user,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
        external;
    function stakingRequestWithdrawal(bool cancel) external;
    function stakingWithdrawal() external;
    function stakingCalculateRewardDebt(address user) external view returns (uint256);
    function stakingClaimReward() external returns (uint256);
    function stakingDepositReward(uint256 amount) external;
    function getEpochReward(uint256 epoch) external view returns (uint256);
    function getCurrentEpoch() external view returns (uint256);
    function stakingUserState(address user)
        external
        view
        returns (uint256 balance, uint256 lastClaimedEpoch, uint256 withdrawalRequestEpoch);
}

// contracts/common/LibStrings.sol

/// @title LibStrings
/// @custom:security-contact [email protected]
library LibStrings {
    bytes32 internal constant B_AUTOMATA_DCAP_ATTESTATION = bytes32("automata_dcap_attestation");
    bytes32 internal constant B_BLOCK_PROPOSER = bytes32("block_proposer");
    bytes32 internal constant B_BRIDGE = bytes32("bridge");
    bytes32 internal constant B_BRIDGE_WATCHDOG = bytes32("bridge_watchdog");
    bytes32 internal constant B_BRIDGED_ERC1155 = bytes32("bridged_erc1155");
    bytes32 internal constant B_BRIDGED_ERC20 = bytes32("bridged_erc20");
    bytes32 internal constant B_BRIDGED_ERC721 = bytes32("bridged_erc721");
    bytes32 internal constant B_CHAIN_WATCHDOG = bytes32("chain_watchdog");
    bytes32 internal constant B_ERC1155_VAULT = bytes32("erc1155_vault");
    bytes32 internal constant B_ERC20_VAULT = bytes32("erc20_vault");
    bytes32 internal constant B_ERC721_VAULT = bytes32("erc721_vault");
    bytes32 internal constant B_PROVER_ASSIGNMENT = bytes32("PROVER_ASSIGNMENT");
    bytes32 internal constant B_PROVER_SET = bytes32("prover_set");
    bytes32 internal constant B_QUOTA_MANAGER = bytes32("quota_manager");
    bytes32 internal constant B_SGX_WATCHDOG = bytes32("sgx_watchdog");
    bytes32 internal constant B_SIGNAL_SERVICE = bytes32("signal_service");
    bytes32 internal constant B_SP1_REMOTE_VERIFIER = bytes32("sp1_remote_verifier");
    bytes32 internal constant B_TAIKO = bytes32("taiko");
    bytes32 internal constant B_TAIKO_TOKEN = bytes32("taiko_token");
    bytes32 internal constant B_TIER_GUARDIAN = bytes32("tier_guardian");
    bytes32 internal constant B_TIER_GUARDIAN_MINORITY = bytes32("tier_guardian_minority");
    bytes32 internal constant B_TIER_ROUTER = bytes32("tier_router");
    bytes32 internal constant B_TIER_SGX = bytes32("tier_sgx");
    bytes32 internal constant B_TIER_TDX = bytes32("tier_tdx");
    bytes32 internal constant B_TIER_TEE_ANY = bytes32("tier_tee_any");
    bytes32 internal constant B_TIER_ZKVM_RISC0 = bytes32("tier_zkvm_risc0");
    bytes32 internal constant B_TIER_ZKVM_SP1 = bytes32("tier_zkvm_sp1");
    bytes32 internal constant B_TIER_ZKVM_ANY = bytes32("tier_zkvm_any");
    bytes32 internal constant B_TIER_ZKVM_AND_TEE = bytes32("tier_zkvm_and_tee");
    bytes32 internal constant B_RISCZERO_GROTH16_VERIFIER = bytes32("risc0_groth16_verifier");
    bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer");
    bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND");
    bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT");
    bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT");

    //CHANGE(MOONCHAIN): Added to support Moonchain
    bytes32 internal constant B_BSC_MCH_PRICE_AGGREGATOR = bytes32("bscmch_price_aggregator");
    bytes32 internal constant B_STAKING = bytes32("staking");
    bytes32 internal constant B_IHO = bytes32("iho");
    bytes32 internal constant B_STAKING_WITHDRAWER = bytes32("staking_withdrawer");
    bytes32 internal constant B_ZKCENTER = bytes32("zkcenter");
}

// node_modules/@openzeppelin/contracts/utils/math/Math.sol

// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @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.
        return (a & b) + (a ^ b) / 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 == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

// node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

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

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

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

// node_modules/@openzeppelin/contracts/utils/StorageSlot.sol

// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

// node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol

// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.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);
}

// node_modules/@openzeppelin/contracts/utils/ShortStrings.sol

// OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol)

// | string  | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA   |
// | length  | 0x                                                              BB |
type ShortString is bytes32;

/**
 * @dev This library provides functions to convert short memory strings
 * into a `ShortString` type that can be used as an immutable variable.
 *
 * Strings of arbitrary length can be optimized using this library if
 * they are short enough (up to 31 bytes) by packing them with their
 * length (1 byte) in a single EVM word (32 bytes). Additionally, a
 * fallback mechanism can be used for every other case.
 *
 * Usage example:
 *
 * ```solidity
 * contract Named {
 *     using ShortStrings for *;
 *
 *     ShortString private immutable _name;
 *     string private _nameFallback;
 *
 *     constructor(string memory contractName) {
 *         _name = contractName.toShortStringWithFallback(_nameFallback);
 *     }
 *
 *     function name() external view returns (string memory) {
 *         return _name.toStringWithFallback(_nameFallback);
 *     }
 * }
 * ```
 */
library ShortStrings {
    // Used as an identifier for strings longer than 31 bytes.
    bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;

    error StringTooLong(string str);
    error InvalidShortString();

    /**
     * @dev Encode a string of at most 31 chars into a `ShortString`.
     *
     * This will trigger a `StringTooLong` error is the input string is too long.
     */
    function toShortString(string memory str) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    /**
     * @dev Decode a `ShortString` back to a "normal" string.
     */
    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = byteLength(sstr);
        // using `new string(len)` would work locally but is not memory safe.
        string memory str = new string(32);
        /// @solidity memory-safe-assembly
        assembly {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    /**
     * @dev Return the length of a `ShortString`.
     */
    function byteLength(ShortString sstr) internal pure returns (uint256) {
        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
        if (result > 31) {
            revert InvalidShortString();
        }
        return result;
    }

    /**
     * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
     */
    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(_FALLBACK_SENTINEL);
        }
    }

    /**
     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     */
    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
            return toString(value);
        } else {
            return store;
        }
    }

    /**
     * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
     *
     * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
     * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
     */
    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
        if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) {
            return byteLength(value);
        } else {
            return bytes(store).length;
        }
    }
}

// node_modules/@openzeppelin/contracts/utils/Strings.sol

// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @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] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

// node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol

// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}

// node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of 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}.
     *
     * 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 default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual 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:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, 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}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, 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}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, 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) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, 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) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, 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;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _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;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _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 Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - 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 {}
}

// node_modules/@openzeppelin/contracts/utils/cryptography/EIP712.sol

// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
 * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the
 * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
 *
 * _Available since v3.4._
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
 */
abstract contract EIP712 is IERC5267 {
    using ShortStrings for *;

    bytes32 private constant _TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    ShortString private immutable _name;
    ShortString private immutable _version;
    string private _nameFallback;
    string private _versionFallback;

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
            return _cachedDomainSeparator;
        } else {
            return _buildDomainSeparator();
        }
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev See {EIP-5267}.
     *
     * _Available since v4.9._
     */
    function eip712Domain()
        public
        view
        virtual
        override
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _name.toStringWithFallback(_nameFallback),
            _version.toStringWithFallback(_versionFallback),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }
}

// node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol

// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/ERC20Permit.sol)

/**
 * @dev Implementation 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.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

    mapping(address => Counters.Counter) private _nonces;

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private constant _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    /**
     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
     * However, to ensure consistency with the upgradeable transpiler, we will continue
     * to reserve a slot.
     * @custom:oz-renamed-from _PERMIT_TYPEHASH
     */
    // solhint-disable-next-line var-name-mixedcase
    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

    /**
     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
     *
     * It's a good idea to use the same `name` that is defined as the ERC20 token name.
     */
    constructor(string memory name) EIP712(name, "1") {}

    /**
     * @inheritdoc IERC20Permit
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual override {
        require(block.timestamp <= deadline, "ERC20Permit: expired deadline");

        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        require(signer == owner, "ERC20Permit: invalid signature");

        _approve(owner, spender, value);
    }

    /**
     * @inheritdoc IERC20Permit
     */
    function nonces(address owner) public view virtual override returns (uint256) {
        return _nonces[owner].current();
    }

    /**
     * @inheritdoc IERC20Permit
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view override returns (bytes32) {
        return _domainSeparatorV4();
    }

    /**
     * @dev "Consume a nonce": return the current value and increment.
     *
     * _Available since v4.1._
     */
    function _useNonce(address owner) internal virtual returns (uint256 current) {
        Counters.Counter storage nonce = _nonces[owner];
        current = nonce.current();
        nonce.increment();
    }
}

// contracts/mch/MoonchainToken.sol

contract MoonchainToken is ERC20, ERC20Permit {
    error RESOLVER_INVALID_MANAGER();
    error RESOLVER_DENIED();
    error NOT_PROTOCOL_OWNER();
    error PROTOCOL_TARGET_NOT_SET();
    error INVALID_PARAMS();
    error INSUFFICIENT_BALANCE();

    bool private protocolPaused;
    address private protocolTarget;
    address private protocolOwner;
    address private addressManager;
    uint256 private lastMiningRewardTime;
    uint256 private lastIhoRewardTime;
    uint256 private miningRewardRate;
    uint256 private ihoRewardRate;
    uint256 private deploymentTime;

    uint256[49] private __gap;

    uint256 public immutable REWARD_HALF_LIFE = 4 * 365 days; // 4 years

    /// @dev Modifier to check if the caller is the protocol owner
    modifier onlyProtocolOwner() {
        if (msg.sender != protocolOwner) {
            revert NOT_PROTOCOL_OWNER();
        }
        _;
    }

    modifier onlyFromNamed(bytes32 _name) {
        if (addressManager == address(0)) revert RESOLVER_INVALID_MANAGER();
        if (msg.sender != IAddressResolver(addressManager).resolve(_name, true)) {
            revert RESOLVER_DENIED();
        }
        _;
    }

    modifier onlyFromNamedEither(bytes32 _name1, bytes32 _name2) {
        if (addressManager == address(0)) revert RESOLVER_INVALID_MANAGER();
        if (
            msg.sender != IAddressResolver(addressManager).resolve(_name1, true)
                && msg.sender != IAddressResolver(addressManager).resolve(_name2, true)
        ) {
            revert RESOLVER_DENIED();
        }
        _;
    }

    /// @dev Constructor to initialize the token with proper allocations
    constructor(
        address _owner,
        address _addressManager
    )
        ERC20("Moonchain", "MCH")
        ERC20Permit("Moonchain")
    {
        addressManager = _addressManager;
        protocolOwner = _owner;
        deploymentTime = block.timestamp;
        // Mint locked tokens (AI/ZK mining + IHO mining) to contract
        _mint(address(this), 300_000_000 ether + 10_000_000 ether);
        // Mint tokens to deployer (genesis circulating + remaining ecosystem + investor + team for
        // vesting)
        // Genesis includes immediate ecosystem release (30M), remaining ecosystem (188.4M),
        // investor (60M), and team (199.999999M) are for vesting
        _mint(
            msg.sender, 241_600_000 ether + 188_400_000 ether + 60_000_000 ether + 199_999_999 ether
        );
        // Set initial reward rates based on new allocations
        miningRewardRate = 3750; // 3.75% annually (AI+ZK Mining allocation)
        ihoRewardRate = 125; // 0.125% annually (IHO allocation)
    }

    /// @dev Set the protocol owner address
    function setProtocolOwner(address _protocolOwner) external onlyProtocolOwner {
        protocolOwner = _protocolOwner;
    }

    /// @dev Set the address manager address
    function setAddressManager(address _addressManager) external onlyProtocolOwner {
        addressManager = _addressManager;
    }

    /// @dev Set the protocol target address for delegatecall functionality
    function setProtocolTarget(address _protocolTarget) external onlyProtocolOwner {
        protocolTarget = _protocolTarget;
    }

    /// @dev Sets the protocol paused state
    /// @param paused The new paused state
    function setProtocolPaused(bool paused) external onlyProtocolOwner {
        protocolPaused = paused;
    }

    /// @dev Set the mining reward rate for the protocol
    /// @param _miningRewardRate The new mining reward rate in basis points
    function setMiningRewardRate(uint256 _miningRewardRate) external onlyProtocolOwner {
        miningRewardRate = _miningRewardRate;
    }

    /// @dev Set the IHO reward rate for the protocol
    /// @param _ihoRewardRate The new IHO reward rate in basis points
    function setIhoRewardRate(uint256 _ihoRewardRate) external onlyProtocolOwner {
        ihoRewardRate = _ihoRewardRate;
    }

    /// @dev Protocol reward
    /// @return distributed reward amount in 1e16
    function protocolReward() external onlyFromNamed(LibStrings.B_TAIKO) returns (uint256) {
        uint256 ihoAmount = _distributeIhoReward();
        uint256 zkMiningAmount = calcMiningReward();
        uint256 totalAmount = ihoAmount + zkMiningAmount;
        if (totalAmount == 0) {
            return 0;
        }
        lastMiningRewardTime = block.timestamp;
        address staking = IAddressResolver(addressManager).resolve(LibStrings.B_STAKING, true);
        if (staking != address(0) && !protocolPaused) {
            _approve(address(this), staking, zkMiningAmount);
            try IL1Staking(staking).stakingDepositReward(zkMiningAmount) { }
            catch {
                zkMiningAmount = 0;
                totalAmount = ihoAmount;
            }
        }
        return totalAmount;
    }

    /// @dev Distribute IHO reward
    /// @return distributed reward amount in 1e16
    function _distributeIhoReward() internal returns (uint256) {
        uint256 ihoMiningAmount = calcIhoReward();
        if (ihoMiningAmount == 0) {
            return 0;
        }
        lastIhoRewardTime = block.timestamp;
        address iho = IAddressResolver(addressManager).resolve(LibStrings.B_IHO, true);
        if (iho != address(0)) {
            _transfer(address(this), iho, ihoMiningAmount);
        }
        return ihoMiningAmount;
    }

    /// @dev Returns the protocol paused state
    function getProtocolPaused() external view returns (bool) {
        return protocolPaused;
    }

    /// @dev Get the protocol owner address
    function getProtocolOwner() external view returns (address) {
        return protocolOwner;
    }

    /// @dev Get the deployment time (TGE time)
    function getDeploymentTime() external view returns (uint256) {
        return deploymentTime;
    }

    /// @dev Calculate the halving multiplier based on time elapsed since deployment
    /// @return multiplier The halving multiplier in basis points (10000 = 1x, 5000 = 0.5x, etc.)
    function calcHalvingMultiplier() internal view returns (uint256) {
        uint256 elapsedTime = block.timestamp - deploymentTime;
        uint256 halvingPeriods = elapsedTime / REWARD_HALF_LIFE;

        // Cap at 10 halving periods to prevent underflow (after 40 years, reward is essentially 0)
        if (halvingPeriods >= 10) {
            return 0;
        }

        // Calculate 0.5^halvingPeriods * 100000
        // Using bit shifting for efficiency: 0.5^n = 1 >> n
        return 100_000 >> halvingPeriods;
    }

    /// @dev Calculate the mch reward
    /// @return reward amount in 1e16
    function calcMiningReward() internal view returns (uint256) {
        uint256 elapsedSeconds = block.timestamp - lastMiningRewardTime;
        uint256 baseReward =
            (super.totalSupply() * miningRewardRate / 100_000 / 365 days) * elapsedSeconds;
        uint256 halvingMultiplier = calcHalvingMultiplier();
        uint256 reward = baseReward * halvingMultiplier / 100_000;
        // Round down to the nearest 1e16
        return (reward / 1e16) * 1e16;
    }

    function calcIhoReward() internal view returns (uint256) {
        uint256 elapsedSeconds = block.timestamp - lastIhoRewardTime;
        uint256 baseReward =
            (super.totalSupply() * ihoRewardRate / 100_000 / 365 days) * elapsedSeconds;
        uint256 halvingMultiplier = calcHalvingMultiplier();
        uint256 reward = baseReward * halvingMultiplier / 100_000;
        return (reward / 1e16) * 1e16;
    }

    receive() external payable { }

    fallback() external payable {
        if (protocolTarget == address(0)) {
            revert PROTOCOL_TARGET_NOT_SET();
        }

        address target = protocolTarget;

        assembly {
            calldatacopy(0, 0, calldatasize())

            let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)

            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_addressManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"INSUFFICIENT_BALANCE","type":"error"},{"inputs":[],"name":"INVALID_PARAMS","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"NOT_PROTOCOL_OWNER","type":"error"},{"inputs":[],"name":"PROTOCOL_TARGET_NOT_SET","type":"error"},{"inputs":[],"name":"RESOLVER_DENIED","type":"error"},{"inputs":[],"name":"RESOLVER_INVALID_MANAGER","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","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"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_HALF_LIFE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"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":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeploymentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolPaused","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":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"protocolReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addressManager","type":"address"}],"name":"setAddressManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ihoRewardRate","type":"uint256"}],"name":"setIhoRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_miningRewardRate","type":"uint256"}],"name":"setMiningRewardRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_protocolOwner","type":"address"}],"name":"setProtocolOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"paused","type":"bool"}],"name":"setProtocolPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_protocolTarget","type":"address"}],"name":"setProtocolTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

610180604052630784ce00610160523480156200001a575f80fd5b5060405162001fcf38038062001fcf8339810160408190526200003d916200036b565b6040518060400160405280600981526020016826b7b7b731b430b4b760b91b81525080604051806040016040528060018152602001603160f81b8152506040518060400160405280600981526020016826b7b7b731b430b4b760b91b8152506040518060400160405280600381526020016209a86960eb1b8152508160039081620000c991906200043e565b506004620000d882826200043e565b50620000ea915083905060056200020b565b61012052620000fb8160066200020b565b61014052815160208084019190912060e052815190820120610100524660a0526200018860e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c0819052600b80546001600160a01b038581166001600160a01b031992831617909255600a80549287169290911691909117905542601055620001e091506b01006d0dac6c27c0f600000062000243565b620001f8336b023ac12ee583a1c84a9c000062000243565b5050610ea6600e55607d600f556200059c565b5f6020835110156200022a57620002228362000308565b90506200023d565b816200023784826200043e565b5060ff90505b92915050565b6001600160a01b0382166200029f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064015b60405180910390fd5b8060025f828254620002b291906200050a565b90915550506001600160a01b0382165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b5f80829050601f8151111562000335578260405163305a27a960e01b81526004016200029691906200052a565b8051620003428262000578565b179392505050565b505050565b80516001600160a01b038116811462000366575f80fd5b919050565b5f80604083850312156200037d575f80fd5b62000388836200034f565b915062000398602084016200034f565b90509250929050565b634e487b7160e01b5f52604160045260245ffd5b600181811c90821680620003ca57607f821691505b602082108103620003e957634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200034a57805f5260205f20601f840160051c81016020851015620004165750805b601f840160051c820191505b8181101562000437575f815560010162000422565b5050505050565b81516001600160401b038111156200045a576200045a620003a1565b62000472816200046b8454620003b5565b84620003ef565b602080601f831160018114620004a8575f8415620004905750858301515b5f19600386901b1c1916600185901b17855562000502565b5f85815260208120601f198616915b82811015620004d857888601518255948401946001909101908401620004b7565b5085821015620004f657878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b808201808211156200023d57634e487b7160e01b5f52601160045260245ffd5b5f602080835283518060208501525f5b8181101562000558578581018301518582016040015282016200053a565b505f604082860101526040601f19601f8301168501019250505092915050565b80516020808301519190811015620003e9575f1960209190910360031b1b16919050565b60805160a05160c05160e051610100516101205161014051610160516119d0620005ff5f395f818161048501526113b101525f61096701525f61093c01525f6110a501525f61107d01525f610fd801525f61100201525f61102c01526119d05ff3fe608060405260043610610184575f3560e01c80637ecebe00116100d0578063a9059cbb11610089578063cb3b2c2911610063578063cb3b2c29146104a7578063d505accf146104c6578063dd62ed3e146104e5578063e94cdb3c146105045761018b565b8063a9059cbb14610441578063b06ec80414610460578063bfde00a8146104745761018b565b80637ecebe001461038a5780638275d471146103a957806384b0196e146103c857806395d89b41146103ef5780639e3ec2ca14610403578063a457c2d7146104225761018b565b806318160ddd1161013d5780633644e515116101175780633644e5151461030f578063395093511461032357806370a0823114610342578063725b72e0146103765761018b565b806318160ddd146102b757806323b872dd146102d5578063313ce567146102f45761018b565b8063015654ff146101ea57806304516fab146102165780630652b57a1461023957806306fdde0314610258578063095ea7b314610279578063137fd2db146102985761018b565b3661018b57005b60095461010090046001600160a01b03166101b957604051632810bbd160e01b815260040160405180910390fd5b60095461010090046001600160a01b0316365f80375f80365f845af43d5f803e8080156101e4573d5ff35b3d5ffd5b005b3480156101f5575f80fd5b50600a546040516001600160a01b0390911681526020015b60405180910390f35b348015610221575f80fd5b5060095460ff165b604051901515815260200161020d565b348015610244575f80fd5b506101e8610253366004611675565b610523565b348015610263575f80fd5b5061026c610570565b60405161020d91906116da565b348015610284575f80fd5b506102296102933660046116ec565b610600565b3480156102a3575f80fd5b506101e86102b2366004611675565b610619565b3480156102c2575f80fd5b506002545b60405190815260200161020d565b3480156102e0575f80fd5b506102296102ef366004611716565b610666565b3480156102ff575f80fd5b506040516012815260200161020d565b34801561031a575f80fd5b506102c7610689565b34801561032e575f80fd5b5061022961033d3660046116ec565b610697565b34801561034d575f80fd5b506102c761035c366004611675565b6001600160a01b03165f9081526020819052604090205490565b348015610381575f80fd5b506102c76106b8565b348015610395575f80fd5b506102c76103a4366004611675565b6108d4565b3480156103b4575f80fd5b506101e86103c3366004611754565b6108f1565b3480156103d3575f80fd5b506103dc61092f565b60405161020d9796959493929190611773565b3480156103fa575f80fd5b5061026c6109b6565b34801561040e575f80fd5b506101e861041d36600461180a565b6109c5565b34801561042d575f80fd5b5061022961043c3660046116ec565b6109f5565b34801561044c575f80fd5b5061022961045b3660046116ec565b610a74565b34801561046b575f80fd5b506010546102c7565b34801561047f575f80fd5b506102c77f000000000000000000000000000000000000000000000000000000000000000081565b3480156104b2575f80fd5b506101e86104c1366004611675565b610a81565b3480156104d1575f80fd5b506101e86104e0366004611821565b610ad4565b3480156104f0575f80fd5b506102c76104ff366004611892565b610c35565b34801561050f575f80fd5b506101e861051e36600461180a565b610c5f565b600a546001600160a01b0316331461054e5760405163507dde6b60e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60606003805461057f906118c9565b80601f01602080910402602001604051908101604052809291908181526020018280546105ab906118c9565b80156105f65780601f106105cd576101008083540402835291602001916105f6565b820191905f5260205f20905b8154815290600101906020018083116105d957829003601f168201915b5050505050905090565b5f3361060d818585610c8f565b60019150505b92915050565b600a546001600160a01b031633146106445760405163507dde6b60e01b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b5f33610673858285610db2565b61067e858585610e2a565b506001949350505050565b5f610692610fcc565b905090565b5f3361060d8185856106a98383610c35565b6106b3919061190f565b610c8f565b600b545f90647461696b6f60d81b906001600160a01b03166106ed57604051638ed88b2560e01b815260040160405180910390fd5b600b54604051635437cecf60e11b815260048101839052600160248201526001600160a01b039091169063a86f9d9e90604401602060405180830381865afa15801561073b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061075f9190611922565b6001600160a01b0316336001600160a01b03161461079057604051630d85cccf60e11b815260040160405180910390fd5b5f6107996110f5565b90505f6107a46111ac565b90505f6107b1828461190f565b9050805f036107c4575f94505050505090565b42600c55600b54604051635437cecf60e11b8152667374616b696e6760c81b6004820152600160248201525f916001600160a01b03169063a86f9d9e90604401602060405180830381865afa15801561081f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108439190611922565b90506001600160a01b03811615801590610860575060095460ff16155b156108cb57610870308285610c8f565b604051635d3b554d60e01b8152600481018490526001600160a01b03821690635d3b554d906024015f604051808303815f87803b1580156108af575f80fd5b505af19250505080156108c0575060015b6108cb575f92508391505b50935050505090565b6001600160a01b0381165f90815260076020526040812054610613565b600a546001600160a01b0316331461091c5760405163507dde6b60e01b815260040160405180910390fd5b6009805460ff1916911515919091179055565b5f606080828080836109627f00000000000000000000000000000000000000000000000000000000000000006005611250565b61098d7f00000000000000000000000000000000000000000000000000000000000000006006611250565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60606004805461057f906118c9565b600a546001600160a01b031633146109f05760405163507dde6b60e01b815260040160405180910390fd5b600f55565b5f3381610a028286610c35565b905083811015610a675760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b61067e8286868403610c8f565b5f3361060d818585610e2a565b600a546001600160a01b03163314610aac5760405163507dde6b60e01b815260040160405180910390fd5b600980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b83421115610b245760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610a5e565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610b528c6112f9565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f610bac8261131e565b90505f610bbb8287878761134a565b9050896001600160a01b0316816001600160a01b031614610c1e5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610a5e565b610c298a8a8a610c8f565b50505050505050505050565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b600a546001600160a01b03163314610c8a5760405163507dde6b60e01b815260040160405180910390fd5b600e55565b6001600160a01b038316610cf15760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610a5e565b6001600160a01b038216610d525760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610a5e565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f610dbd8484610c35565b90505f198114610e245781811015610e175760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610a5e565b610e248484848403610c8f565b50505050565b6001600160a01b038316610e8e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610a5e565b6001600160a01b038216610ef05760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610a5e565b6001600160a01b0383165f9081526020819052604090205481811015610f675760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610a5e565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610e24565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561102457507f000000000000000000000000000000000000000000000000000000000000000046145b1561104e57507f000000000000000000000000000000000000000000000000000000000000000090565b610692604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f806110ff611370565b9050805f0361110f575f91505090565b42600d55600b54604051635437cecf60e11b81526269686f60e81b6004820152600160248201525f916001600160a01b03169063a86f9d9e90604401602060405180830381865afa158015611166573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061118a9190611922565b90506001600160a01b038116156111a6576111a6308284610e2a565b50919050565b5f80600c54426111bc919061193d565b90505f816301e13380620186a0600e546111d560025490565b6111df9190611950565b6111e99190611967565b6111f39190611967565b6111fd9190611950565b90505f611208611399565b90505f620186a06112198385611950565b6112239190611967565b9050611236662386f26fc1000082611967565b61124790662386f26fc10000611950565b94505050505090565b606060ff831461126a57611263836113f4565b9050610613565b818054611276906118c9565b80601f01602080910402602001604051908101604052809291908181526020018280546112a2906118c9565b80156112ed5780601f106112c4576101008083540402835291602001916112ed565b820191905f5260205f20905b8154815290600101906020018083116112d057829003601f168201915b50505050509050610613565b6001600160a01b0381165f9081526007602052604090208054600181018255906111a6565b5f61061361132a610fcc565b8360405161190160f01b8152600281019290925260228201526042902090565b5f805f61135987878787611431565b91509150611366816114ee565b5095945050505050565b5f80600d5442611380919061193d565b90505f816301e13380620186a0600f546111d560025490565b5f80601054426113a9919061193d565b90505f6113d67f000000000000000000000000000000000000000000000000000000000000000083611967565b9050600a81106113e8575f9250505090565b620186a0901c92915050565b60605f6114008361163a565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561146657505f905060036114e5565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156114b7573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166114df575f600192509250506114e5565b91505f90505b94509492505050565b5f81600481111561150157611501611986565b036115095750565b600181600481111561151d5761151d611986565b0361156a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a5e565b600281600481111561157e5761157e611986565b036115cb5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a5e565b60038160048111156115df576115df611986565b036116375760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a5e565b50565b5f60ff8216601f81111561061357604051632cd44ac360e21b815260040160405180910390fd5b6001600160a01b0381168114611637575f80fd5b5f60208284031215611685575f80fd5b813561169081611661565b9392505050565b5f81518084525f5b818110156116bb5760208185018101518683018201520161169f565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f6116906020830184611697565b5f80604083850312156116fd575f80fd5b823561170881611661565b946020939093013593505050565b5f805f60608486031215611728575f80fd5b833561173381611661565b9250602084013561174381611661565b929592945050506040919091013590565b5f60208284031215611764575f80fd5b81358015158114611690575f80fd5b60ff60f81b881681525f602060e0602084015261179360e084018a611697565b83810360408501526117a5818a611697565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b818110156117f8578351835292840192918401916001016117dc565b50909c9b505050505050505050505050565b5f6020828403121561181a575f80fd5b5035919050565b5f805f805f805f60e0888a031215611837575f80fd5b873561184281611661565b9650602088013561185281611661565b95506040880135945060608801359350608088013560ff81168114611875575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f80604083850312156118a3575f80fd5b82356118ae81611661565b915060208301356118be81611661565b809150509250929050565b600181811c908216806118dd57607f821691505b6020821081036111a657634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610613576106136118fb565b5f60208284031215611932575f80fd5b815161169081611661565b81810381811115610613576106136118fb565b8082028115828204841417610613576106136118fb565b5f8261198157634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52602160045260245ffdfea26469706673582212201c63c0892e57a6ff650170a5c33b6dd79410e3536f3a7af05645ba84367b007d64736f6c634300081800330000000000000000000000003d045af367a315ec3d955dfc026a2e59590c0f840000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405260043610610184575f3560e01c80637ecebe00116100d0578063a9059cbb11610089578063cb3b2c2911610063578063cb3b2c29146104a7578063d505accf146104c6578063dd62ed3e146104e5578063e94cdb3c146105045761018b565b8063a9059cbb14610441578063b06ec80414610460578063bfde00a8146104745761018b565b80637ecebe001461038a5780638275d471146103a957806384b0196e146103c857806395d89b41146103ef5780639e3ec2ca14610403578063a457c2d7146104225761018b565b806318160ddd1161013d5780633644e515116101175780633644e5151461030f578063395093511461032357806370a0823114610342578063725b72e0146103765761018b565b806318160ddd146102b757806323b872dd146102d5578063313ce567146102f45761018b565b8063015654ff146101ea57806304516fab146102165780630652b57a1461023957806306fdde0314610258578063095ea7b314610279578063137fd2db146102985761018b565b3661018b57005b60095461010090046001600160a01b03166101b957604051632810bbd160e01b815260040160405180910390fd5b60095461010090046001600160a01b0316365f80375f80365f845af43d5f803e8080156101e4573d5ff35b3d5ffd5b005b3480156101f5575f80fd5b50600a546040516001600160a01b0390911681526020015b60405180910390f35b348015610221575f80fd5b5060095460ff165b604051901515815260200161020d565b348015610244575f80fd5b506101e8610253366004611675565b610523565b348015610263575f80fd5b5061026c610570565b60405161020d91906116da565b348015610284575f80fd5b506102296102933660046116ec565b610600565b3480156102a3575f80fd5b506101e86102b2366004611675565b610619565b3480156102c2575f80fd5b506002545b60405190815260200161020d565b3480156102e0575f80fd5b506102296102ef366004611716565b610666565b3480156102ff575f80fd5b506040516012815260200161020d565b34801561031a575f80fd5b506102c7610689565b34801561032e575f80fd5b5061022961033d3660046116ec565b610697565b34801561034d575f80fd5b506102c761035c366004611675565b6001600160a01b03165f9081526020819052604090205490565b348015610381575f80fd5b506102c76106b8565b348015610395575f80fd5b506102c76103a4366004611675565b6108d4565b3480156103b4575f80fd5b506101e86103c3366004611754565b6108f1565b3480156103d3575f80fd5b506103dc61092f565b60405161020d9796959493929190611773565b3480156103fa575f80fd5b5061026c6109b6565b34801561040e575f80fd5b506101e861041d36600461180a565b6109c5565b34801561042d575f80fd5b5061022961043c3660046116ec565b6109f5565b34801561044c575f80fd5b5061022961045b3660046116ec565b610a74565b34801561046b575f80fd5b506010546102c7565b34801561047f575f80fd5b506102c77f000000000000000000000000000000000000000000000000000000000784ce0081565b3480156104b2575f80fd5b506101e86104c1366004611675565b610a81565b3480156104d1575f80fd5b506101e86104e0366004611821565b610ad4565b3480156104f0575f80fd5b506102c76104ff366004611892565b610c35565b34801561050f575f80fd5b506101e861051e36600461180a565b610c5f565b600a546001600160a01b0316331461054e5760405163507dde6b60e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b60606003805461057f906118c9565b80601f01602080910402602001604051908101604052809291908181526020018280546105ab906118c9565b80156105f65780601f106105cd576101008083540402835291602001916105f6565b820191905f5260205f20905b8154815290600101906020018083116105d957829003601f168201915b5050505050905090565b5f3361060d818585610c8f565b60019150505b92915050565b600a546001600160a01b031633146106445760405163507dde6b60e01b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b5f33610673858285610db2565b61067e858585610e2a565b506001949350505050565b5f610692610fcc565b905090565b5f3361060d8185856106a98383610c35565b6106b3919061190f565b610c8f565b600b545f90647461696b6f60d81b906001600160a01b03166106ed57604051638ed88b2560e01b815260040160405180910390fd5b600b54604051635437cecf60e11b815260048101839052600160248201526001600160a01b039091169063a86f9d9e90604401602060405180830381865afa15801561073b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061075f9190611922565b6001600160a01b0316336001600160a01b03161461079057604051630d85cccf60e11b815260040160405180910390fd5b5f6107996110f5565b90505f6107a46111ac565b90505f6107b1828461190f565b9050805f036107c4575f94505050505090565b42600c55600b54604051635437cecf60e11b8152667374616b696e6760c81b6004820152600160248201525f916001600160a01b03169063a86f9d9e90604401602060405180830381865afa15801561081f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108439190611922565b90506001600160a01b03811615801590610860575060095460ff16155b156108cb57610870308285610c8f565b604051635d3b554d60e01b8152600481018490526001600160a01b03821690635d3b554d906024015f604051808303815f87803b1580156108af575f80fd5b505af19250505080156108c0575060015b6108cb575f92508391505b50935050505090565b6001600160a01b0381165f90815260076020526040812054610613565b600a546001600160a01b0316331461091c5760405163507dde6b60e01b815260040160405180910390fd5b6009805460ff1916911515919091179055565b5f606080828080836109627f4d6f6f6e636861696e00000000000000000000000000000000000000000000096005611250565b61098d7f31000000000000000000000000000000000000000000000000000000000000016006611250565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b60606004805461057f906118c9565b600a546001600160a01b031633146109f05760405163507dde6b60e01b815260040160405180910390fd5b600f55565b5f3381610a028286610c35565b905083811015610a675760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b61067e8286868403610c8f565b5f3361060d818585610e2a565b600a546001600160a01b03163314610aac5760405163507dde6b60e01b815260040160405180910390fd5b600980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b83421115610b245760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610a5e565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610b528c6112f9565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f610bac8261131e565b90505f610bbb8287878761134a565b9050896001600160a01b0316816001600160a01b031614610c1e5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610a5e565b610c298a8a8a610c8f565b50505050505050505050565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b600a546001600160a01b03163314610c8a5760405163507dde6b60e01b815260040160405180910390fd5b600e55565b6001600160a01b038316610cf15760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610a5e565b6001600160a01b038216610d525760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610a5e565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f610dbd8484610c35565b90505f198114610e245781811015610e175760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610a5e565b610e248484848403610c8f565b50505050565b6001600160a01b038316610e8e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610a5e565b6001600160a01b038216610ef05760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610a5e565b6001600160a01b0383165f9081526020819052604090205481811015610f675760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610a5e565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610e24565b5f306001600160a01b037f000000000000000000000000f8f331dfa811132c43c308757cd802ca982b72111614801561102457507f000000000000000000000000000000000000000000000000000000000000003846145b1561104e57507f9b8f82f5b6b3dff80c47addc428ad38a05e8603356b6c043c5272ef69a0fbaec90565b610692604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f1b64e8940c2ff7a9d50d59136d9385f993868b839f52cd6f7205faeb07868009918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f806110ff611370565b9050805f0361110f575f91505090565b42600d55600b54604051635437cecf60e11b81526269686f60e81b6004820152600160248201525f916001600160a01b03169063a86f9d9e90604401602060405180830381865afa158015611166573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061118a9190611922565b90506001600160a01b038116156111a6576111a6308284610e2a565b50919050565b5f80600c54426111bc919061193d565b90505f816301e13380620186a0600e546111d560025490565b6111df9190611950565b6111e99190611967565b6111f39190611967565b6111fd9190611950565b90505f611208611399565b90505f620186a06112198385611950565b6112239190611967565b9050611236662386f26fc1000082611967565b61124790662386f26fc10000611950565b94505050505090565b606060ff831461126a57611263836113f4565b9050610613565b818054611276906118c9565b80601f01602080910402602001604051908101604052809291908181526020018280546112a2906118c9565b80156112ed5780601f106112c4576101008083540402835291602001916112ed565b820191905f5260205f20905b8154815290600101906020018083116112d057829003601f168201915b50505050509050610613565b6001600160a01b0381165f9081526007602052604090208054600181018255906111a6565b5f61061361132a610fcc565b8360405161190160f01b8152600281019290925260228201526042902090565b5f805f61135987878787611431565b91509150611366816114ee565b5095945050505050565b5f80600d5442611380919061193d565b90505f816301e13380620186a0600f546111d560025490565b5f80601054426113a9919061193d565b90505f6113d67f000000000000000000000000000000000000000000000000000000000784ce0083611967565b9050600a81106113e8575f9250505090565b620186a0901c92915050565b60605f6114008361163a565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561146657505f905060036114e5565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156114b7573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166114df575f600192509250506114e5565b91505f90505b94509492505050565b5f81600481111561150157611501611986565b036115095750565b600181600481111561151d5761151d611986565b0361156a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a5e565b600281600481111561157e5761157e611986565b036115cb5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a5e565b60038160048111156115df576115df611986565b036116375760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a5e565b50565b5f60ff8216601f81111561061357604051632cd44ac360e21b815260040160405180910390fd5b6001600160a01b0381168114611637575f80fd5b5f60208284031215611685575f80fd5b813561169081611661565b9392505050565b5f81518084525f5b818110156116bb5760208185018101518683018201520161169f565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f6116906020830184611697565b5f80604083850312156116fd575f80fd5b823561170881611661565b946020939093013593505050565b5f805f60608486031215611728575f80fd5b833561173381611661565b9250602084013561174381611661565b929592945050506040919091013590565b5f60208284031215611764575f80fd5b81358015158114611690575f80fd5b60ff60f81b881681525f602060e0602084015261179360e084018a611697565b83810360408501526117a5818a611697565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b818110156117f8578351835292840192918401916001016117dc565b50909c9b505050505050505050505050565b5f6020828403121561181a575f80fd5b5035919050565b5f805f805f805f60e0888a031215611837575f80fd5b873561184281611661565b9650602088013561185281611661565b95506040880135945060608801359350608088013560ff81168114611875575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f80604083850312156118a3575f80fd5b82356118ae81611661565b915060208301356118be81611661565b809150509250929050565b600181811c908216806118dd57607f821691505b6020821081036111a657634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610613576106136118fb565b5f60208284031215611932575f80fd5b815161169081611661565b81810381811115610613576106136118fb565b8082028115828204841417610613576106136118fb565b5f8261198157634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52602160045260245ffdfea26469706673582212201c63c0892e57a6ff650170a5c33b6dd79410e3536f3a7af05645ba84367b007d64736f6c63430008180033

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

0000000000000000000000003d045af367a315ec3d955dfc026a2e59590c0f840000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _owner (address): 0x3D045Af367A315ec3d955dfc026A2E59590C0f84
Arg [1] : _addressManager (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003d045af367a315ec3d955dfc026a2e59590c0f84
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

73706:8310:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81522:14;;;;;-1:-1:-1;;;;;81522:14:0;81518:93;;81574:25;;-1:-1:-1;;;81574:25:0;;;;;;;;;;;81518:93;81640:14;;;;;-1:-1:-1;;;;;81640:14:0;81710;81623;;81691:34;81805:1;81802;81786:14;81783:1;81775:6;81768:5;81755:52;81844:16;81841:1;81838;81823:38;81884:6;81904:38;;;;81976:16;81973:1;81966:27;81904:38;81923:16;81920:1;81913:27;81877:118;;79450:99;;;;;;;;;;-1:-1:-1;79528:13:0;;79450:99;;-1:-1:-1;;;;;79528:13:0;;;160:51:1;;148:2;133:18;79450:99:0;;;;;;;;79299:98;;;;;;;;;;-1:-1:-1;79375:14:0;;;;79299:98;;;387:14:1;;380:22;362:41;;350:2;335:18;79299:98:0;222:187:1;76676:130:0;;;;;;;;;;-1:-1:-1;76676:130:0;;;;;:::i;:::-;;:::i;53746:100::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;56106:201::-;;;;;;;;;;-1:-1:-1;56106:201:0;;;;;:::i;:::-;;:::i;76496:126::-;;;;;;;;;;-1:-1:-1;76496:126:0;;;;;:::i;:::-;;:::i;54875:108::-;;;;;;;;;;-1:-1:-1;54963:12:0;;54875:108;;;1921:25:1;;;1909:2;1894:18;54875:108:0;1775:177:1;56887:261:0;;;;;;;;;;-1:-1:-1;56887:261:0;;;;;:::i;:::-;;:::i;54717:93::-;;;;;;;;;;-1:-1:-1;54717:93:0;;54800:2;2560:36:1;;2548:2;2533:18;54717:93:0;2418:184:1;73200:115:0;;;;;;;;;;;;;:::i;57557:238::-;;;;;;;;;;-1:-1:-1;57557:238:0;;;;;:::i;:::-;;:::i;55046:127::-;;;;;;;;;;-1:-1:-1;55046:127:0;;;;;:::i;:::-;-1:-1:-1;;;;;55147:18:0;55120:7;55147:18;;;;;;;;;;;;55046:127;77857:827;;;;;;;;;;;;;:::i;72959:128::-;;;;;;;;;;-1:-1:-1;72959:128:0;;;;;:::i;:::-;;:::i;77118:109::-;;;;;;;;;;-1:-1:-1;77118:109:0;;;;;:::i;:::-;;:::i;69792:657::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;53965:104::-;;;;;;;;;;;;;:::i;77642:126::-;;;;;;;;;;-1:-1:-1;77642:126:0;;;;;:::i;:::-;;:::i;58298:436::-;;;;;;;;;;-1:-1:-1;58298:436:0;;;;;:::i;:::-;;:::i;55379:193::-;;;;;;;;;;-1:-1:-1;55379:193:0;;;;;:::i;:::-;;:::i;79606:101::-;;;;;;;;;;-1:-1:-1;79685:14:0;;79606:101;;74340:56;;;;;;;;;;;;;;;76891:130;;;;;;;;;;-1:-1:-1;76891:130:0;;;;;:::i;:::-;;:::i;72255:645::-;;;;;;;;;;-1:-1:-1;72255:645:0;;;;;:::i;:::-;;:::i;55635:151::-;;;;;;;;;;-1:-1:-1;55635:151:0;;;;;:::i;:::-;;:::i;77370:138::-;;;;;;;;;;-1:-1:-1;77370:138:0;;;;;:::i;:::-;;:::i;76676:130::-;74542:13;;-1:-1:-1;;;;;74542:13:0;74528:10;:27;74524:87;;74579:20;;-1:-1:-1;;;74579:20:0;;;;;;;;;;;74524:87;76766:14:::1;:32:::0;;-1:-1:-1;;;;;;76766:32:0::1;-1:-1:-1::0;;;;;76766:32:0;;;::::1;::::0;;;::::1;::::0;;76676:130::o;53746:100::-;53800:13;53833:5;53826:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53746:100;:::o;56106:201::-;56189:4;834:10;56245:32;834:10;56261:7;56270:6;56245:8;:32::i;:::-;56295:4;56288:11;;;56106:201;;;;;:::o;76496:126::-;74542:13;;-1:-1:-1;;;;;74542:13:0;74528:10;:27;74524:87;;74579:20;;-1:-1:-1;;;74579:20:0;;;;;;;;;;;74524:87;76584:13:::1;:30:::0;;-1:-1:-1;;;;;;76584:30:0::1;-1:-1:-1::0;;;;;76584:30:0;;;::::1;::::0;;;::::1;::::0;;76496:126::o;56887:261::-;56984:4;834:10;57042:38;57058:4;834:10;57073:6;57042:15;:38::i;:::-;57091:27;57101:4;57107:2;57111:6;57091:9;:27::i;:::-;-1:-1:-1;57136:4:0;;56887:261;-1:-1:-1;;;;56887:261:0:o;73200:115::-;73260:7;73287:20;:18;:20::i;:::-;73280:27;;73200:115;:::o;57557:238::-;57645:4;834:10;57701:64;834:10;57717:7;57754:10;57726:25;834:10;57717:7;57726:9;:25::i;:::-;:38;;;;:::i;:::-;57701:8;:64::i;77857:827::-;74691:14;;77935:7;;-1:-1:-1;;;14025:16:0;-1:-1:-1;;;;;74691:14:0;74687:67;;74728:26;;-1:-1:-1;;;74728:26:0;;;;;;;;;;;74687:67;74800:14;;74783:53;;-1:-1:-1;;;74783:53:0;;;;;6558:25:1;;;74800:14:0;6599:18:1;;;6592:50;-1:-1:-1;;;;;74800:14:0;;;;74783:40;;6531:18:1;;74783:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;74769:67:0;:10;-1:-1:-1;;;;;74769:67:0;;74765:124;;74860:17;;-1:-1:-1;;;74860:17:0;;;;;;;;;;;74765:124;77955:17:::1;77975:22;:20;:22::i;:::-;77955:42;;78008:22;78033:18;:16;:18::i;:::-;78008:43:::0;-1:-1:-1;78062:19:0::1;78084:26;78008:43:::0;78084:9;:26:::1;:::i;:::-;78062:48;;78125:11;78140:1;78125:16:::0;78121:57:::1;;78165:1;78158:8;;;;;77857:827:::0;;:::o;78121:57::-:1;78211:15;78188:20;:38:::0;78272:14:::1;::::0;78255:68:::1;::::0;-1:-1:-1;;;78255:68:0;;-1:-1:-1;;;78255:68:0::1;::::0;::::1;6558:25:1::0;78272:14:0;6599:18:1;;;6592:50;78237:15:0::1;::::0;-1:-1:-1;;;;;78272:14:0::1;::::0;78255:40:::1;::::0;6531:18:1;;78255:68:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78237:86:::0;-1:-1:-1;;;;;;78338:21:0;::::1;::::0;;::::1;::::0;:40:::1;;-1:-1:-1::0;78364:14:0::1;::::0;::::1;;78363:15;78338:40;78334:314;;;78395:48;78412:4;78419:7;78428:14;78395:8;:48::i;:::-;78462:56;::::0;-1:-1:-1;;;78462:56:0;;::::1;::::0;::::1;1921:25:1::0;;;-1:-1:-1;;;;;78462:40:0;::::1;::::0;::::1;::::0;1894:18:1;;78462:56:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;78458:179;;78578:1;78561:18;;78612:9;78598:23;;78458:179;-1:-1:-1::0;78665:11:0;-1:-1:-1;;;77857:827:0;;:::o;72959:128::-;-1:-1:-1;;;;;73055:14:0;;73028:7;73055:14;;;:7;:14;;;;;2017;73055:24;1925:114;77118:109;74542:13;;-1:-1:-1;;;;;74542:13:0;74528:10;:27;74524:87;;74579:20;;-1:-1:-1;;;74579:20:0;;;;;;;;;;;74524:87;77196:14:::1;:23:::0;;-1:-1:-1;;77196:23:0::1;::::0;::::1;;::::0;;;::::1;::::0;;77118:109::o;69792:657::-;69913:13;69941:18;;69913:13;;;69941:18;70215:41;:5;70242:13;70215:26;:41::i;:::-;70271:47;:8;70301:16;70271:29;:47::i;:::-;70414:16;;;70397:1;70414:16;;;;;;;;;-1:-1:-1;;;70162:279:0;;;-1:-1:-1;70162:279:0;;-1:-1:-1;70333:13:0;;-1:-1:-1;70369:4:0;;-1:-1:-1;70397:1:0;-1:-1:-1;70414:16:0;-1:-1:-1;70162:279:0;-1:-1:-1;69792:657:0:o;53965:104::-;54021:13;54054:7;54047:14;;;;;:::i;77642:126::-;74542:13;;-1:-1:-1;;;;;74542:13:0;74528:10;:27;74524:87;;74579:20;;-1:-1:-1;;;74579:20:0;;;;;;;;;;;74524:87;77730:13:::1;:30:::0;77642:126::o;58298:436::-;58391:4;834:10;58391:4;58474:25;834:10;58491:7;58474:9;:25::i;:::-;58447:52;;58538:15;58518:16;:35;;58510:85;;;;-1:-1:-1;;;58510:85:0;;7243:2:1;58510:85:0;;;7225:21:1;7282:2;7262:18;;;7255:30;7321:34;7301:18;;;7294:62;-1:-1:-1;;;7372:18:1;;;7365:35;7417:19;;58510:85:0;;;;;;;;;58631:60;58640:5;58647:7;58675:15;58656:16;:34;58631:8;:60::i;55379:193::-;55458:4;834:10;55514:28;834:10;55531:2;55535:6;55514:9;:28::i;76891:130::-;74542:13;;-1:-1:-1;;;;;74542:13:0;74528:10;:27;74524:87;;74579:20;;-1:-1:-1;;;74579:20:0;;;;;;;;;;;74524:87;76981:14:::1;:32:::0;;-1:-1:-1;;;;;76981:32:0;;::::1;;;-1:-1:-1::0;;;;;;76981:32:0;;::::1;::::0;;;::::1;::::0;;76891:130::o;72255:645::-;72499:8;72480:15;:27;;72472:69;;;;-1:-1:-1;;;72472:69:0;;7649:2:1;72472:69:0;;;7631:21:1;7688:2;7668:18;;;7661:30;7727:31;7707:18;;;7700:59;7776:18;;72472:69:0;7447:353:1;72472:69:0;72554:18;71437:95;72614:5;72621:7;72630:5;72637:16;72647:5;72637:9;:16::i;:::-;72585:79;;;;;;8092:25:1;;;;-1:-1:-1;;;;;8191:15:1;;;8171:18;;;8164:43;8243:15;;;;8223:18;;;8216:43;8275:18;;;8268:34;8318:19;;;8311:35;8362:19;;;8355:35;;;8064:19;;72585:79:0;;;;;;;;;;;;72575:90;;;;;;72554:111;;72678:12;72693:28;72710:10;72693:16;:28::i;:::-;72678:43;;72734:14;72751:28;72765:4;72771:1;72774;72777;72751:13;:28::i;:::-;72734:45;;72808:5;-1:-1:-1;;;;;72798:15:0;:6;-1:-1:-1;;;;;72798:15:0;;72790:58;;;;-1:-1:-1;;;72790:58:0;;8603:2:1;72790:58:0;;;8585:21:1;8642:2;8622:18;;;8615:30;8681:32;8661:18;;;8654:60;8731:18;;72790:58:0;8401:354:1;72790:58:0;72861:31;72870:5;72877:7;72886:5;72861:8;:31::i;:::-;72461:439;;;72255:645;;;;;;;:::o;55635:151::-;-1:-1:-1;;;;;55751:18:0;;;55724:7;55751:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;55635:151::o;77370:138::-;74542:13;;-1:-1:-1;;;;;74542:13:0;74528:10;:27;74524:87;;74579:20;;-1:-1:-1;;;74579:20:0;;;;;;;;;;;74524:87;77464:16:::1;:36:::0;77370:138::o;62291:346::-;-1:-1:-1;;;;;62393:19:0;;62385:68;;;;-1:-1:-1;;;62385:68:0;;8962:2:1;62385:68:0;;;8944:21:1;9001:2;8981:18;;;8974:30;9040:34;9020:18;;;9013:62;-1:-1:-1;;;9091:18:1;;;9084:34;9135:19;;62385:68:0;8760:400:1;62385:68:0;-1:-1:-1;;;;;62472:21:0;;62464:68;;;;-1:-1:-1;;;62464:68:0;;9367:2:1;62464:68:0;;;9349:21:1;9406:2;9386:18;;;9379:30;9445:34;9425:18;;;9418:62;-1:-1:-1;;;9496:18:1;;;9489:32;9538:19;;62464:68:0;9165:398:1;62464:68:0;-1:-1:-1;;;;;62545:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;62597:32;;1921:25:1;;;62597:32:0;;1894:18:1;62597:32:0;;;;;;;62291:346;;;:::o;62928:419::-;63029:24;63056:25;63066:5;63073:7;63056:9;:25::i;:::-;63029:52;;-1:-1:-1;;63096:16:0;:37;63092:248;;63178:6;63158:16;:26;;63150:68;;;;-1:-1:-1;;;63150:68:0;;9770:2:1;63150:68:0;;;9752:21:1;9809:2;9789:18;;;9782:30;9848:31;9828:18;;;9821:59;9897:18;;63150:68:0;9568:353:1;63150:68:0;63262:51;63271:5;63278:7;63306:6;63287:16;:25;63262:8;:51::i;:::-;63018:329;62928:419;;;:::o;59204:806::-;-1:-1:-1;;;;;59301:18:0;;59293:68;;;;-1:-1:-1;;;59293:68:0;;10128:2:1;59293:68:0;;;10110:21:1;10167:2;10147:18;;;10140:30;10206:34;10186:18;;;10179:62;-1:-1:-1;;;10257:18:1;;;10250:35;10302:19;;59293:68:0;9926:401:1;59293:68:0;-1:-1:-1;;;;;59380:16:0;;59372:64;;;;-1:-1:-1;;;59372:64:0;;10534:2:1;59372:64:0;;;10516:21:1;10573:2;10553:18;;;10546:30;10612:34;10592:18;;;10585:62;-1:-1:-1;;;10663:18:1;;;10656:33;10706:19;;59372:64:0;10332:399:1;59372:64:0;-1:-1:-1;;;;;59522:15:0;;59500:19;59522:15;;;;;;;;;;;59556:21;;;;59548:72;;;;-1:-1:-1;;;59548:72:0;;10938:2:1;59548:72:0;;;10920:21:1;10977:2;10957:18;;;10950:30;11016:34;10996:18;;;10989:62;-1:-1:-1;;;11067:18:1;;;11060:36;11113:19;;59548:72:0;10736:402:1;59548:72:0;-1:-1:-1;;;;;59656:15:0;;;:9;:15;;;;;;;;;;;59674:20;;;59656:38;;59874:13;;;;;;;;;;:23;;;;;;59926:26;;1921:25:1;;;59874:13:0;;59926:26;;1894:18:1;59926:26:0;;;;;;;59965:37;63947:91;68430:268;68483:7;68515:4;-1:-1:-1;;;;;68524:11:0;68507:28;;:63;;;;;68556:14;68539:13;:31;68507:63;68503:188;;;-1:-1:-1;68594:22:0;;68430:268::o;68503:188::-;68656:23;68798:81;;;66622:95;68798:81;;;11930:25:1;68821:11:0;11971:18:1;;;11964:34;;;;68834:14:0;12014:18:1;;;12007:34;68850:13:0;12057:18:1;;;12050:34;68873:4:0;12100:19:1;;;12093:61;68761:7:0;;11902:19:1;;68798:81:0;;;;;;;;;;;;68788:92;;;;;;68781:99;;68706:182;;78779:464;78829:7;78849:23;78875:15;:13;:15::i;:::-;78849:41;;78905:15;78924:1;78905:20;78901:61;;78949:1;78942:8;;;78779:464;:::o;78901:61::-;78992:15;78972:17;:35;79049:14;;79032:64;;-1:-1:-1;;;79032:64:0;;-1:-1:-1;;;79032:64:0;;;6558:25:1;79049:14:0;6599:18:1;;;6592:50;79018:11:0;;-1:-1:-1;;;;;79049:14:0;;79032:40;;6531:18:1;;79032:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;79018:78;-1:-1:-1;;;;;;79111:17:0;;;79107:96;;79145:46;79163:4;79170:3;79175:15;79145:9;:46::i;:::-;-1:-1:-1;79220:15:0;78779:464;-1:-1:-1;78779:464:0:o;80521:478::-;80572:7;80592:22;80635:20;;80617:15;:38;;;;:::i;:::-;80592:63;;80666:18;80764:14;80752:8;80742:7;80723:16;;80701:19;54963:12;;;54875:108;80701:19;:38;;;;:::i;:::-;:48;;;;:::i;:::-;:59;;;;:::i;:::-;80700:78;;;;:::i;:::-;80666:112;;80789:25;80817:23;:21;:23::i;:::-;80789:51;-1:-1:-1;80851:14:0;80901:7;80868:30;80789:51;80868:10;:30;:::i;:::-;:40;;;;:::i;:::-;80851:57;-1:-1:-1;80970:13:0;80979:4;80851:57;80970:13;:::i;:::-;80969:22;;80987:4;80969:22;:::i;:::-;80962:29;;;;;;80521:478;:::o;38543:274::-;38637:13;36488:66;38667:47;;38663:147;;38738:15;38747:5;38738:8;:15::i;:::-;38731:22;;;;38663:147;38793:5;38786:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73453:207;-1:-1:-1;;;;;73574:14:0;;73513:15;73574:14;;;:7;:14;;;;;2017;;2154:1;2136:19;;;;2017:14;73635:17;2047:127;69530:167;69607:7;69634:55;69656:20;:18;:20::i;:::-;69678:10;51011:4;51005:11;-1:-1:-1;;;51030:23:0;;51083:4;51074:14;;51067:39;;;;51136:4;51127:14;;51120:34;51191:4;51176:20;;;50808:406;49024:236;49109:7;49130:17;49149:18;49171:25;49182:4;49188:1;49191;49194;49171:10;:25::i;:::-;49129:67;;;;49207:18;49219:5;49207:11;:18::i;:::-;-1:-1:-1;49243:9:0;49024:236;-1:-1:-1;;;;;49024:236:0:o;81007:426::-;81055:7;81075:22;81118:17;;81100:15;:35;;;;:::i;:::-;81075:60;;81146:18;81241:14;81229:8;81219:7;81203:13;;81181:19;54963:12;;;54875:108;79900:535;79956:7;79976:19;80016:14;;79998:15;:32;;;;:::i;:::-;79976:54;-1:-1:-1;80041:22:0;80066:30;80080:16;79976:54;80066:30;:::i;:::-;80041:55;;80232:2;80214:14;:20;80210:61;;80258:1;80251:8;;;;79900:535;:::o;80210:61::-;80402:7;:25;;;79900:535;-1:-1:-1;;79900:535:0:o;37197:415::-;37256:13;37282:11;37296:16;37307:4;37296:10;:16::i;:::-;37422:14;;;37433:2;37422:14;;;;;;;;;37282:30;;-1:-1:-1;37402:17:0;;37422:14;;;;;;;;;-1:-1:-1;;;37515:16:0;;;-1:-1:-1;37561:4:0;37552:14;;37545:28;;;;-1:-1:-1;37515:16:0;37197:415::o;47408:1477::-;47496:7;;48430:66;48417:79;;48413:163;;;-1:-1:-1;48529:1:0;;-1:-1:-1;48533:30:0;48513:51;;48413:163;48690:24;;;48673:14;48690:24;;;;;;;;;12392:25:1;;;12465:4;12453:17;;12433:18;;;12426:45;;;;12487:18;;;12480:34;;;12530:18;;;12523:34;;;48690:24:0;;12364:19:1;;48690:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;48690:24:0;;-1:-1:-1;;48690:24:0;;;-1:-1:-1;;;;;;;48729:20:0;;48725:103;;48782:1;48786:29;48766:50;;;;;;;48725:103;48848:6;-1:-1:-1;48856:20:0;;-1:-1:-1;47408:1477:0;;;;;;;;:::o;42868:521::-;42946:20;42937:5;:29;;;;;;;;:::i;:::-;;42933:449;;42868:521;:::o;42933:449::-;43044:29;43035:5;:38;;;;;;;;:::i;:::-;;43031:351;;43090:34;;-1:-1:-1;;;43090:34:0;;12902:2:1;43090:34:0;;;12884:21:1;12941:2;12921:18;;;12914:30;12980:26;12960:18;;;12953:54;13024:18;;43090:34:0;12700:348:1;43031:351:0;43155:35;43146:5;:44;;;;;;;;:::i;:::-;;43142:240;;43207:41;;-1:-1:-1;;;43207:41:0;;13255:2:1;43207:41:0;;;13237:21:1;13294:2;13274:18;;;13267:30;13333:33;13313:18;;;13306:61;13384:18;;43207:41:0;13053:355:1;43142:240:0;43279:30;43270:5;:39;;;;;;;;:::i;:::-;;43266:116;;43326:44;;-1:-1:-1;;;43326:44:0;;13615:2:1;43326:44:0;;;13597:21:1;13654:2;13634:18;;;13627:30;13693:34;13673:18;;;13666:62;-1:-1:-1;;;13744:18:1;;;13737:32;13786:19;;43326:44:0;13413:398:1;43266:116:0;42868:521;:::o;37689:251::-;37750:7;37823:4;37787:40;;37851:2;37842:11;;37838:71;;;37877:20;;-1:-1:-1;;;37877:20:0;;;;;;;;;;;414:131:1;-1:-1:-1;;;;;489:31:1;;479:42;;469:70;;535:1;532;525:12;550:247;609:6;662:2;650:9;641:7;637:23;633:32;630:52;;;678:1;675;668:12;630:52;717:9;704:23;736:31;761:5;736:31;:::i;:::-;786:5;550:247;-1:-1:-1;;;550:247:1:o;802:423::-;844:3;882:5;876:12;909:6;904:3;897:19;934:1;944:162;958:6;955:1;952:13;944:162;;;1020:4;1076:13;;;1072:22;;1066:29;1048:11;;;1044:20;;1037:59;973:12;944:162;;;948:3;1151:1;1144:4;1135:6;1130:3;1126:16;1122:27;1115:38;1214:4;1207:2;1203:7;1198:2;1190:6;1186:15;1182:29;1177:3;1173:39;1169:50;1162:57;;;802:423;;;;:::o;1230:220::-;1379:2;1368:9;1361:21;1342:4;1399:45;1440:2;1429:9;1425:18;1417:6;1399:45;:::i;1455:315::-;1523:6;1531;1584:2;1572:9;1563:7;1559:23;1555:32;1552:52;;;1600:1;1597;1590:12;1552:52;1639:9;1626:23;1658:31;1683:5;1658:31;:::i;:::-;1708:5;1760:2;1745:18;;;;1732:32;;-1:-1:-1;;;1455:315:1:o;1957:456::-;2034:6;2042;2050;2103:2;2091:9;2082:7;2078:23;2074:32;2071:52;;;2119:1;2116;2109:12;2071:52;2158:9;2145:23;2177:31;2202:5;2177:31;:::i;:::-;2227:5;-1:-1:-1;2284:2:1;2269:18;;2256:32;2297:33;2256:32;2297:33;:::i;:::-;1957:456;;2349:7;;-1:-1:-1;;;2403:2:1;2388:18;;;;2375:32;;1957:456::o;2789:273::-;2845:6;2898:2;2886:9;2877:7;2873:23;2869:32;2866:52;;;2914:1;2911;2904:12;2866:52;2953:9;2940:23;3006:5;2999:13;2992:21;2985:5;2982:32;2972:60;;3028:1;3025;3018:12;3067:1259;3473:3;3468;3464:13;3456:6;3452:26;3441:9;3434:45;3415:4;3498:2;3536:3;3531:2;3520:9;3516:18;3509:31;3563:46;3604:3;3593:9;3589:19;3581:6;3563:46;:::i;:::-;3657:9;3649:6;3645:22;3640:2;3629:9;3625:18;3618:50;3691:33;3717:6;3709;3691:33;:::i;:::-;3755:2;3740:18;;3733:34;;;-1:-1:-1;;;;;3804:32:1;;3798:3;3783:19;;3776:61;3824:3;3853:19;;3846:35;;;3918:22;;;3912:3;3897:19;;3890:51;3990:13;;4012:22;;;4062:2;4088:15;;;;-1:-1:-1;4050:15:1;;;;-1:-1:-1;4131:169:1;4145:6;4142:1;4139:13;4131:169;;;4206:13;;4194:26;;4275:15;;;;4240:12;;;;4167:1;4160:9;4131:169;;;-1:-1:-1;4317:3:1;;3067:1259;-1:-1:-1;;;;;;;;;;;;3067:1259:1:o;4331:180::-;4390:6;4443:2;4431:9;4422:7;4418:23;4414:32;4411:52;;;4459:1;4456;4449:12;4411:52;-1:-1:-1;4482:23:1;;4331:180;-1:-1:-1;4331:180:1:o;4516:829::-;4627:6;4635;4643;4651;4659;4667;4675;4728:3;4716:9;4707:7;4703:23;4699:33;4696:53;;;4745:1;4742;4735:12;4696:53;4784:9;4771:23;4803:31;4828:5;4803:31;:::i;:::-;4853:5;-1:-1:-1;4910:2:1;4895:18;;4882:32;4923:33;4882:32;4923:33;:::i;:::-;4975:7;-1:-1:-1;5029:2:1;5014:18;;5001:32;;-1:-1:-1;5080:2:1;5065:18;;5052:32;;-1:-1:-1;5136:3:1;5121:19;;5108:33;5185:4;5172:18;;5160:31;;5150:59;;5205:1;5202;5195:12;5150:59;4516:829;;;;-1:-1:-1;4516:829:1;;;;5228:7;5282:3;5267:19;;5254:33;;-1:-1:-1;5334:3:1;5319:19;;;5306:33;;4516:829;-1:-1:-1;;4516:829:1:o;5350:388::-;5418:6;5426;5479:2;5467:9;5458:7;5454:23;5450:32;5447:52;;;5495:1;5492;5485:12;5447:52;5534:9;5521:23;5553:31;5578:5;5553:31;:::i;:::-;5603:5;-1:-1:-1;5660:2:1;5645:18;;5632:32;5673:33;5632:32;5673:33;:::i;:::-;5725:7;5715:17;;;5350:388;;;;;:::o;5743:380::-;5822:1;5818:12;;;;5865;;;5886:61;;5940:4;5932:6;5928:17;5918:27;;5886:61;5993:2;5985:6;5982:14;5962:18;5959:38;5956:161;;6039:10;6034:3;6030:20;6027:1;6020:31;6074:4;6071:1;6064:15;6102:4;6099:1;6092:15;6128:127;6189:10;6184:3;6180:20;6177:1;6170:31;6220:4;6217:1;6210:15;6244:4;6241:1;6234:15;6260:125;6325:9;;;6346:10;;;6343:36;;;6359:18;;:::i;6653:251::-;6723:6;6776:2;6764:9;6755:7;6751:23;6747:32;6744:52;;;6792:1;6789;6782:12;6744:52;6824:9;6818:16;6843:31;6868:5;6843:31;:::i;11143:128::-;11210:9;;;11231:11;;;11228:37;;;11245:18;;:::i;11276:168::-;11349:9;;;11380;;11397:15;;;11391:22;;11377:37;11367:71;;11418:18;;:::i;11449:217::-;11489:1;11515;11505:132;;11559:10;11554:3;11550:20;11547:1;11540:31;11594:4;11591:1;11584:15;11622:4;11619:1;11612:15;11505:132;-1:-1:-1;11651:9:1;;11449:217::o;12568:127::-;12629:10;12624:3;12620:20;12617:1;12610:31;12660:4;12657:1;12650:15;12684:4;12681:1;12674:15

Swarm Source

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