frxETH Price: $3,454.11 (-0.16%)

Token

Frax Share (FXS)
 

Overview

Max Total Supply

3,154,192.42411953192949951 FXS

Holders

922 ( 0.217%)

Market

Price

$2.48 @ 0.000718 frxETH (+2.67%)

Onchain Market Cap

$7,822,397.21

Circulating Supply Market Cap

$200,430,087.00

Other Info

Token Contract (WITH 18 Decimals)

Balance
3.32194157010278361 FXS

Value
$8.24 ( ~0.0023855619369734 frxETH) [0.0001%]
0x161d9b5d6e3ed8d9c1d36a7caf971901c60b9222
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

FXS is the value accrual and governance token of the entire Frax ecosystem. Frax is a fractional-algorithmic stablecoin protocol. It aims to provide a highly scalable, decentralized, algorithmic money in place of fixed-supply assets like BTC.

Market

Volume (24H):$24,742,335.00
Market Capitalization:$200,430,087.00
Circulating Supply:80,562,382.00 FXS
Market Data Source: Coinmarketcap

Contract Source Code Verified (Genesis Bytecode Match Only)

Contract Name:
Fxs

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
No with 200 runs

Other Settings:
london EvmVersion, MIT license
File 1 of 25 : Fxs.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

import { ERC20PermitPermissionedOptiMintable } from "./ERC20PermitPermissionedOptiMintable.sol";

contract Fxs is ERC20PermitPermissionedOptiMintable {
    /// @param _creator_address The contract creator
    /// @param _timelock_address The timelock
    /// @param _bridge Address of the L2 standard bridge
    /// @param _remoteToken Address of the corresponding L1 token
    constructor(
        address _creator_address,
        address _timelock_address,
        address _bridge,
        address _remoteToken
    )
        ERC20PermitPermissionedOptiMintable(
            _creator_address,
            _timelock_address,
            _bridge,
            _remoteToken,
            "Frax Share",
            "FXS"
        )
    {}
}

File 2 of 25 : ERC20PermitPermissionedOptiMintable.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import { IERC20 } from "@openzeppelin-5/contracts/token/ERC20/IERC20.sol";
import { ERC20Permit, ERC20 } from "@openzeppelin-5/contracts/token/ERC20/extensions/ERC20Permit.sol";
import { ERC20Burnable } from "@openzeppelin-5/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import { IERC165 } from "@openzeppelin-5/contracts/utils/introspection/IERC165.sol";
import {
    ILegacyMintableERC20,
    IOptimismMintableERC20
} from "@eth-optimism/contracts-bedrock/src/universal/IOptimismMintableERC20.sol";
import { ISemver } from "@eth-optimism/contracts-bedrock/src/universal/ISemver.sol";
import { OwnedV2 } from "./OwnedV2.sol";

/// @title Parent contract for frxETH.sol, but also CrossChainCanonicalV2
/**
 * @notice Combines Openzeppelin's ERC20Permit and ERC20Burnable with Synthetix's Owned and Optimism's OptimismMintableERC20.
 *     Also includes a list of authorized minters
 */
/// @dev ERC20PermitPermissionedOptiMintable adheres to EIP-712/EIP-2612 and can use permits
contract ERC20PermitPermissionedOptiMintable is
    ERC20Permit,
    ERC20Burnable,
    OwnedV2,
    IOptimismMintableERC20,
    ILegacyMintableERC20,
    ISemver
{
    /// @custom:semver 1.0.0
    string public constant version = "1.0.0";

    /// @notice The timelock address
    address public timelock_address;

    /// @notice Address of the L2 StandardBridge on this network.
    address public immutable BRIDGE;

    /// @notice Address of the corresponding version of this token on the remote chain.
    address public immutable REMOTE_TOKEN;

    /// @notice Array of the non-bridge minters
    address[] public minters_array;

    /// @notice Mapping of the non-bridge minters
    /// @dev Mapping is used for faster verification
    mapping(address => bool) public minters;

    /* ========== CONSTRUCTOR ========== */

    /// @custom:semver 1.0.0
    /// @param _creator_address The contract creator
    /// @param _timelock_address The timelock
    /// @param _bridge Address of the L2 standard bridge
    /// @param _remoteToken Address of the corresponding L1 token
    /// @param _name ERC20 name
    /// @param _symbol ERC20 symbol
    constructor(
        address _creator_address,
        address _timelock_address,
        address _bridge,
        address _remoteToken,
        string memory _name,
        string memory _symbol
    ) ERC20(_name, _symbol) ERC20Permit(_name) OwnedV2(_creator_address) {
        REMOTE_TOKEN = _remoteToken;
        BRIDGE = _bridge;
        timelock_address = _timelock_address;
    }

    /* ========== MODIFIERS ========== */

    /// @notice A modifier that only allows the contract owner or the timelock to call
    modifier onlyByOwnGov() {
        require(msg.sender == timelock_address || msg.sender == owner, "Not owner or timelock");
        _;
    }

    /// @notice A modifier that only allows a non-bridge minter to call
    modifier onlyMinters() {
        require(minters[msg.sender] == true, "Only minters");
        _;
    }

    /// @notice A modifier that only allows the bridge to call
    modifier onlyBridge() {
        require(msg.sender == BRIDGE, "OptimismMintableERC20: only bridge can mint and burn");
        _;
    }

    /* ========== LEGACY VIEWS ========== */

    /// @custom:legacy
    /// @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.
    /// @return address The L1 remote token address
    function l1Token() public view returns (address) {
        return REMOTE_TOKEN;
    }

    /// @custom:legacy
    /// @notice Legacy getter for the bridge. Use BRIDGE going forward.
    /// @return address The bridge address
    function l2Bridge() public view returns (address) {
        return BRIDGE;
    }

    /// @custom:legacy
    /// @notice Legacy getter for REMOTE_TOKEN
    /// @return address The L1 remote token address
    function remoteToken() public view returns (address) {
        return REMOTE_TOKEN;
    }

    /// @custom:legacy
    /// @notice Legacy getter for BRIDGE
    /// @return address The bridge address
    function bridge() public view returns (address) {
        return BRIDGE;
    }

    /// @notice ERC165 interface check function.
    /// @param _interfaceId Interface ID to check.
    /// @return Whether or not the interface is supported by this contract.
    function supportsInterface(bytes4 _interfaceId) external pure virtual returns (bool) {
        bytes4 iface1 = type(IERC165).interfaceId;
        // Interface corresponding to the legacy L2StandardERC20.
        bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;
        // Interface corresponding to the updated OptimismMintableERC20 (this contract).
        bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;
        return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;
    }

    /* ========== RESTRICTED FUNCTIONS [BRIDGE] ========== */

    /// @notice Allows the StandardBridge on this network to mint tokens.
    /// @param _to     Address to mint tokens to.
    /// @param _amount Amount of tokens to mint.
    function mint(
        address _to,
        uint256 _amount
    ) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyBridge {
        _mint(_to, _amount);
        emit Mint(_to, _amount);
    }

    /// @notice Allows the StandardBridge on this network to burn tokens.
    /// @param _from   Address to burn tokens from.
    /// @param _amount Amount of tokens to burn.
    function burn(
        address _from,
        uint256 _amount
    ) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyBridge {
        _burn(_from, _amount);
        emit Burn(_from, _amount);
    }

    /* ========== RESTRICTED FUNCTIONS [NON-BRIDGE MINTERS] ========== */

    /// @notice Used by non-bridge minters to burn tokens
    /// @param b_address Address of the account to burn from
    /// @param b_amount Amount of tokens to burn
    function minter_burn_from(address b_address, uint256 b_amount) public onlyMinters {
        super.burnFrom(b_address, b_amount);
        emit TokenMinterBurned(b_address, msg.sender, b_amount);
    }

    /// @notice Used by non-bridge minters to mint new tokens
    /// @param m_address Address of the account to mint to
    /// @param m_amount Amount of tokens to mint
    function minter_mint(address m_address, uint256 m_amount) public onlyMinters {
        super._mint(m_address, m_amount);
        emit TokenMinterMinted(msg.sender, m_address, m_amount);
    }

    /// @notice Adds a non-bridge minter
    /// @param minter_address Address of minter to add
    function addMinter(address minter_address) public onlyByOwnGov {
        require(minter_address != address(0), "Zero address detected");

        require(minters[minter_address] == false, "Address already exists");
        minters[minter_address] = true;
        minters_array.push(minter_address);

        emit MinterAdded(minter_address);
    }

    /// @notice Removes a non-bridge minter
    /// @param minter_address Address of minter to remove
    function removeMinter(address minter_address) public onlyByOwnGov {
        require(minter_address != address(0), "Zero address detected");
        require(minters[minter_address] == true, "Address nonexistant");

        // Delete from the mapping
        delete minters[minter_address];

        // 'Delete' from the array by setting the address to 0x0
        for (uint256 i = 0; i < minters_array.length; i++) {
            if (minters_array[i] == minter_address) {
                minters_array[i] = address(0); // This will leave a null in the array and keep the indices the same
                break;
            }
        }

        emit MinterRemoved(minter_address);
    }

    /* ========== RESTRICTED FUNCTIONS [ADMIN-RELATED] ========== */

    /// @notice Sets the timelock address
    /// @param _timelock_address Address of the timelock
    function setTimelock(address _timelock_address) public onlyByOwnGov {
        require(_timelock_address != address(0), "Zero address detected");
        timelock_address = _timelock_address;
        emit TimelockChanged(_timelock_address);
    }

    /* ========== EVENTS ========== */

    /// @notice Emitted whenever the bridge burns tokens from an account
    /// @param account Address of the account tokens are being burned from
    /// @param amount  Amount of tokens burned
    event Burn(address indexed account, uint256 amount);

    /// @notice Emitted whenever the bridge mints tokens to an account
    /// @param account Address of the account tokens are being minted for
    /// @param amount  Amount of tokens minted.
    event Mint(address indexed account, uint256 amount);

    /// @notice Emitted when a non-bridge minter is added
    /// @param minter_address Address of the new minter
    event MinterAdded(address minter_address);

    /// @notice Emitted when a non-bridge minter is removed
    /// @param minter_address Address of the removed minter
    event MinterRemoved(address minter_address);

    /// @notice Emitted when the timelock address changes
    /// @param timelock_address Address of the removed timelock
    event TimelockChanged(address timelock_address);

    /// @notice Emitted when a non-bridge minter burns tokens
    /// @param from The account whose tokens are burned
    /// @param to The minter doing the burning
    /// @param amount Amount of tokens burned
    event TokenMinterBurned(address indexed from, address indexed to, uint256 amount);

    /// @notice Emitted when a non-bridge minter mints tokens
    /// @param from The minter doing the minting
    /// @param to The account that gets the newly minted tokens
    /// @param amount Amount of tokens minted
    event TokenMinterMinted(address indexed from, address indexed to, uint256 amount);
}

File 3 of 25 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

File 4 of 25 : ERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Permit.sol)

pragma solidity ^0.8.20;

import {IERC20Permit} from "./IERC20Permit.sol";
import {ERC20} from "../ERC20.sol";
import {ECDSA} from "../../../utils/cryptography/ECDSA.sol";
import {EIP712} from "../../../utils/cryptography/EIP712.sol";
import {Nonces} from "../../../utils/Nonces.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.
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
    bytes32 private constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    /**
     * @dev Permit deadline has expired.
     */
    error ERC2612ExpiredSignature(uint256 deadline);

    /**
     * @dev Mismatched signature.
     */
    error ERC2612InvalidSigner(address signer, address owner);

    /**
     * @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 {
        if (block.timestamp > deadline) {
            revert ERC2612ExpiredSignature(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);
        if (signer != owner) {
            revert ERC2612InvalidSigner(signer, owner);
        }

        _approve(owner, spender, value);
    }

    /**
     * @inheritdoc IERC20Permit
     */
    function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) {
        return super.nonces(owner);
    }

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

File 5 of 25 : ERC20Burnable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.20;

import {ERC20} from "../ERC20.sol";
import {Context} from "../../../utils/Context.sol";

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys a `value` amount of tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 value) public virtual {
        _burn(_msgSender(), value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, deducting from
     * the caller's allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `value`.
     */
    function burnFrom(address account, uint256 value) public virtual {
        _spendAllowance(account, _msgSender(), value);
        _burn(account, value);
    }
}

File 6 of 25 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

File 7 of 25 : IOptimismMintableERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/// @title IOptimismMintableERC20
/// @notice This interface is available on the OptimismMintableERC20 contract.
///         We declare it as a separate interface so that it can be used in
///         custom implementations of OptimismMintableERC20.
interface IOptimismMintableERC20 is IERC165 {
    function remoteToken() external view returns (address);

    function bridge() external returns (address);

    function mint(address _to, uint256 _amount) external;

    function burn(address _from, uint256 _amount) external;
}

/// @custom:legacy
/// @title ILegacyMintableERC20
/// @notice This interface was available on the legacy L2StandardERC20 contract.
///         It remains available on the OptimismMintableERC20 contract for
///         backwards compatibility.
interface ILegacyMintableERC20 is IERC165 {
    function l1Token() external view returns (address);

    function mint(address _to, uint256 _amount) external;

    function burn(address _from, uint256 _amount) external;
}

File 8 of 25 : ISemver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title ISemver
/// @notice ISemver is a simple contract for ensuring that contracts are
///         versioned using semantic versioning.
interface ISemver {
    /// @notice Getter for the semantic version of the contract. This is not
    ///         meant to be used onchain but instead meant to be used by offchain
    ///         tooling.
    /// @return Semver contract version as a string.
    function version() external view returns (string memory);
}

File 9 of 25 : OwnedV2.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.4;

// https://docs.synthetix.io/contracts/Owned
contract OwnedV2 {
    error OwnerCannotBeZero();
    error InvalidOwnershipAcceptance();
    error OnlyOwner();

    address public owner;
    address public nominatedOwner;

    constructor(address _owner) {
        // require(_owner != address(0), "Owner address cannot be 0");
        if (_owner == address(0)) revert OwnerCannotBeZero();
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        // require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        if (msg.sender != nominatedOwner) revert InvalidOwnershipAcceptance();
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    modifier onlyOwner() {
        // require(msg.sender == owner, "Only the contract owner may perform this action");
        if (msg.sender != owner) revert OnlyOwner();
        _;
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}

File 10 of 25 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

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

File 11 of 25 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.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}.
 *
 * 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.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the 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 `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

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

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

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

        emit Transfer(from, to, value);
    }

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

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

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

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

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

File 12 of 25 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

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

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile 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 {MessageHashUtils-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]
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
        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, bytes32(signature.length));
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
        _throwError(error, errorArg);
        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]
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
        unchecked {
            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            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.
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError, bytes32) {
        // 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, s);
        }

        // 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, bytes32(0));
        }

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @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, bytes32 errorArg) = tryRecover(hash, v, r, s);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}

File 13 of 25 : EIP712.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.20;

import {MessageHashUtils} from "./MessageHashUtils.sol";
import {ShortStrings, ShortString} from "../ShortStrings.sol";
import {IERC5267} from "../../interfaces/IERC5267.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
 * encoding is very generic and therefore its 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 order to
 * produce the hash of their typed data 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.
 *
 * @custom:oz-upgrades-unsafe-allow state-variable-immutable
 */
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 MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    /**
     * @dev See {IERC-5267}.
     */
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f", // 01111
            _EIP712Name(),
            _EIP712Version(),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }

    /**
     * @dev The name parameter for the EIP712 domain.
     *
     * NOTE: By default this function reads _name which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _EIP712Name() internal view returns (string memory) {
        return _name.toStringWithFallback(_nameFallback);
    }

    /**
     * @dev The version parameter for the EIP712 domain.
     *
     * NOTE: By default this function reads _version which is an immutable value.
     * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
     */
    // solhint-disable-next-line func-name-mixedcase
    function _EIP712Version() internal view returns (string memory) {
        return _version.toStringWithFallback(_versionFallback);
    }
}

File 14 of 25 : Nonces.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)
pragma solidity ^0.8.20;

/**
 * @dev Provides tracking nonces for addresses. Nonces will only increment.
 */
abstract contract Nonces {
    /**
     * @dev The nonce used for an `account` is not the expected current nonce.
     */
    error InvalidAccountNonce(address account, uint256 currentNonce);

    mapping(address account => uint256) private _nonces;

    /**
     * @dev Returns the next unused nonce for an address.
     */
    function nonces(address owner) public view virtual returns (uint256) {
        return _nonces[owner];
    }

    /**
     * @dev Consumes a nonce.
     *
     * Returns the current value and increments nonce.
     */
    function _useNonce(address owner) internal virtual returns (uint256) {
        // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be
        // decremented or reset. This guarantees that the nonce never overflows.
        unchecked {
            // It is important to do x++ and not ++x here.
            return _nonces[owner]++;
        }
    }

    /**
     * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.
     */
    function _useCheckedNonce(address owner, uint256 nonce) internal virtual {
        uint256 current = _useNonce(owner);
        if (nonce != current) {
            revert InvalidAccountNonce(owner, current);
        }
    }
}

File 15 of 25 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

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

File 16 of 25 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

File 17 of 25 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

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

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

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

File 18 of 25 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

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

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

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

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

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

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

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

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

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

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

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

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

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

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

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

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

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

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

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 19 of 25 : MessageHashUtils.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)

pragma solidity ^0.8.20;

import {Strings} from "../Strings.sol";

/**
 * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
 *
 * The library provides methods for generating a hash of a message that conforms to the
 * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
 * specifications.
 */
library MessageHashUtils {
    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing a bytes32 `messageHash` with
     * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
     * keccak256, although any bytes32 value can be safely used because the final digest will
     * be re-hashed.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
        }
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x45` (`personal_sign` messages).
     *
     * The digest is calculated by prefixing an arbitrary `message` with
     * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
     *
     * See {ECDSA-recover}.
     */
    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
        return
            keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-191 signed data with version
     * `0x00` (data with intended validator).
     *
     * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
     * `validator` address. Then hashing the result.
     *
     * See {ECDSA-recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(hex"19_00", validator, data));
    }

    /**
     * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).
     *
     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
     * `\x19\x01` and hashing the result. It corresponds to the hash signed by the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
     *
     * See {ECDSA-recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, hex"19_01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            digest := keccak256(ptr, 0x42)
        }
    }
}

File 20 of 25 : ShortStrings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.20;

import {StorageSlot} from "./StorageSlot.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;
        }
    }
}

File 21 of 25 : IERC5267.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.20;

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
        );
}

File 22 of 25 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";

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

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @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), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(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) {
        uint256 localValue = value;
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = HEX_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        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 bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 23 of 25 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

/**
 * @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(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 */
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
        }
    }
}

File 24 of 25 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @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 towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (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 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                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.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 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.

            uint256 twos = denominator & (0 - denominator);
            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 (unsignedRoundsUp(rounding) && 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
     * towards zero.
     *
     * 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 25 of 25 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

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

Settings
{
  "remappings": [
    "frax-std/=lib/frax-standard-solidity/src/",
    "@eth-optimism/=lib/optimism/packages/",
    "lib/optimism/packages/contracts-bedrock:src/=lib/optimism/packages/contracts-bedrock/src/",
    "@openzeppelin-4/=node_modules/@openzeppelin-4/",
    "@openzeppelin-5/=node_modules/@openzeppelin-5/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@rari-capital/=node_modules/@rari-capital/",
    "clones-with-immutable-args/=lib/optimism/packages/contracts-bedrock/lib/clones-with-immutable-args/src/",
    "ds-test/=lib/frax-standard-solidity/lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/frax-standard-solidity/lib/forge-std/src/",
    "frax-standard-solidity/=lib/frax-standard-solidity/src/",
    "kontrol-cheatcodes/=lib/optimism/packages/contracts-bedrock/lib/kontrol-cheatcodes/src/",
    "lib-keccak/=lib/optimism/packages/contracts-bedrock/lib/lib-keccak/contracts/",
    "openzeppelin-contracts-upgradeable/=lib/optimism/packages/contracts-bedrock/lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/optimism/packages/contracts-bedrock/lib/openzeppelin-contracts/",
    "optimism/=lib/optimism/",
    "safe-contracts/=lib/optimism/packages/contracts-bedrock/lib/safe-contracts/contracts/",
    "solady/=lib/optimism/packages/contracts-bedrock/lib/solady/",
    "solidity-bytes-utils/=lib/frax-standard-solidity/lib/solidity-bytes-utils/",
    "solmate/=lib/optimism/packages/contracts-bedrock/lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": false
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_creator_address","type":"address"},{"internalType":"address","name":"_timelock_address","type":"address"},{"internalType":"address","name":"_bridge","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidOwnershipAcceptance","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"OwnerCannotBeZero","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":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter_address","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter_address","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"timelock_address","type":"address"}],"name":"TimelockChanged","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":"amount","type":"uint256"}],"name":"TokenMinterBurned","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":"amount","type":"uint256"}],"name":"TokenMinterMinted","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"},{"inputs":[],"name":"BRIDGE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REMOTE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter_address","type":"address"}],"name":"addMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","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":"l1Token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2Bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"b_address","type":"address"},{"internalType":"uint256","name":"b_amount","type":"uint256"}],"name":"minter_burn_from","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"m_address","type":"address"},{"internalType":"uint256","name":"m_amount","type":"uint256"}],"name":"minter_mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"minters_array","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"remoteToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter_address","type":"address"}],"name":"removeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_timelock_address","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelock_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50600436106102275760003560e01c806379cc679011610130578063bdacb303116100b8578063dc6663c71161007c578063dc6663c714610646578063dd62ed3e14610664578063e78cea9214610694578063ee9a31a2146106b2578063f46eccc4146106d057610227565b8063bdacb303146105a2578063c01e1bd6146105be578063d505accf146105dc578063d6c0b2c4146105f8578063d73ced041461061657610227565b806395d89b41116100ff57806395d89b41146104fe578063983b2d561461051c5780639dc29fac14610538578063a9059cbb14610554578063ae1f6aaf1461058457610227565b806379cc6790146104705780637ecebe001461048c57806384b0196e146104bc5780638da5cb5b146104e057610227565b80633644e515116101b357806354fd4d501161018257806354fd4d50146103e05780636a257ebc146103fe57806370a082311461041a5780637941bc891461044a57806379ba50971461046657610227565b80633644e5151461036c57806340c10f191461038a57806342966c68146103a657806353a47bb7146103c257610227565b80631627540c116101fa5780631627540c146102c857806318160ddd146102e457806323b872dd146103025780633092afd514610332578063313ce5671461034e57610227565b806301ffc9a71461022c578063033964be1461025c57806306fdde031461027a578063095ea7b314610298575b600080fd5b61024660048036038101906102419190612b5b565b610700565b6040516102539190612ba3565b60405180910390f35b61026461084b565b6040516102719190612bff565b60405180910390f35b61028261086f565b60405161028f9190612caa565b60405180910390f35b6102b260048036038101906102ad9190612d2e565b610901565b6040516102bf9190612ba3565b60405180910390f35b6102e260048036038101906102dd9190612d6e565b610924565b005b6102ec610a26565b6040516102f99190612daa565b60405180910390f35b61031c60048036038101906103179190612dc5565b610a30565b6040516103299190612ba3565b60405180910390f35b61034c60048036038101906103479190612d6e565b610a5f565b005b610356610dc4565b6040516103639190612e34565b60405180910390f35b610374610dcd565b6040516103819190612e68565b60405180910390f35b6103a4600480360381019061039f9190612d2e565b610ddc565b005b6103c060048036038101906103bb9190612e83565b610ec6565b005b6103ca610eda565b6040516103d79190612bff565b60405180910390f35b6103e8610f00565b6040516103f59190612caa565b60405180910390f35b61041860048036038101906104139190612d2e565b610f39565b005b610434600480360381019061042f9190612d6e565b61103f565b6040516104419190612daa565b60405180910390f35b610464600480360381019061045f9190612d2e565b611087565b005b61046e61118d565b005b61048a60048036038101906104859190612d2e565b611338565b005b6104a660048036038101906104a19190612d6e565b611358565b6040516104b39190612daa565b60405180910390f35b6104c461136a565b6040516104d79796959493929190612fa9565b60405180910390f35b6104e8611414565b6040516104f59190612bff565b60405180910390f35b61050661143a565b6040516105139190612caa565b60405180910390f35b61053660048036038101906105319190612d6e565b6114cc565b005b610552600480360381019061054d9190612d2e565b6117ab565b005b61056e60048036038101906105699190612d2e565b611895565b60405161057b9190612ba3565b60405180910390f35b61058c6118b8565b6040516105999190612bff565b60405180910390f35b6105bc60048036038101906105b79190612d6e565b6118e0565b005b6105c6611ab2565b6040516105d39190612bff565b60405180910390f35b6105f660048036038101906105f19190613085565b611ada565b005b610600611c22565b60405161060d9190612bff565b60405180910390f35b610630600480360381019061062b9190612e83565b611c4a565b60405161063d9190612bff565b60405180910390f35b61064e611c89565b60405161065b9190612bff565b60405180910390f35b61067e60048036038101906106799190613127565b611caf565b60405161068b9190612daa565b60405180910390f35b61069c611d36565b6040516106a99190612bff565b60405180910390f35b6106ba611d5e565b6040516106c79190612bff565b60405180910390f35b6106ea60048036038101906106e59190612d6e565b611d82565b6040516106f79190612ba3565b60405180910390f35b6000807f01ffc9a700000000000000000000000000000000000000000000000000000000905060007f1d1d8b6300000000000000000000000000000000000000000000000000000000905060007fec4fc8e3000000000000000000000000000000000000000000000000000000009050827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107f95750817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108415750807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9350505050919050565b7f0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d081565b60606003805461087e90613196565b80601f01602080910402602001604051908101604052809291908181526020018280546108aa90613196565b80156108f75780601f106108cc576101008083540402835291602001916108f7565b820191906000526020600020905b8154815290600101906020018083116108da57829003601f168201915b5050505050905090565b60008061090c611da2565b9050610919818585611daa565b600191505092915050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109ab576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2281604051610a1b9190612bff565b60405180910390a150565b6000600254905090565b600080610a3b611da2565b9050610a48858285611dbc565b610a53858585611e50565b60019150509392505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610b085750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610b47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3e90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bad9061327f565b60405180910390fd5b60011515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610c49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c40906132eb565b60405180910390fd5b600c60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905560005b600b80549050811015610d89578173ffffffffffffffffffffffffffffffffffffffff16600b8281548110610cd357610cd261330b565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610d7c576000600b8281548110610d2f57610d2e61330b565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610d89565b8080600101915050610c9b565b507fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669281604051610db99190612bff565b60405180910390a150565b60006012905090565b6000610dd7611f44565b905090565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e61906133ac565b60405180910390fd5b610e748282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610eba9190612daa565b60405180910390a25050565b610ed7610ed1611da2565b8261207d565b50565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc390613418565b60405180910390fd5b610fd68282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe0dcb47e0eb67e20e87f3e34aab31c669ecec7466e8b7fb329d586dadebac6b6836040516110339190612daa565b60405180910390a35050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461111a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111190613418565b60405180910390fd5b6111248282611338565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fdc7fd22bc401e7c6b9be2c2736286a2a42ea0c6307bc97ff0fb12bd0abd2c747836040516111819190612daa565b60405180910390a35050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611214576040517fd74b334e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611289929190613438565b60405180910390a1600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61134a82611344611da2565b83611dbc565b611354828261207d565b5050565b6000611363826120ff565b9050919050565b60006060806000806000606061137e612148565b611386612183565b46306000801b600067ffffffffffffffff8111156113a7576113a6613461565b5b6040519080825280602002602001820160405280156113d55781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606004805461144990613196565b80601f016020809104026020016040519081016040528092919081815260200182805461147590613196565b80156114c25780601f10611497576101008083540402835291602001916114c2565b820191906000526020600020905b8154815290600101906020018083116114a557829003601f168201915b5050505050905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806115755750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6115b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ab90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161a9061327f565b60405180910390fd5b60001515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146116b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ad906134dc565b60405180910390fd5b6001600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600b819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6816040516117a09190612bff565b60405180910390a150565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611839576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611830906133ac565b60405180910390fd5b611843828261207d565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516118899190612daa565b60405180910390a25050565b6000806118a0611da2565b90506118ad818585611e50565b600191505092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806119895750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6119c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bf90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2e9061327f565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff02fdf7b40fb25784d39342249bbb15cee2bc0288f75ded1cf8ad2e63d4d91aa81604051611aa79190612bff565b60405180910390a150565b60007f0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0905090565b83421115611b1f57836040517f62791302000000000000000000000000000000000000000000000000000000008152600401611b169190612daa565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888611b4e8c6121be565b89604051602001611b64969594939291906134fc565b6040516020818303038152906040528051906020012090506000611b8782612215565b90506000611b978287878761222f565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611c0b57808a6040517f4b800e46000000000000000000000000000000000000000000000000000000008152600401611c02929190613438565b60405180910390fd5b611c168a8a8a611daa565b50505050505050505050565b60007f0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0905090565b600b8181548110611c5a57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b7f000000000000000000000000420000000000000000000000000000000000001081565b600c6020528060005260406000206000915054906101000a900460ff1681565b600033905090565b611db7838383600161225f565b505050565b6000611dc88484611caf565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611e4a5781811015611e3a578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611e319392919061355d565b60405180910390fd5b611e498484848403600061225f565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611ec25760006040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611eb99190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f345760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611f2b9190612bff565b60405180910390fd5b611f3f838383612436565b505050565b60007f00000000000000000000000013fe62cb24aea5afd179f20d362c056c3881abca73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611fc057507f00000000000000000000000000000000000000000000000000000000000000fc46145b15611fed577f6224ac8480dc16dec96f856ba716934146bf37e75d4e59c54f17634367cc96849050611ff8565b611ff561265b565b90505b90565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361206d5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016120649190612bff565b60405180910390fd5b61207960008383612436565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120ef5760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016120e69190612bff565b60405180910390fd5b6120fb82600083612436565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606061217e60057f467261782053686172650000000000000000000000000000000000000000000a6126f190919063ffffffff16565b905090565b60606121b960067f31000000000000000000000000000000000000000000000000000000000000016126f190919063ffffffff16565b905090565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050559050919050565b6000612228612222611f44565b836127a1565b9050919050565b600080600080612241888888886127e2565b92509250925061225182826128d6565b829350505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122d15760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122c89190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036123435760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161233a9190612bff565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612430578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516124279190612daa565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361248857806002600082825461247c91906135c3565b9250508190555061255b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612514578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161250b9392919061355d565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036125a457806002600082825403925050819055506125f1565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161264e9190612daa565b60405180910390a3505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f27a3410fe7cefb524c4f5c673e34676bf779b4e6eb800cf8c4c84158c29bc12d7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc646306040516020016126d69594939291906135f7565b60405160208183030381529060405280519060200120905090565b606060ff60001b831461270e5761270783612a3a565b905061279b565b81805461271a90613196565b80601f016020809104026020016040519081016040528092919081815260200182805461274690613196565b80156127935780601f1061276857610100808354040283529160200191612793565b820191906000526020600020905b81548152906001019060200180831161277657829003601f168201915b505050505090505b92915050565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c11156128225760006003859250925092506128cc565b600060018888888860405160008152602001604052604051612847949392919061364a565b6020604051602081039080840390855afa158015612869573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128bd57600060016000801b935093509350506128cc565b8060008060001b935093509350505b9450945094915050565b600060038111156128ea576128e961368f565b5b8260038111156128fd576128fc61368f565b5b0315612a3657600160038111156129175761291661368f565b5b82600381111561292a5761292961368f565b5b03612961576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260038111156129755761297461368f565b5b8260038111156129885761298761368f565b5b036129cd578060001c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016129c49190612daa565b60405180910390fd5b6003808111156129e0576129df61368f565b5b8260038111156129f3576129f261368f565b5b03612a3557806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612a2c9190612e68565b60405180910390fd5b5b5050565b60606000612a4783612aae565b90506000602067ffffffffffffffff811115612a6657612a65613461565b5b6040519080825280601f01601f191660200182016040528015612a985781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60008060ff8360001c169050601f811115612af5576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612b3881612b03565b8114612b4357600080fd5b50565b600081359050612b5581612b2f565b92915050565b600060208284031215612b7157612b70612afe565b5b6000612b7f84828501612b46565b91505092915050565b60008115159050919050565b612b9d81612b88565b82525050565b6000602082019050612bb86000830184612b94565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612be982612bbe565b9050919050565b612bf981612bde565b82525050565b6000602082019050612c146000830184612bf0565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612c54578082015181840152602081019050612c39565b60008484015250505050565b6000601f19601f8301169050919050565b6000612c7c82612c1a565b612c868185612c25565b9350612c96818560208601612c36565b612c9f81612c60565b840191505092915050565b60006020820190508181036000830152612cc48184612c71565b905092915050565b612cd581612bde565b8114612ce057600080fd5b50565b600081359050612cf281612ccc565b92915050565b6000819050919050565b612d0b81612cf8565b8114612d1657600080fd5b50565b600081359050612d2881612d02565b92915050565b60008060408385031215612d4557612d44612afe565b5b6000612d5385828601612ce3565b9250506020612d6485828601612d19565b9150509250929050565b600060208284031215612d8457612d83612afe565b5b6000612d9284828501612ce3565b91505092915050565b612da481612cf8565b82525050565b6000602082019050612dbf6000830184612d9b565b92915050565b600080600060608486031215612dde57612ddd612afe565b5b6000612dec86828701612ce3565b9350506020612dfd86828701612ce3565b9250506040612e0e86828701612d19565b9150509250925092565b600060ff82169050919050565b612e2e81612e18565b82525050565b6000602082019050612e496000830184612e25565b92915050565b6000819050919050565b612e6281612e4f565b82525050565b6000602082019050612e7d6000830184612e59565b92915050565b600060208284031215612e9957612e98612afe565b5b6000612ea784828501612d19565b91505092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b612ee581612eb0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612f2081612cf8565b82525050565b6000612f328383612f17565b60208301905092915050565b6000602082019050919050565b6000612f5682612eeb565b612f608185612ef6565b9350612f6b83612f07565b8060005b83811015612f9c578151612f838882612f26565b9750612f8e83612f3e565b925050600181019050612f6f565b5085935050505092915050565b600060e082019050612fbe600083018a612edc565b8181036020830152612fd08189612c71565b90508181036040830152612fe48188612c71565b9050612ff36060830187612d9b565b6130006080830186612bf0565b61300d60a0830185612e59565b81810360c083015261301f8184612f4b565b905098975050505050505050565b61303681612e18565b811461304157600080fd5b50565b6000813590506130538161302d565b92915050565b61306281612e4f565b811461306d57600080fd5b50565b60008135905061307f81613059565b92915050565b600080600080600080600060e0888a0312156130a4576130a3612afe565b5b60006130b28a828b01612ce3565b97505060206130c38a828b01612ce3565b96505060406130d48a828b01612d19565b95505060606130e58a828b01612d19565b94505060806130f68a828b01613044565b93505060a06131078a828b01613070565b92505060c06131188a828b01613070565b91505092959891949750929550565b6000806040838503121561313e5761313d612afe565b5b600061314c85828601612ce3565b925050602061315d85828601612ce3565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806131ae57607f821691505b6020821081036131c1576131c0613167565b5b50919050565b7f4e6f74206f776e6572206f722074696d656c6f636b0000000000000000000000600082015250565b60006131fd601583612c25565b9150613208826131c7565b602082019050919050565b6000602082019050818103600083015261322c816131f0565b9050919050565b7f5a65726f20616464726573732064657465637465640000000000000000000000600082015250565b6000613269601583612c25565b915061327482613233565b602082019050919050565b600060208201905081810360008301526132988161325c565b9050919050565b7f41646472657373206e6f6e6578697374616e7400000000000000000000000000600082015250565b60006132d5601383612c25565b91506132e08261329f565b602082019050919050565b60006020820190508181036000830152613304816132c8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460008201527f67652063616e206d696e7420616e64206275726e000000000000000000000000602082015250565b6000613396603483612c25565b91506133a18261333a565b604082019050919050565b600060208201905081810360008301526133c581613389565b9050919050565b7f4f6e6c79206d696e746572730000000000000000000000000000000000000000600082015250565b6000613402600c83612c25565b915061340d826133cc565b602082019050919050565b60006020820190508181036000830152613431816133f5565b9050919050565b600060408201905061344d6000830185612bf0565b61345a6020830184612bf0565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4164647265737320616c72656164792065786973747300000000000000000000600082015250565b60006134c6601683612c25565b91506134d182613490565b602082019050919050565b600060208201905081810360008301526134f5816134b9565b9050919050565b600060c0820190506135116000830189612e59565b61351e6020830188612bf0565b61352b6040830187612bf0565b6135386060830186612d9b565b6135456080830185612d9b565b61355260a0830184612d9b565b979650505050505050565b60006060820190506135726000830186612bf0565b61357f6020830185612d9b565b61358c6040830184612d9b565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006135ce82612cf8565b91506135d983612cf8565b92508282019050808211156135f1576135f0613594565b5b92915050565b600060a08201905061360c6000830188612e59565b6136196020830187612e59565b6136266040830186612e59565b6136336060830185612d9b565b6136406080830184612bf0565b9695505050505050565b600060808201905061365f6000830187612e59565b61366c6020830186612e25565b6136796040830185612e59565b6136866060830184612e59565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102275760003560e01c806379cc679011610130578063bdacb303116100b8578063dc6663c71161007c578063dc6663c714610646578063dd62ed3e14610664578063e78cea9214610694578063ee9a31a2146106b2578063f46eccc4146106d057610227565b8063bdacb303146105a2578063c01e1bd6146105be578063d505accf146105dc578063d6c0b2c4146105f8578063d73ced041461061657610227565b806395d89b41116100ff57806395d89b41146104fe578063983b2d561461051c5780639dc29fac14610538578063a9059cbb14610554578063ae1f6aaf1461058457610227565b806379cc6790146104705780637ecebe001461048c57806384b0196e146104bc5780638da5cb5b146104e057610227565b80633644e515116101b357806354fd4d501161018257806354fd4d50146103e05780636a257ebc146103fe57806370a082311461041a5780637941bc891461044a57806379ba50971461046657610227565b80633644e5151461036c57806340c10f191461038a57806342966c68146103a657806353a47bb7146103c257610227565b80631627540c116101fa5780631627540c146102c857806318160ddd146102e457806323b872dd146103025780633092afd514610332578063313ce5671461034e57610227565b806301ffc9a71461022c578063033964be1461025c57806306fdde031461027a578063095ea7b314610298575b600080fd5b61024660048036038101906102419190612b5b565b610700565b6040516102539190612ba3565b60405180910390f35b61026461084b565b6040516102719190612bff565b60405180910390f35b61028261086f565b60405161028f9190612caa565b60405180910390f35b6102b260048036038101906102ad9190612d2e565b610901565b6040516102bf9190612ba3565b60405180910390f35b6102e260048036038101906102dd9190612d6e565b610924565b005b6102ec610a26565b6040516102f99190612daa565b60405180910390f35b61031c60048036038101906103179190612dc5565b610a30565b6040516103299190612ba3565b60405180910390f35b61034c60048036038101906103479190612d6e565b610a5f565b005b610356610dc4565b6040516103639190612e34565b60405180910390f35b610374610dcd565b6040516103819190612e68565b60405180910390f35b6103a4600480360381019061039f9190612d2e565b610ddc565b005b6103c060048036038101906103bb9190612e83565b610ec6565b005b6103ca610eda565b6040516103d79190612bff565b60405180910390f35b6103e8610f00565b6040516103f59190612caa565b60405180910390f35b61041860048036038101906104139190612d2e565b610f39565b005b610434600480360381019061042f9190612d6e565b61103f565b6040516104419190612daa565b60405180910390f35b610464600480360381019061045f9190612d2e565b611087565b005b61046e61118d565b005b61048a60048036038101906104859190612d2e565b611338565b005b6104a660048036038101906104a19190612d6e565b611358565b6040516104b39190612daa565b60405180910390f35b6104c461136a565b6040516104d79796959493929190612fa9565b60405180910390f35b6104e8611414565b6040516104f59190612bff565b60405180910390f35b61050661143a565b6040516105139190612caa565b60405180910390f35b61053660048036038101906105319190612d6e565b6114cc565b005b610552600480360381019061054d9190612d2e565b6117ab565b005b61056e60048036038101906105699190612d2e565b611895565b60405161057b9190612ba3565b60405180910390f35b61058c6118b8565b6040516105999190612bff565b60405180910390f35b6105bc60048036038101906105b79190612d6e565b6118e0565b005b6105c6611ab2565b6040516105d39190612bff565b60405180910390f35b6105f660048036038101906105f19190613085565b611ada565b005b610600611c22565b60405161060d9190612bff565b60405180910390f35b610630600480360381019061062b9190612e83565b611c4a565b60405161063d9190612bff565b60405180910390f35b61064e611c89565b60405161065b9190612bff565b60405180910390f35b61067e60048036038101906106799190613127565b611caf565b60405161068b9190612daa565b60405180910390f35b61069c611d36565b6040516106a99190612bff565b60405180910390f35b6106ba611d5e565b6040516106c79190612bff565b60405180910390f35b6106ea60048036038101906106e59190612d6e565b611d82565b6040516106f79190612ba3565b60405180910390f35b6000807f01ffc9a700000000000000000000000000000000000000000000000000000000905060007f1d1d8b6300000000000000000000000000000000000000000000000000000000905060007fec4fc8e3000000000000000000000000000000000000000000000000000000009050827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107f95750817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108415750807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9350505050919050565b7f0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d081565b60606003805461087e90613196565b80601f01602080910402602001604051908101604052809291908181526020018280546108aa90613196565b80156108f75780601f106108cc576101008083540402835291602001916108f7565b820191906000526020600020905b8154815290600101906020018083116108da57829003601f168201915b5050505050905090565b60008061090c611da2565b9050610919818585611daa565b600191505092915050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109ab576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2281604051610a1b9190612bff565b60405180910390a150565b6000600254905090565b600080610a3b611da2565b9050610a48858285611dbc565b610a53858585611e50565b60019150509392505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610b085750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610b47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3e90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bad9061327f565b60405180910390fd5b60011515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610c49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c40906132eb565b60405180910390fd5b600c60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905560005b600b80549050811015610d89578173ffffffffffffffffffffffffffffffffffffffff16600b8281548110610cd357610cd261330b565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610d7c576000600b8281548110610d2f57610d2e61330b565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610d89565b8080600101915050610c9b565b507fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669281604051610db99190612bff565b60405180910390a150565b60006012905090565b6000610dd7611f44565b905090565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e61906133ac565b60405180910390fd5b610e748282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610eba9190612daa565b60405180910390a25050565b610ed7610ed1611da2565b8261207d565b50565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc390613418565b60405180910390fd5b610fd68282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe0dcb47e0eb67e20e87f3e34aab31c669ecec7466e8b7fb329d586dadebac6b6836040516110339190612daa565b60405180910390a35050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461111a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111190613418565b60405180910390fd5b6111248282611338565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fdc7fd22bc401e7c6b9be2c2736286a2a42ea0c6307bc97ff0fb12bd0abd2c747836040516111819190612daa565b60405180910390a35050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611214576040517fd74b334e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611289929190613438565b60405180910390a1600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61134a82611344611da2565b83611dbc565b611354828261207d565b5050565b6000611363826120ff565b9050919050565b60006060806000806000606061137e612148565b611386612183565b46306000801b600067ffffffffffffffff8111156113a7576113a6613461565b5b6040519080825280602002602001820160405280156113d55781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606004805461144990613196565b80601f016020809104026020016040519081016040528092919081815260200182805461147590613196565b80156114c25780601f10611497576101008083540402835291602001916114c2565b820191906000526020600020905b8154815290600101906020018083116114a557829003601f168201915b5050505050905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806115755750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6115b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ab90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161a9061327f565b60405180910390fd5b60001515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146116b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ad906134dc565b60405180910390fd5b6001600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600b819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6816040516117a09190612bff565b60405180910390a150565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611839576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611830906133ac565b60405180910390fd5b611843828261207d565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516118899190612daa565b60405180910390a25050565b6000806118a0611da2565b90506118ad818585611e50565b600191505092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806119895750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6119c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bf90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2e9061327f565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff02fdf7b40fb25784d39342249bbb15cee2bc0288f75ded1cf8ad2e63d4d91aa81604051611aa79190612bff565b60405180910390a150565b60007f0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0905090565b83421115611b1f57836040517f62791302000000000000000000000000000000000000000000000000000000008152600401611b169190612daa565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888611b4e8c6121be565b89604051602001611b64969594939291906134fc565b6040516020818303038152906040528051906020012090506000611b8782612215565b90506000611b978287878761222f565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611c0b57808a6040517f4b800e46000000000000000000000000000000000000000000000000000000008152600401611c02929190613438565b60405180910390fd5b611c168a8a8a611daa565b50505050505050505050565b60007f0000000000000000000000003432b6a60d23ca0dfca7761b7ab56459d9c964d0905090565b600b8181548110611c5a57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b7f000000000000000000000000420000000000000000000000000000000000001081565b600c6020528060005260406000206000915054906101000a900460ff1681565b600033905090565b611db7838383600161225f565b505050565b6000611dc88484611caf565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611e4a5781811015611e3a578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611e319392919061355d565b60405180910390fd5b611e498484848403600061225f565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611ec25760006040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611eb99190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f345760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611f2b9190612bff565b60405180910390fd5b611f3f838383612436565b505050565b60007f00000000000000000000000013fe62cb24aea5afd179f20d362c056c3881abca73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611fc057507f00000000000000000000000000000000000000000000000000000000000000fc46145b15611fed577f6224ac8480dc16dec96f856ba716934146bf37e75d4e59c54f17634367cc96849050611ff8565b611ff561265b565b90505b90565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361206d5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016120649190612bff565b60405180910390fd5b61207960008383612436565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120ef5760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016120e69190612bff565b60405180910390fd5b6120fb82600083612436565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606061217e60057f467261782053686172650000000000000000000000000000000000000000000a6126f190919063ffffffff16565b905090565b60606121b960067f31000000000000000000000000000000000000000000000000000000000000016126f190919063ffffffff16565b905090565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050559050919050565b6000612228612222611f44565b836127a1565b9050919050565b600080600080612241888888886127e2565b92509250925061225182826128d6565b829350505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122d15760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122c89190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036123435760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161233a9190612bff565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612430578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516124279190612daa565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361248857806002600082825461247c91906135c3565b9250508190555061255b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612514578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161250b9392919061355d565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036125a457806002600082825403925050819055506125f1565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161264e9190612daa565b60405180910390a3505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f27a3410fe7cefb524c4f5c673e34676bf779b4e6eb800cf8c4c84158c29bc12d7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc646306040516020016126d69594939291906135f7565b60405160208183030381529060405280519060200120905090565b606060ff60001b831461270e5761270783612a3a565b905061279b565b81805461271a90613196565b80601f016020809104026020016040519081016040528092919081815260200182805461274690613196565b80156127935780601f1061276857610100808354040283529160200191612793565b820191906000526020600020905b81548152906001019060200180831161277657829003601f168201915b505050505090505b92915050565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c11156128225760006003859250925092506128cc565b600060018888888860405160008152602001604052604051612847949392919061364a565b6020604051602081039080840390855afa158015612869573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128bd57600060016000801b935093509350506128cc565b8060008060001b935093509350505b9450945094915050565b600060038111156128ea576128e961368f565b5b8260038111156128fd576128fc61368f565b5b0315612a3657600160038111156129175761291661368f565b5b82600381111561292a5761292961368f565b5b03612961576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260038111156129755761297461368f565b5b8260038111156129885761298761368f565b5b036129cd578060001c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016129c49190612daa565b60405180910390fd5b6003808111156129e0576129df61368f565b5b8260038111156129f3576129f261368f565b5b03612a3557806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612a2c9190612e68565b60405180910390fd5b5b5050565b60606000612a4783612aae565b90506000602067ffffffffffffffff811115612a6657612a65613461565b5b6040519080825280601f01601f191660200182016040528015612a985781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60008060ff8360001c169050601f811115612af5576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612b3881612b03565b8114612b4357600080fd5b50565b600081359050612b5581612b2f565b92915050565b600060208284031215612b7157612b70612afe565b5b6000612b7f84828501612b46565b91505092915050565b60008115159050919050565b612b9d81612b88565b82525050565b6000602082019050612bb86000830184612b94565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612be982612bbe565b9050919050565b612bf981612bde565b82525050565b6000602082019050612c146000830184612bf0565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612c54578082015181840152602081019050612c39565b60008484015250505050565b6000601f19601f8301169050919050565b6000612c7c82612c1a565b612c868185612c25565b9350612c96818560208601612c36565b612c9f81612c60565b840191505092915050565b60006020820190508181036000830152612cc48184612c71565b905092915050565b612cd581612bde565b8114612ce057600080fd5b50565b600081359050612cf281612ccc565b92915050565b6000819050919050565b612d0b81612cf8565b8114612d1657600080fd5b50565b600081359050612d2881612d02565b92915050565b60008060408385031215612d4557612d44612afe565b5b6000612d5385828601612ce3565b9250506020612d6485828601612d19565b9150509250929050565b600060208284031215612d8457612d83612afe565b5b6000612d9284828501612ce3565b91505092915050565b612da481612cf8565b82525050565b6000602082019050612dbf6000830184612d9b565b92915050565b600080600060608486031215612dde57612ddd612afe565b5b6000612dec86828701612ce3565b9350506020612dfd86828701612ce3565b9250506040612e0e86828701612d19565b9150509250925092565b600060ff82169050919050565b612e2e81612e18565b82525050565b6000602082019050612e496000830184612e25565b92915050565b6000819050919050565b612e6281612e4f565b82525050565b6000602082019050612e7d6000830184612e59565b92915050565b600060208284031215612e9957612e98612afe565b5b6000612ea784828501612d19565b91505092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b612ee581612eb0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612f2081612cf8565b82525050565b6000612f328383612f17565b60208301905092915050565b6000602082019050919050565b6000612f5682612eeb565b612f608185612ef6565b9350612f6b83612f07565b8060005b83811015612f9c578151612f838882612f26565b9750612f8e83612f3e565b925050600181019050612f6f565b5085935050505092915050565b600060e082019050612fbe600083018a612edc565b8181036020830152612fd08189612c71565b90508181036040830152612fe48188612c71565b9050612ff36060830187612d9b565b6130006080830186612bf0565b61300d60a0830185612e59565b81810360c083015261301f8184612f4b565b905098975050505050505050565b61303681612e18565b811461304157600080fd5b50565b6000813590506130538161302d565b92915050565b61306281612e4f565b811461306d57600080fd5b50565b60008135905061307f81613059565b92915050565b600080600080600080600060e0888a0312156130a4576130a3612afe565b5b60006130b28a828b01612ce3565b97505060206130c38a828b01612ce3565b96505060406130d48a828b01612d19565b95505060606130e58a828b01612d19565b94505060806130f68a828b01613044565b93505060a06131078a828b01613070565b92505060c06131188a828b01613070565b91505092959891949750929550565b6000806040838503121561313e5761313d612afe565b5b600061314c85828601612ce3565b925050602061315d85828601612ce3565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806131ae57607f821691505b6020821081036131c1576131c0613167565b5b50919050565b7f4e6f74206f776e6572206f722074696d656c6f636b0000000000000000000000600082015250565b60006131fd601583612c25565b9150613208826131c7565b602082019050919050565b6000602082019050818103600083015261322c816131f0565b9050919050565b7f5a65726f20616464726573732064657465637465640000000000000000000000600082015250565b6000613269601583612c25565b915061327482613233565b602082019050919050565b600060208201905081810360008301526132988161325c565b9050919050565b7f41646472657373206e6f6e6578697374616e7400000000000000000000000000600082015250565b60006132d5601383612c25565b91506132e08261329f565b602082019050919050565b60006020820190508181036000830152613304816132c8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460008201527f67652063616e206d696e7420616e64206275726e000000000000000000000000602082015250565b6000613396603483612c25565b91506133a18261333a565b604082019050919050565b600060208201905081810360008301526133c581613389565b9050919050565b7f4f6e6c79206d696e746572730000000000000000000000000000000000000000600082015250565b6000613402600c83612c25565b915061340d826133cc565b602082019050919050565b60006020820190508181036000830152613431816133f5565b9050919050565b600060408201905061344d6000830185612bf0565b61345a6020830184612bf0565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4164647265737320616c72656164792065786973747300000000000000000000600082015250565b60006134c6601683612c25565b91506134d182613490565b602082019050919050565b600060208201905081810360008301526134f5816134b9565b9050919050565b600060c0820190506135116000830189612e59565b61351e6020830188612bf0565b61352b6040830187612bf0565b6135386060830186612d9b565b6135456080830185612d9b565b61355260a0830184612d9b565b979650505050505050565b60006060820190506135726000830186612bf0565b61357f6020830185612d9b565b61358c6040830184612d9b565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006135ce82612cf8565b91506135d983612cf8565b92508282019050808211156135f1576135f0613594565b5b92915050565b600060a08201905061360c6000830188612e59565b6136196020830187612e59565b6136266040830186612e59565b6136336060830185612d9b565b6136406080830184612bf0565b9695505050505050565b600060808201905061365f6000830187612e59565b61366c6020830186612e25565b6136796040830185612e59565b6136866060830184612e59565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd

Deployed Bytecode Sourcemap

169:637:23:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4357:519:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1560:37;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2074:89:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4293:186;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;541:138:24;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3144:97:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5039:244;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7113:683:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3002:82:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2656:112:7;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5118:218:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;618:87:6;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;260:29:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1246:40:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6365:191;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3299:116:4;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5990:199:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;685:348:24;;;:::i;:::-;;1021:158:6;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2406:143:7;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5144:557:16;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;234:20:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2276:93:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6658:347:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5517:224;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3610:178:4;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3687:80:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7971:245;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3458:85;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1680:672:7;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3895:89:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1652:30;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1330:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3846:140:4;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4097:78:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1434:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1792:39;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4357:519;4436:4;4452:13;4468:25;4452:41;;4569:13;4585:38;4569:54;;4722:13;4738:40;4722:56;;4811:6;4795:22;;;:12;:22;;;;:48;;;;4837:6;4821:22;;;:12;:22;;;;4795:48;:74;;;;4863:6;4847:22;;;:12;:22;;;;4795:74;4788:81;;;;;4357:519;;;:::o;1560:37::-;;;:::o;2074:89:4:-;2119:13;2151:5;2144:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89;:::o;4293:186::-;4366:4;4382:13;4398:12;:10;:12::i;:::-;4382:28;;4420:31;4429:5;4436:7;4445:5;4420:8;:31::i;:::-;4468:4;4461:11;;;4293:186;;;;:::o;541:138:24:-;1180:5;;;;;;;;;;;1166:19;;:10;:19;;;1162:43;;1194:11;;;;;;;;;;;;;;1162:43;629:6:::1;612:14;;:23;;;;;;;;;;;;;;;;;;650:22;665:6;650:22;;;;;;:::i;:::-;;;;;;;;541:138:::0;:::o;3144:97:4:-;3196:7;3222:12;;3215:19;;3144:97;:::o;5039:244::-;5126:4;5142:15;5160:12;:10;:12::i;:::-;5142:30;;5182:37;5198:4;5204:7;5213:5;5182:15;:37::i;:::-;5229:26;5239:4;5245:2;5249:5;5229:9;:26::i;:::-;5272:4;5265:11;;;5039:244;;;;;:::o;7113:683:22:-;2779:16;;;;;;;;;;;2765:30;;:10;:30;;;:53;;;;2813:5;;;;;;;;;;;2799:19;;:10;:19;;;2765:53;2757:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;7223:1:::1;7197:28;;:14;:28;;::::0;7189:62:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;7296:4;7269:31;;:7;:23;7277:14;7269:23;;;;;;;;;;;;;;;;;;;;;;;;;:31;;;7261:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;7377:7;:23;7385:14;7377:23;;;;;;;;;;;;;;;;7370:30;;;;;;;;;;;7481:9;7476:269;7500:13;:20;;;;7496:1;:24;7476:269;;;7565:14;7545:34;;:13;7559:1;7545:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:34;;::::0;7541:194:::1;;7626:1;7599:13;7613:1;7599:16;;;;;;;;:::i;:::-;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;7715:5;;7541:194;7522:3;;;;;;;7476:269;;;;7760:29;7774:14;7760:29;;;;;;:::i;:::-;;;;;;;;7113:683:::0;:::o;3002:82:4:-;3051:5;3075:2;3068:9;;3002:82;:::o;2656:112:7:-;2715:7;2741:20;:18;:20::i;:::-;2734:27;;2656:112;:::o;5118:218:22:-;3166:6;3152:20;;:10;:20;;;3144:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;5277:19:::1;5283:3;5288:7;5277:5;:19::i;:::-;5316:3;5311:18;;;5321:7;5311:18;;;;;;:::i;:::-;;;;;;;;5118:218:::0;;:::o;618:87:6:-;672:26;678:12;:10;:12::i;:::-;692:5;672;:26::i;:::-;618:87;:::o;260:29:24:-;;;;;;;;;;;;;:::o;1246:40:22:-;;;;;;;;;;;;;;;;;;;:::o;6365:191::-;3004:4;2981:27;;:7;:19;2989:10;2981:19;;;;;;;;;;;;;;;;;;;;;;;;;:27;;;2973:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;6452:32:::1;6464:9;6475:8;6452:11;:32::i;:::-;6529:9;6499:50;;6517:10;6499:50;;;6540:8;6499:50;;;;;;:::i;:::-;;;;;;;;6365:191:::0;;:::o;3299:116:4:-;3364:7;3390:9;:18;3400:7;3390:18;;;;;;;;;;;;;;;;3383:25;;3299:116;;;:::o;5990:199:22:-;3004:4;2981:27;;:7;:19;2989:10;2981:19;;;;;;;;;;;;;;;;;;;;;;;;;:27;;;2973:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;6082:35:::1;6097:9;6108:8;6082:14;:35::i;:::-;6161:10;6132:50;;6150:9;6132:50;;;6173:8;6132:50;;;;;;:::i;:::-;;;;;;;;5990:199:::0;;:::o;685:348:24:-;856:14;;;;;;;;;;;842:28;;:10;:28;;;838:69;;879:28;;;;;;;;;;;;;;838:69;922:35;935:5;;;;;;;;;;;942:14;;;;;;;;;;;922:35;;;;;;;:::i;:::-;;;;;;;;975:14;;;;;;;;;;;967:5;;:22;;;;;;;;;;;;;;;;;;1024:1;999:14;;:27;;;;;;;;;;;;;;;;;;685:348::o;1021:158:6:-;1096:45;1112:7;1121:12;:10;:12::i;:::-;1135:5;1096:15;:45::i;:::-;1151:21;1157:7;1166:5;1151;:21::i;:::-;1021:158;;:::o;2406:143:7:-;2497:7;2523:19;2536:5;2523:12;:19::i;:::-;2516:26;;2406:143;;;:::o;5144:557:16:-;5242:13;5269:18;5301:21;5336:15;5365:25;5404:12;5430:27;5533:13;:11;:13::i;:::-;5560:16;:14;:16::i;:::-;5590:13;5625:4;5652:1;5644:10;;5682:1;5668:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5482:212;;;;;;;;;;;;;;;;;;;;;5144:557;;;;;;;:::o;234:20:24:-;;;;;;;;;;;;;:::o;2276:93:4:-;2323:13;2355:7;2348:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2276:93;:::o;6658:347:22:-;2779:16;;;;;;;;;;;2765:30;;:10;:30;;;:53;;;;2813:5;;;;;;;;;;;2799:19;;:10;:19;;;2765:53;2757:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;6765:1:::1;6739:28;;:14;:28;;::::0;6731:62:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;6839:5;6812:32;;:7;:23;6820:14;6812:23;;;;;;;;;;;;;;;;;;;;;;;;;:32;;;6804:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;6907:4;6881:7;:23;6889:14;6881:23;;;;;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;6921:13;6940:14;6921:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6971:27;6983:14;6971:27;;;;;;:::i;:::-;;;;;;;;6658:347:::0;:::o;5517:224::-;3166:6;3152:20;;:10;:20;;;3144:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;5678:21:::1;5684:5;5691:7;5678:5;:21::i;:::-;5719:5;5714:20;;;5726:7;5714:20;;;;;;:::i;:::-;;;;;;;;5517:224:::0;;:::o;3610:178:4:-;3679:4;3695:13;3711:12;:10;:12::i;:::-;3695:28;;3733:27;3743:5;3750:2;3754:5;3733:9;:27::i;:::-;3777:4;3770:11;;;3610:178;;;;:::o;3687:80:22:-;3728:7;3754:6;3747:13;;3687:80;:::o;7971:245::-;2779:16;;;;;;;;;;;2765:30;;:10;:30;;;:53;;;;2813:5;;;;;;;;;;;2799:19;;:10;:19;;;2765:53;2757:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;8086:1:::1;8057:31;;:17;:31;;::::0;8049:65:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;8143:17;8124:16;;:36;;;;;;;;;;;;;;;;;;8175:34;8191:17;8175:34;;;;;;:::i;:::-;;;;;;;;7971:245:::0;:::o;3458:85::-;3498:7;3524:12;3517:19;;3458:85;:::o;1680:672:7:-;1901:8;1883:15;:26;1879:97;;;1956:8;1932:33;;;;;;;;;;;:::i;:::-;;;;;;;;1879:97;1986:18;1022:95;2045:5;2052:7;2061:5;2068:16;2078:5;2068:9;:16::i;:::-;2086:8;2017:78;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2007:89;;;;;;1986:110;;2107:12;2122:28;2139:10;2122:16;:28::i;:::-;2107:43;;2161:14;2178:28;2192:4;2198:1;2201;2204;2178:13;:28::i;:::-;2161:45;;2230:5;2220:15;;:6;:15;;;2216:88;;2279:6;2287:5;2258:35;;;;;;;;;;;;:::i;:::-;;;;;;;;2216:88;2314:31;2323:5;2330:7;2339:5;2314:8;:31::i;:::-;1869:483;;;1680:672;;;;;;;:::o;3895:89:22:-;3939:7;3965:12;3958:19;;3895:89;:::o;1652:30::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1330:31::-;;;;;;;;;;;;;:::o;3846:140:4:-;3926:7;3952:11;:18;3964:5;3952:18;;;;;;;;;;;;;;;:27;3971:7;3952:27;;;;;;;;;;;;;;;;3945:34;;3846:140;;;;:::o;4097:78:22:-;4136:7;4162:6;4155:13;;4097:78;:::o;1434:31::-;;;:::o;1792:39::-;;;;;;;;;;;;;;;;;;;;;;:::o;656:96:10:-;709:7;735:10;728:17;;656:96;:::o;8989:128:4:-;9073:37;9082:5;9089:7;9098:5;9105:4;9073:8;:37::i;:::-;8989:128;;;:::o;10663:477::-;10762:24;10789:25;10799:5;10806:7;10789:9;:25::i;:::-;10762:52;;10848:17;10828:16;:37;10824:310;;10904:5;10885:16;:24;10881:130;;;10963:7;10972:16;10990:5;10936:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;10881:130;11052:57;11061:5;11068:7;11096:5;11077:16;:24;11103:5;11052:8;:57::i;:::-;10824:310;10752:388;10663:477;;;:::o;5656:300::-;5755:1;5739:18;;:4;:18;;;5735:86;;5807:1;5780:30;;;;;;;;;;;:::i;:::-;;;;;;;;5735:86;5848:1;5834:16;;:2;:16;;;5830:86;;5902:1;5873:32;;;;;;;;;;;:::i;:::-;;;;;;;;5830:86;5925:24;5933:4;5939:2;5943:5;5925:7;:24::i;:::-;5656:300;;;:::o;3845:262:16:-;3898:7;3938:11;3921:28;;3929:4;3921:28;;;:63;;;;;3970:14;3953:13;:31;3921:63;3917:184;;;4007:22;4000:29;;;;3917:184;4067:23;:21;:23::i;:::-;4060:30;;3845:262;;:::o;7721:208:4:-;7810:1;7791:21;;:7;:21;;;7787:91;;7864:1;7835:32;;;;;;;;;;;:::i;:::-;;;;;;;;7787:91;7887:35;7903:1;7907:7;7916:5;7887:7;:35::i;:::-;7721:208;;:::o;8247:206::-;8336:1;8317:21;;:7;:21;;;8313:89;;8388:1;8361:30;;;;;;;;;;;:::i;:::-;;;;;;;;8313:89;8411:35;8419:7;8436:1;8440:5;8411:7;:35::i;:::-;8247:206;;:::o;538:107:11:-;598:7;624;:14;632:5;624:14;;;;;;;;;;;;;;;;617:21;;538:107;;;:::o;6021:126:16:-;6067:13;6099:41;6126:13;6099:5;:26;;:41;;;;:::i;:::-;6092:48;;6021:126;:::o;6473:135::-;6522:13;6554:47;6584:16;6554:8;:29;;:47;;;;:::i;:::-;6547:54;;6473:135;:::o;759:395:11:-;819:7;1121;:14;1129:5;1121:14;;;;;;;;;;;;;;;;:16;;;;;;;;;;;;1114:23;;759:395;;;:::o;4917:176:16:-;4994:7;5020:66;5053:20;:18;:20::i;:::-;5075:10;5020:32;:66::i;:::-;5013:73;;4917:176;;;:::o;6803:260:15:-;6888:7;6908:17;6927:18;6947:16;6967:25;6978:4;6984:1;6987;6990;6967:10;:25::i;:::-;6907:85;;;;;;7002:28;7014:5;7021:8;7002:11;:28::i;:::-;7047:9;7040:16;;;;;6803:260;;;;;;:::o;9949:432:4:-;10078:1;10061:19;;:5;:19;;;10057:89;;10132:1;10103:32;;;;;;;;;;;:::i;:::-;;;;;;;;10057:89;10178:1;10159:21;;:7;:21;;;10155:90;;10231:1;10203:31;;;;;;;;;;;:::i;:::-;;;;;;;;10155:90;10284:5;10254:11;:18;10266:5;10254:18;;;;;;;;;;;;;;;:27;10273:7;10254:27;;;;;;;;;;;;;;;:35;;;;10303:9;10299:76;;;10349:7;10333:31;;10342:5;10333:31;;;10358:5;10333:31;;;;;;:::i;:::-;;;;;;;;10299:76;9949:432;;;;:::o;6271:1107::-;6376:1;6360:18;;:4;:18;;;6356:540;;6512:5;6496:12;;:21;;;;;;;:::i;:::-;;;;;;;;6356:540;;;6548:19;6570:9;:15;6580:4;6570:15;;;;;;;;;;;;;;;;6548:37;;6617:5;6603:11;:19;6599:115;;;6674:4;6680:11;6693:5;6649:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;6599:115;6866:5;6852:11;:19;6834:9;:15;6844:4;6834:15;;;;;;;;;;;;;;;:37;;;;6534:362;6356:540;6924:1;6910:16;;:2;:16;;;6906:425;;7089:5;7073:12;;:21;;;;;;;;;;;6906:425;;;7301:5;7284:9;:13;7294:2;7284:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;6906:425;7361:2;7346:25;;7355:4;7346:25;;;7365:5;7346:25;;;;;;:::i;:::-;;;;;;;;6271:1107;;;:::o;4113:179:16:-;4168:7;2079:95;4226:11;4239:14;4255:13;4278:4;4204:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4194:91;;;;;;4187:98;;4113:179;:::o;3385:267:12:-;3479:13;1390:66;3537:17;;3527:5;3508:46;3504:142;;3577:15;3586:5;3577:8;:15::i;:::-;3570:22;;;;3504:142;3630:5;3623:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3385:267;;;;;:::o;3353:401:17:-;3446:14;3555:4;3549:11;3585:10;3580:3;3573:23;3632:15;3625:4;3620:3;3616:14;3609:39;3684:10;3677:4;3672:3;3668:14;3661:34;3733:4;3728:3;3718:20;3708:30;;3524:224;3353:401;;;;:::o;5140:1530:15:-;5266:7;5275:12;5289:7;6199:66;6194:1;6186:10;;:79;6182:164;;;6297:1;6301:30;6333:1;6281:54;;;;;;;;6182:164;6440:14;6457:24;6467:4;6473:1;6476;6479;6457:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6440:41;;6513:1;6495:20;;:6;:20;;;6491:113;;6547:1;6551:29;6590:1;6582:10;;6531:62;;;;;;;;;6491:113;6622:6;6630:20;6660:1;6652:10;;6614:49;;;;;;;5140:1530;;;;;;;;;:::o;7196:532::-;7291:20;7282:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;7278:444;7327:7;7278:444;7387:29;7378:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;7374:348;;7439:23;;;;;;;;;;;;;;7374:348;7492:35;7483:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;7479:243;;7586:8;7578:17;;7550:46;;;;;;;;;;;:::i;:::-;;;;;;;;7479:243;7626:30;7617:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;7613:109;;7702:8;7679:32;;;;;;;;;;;:::i;:::-;;;;;;;;7613:109;7196:532;;;:::o;2078:405:12:-;2137:13;2162:11;2176:16;2187:4;2176:10;:16::i;:::-;2162:30;;2280:17;2311:2;2300:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2280:34;;2402:3;2397;2390:16;2442:4;2435;2430:3;2426:14;2419:28;2473:3;2466:10;;;;2078:405;;;:::o;2555:245::-;2616:7;2635:14;2688:4;2679;2652:33;;:40;2635:57;;2715:2;2706:6;:11;2702:69;;;2740:20;;;;;;;;;;;;;;2702:69;2787:6;2780:13;;;2555:245;;;:::o;88:117:25:-;197:1;194;187:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:126::-;1555:7;1595:42;1588:5;1584:54;1573:65;;1518:126;;;:::o;1650:96::-;1687:7;1716:24;1734:5;1716:24;:::i;:::-;1705:35;;1650:96;;;:::o;1752:118::-;1839:24;1857:5;1839:24;:::i;:::-;1834:3;1827:37;1752:118;;:::o;1876:222::-;1969:4;2007:2;1996:9;1992:18;1984:26;;2020:71;2088:1;2077:9;2073:17;2064:6;2020:71;:::i;:::-;1876:222;;;;:::o;2104:99::-;2156:6;2190:5;2184:12;2174:22;;2104:99;;;:::o;2209:169::-;2293:11;2327:6;2322:3;2315:19;2367:4;2362:3;2358:14;2343:29;;2209:169;;;;:::o;2384:246::-;2465:1;2475:113;2489:6;2486:1;2483:13;2475:113;;;2574:1;2569:3;2565:11;2559:18;2555:1;2550:3;2546:11;2539:39;2511:2;2508:1;2504:10;2499:15;;2475:113;;;2622:1;2613:6;2608:3;2604:16;2597:27;2446:184;2384:246;;;:::o;2636:102::-;2677:6;2728:2;2724:7;2719:2;2712:5;2708:14;2704:28;2694:38;;2636:102;;;:::o;2744:377::-;2832:3;2860:39;2893:5;2860:39;:::i;:::-;2915:71;2979:6;2974:3;2915:71;:::i;:::-;2908:78;;2995:65;3053:6;3048:3;3041:4;3034:5;3030:16;2995:65;:::i;:::-;3085:29;3107:6;3085:29;:::i;:::-;3080:3;3076:39;3069:46;;2836:285;2744:377;;;;:::o;3127:313::-;3240:4;3278:2;3267:9;3263:18;3255:26;;3327:9;3321:4;3317:20;3313:1;3302:9;3298:17;3291:47;3355:78;3428:4;3419:6;3355:78;:::i;:::-;3347:86;;3127:313;;;;:::o;3446:122::-;3519:24;3537:5;3519:24;:::i;:::-;3512:5;3509:35;3499:63;;3558:1;3555;3548:12;3499:63;3446:122;:::o;3574:139::-;3620:5;3658:6;3645:20;3636:29;;3674:33;3701:5;3674:33;:::i;:::-;3574:139;;;;:::o;3719:77::-;3756:7;3785:5;3774:16;;3719:77;;;:::o;3802:122::-;3875:24;3893:5;3875:24;:::i;:::-;3868:5;3865:35;3855:63;;3914:1;3911;3904:12;3855:63;3802:122;:::o;3930:139::-;3976:5;4014:6;4001:20;3992:29;;4030:33;4057:5;4030:33;:::i;:::-;3930:139;;;;:::o;4075:474::-;4143:6;4151;4200:2;4188:9;4179:7;4175:23;4171:32;4168:119;;;4206:79;;:::i;:::-;4168:119;4326:1;4351:53;4396:7;4387:6;4376:9;4372:22;4351:53;:::i;:::-;4341:63;;4297:117;4453:2;4479:53;4524:7;4515:6;4504:9;4500:22;4479:53;:::i;:::-;4469:63;;4424:118;4075:474;;;;;:::o;4555:329::-;4614:6;4663:2;4651:9;4642:7;4638:23;4634:32;4631:119;;;4669:79;;:::i;:::-;4631:119;4789:1;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4760:117;4555:329;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:619::-;5319:6;5327;5335;5384:2;5372:9;5363:7;5359:23;5355:32;5352:119;;;5390:79;;:::i;:::-;5352:119;5510:1;5535:53;5580:7;5571:6;5560:9;5556:22;5535:53;:::i;:::-;5525:63;;5481:117;5637:2;5663:53;5708:7;5699:6;5688:9;5684:22;5663:53;:::i;:::-;5653:63;;5608:118;5765:2;5791:53;5836:7;5827:6;5816:9;5812:22;5791:53;:::i;:::-;5781:63;;5736:118;5242:619;;;;;:::o;5867:86::-;5902:7;5942:4;5935:5;5931:16;5920:27;;5867:86;;;:::o;5959:112::-;6042:22;6058:5;6042:22;:::i;:::-;6037:3;6030:35;5959:112;;:::o;6077:214::-;6166:4;6204:2;6193:9;6189:18;6181:26;;6217:67;6281:1;6270:9;6266:17;6257:6;6217:67;:::i;:::-;6077:214;;;;:::o;6297:77::-;6334:7;6363:5;6352:16;;6297:77;;;:::o;6380:118::-;6467:24;6485:5;6467:24;:::i;:::-;6462:3;6455:37;6380:118;;:::o;6504:222::-;6597:4;6635:2;6624:9;6620:18;6612:26;;6648:71;6716:1;6705:9;6701:17;6692:6;6648:71;:::i;:::-;6504:222;;;;:::o;6732:329::-;6791:6;6840:2;6828:9;6819:7;6815:23;6811:32;6808:119;;;6846:79;;:::i;:::-;6808:119;6966:1;6991:53;7036:7;7027:6;7016:9;7012:22;6991:53;:::i;:::-;6981:63;;6937:117;6732:329;;;;:::o;7067:149::-;7103:7;7143:66;7136:5;7132:78;7121:89;;7067:149;;;:::o;7222:115::-;7307:23;7324:5;7307:23;:::i;:::-;7302:3;7295:36;7222:115;;:::o;7343:114::-;7410:6;7444:5;7438:12;7428:22;;7343:114;;;:::o;7463:184::-;7562:11;7596:6;7591:3;7584:19;7636:4;7631:3;7627:14;7612:29;;7463:184;;;;:::o;7653:132::-;7720:4;7743:3;7735:11;;7773:4;7768:3;7764:14;7756:22;;7653:132;;;:::o;7791:108::-;7868:24;7886:5;7868:24;:::i;:::-;7863:3;7856:37;7791:108;;:::o;7905:179::-;7974:10;7995:46;8037:3;8029:6;7995:46;:::i;:::-;8073:4;8068:3;8064:14;8050:28;;7905:179;;;;:::o;8090:113::-;8160:4;8192;8187:3;8183:14;8175:22;;8090:113;;;:::o;8239:732::-;8358:3;8387:54;8435:5;8387:54;:::i;:::-;8457:86;8536:6;8531:3;8457:86;:::i;:::-;8450:93;;8567:56;8617:5;8567:56;:::i;:::-;8646:7;8677:1;8662:284;8687:6;8684:1;8681:13;8662:284;;;8763:6;8757:13;8790:63;8849:3;8834:13;8790:63;:::i;:::-;8783:70;;8876:60;8929:6;8876:60;:::i;:::-;8866:70;;8722:224;8709:1;8706;8702:9;8697:14;;8662:284;;;8666:14;8962:3;8955:10;;8363:608;;;8239:732;;;;:::o;8977:1215::-;9326:4;9364:3;9353:9;9349:19;9341:27;;9378:69;9444:1;9433:9;9429:17;9420:6;9378:69;:::i;:::-;9494:9;9488:4;9484:20;9479:2;9468:9;9464:18;9457:48;9522:78;9595:4;9586:6;9522:78;:::i;:::-;9514:86;;9647:9;9641:4;9637:20;9632:2;9621:9;9617:18;9610:48;9675:78;9748:4;9739:6;9675:78;:::i;:::-;9667:86;;9763:72;9831:2;9820:9;9816:18;9807:6;9763:72;:::i;:::-;9845:73;9913:3;9902:9;9898:19;9889:6;9845:73;:::i;:::-;9928;9996:3;9985:9;9981:19;9972:6;9928:73;:::i;:::-;10049:9;10043:4;10039:20;10033:3;10022:9;10018:19;10011:49;10077:108;10180:4;10171:6;10077:108;:::i;:::-;10069:116;;8977:1215;;;;;;;;;;:::o;10198:118::-;10269:22;10285:5;10269:22;:::i;:::-;10262:5;10259:33;10249:61;;10306:1;10303;10296:12;10249:61;10198:118;:::o;10322:135::-;10366:5;10404:6;10391:20;10382:29;;10420:31;10445:5;10420:31;:::i;:::-;10322:135;;;;:::o;10463:122::-;10536:24;10554:5;10536:24;:::i;:::-;10529:5;10526:35;10516:63;;10575:1;10572;10565:12;10516:63;10463:122;:::o;10591:139::-;10637:5;10675:6;10662:20;10653:29;;10691:33;10718:5;10691:33;:::i;:::-;10591:139;;;;:::o;10736:1199::-;10847:6;10855;10863;10871;10879;10887;10895;10944:3;10932:9;10923:7;10919:23;10915:33;10912:120;;;10951:79;;:::i;:::-;10912:120;11071:1;11096:53;11141:7;11132:6;11121:9;11117:22;11096:53;:::i;:::-;11086:63;;11042:117;11198:2;11224:53;11269:7;11260:6;11249:9;11245:22;11224:53;:::i;:::-;11214:63;;11169:118;11326:2;11352:53;11397:7;11388:6;11377:9;11373:22;11352:53;:::i;:::-;11342:63;;11297:118;11454:2;11480:53;11525:7;11516:6;11505:9;11501:22;11480:53;:::i;:::-;11470:63;;11425:118;11582:3;11609:51;11652:7;11643:6;11632:9;11628:22;11609:51;:::i;:::-;11599:61;;11553:117;11709:3;11736:53;11781:7;11772:6;11761:9;11757:22;11736:53;:::i;:::-;11726:63;;11680:119;11838:3;11865:53;11910:7;11901:6;11890:9;11886:22;11865:53;:::i;:::-;11855:63;;11809:119;10736:1199;;;;;;;;;;:::o;11941:474::-;12009:6;12017;12066:2;12054:9;12045:7;12041:23;12037:32;12034:119;;;12072:79;;:::i;:::-;12034:119;12192:1;12217:53;12262:7;12253:6;12242:9;12238:22;12217:53;:::i;:::-;12207:63;;12163:117;12319:2;12345:53;12390:7;12381:6;12370:9;12366:22;12345:53;:::i;:::-;12335:63;;12290:118;11941:474;;;;;:::o;12421:180::-;12469:77;12466:1;12459:88;12566:4;12563:1;12556:15;12590:4;12587:1;12580:15;12607:320;12651:6;12688:1;12682:4;12678:12;12668:22;;12735:1;12729:4;12725:12;12756:18;12746:81;;12812:4;12804:6;12800:17;12790:27;;12746:81;12874:2;12866:6;12863:14;12843:18;12840:38;12837:84;;12893:18;;:::i;:::-;12837:84;12658:269;12607:320;;;:::o;12933:171::-;13073:23;13069:1;13061:6;13057:14;13050:47;12933:171;:::o;13110:366::-;13252:3;13273:67;13337:2;13332:3;13273:67;:::i;:::-;13266:74;;13349:93;13438:3;13349:93;:::i;:::-;13467:2;13462:3;13458:12;13451:19;;13110:366;;;:::o;13482:419::-;13648:4;13686:2;13675:9;13671:18;13663:26;;13735:9;13729:4;13725:20;13721:1;13710:9;13706:17;13699:47;13763:131;13889:4;13763:131;:::i;:::-;13755:139;;13482:419;;;:::o;13907:171::-;14047:23;14043:1;14035:6;14031:14;14024:47;13907:171;:::o;14084:366::-;14226:3;14247:67;14311:2;14306:3;14247:67;:::i;:::-;14240:74;;14323:93;14412:3;14323:93;:::i;:::-;14441:2;14436:3;14432:12;14425:19;;14084:366;;;:::o;14456:419::-;14622:4;14660:2;14649:9;14645:18;14637:26;;14709:9;14703:4;14699:20;14695:1;14684:9;14680:17;14673:47;14737:131;14863:4;14737:131;:::i;:::-;14729:139;;14456:419;;;:::o;14881:169::-;15021:21;15017:1;15009:6;15005:14;14998:45;14881:169;:::o;15056:366::-;15198:3;15219:67;15283:2;15278:3;15219:67;:::i;:::-;15212:74;;15295:93;15384:3;15295:93;:::i;:::-;15413:2;15408:3;15404:12;15397:19;;15056:366;;;:::o;15428:419::-;15594:4;15632:2;15621:9;15617:18;15609:26;;15681:9;15675:4;15671:20;15667:1;15656:9;15652:17;15645:47;15709:131;15835:4;15709:131;:::i;:::-;15701:139;;15428:419;;;:::o;15853:180::-;15901:77;15898:1;15891:88;15998:4;15995:1;15988:15;16022:4;16019:1;16012:15;16039:239;16179:34;16175:1;16167:6;16163:14;16156:58;16248:22;16243:2;16235:6;16231:15;16224:47;16039:239;:::o;16284:366::-;16426:3;16447:67;16511:2;16506:3;16447:67;:::i;:::-;16440:74;;16523:93;16612:3;16523:93;:::i;:::-;16641:2;16636:3;16632:12;16625:19;;16284:366;;;:::o;16656:419::-;16822:4;16860:2;16849:9;16845:18;16837:26;;16909:9;16903:4;16899:20;16895:1;16884:9;16880:17;16873:47;16937:131;17063:4;16937:131;:::i;:::-;16929:139;;16656:419;;;:::o;17081:162::-;17221:14;17217:1;17209:6;17205:14;17198:38;17081:162;:::o;17249:366::-;17391:3;17412:67;17476:2;17471:3;17412:67;:::i;:::-;17405:74;;17488:93;17577:3;17488:93;:::i;:::-;17606:2;17601:3;17597:12;17590:19;;17249:366;;;:::o;17621:419::-;17787:4;17825:2;17814:9;17810:18;17802:26;;17874:9;17868:4;17864:20;17860:1;17849:9;17845:17;17838:47;17902:131;18028:4;17902:131;:::i;:::-;17894:139;;17621:419;;;:::o;18046:332::-;18167:4;18205:2;18194:9;18190:18;18182:26;;18218:71;18286:1;18275:9;18271:17;18262:6;18218:71;:::i;:::-;18299:72;18367:2;18356:9;18352:18;18343:6;18299:72;:::i;:::-;18046:332;;;;;:::o;18384:180::-;18432:77;18429:1;18422:88;18529:4;18526:1;18519:15;18553:4;18550:1;18543:15;18570:172;18710:24;18706:1;18698:6;18694:14;18687:48;18570:172;:::o;18748:366::-;18890:3;18911:67;18975:2;18970:3;18911:67;:::i;:::-;18904:74;;18987:93;19076:3;18987:93;:::i;:::-;19105:2;19100:3;19096:12;19089:19;;18748:366;;;:::o;19120:419::-;19286:4;19324:2;19313:9;19309:18;19301:26;;19373:9;19367:4;19363:20;19359:1;19348:9;19344:17;19337:47;19401:131;19527:4;19401:131;:::i;:::-;19393:139;;19120:419;;;:::o;19545:775::-;19778:4;19816:3;19805:9;19801:19;19793:27;;19830:71;19898:1;19887:9;19883:17;19874:6;19830:71;:::i;:::-;19911:72;19979:2;19968:9;19964:18;19955:6;19911:72;:::i;:::-;19993;20061:2;20050:9;20046:18;20037:6;19993:72;:::i;:::-;20075;20143:2;20132:9;20128:18;20119:6;20075:72;:::i;:::-;20157:73;20225:3;20214:9;20210:19;20201:6;20157:73;:::i;:::-;20240;20308:3;20297:9;20293:19;20284:6;20240:73;:::i;:::-;19545:775;;;;;;;;;:::o;20326:442::-;20475:4;20513:2;20502:9;20498:18;20490:26;;20526:71;20594:1;20583:9;20579:17;20570:6;20526:71;:::i;:::-;20607:72;20675:2;20664:9;20660:18;20651:6;20607:72;:::i;:::-;20689;20757:2;20746:9;20742:18;20733:6;20689:72;:::i;:::-;20326:442;;;;;;:::o;20774:180::-;20822:77;20819:1;20812:88;20919:4;20916:1;20909:15;20943:4;20940:1;20933:15;20960:191;21000:3;21019:20;21037:1;21019:20;:::i;:::-;21014:25;;21053:20;21071:1;21053:20;:::i;:::-;21048:25;;21096:1;21093;21089:9;21082:16;;21117:3;21114:1;21111:10;21108:36;;;21124:18;;:::i;:::-;21108:36;20960:191;;;;:::o;21157:664::-;21362:4;21400:3;21389:9;21385:19;21377:27;;21414:71;21482:1;21471:9;21467:17;21458:6;21414:71;:::i;:::-;21495:72;21563:2;21552:9;21548:18;21539:6;21495:72;:::i;:::-;21577;21645:2;21634:9;21630:18;21621:6;21577:72;:::i;:::-;21659;21727:2;21716:9;21712:18;21703:6;21659:72;:::i;:::-;21741:73;21809:3;21798:9;21794:19;21785:6;21741:73;:::i;:::-;21157:664;;;;;;;;:::o;21827:545::-;22000:4;22038:3;22027:9;22023:19;22015:27;;22052:71;22120:1;22109:9;22105:17;22096:6;22052:71;:::i;:::-;22133:68;22197:2;22186:9;22182:18;22173:6;22133:68;:::i;:::-;22211:72;22279:2;22268:9;22264:18;22255:6;22211:72;:::i;:::-;22293;22361:2;22350:9;22346:18;22337:6;22293:72;:::i;:::-;21827:545;;;;;;;:::o;22378:180::-;22426:77;22423:1;22416:88;22523:4;22520:1;22513:15;22547:4;22544:1;22537:15

[ 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.