FTM Price: $0.700244 (+1.71%)
 

Overview

Max Total Supply

5,511,061.599082291429387936 sASNT

Holders

176

Total Transfers

-

Market

Price

$0.00 @ 0.000000 FTM

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

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

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
sASNTToken

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 18 of 19: sASNTToken.sol
// SPDX-License-Identifier: MIT

//     ___                         __ 
//    /   |  _____________  ____  / /_
//   / /| | / ___/ ___/ _ \/ __ \/ __/
//  / ___ |(__  |__  )  __/ / / / /_  
// /_/  |_/____/____/\___/_/ /_/\__/  
// 
// 2022 - Assent Protocol

pragma solidity 0.8.11;

import "./ERC20Permit.sol";
import "./ERC20Burnable.sol";
import "./AccessControl.sol";
import "./Pausable.sol";
import "./SafeERC20.sol";

contract sASNTToken is
    ERC20Burnable,
    ERC20Permit,
    AccessControl,
    Pausable
{
    using SafeERC20 for IERC20;
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant RESCUER_ROLE = keccak256("RESCUER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    constructor() ERC20("Assent Protocol sASNT Token", "sASNT") ERC20Permit("Assent Protocol") {
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _setupRole(PAUSER_ROLE, msg.sender);
        _setupRole(MINTER_ROLE, msg.sender);
        _setupRole(RESCUER_ROLE, msg.sender);
    }

    function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
        _mint(to, amount);
    }

    function rescueTokens(IERC20 token, uint256 value)
        external
        onlyRole(RESCUER_ROLE)
    {
        token.transfer(msg.sender, value);
    }

    function pause() external onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() external onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal override whenNotPaused {
        super._beforeTokenTransfer(from, to, amount);
    }
}

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

pragma solidity ^0.8.0;

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

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

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

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

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

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

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

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

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

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

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

        _revokeRole(role, account);
    }

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

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

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 2 of 19: Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 3 of 19: Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

File 4 of 19: Counters.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

File 5 of 19: ECDSA.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Strings.sol";

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

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

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

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

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

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

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

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

        return (signer, RecoverError.NoError);
    }

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

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

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

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 6 of 19: EIP712.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ECDSA.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // 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 _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;
    address private immutable _CACHED_THIS;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @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) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _CACHED_THIS = address(this);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

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

File 7 of 19: ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

File 8 of 19: ERC20.sol
// SPDX-License-Identifier: MIT

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

pragma solidity ^0.8.0;



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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

        return true;
    }

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

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

        return true;
    }

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

        _beforeTokenTransfer(sender, recipient, amount);

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

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

File 9 of 19: ERC20Burnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC20.sol";

pragma solidity ^0.8.0;

/**
 * @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 `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` 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
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        uint256 currentAllowance = allowance(account, _msgSender());
        require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
        unchecked {
            _approve(account, _msgSender(), currentAllowance - amount);
        }
        _burn(account, amount);
    }
}

File 10 of 19: ERC20Permit.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20Permit.sol";
import "./ERC20.sol";
import "./EIP712.sol";
import "./Counters.sol";

/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * _Available since v3.4._
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
    using Counters for Counters.Counter;

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

    // solhint-disable-next-line var-name-mixedcase
    bytes32 private immutable _PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

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

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

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

        bytes32 hash = _hashTypedDataV4(structHash);

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

        _approve(owner, spender, value);
    }

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

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

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

File 11 of 19: IAccessControl.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

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

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

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

File 12 of 19: IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

File 13 of 19: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 14 of 19: IERC20Metadata.sol
// SPDX-License-Identifier: MIT

import "./IERC20.sol";

pragma solidity ^0.8.0;

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

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

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

File 15 of 19: IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

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

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

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

File 16 of 19: Pausable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

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

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESCUER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101606040527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610140523480156200003757600080fd5b506040518060400160405280600f81526020016e105cdcd95b9d08141c9bdd1bd8dbdb608a1b81525080604051806040016040528060018152602001603160f81b8152506040518060400160405280601b81526020017f417373656e742050726f746f636f6c207341534e5420546f6b656e0000000000815250604051806040016040528060058152602001641cd054d39560da1b8152508160039080519060200190620000e7929190620002e5565b508051620000fd906004906020840190620002e5565b5050825160209384012082519284019290922060e08390526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818901819052818301979097526060810194909452608080850193909352308483018190528151808603909301835260c0948501909152815191909601209052929092526101205250506007805460ff19169055620001a760003362000231565b620001d37f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a3362000231565b620001ff7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63362000231565b6200022b7fcf6f9f892731e14b8859835f2ff35575f447fb501f46243c4eb8bac19e31a0503362000231565b620003c8565b6200023d828262000241565b5050565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff166200023d5760008281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620002a13390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b828054620002f3906200038b565b90600052602060002090601f01602090048101928262000317576000855562000362565b82601f106200033257805160ff191683800117855562000362565b8280016001018555821562000362579182015b828111156200036257825182559160200191906001019062000345565b506200037092915062000374565b5090565b5b8082111562000370576000815560010162000375565b600181811c90821680620003a057607f821691505b60208210811415620003c257634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e051610100516101205161014051611d35620004236000396000610a3301526000610fda015260006110290152600061100401526000610f5d01526000610f8701526000610fb10152611d356000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c80635c975abb1161010f578063a217fddf116100a2578063d539139311610071578063d5391393146103fa578063d547741f14610421578063dd62ed3e14610434578063e63ab1e91461046d57600080fd5b8063a217fddf146103b9578063a457c2d7146103c1578063a9059cbb146103d4578063d505accf146103e757600080fd5b80637ecebe00116100de5780637ecebe00146103835780638456cb591461039657806391d148541461039e57806395d89b41146103b157600080fd5b80635c975abb1461031557806370a0823114610320578063713725441461034957806379cc67901461037057600080fd5b8063313ce567116101875780633f4ba83a116101565780633f4ba83a146102d457806340c10f19146102dc57806342966c68146102ef578063573761981461030257600080fd5b8063313ce567146102975780633644e515146102a657806336568abe146102ae57806339509351146102c157600080fd5b806318160ddd116101c357806318160ddd1461023a57806323b872dd1461024c578063248a9ca31461025f5780632f2ff15d1461028257600080fd5b806301ffc9a7146101ea57806306fdde0314610212578063095ea7b314610227575b600080fd5b6101fd6101f8366004611960565b610494565b60405190151581526020015b60405180910390f35b61021a6104cb565b60405161020991906119b6565b6101fd6102353660046119fe565b61055d565b6002545b604051908152602001610209565b6101fd61025a366004611a2a565b610573565b61023e61026d366004611a6b565b60009081526006602052604090206001015490565b610295610290366004611a84565b610622565b005b60405160128152602001610209565b61023e61064d565b6102956102bc366004611a84565b61065c565b6101fd6102cf3660046119fe565b6106da565b610295610716565b6102956102ea3660046119fe565b61074c565b6102956102fd366004611a6b565b610781565b6102956103103660046119fe565b61078b565b60075460ff166101fd565b61023e61032e366004611ab4565b6001600160a01b031660009081526020819052604090205490565b61023e7fcf6f9f892731e14b8859835f2ff35575f447fb501f46243c4eb8bac19e31a05081565b61029561037e3660046119fe565b61082d565b61023e610391366004611ab4565b6108ae565b6102956108cc565b6101fd6103ac366004611a84565b6108ff565b61021a61092a565b61023e600081565b6101fd6103cf3660046119fe565b610939565b6101fd6103e23660046119fe565b6109d2565b6102956103f5366004611ad1565b6109df565b61023e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61029561042f366004611a84565b610b43565b61023e610442366004611b48565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61023e7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b60006001600160e01b03198216637965db0b60e01b14806104c557506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600380546104da90611b76565b80601f016020809104026020016040519081016040528092919081815260200182805461050690611b76565b80156105535780601f1061052857610100808354040283529160200191610553565b820191906000526020600020905b81548152906001019060200180831161053657829003601f168201915b5050505050905090565b600061056a338484610b69565b50600192915050565b6000610580848484610c8d565b6001600160a01b03841660009081526001602090815260408083203384529091529020548281101561060a5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6106178533858403610b69565b506001949350505050565b60008281526006602052604090206001015461063e8133610e66565b6106488383610eca565b505050565b6000610657610f50565b905090565b6001600160a01b03811633146106cc5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610601565b6106d68282611077565b5050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161056a918590610711908690611bc1565b610b69565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6107418133610e66565b6107496110de565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66107778133610e66565b6106488383611171565b610749338261125c565b7fcf6f9f892731e14b8859835f2ff35575f447fb501f46243c4eb8bac19e31a0506107b68133610e66565b60405163a9059cbb60e01b8152336004820152602481018390526001600160a01b0384169063a9059cbb906044016020604051808303816000875af1158015610803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108279190611bd9565b50505050565b60006108398333610442565b9050818110156108975760405162461bcd60e51b8152602060048201526024808201527f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f77604482015263616e636560e01b6064820152608401610601565b6108a48333848403610b69565b610648838361125c565b6001600160a01b0381166000908152600560205260408120546104c5565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6108f78133610e66565b6107496113b6565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600480546104da90611b76565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156109bb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610601565b6109c83385858403610b69565b5060019392505050565b600061056a338484610c8d565b83421115610a2f5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610601565b60007f0000000000000000000000000000000000000000000000000000000000000000888888610a5e8c611431565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610ab982611459565b90506000610ac9828787876114a7565b9050896001600160a01b0316816001600160a01b031614610b2c5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610601565b610b378a8a8a610b69565b50505050505050505050565b600082815260066020526040902060010154610b5f8133610e66565b6106488383611077565b6001600160a01b038316610bcb5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610601565b6001600160a01b038216610c2c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610601565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038316610cf15760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610601565b6001600160a01b038216610d535760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610601565b610d5e8383836114cf565b6001600160a01b03831660009081526020819052604090205481811015610dd65760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610601565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610e0d908490611bc1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e5991815260200190565b60405180910390a3610827565b610e7082826108ff565b6106d657610e88816001600160a01b03166014611515565b610e93836020611515565b604051602001610ea4929190611bfb565b60408051601f198184030181529082905262461bcd60e51b8252610601916004016119b6565b610ed482826108ff565b6106d65760008281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055610f0c3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015610fa957507f000000000000000000000000000000000000000000000000000000000000000046145b15610fd357507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b61108182826108ff565b156106d65760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60075460ff166111275760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610601565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166111c75760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610601565b6111d3600083836114cf565b80600260008282546111e59190611bc1565b90915550506001600160a01b03821660009081526020819052604081208054839290611212908490611bc1565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166112bc5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610601565b6112c8826000836114cf565b6001600160a01b0382166000908152602081905260409020548181101561133c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610601565b6001600160a01b038316600090815260208190526040812083830390556002805484929061136b908490611c70565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60075460ff16156113fc5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610601565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586111543390565b6001600160a01b03811660009081526005602052604090208054600181018255905b50919050565b60006104c5611466610f50565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114b8878787876116b8565b915091506114c5816117a5565b5095945050505050565b60075460ff16156106485760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610601565b60606000611524836002611c87565b61152f906002611bc1565b67ffffffffffffffff81111561154757611547611ca6565b6040519080825280601f01601f191660200182016040528015611571576020820181803683370190505b509050600360fc1b8160008151811061158c5761158c611cbc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106115bb576115bb611cbc565b60200101906001600160f81b031916908160001a90535060006115df846002611c87565b6115ea906001611bc1565b90505b6001811115611662576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061161e5761161e611cbc565b1a60f81b82828151811061163457611634611cbc565b60200101906001600160f81b031916908160001a90535060049490941c9361165b81611cd2565b90506115ed565b5083156116b15760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610601565b9392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156116ef575060009050600361179c565b8460ff16601b1415801561170757508460ff16601c14155b15611718575060009050600461179c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561176c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166117955760006001925092505061179c565b9150600090505b94509492505050565b60008160048111156117b9576117b9611ce9565b14156117c25750565b60018160048111156117d6576117d6611ce9565b14156118245760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610601565b600281600481111561183857611838611ce9565b14156118865760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610601565b600381600481111561189a5761189a611ce9565b14156118f35760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610601565b600481600481111561190757611907611ce9565b14156107495760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610601565b60006020828403121561197257600080fd5b81356001600160e01b0319811681146116b157600080fd5b60005b838110156119a557818101518382015260200161198d565b838111156108275750506000910152565b60208152600082518060208401526119d581604085016020870161198a565b601f01601f19169190910160400192915050565b6001600160a01b038116811461074957600080fd5b60008060408385031215611a1157600080fd5b8235611a1c816119e9565b946020939093013593505050565b600080600060608486031215611a3f57600080fd5b8335611a4a816119e9565b92506020840135611a5a816119e9565b929592945050506040919091013590565b600060208284031215611a7d57600080fd5b5035919050565b60008060408385031215611a9757600080fd5b823591506020830135611aa9816119e9565b809150509250929050565b600060208284031215611ac657600080fd5b81356116b1816119e9565b600080600080600080600060e0888a031215611aec57600080fd5b8735611af7816119e9565b96506020880135611b07816119e9565b95506040880135945060608801359350608088013560ff81168114611b2b57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611b5b57600080fd5b8235611b66816119e9565b91506020830135611aa9816119e9565b600181811c90821680611b8a57607f821691505b6020821081141561145357634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115611bd457611bd4611bab565b500190565b600060208284031215611beb57600080fd5b815180151581146116b157600080fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611c3381601785016020880161198a565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611c6481602884016020880161198a565b01602801949350505050565b600082821015611c8257611c82611bab565b500390565b6000816000190483118215151615611ca157611ca1611bab565b500290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081611ce157611ce1611bab565b506000190190565b634e487b7160e01b600052602160045260246000fdfea26469706673582212201cd88dc81bcea0dba8aeb39b90469e6b357d3d17599a8eafad0c351c41f2eda764736f6c634300080b0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101e55760003560e01c80635c975abb1161010f578063a217fddf116100a2578063d539139311610071578063d5391393146103fa578063d547741f14610421578063dd62ed3e14610434578063e63ab1e91461046d57600080fd5b8063a217fddf146103b9578063a457c2d7146103c1578063a9059cbb146103d4578063d505accf146103e757600080fd5b80637ecebe00116100de5780637ecebe00146103835780638456cb591461039657806391d148541461039e57806395d89b41146103b157600080fd5b80635c975abb1461031557806370a0823114610320578063713725441461034957806379cc67901461037057600080fd5b8063313ce567116101875780633f4ba83a116101565780633f4ba83a146102d457806340c10f19146102dc57806342966c68146102ef578063573761981461030257600080fd5b8063313ce567146102975780633644e515146102a657806336568abe146102ae57806339509351146102c157600080fd5b806318160ddd116101c357806318160ddd1461023a57806323b872dd1461024c578063248a9ca31461025f5780632f2ff15d1461028257600080fd5b806301ffc9a7146101ea57806306fdde0314610212578063095ea7b314610227575b600080fd5b6101fd6101f8366004611960565b610494565b60405190151581526020015b60405180910390f35b61021a6104cb565b60405161020991906119b6565b6101fd6102353660046119fe565b61055d565b6002545b604051908152602001610209565b6101fd61025a366004611a2a565b610573565b61023e61026d366004611a6b565b60009081526006602052604090206001015490565b610295610290366004611a84565b610622565b005b60405160128152602001610209565b61023e61064d565b6102956102bc366004611a84565b61065c565b6101fd6102cf3660046119fe565b6106da565b610295610716565b6102956102ea3660046119fe565b61074c565b6102956102fd366004611a6b565b610781565b6102956103103660046119fe565b61078b565b60075460ff166101fd565b61023e61032e366004611ab4565b6001600160a01b031660009081526020819052604090205490565b61023e7fcf6f9f892731e14b8859835f2ff35575f447fb501f46243c4eb8bac19e31a05081565b61029561037e3660046119fe565b61082d565b61023e610391366004611ab4565b6108ae565b6102956108cc565b6101fd6103ac366004611a84565b6108ff565b61021a61092a565b61023e600081565b6101fd6103cf3660046119fe565b610939565b6101fd6103e23660046119fe565b6109d2565b6102956103f5366004611ad1565b6109df565b61023e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61029561042f366004611a84565b610b43565b61023e610442366004611b48565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61023e7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b60006001600160e01b03198216637965db0b60e01b14806104c557506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600380546104da90611b76565b80601f016020809104026020016040519081016040528092919081815260200182805461050690611b76565b80156105535780601f1061052857610100808354040283529160200191610553565b820191906000526020600020905b81548152906001019060200180831161053657829003601f168201915b5050505050905090565b600061056a338484610b69565b50600192915050565b6000610580848484610c8d565b6001600160a01b03841660009081526001602090815260408083203384529091529020548281101561060a5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6106178533858403610b69565b506001949350505050565b60008281526006602052604090206001015461063e8133610e66565b6106488383610eca565b505050565b6000610657610f50565b905090565b6001600160a01b03811633146106cc5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610601565b6106d68282611077565b5050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161056a918590610711908690611bc1565b610b69565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6107418133610e66565b6107496110de565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66107778133610e66565b6106488383611171565b610749338261125c565b7fcf6f9f892731e14b8859835f2ff35575f447fb501f46243c4eb8bac19e31a0506107b68133610e66565b60405163a9059cbb60e01b8152336004820152602481018390526001600160a01b0384169063a9059cbb906044016020604051808303816000875af1158015610803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108279190611bd9565b50505050565b60006108398333610442565b9050818110156108975760405162461bcd60e51b8152602060048201526024808201527f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f77604482015263616e636560e01b6064820152608401610601565b6108a48333848403610b69565b610648838361125c565b6001600160a01b0381166000908152600560205260408120546104c5565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6108f78133610e66565b6107496113b6565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600480546104da90611b76565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156109bb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610601565b6109c83385858403610b69565b5060019392505050565b600061056a338484610c8d565b83421115610a2f5760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610601565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610a5e8c611431565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610ab982611459565b90506000610ac9828787876114a7565b9050896001600160a01b0316816001600160a01b031614610b2c5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610601565b610b378a8a8a610b69565b50505050505050505050565b600082815260066020526040902060010154610b5f8133610e66565b6106488383611077565b6001600160a01b038316610bcb5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610601565b6001600160a01b038216610c2c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610601565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038316610cf15760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610601565b6001600160a01b038216610d535760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610601565b610d5e8383836114cf565b6001600160a01b03831660009081526020819052604090205481811015610dd65760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610601565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610e0d908490611bc1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e5991815260200190565b60405180910390a3610827565b610e7082826108ff565b6106d657610e88816001600160a01b03166014611515565b610e93836020611515565b604051602001610ea4929190611bfb565b60408051601f198184030181529082905262461bcd60e51b8252610601916004016119b6565b610ed482826108ff565b6106d65760008281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055610f0c3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000306001600160a01b037f000000000000000000000000104b2aa5333966360c4f28c206634759c546b82716148015610fa957507f00000000000000000000000000000000000000000000000000000000000000fa46145b15610fd357507ffe259586219013e37c58f2c85090b5ffa35574f1a83e3a7fb424636e2dabc30790565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f2f6467a1cd0ffa5d3283f6025c0360f611a2ebed770c1e33cf678d34b0b96e71828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b61108182826108ff565b156106d65760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60075460ff166111275760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610601565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0382166111c75760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610601565b6111d3600083836114cf565b80600260008282546111e59190611bc1565b90915550506001600160a01b03821660009081526020819052604081208054839290611212908490611bc1565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166112bc5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610601565b6112c8826000836114cf565b6001600160a01b0382166000908152602081905260409020548181101561133c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610601565b6001600160a01b038316600090815260208190526040812083830390556002805484929061136b908490611c70565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60075460ff16156113fc5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610601565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586111543390565b6001600160a01b03811660009081526005602052604090208054600181018255905b50919050565b60006104c5611466610f50565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006114b8878787876116b8565b915091506114c5816117a5565b5095945050505050565b60075460ff16156106485760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610601565b60606000611524836002611c87565b61152f906002611bc1565b67ffffffffffffffff81111561154757611547611ca6565b6040519080825280601f01601f191660200182016040528015611571576020820181803683370190505b509050600360fc1b8160008151811061158c5761158c611cbc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106115bb576115bb611cbc565b60200101906001600160f81b031916908160001a90535060006115df846002611c87565b6115ea906001611bc1565b90505b6001811115611662576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061161e5761161e611cbc565b1a60f81b82828151811061163457611634611cbc565b60200101906001600160f81b031916908160001a90535060049490941c9361165b81611cd2565b90506115ed565b5083156116b15760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610601565b9392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156116ef575060009050600361179c565b8460ff16601b1415801561170757508460ff16601c14155b15611718575060009050600461179c565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561176c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166117955760006001925092505061179c565b9150600090505b94509492505050565b60008160048111156117b9576117b9611ce9565b14156117c25750565b60018160048111156117d6576117d6611ce9565b14156118245760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610601565b600281600481111561183857611838611ce9565b14156118865760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610601565b600381600481111561189a5761189a611ce9565b14156118f35760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610601565b600481600481111561190757611907611ce9565b14156107495760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610601565b60006020828403121561197257600080fd5b81356001600160e01b0319811681146116b157600080fd5b60005b838110156119a557818101518382015260200161198d565b838111156108275750506000910152565b60208152600082518060208401526119d581604085016020870161198a565b601f01601f19169190910160400192915050565b6001600160a01b038116811461074957600080fd5b60008060408385031215611a1157600080fd5b8235611a1c816119e9565b946020939093013593505050565b600080600060608486031215611a3f57600080fd5b8335611a4a816119e9565b92506020840135611a5a816119e9565b929592945050506040919091013590565b600060208284031215611a7d57600080fd5b5035919050565b60008060408385031215611a9757600080fd5b823591506020830135611aa9816119e9565b809150509250929050565b600060208284031215611ac657600080fd5b81356116b1816119e9565b600080600080600080600060e0888a031215611aec57600080fd5b8735611af7816119e9565b96506020880135611b07816119e9565b95506040880135945060608801359350608088013560ff81168114611b2b57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611b5b57600080fd5b8235611b66816119e9565b91506020830135611aa9816119e9565b600181811c90821680611b8a57607f821691505b6020821081141561145357634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115611bd457611bd4611bab565b500190565b600060208284031215611beb57600080fd5b815180151581146116b157600080fd5b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611c3381601785016020880161198a565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611c6481602884016020880161198a565b01602801949350505050565b600082821015611c8257611c82611bab565b500390565b6000816000190483118215151615611ca157611ca1611bab565b500290565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081611ce157611ce1611bab565b506000190190565b634e487b7160e01b600052602160045260246000fdfea26469706673582212201cd88dc81bcea0dba8aeb39b90469e6b357d3d17599a8eafad0c351c41f2eda764736f6c634300080b0033

Deployed Bytecode Sourcemap

442:1303:18:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2585:204:0;;;;;;:::i;:::-;;:::i;:::-;;;470:14:19;;463:22;445:41;;433:2;418:18;2585:204:0;;;;;;;;2127:123:7;;;:::i;:::-;;;;;;;:::i;4363:169::-;;;;;;:::i;:::-;;:::i;3316:108::-;3404:12;;3316:108;;;1750:25:19;;;1738:2;1723:18;3316:108:7;1604:177:19;5014:492:7;;;;;;:::i;:::-;;:::i;3996:123:0:-;;;;;;:::i;:::-;4062:7;4089:12;;;:6;:12;;;;;:22;;;;3996:123;4381:147;;;;;;:::i;:::-;;:::i;:::-;;3135:116:7;;;3241:2;3076:36:19;;3064:2;3049:18;3135:116:7;2934:184:19;2396:115:9;;;:::i;5429:218:0:-;;;;;;:::i;:::-;;:::i;5915:215:7:-;;;;;;:::i;:::-;;:::i;1454:79:18:-;;;:::i;1088:109::-;;;;;;:::i;:::-;;:::i;493:91:8:-;;;;;;:::i;:::-;;:::i;1205:158:18:-;;;;;;:::i;:::-;;:::i;1070:86:15:-;1141:7;;;;1070:86;;3487:127:7;;;;;;:::i;:::-;-1:-1:-1;;;;;3588:18:7;3561:7;3588:18;;;;;;;;;;;;3487:127;647:64:18;;686:25;647:64;;903:368:8;;;;;;:::i;:::-;;:::i;2138:128:9:-;;;;;;:::i;:::-;;:::i;1371:75:18:-;;;:::i;2881:139:0:-;;;;;;:::i;:::-;;:::i;2369:127:7:-;;;:::i;1972:49:0:-;;2017:4;1972:49;;6633:413:7;;;;;;:::i;:::-;;:::i;3827:175::-;;;;;;:::i;:::-;;:::i;1427:645:9:-;;;;;;:::i;:::-;;:::i;578:62:18:-;;616:24;578:62;;4773:149:0;;;;;;:::i;:::-;;:::i;4065:151:7:-;;;;;;:::i;:::-;-1:-1:-1;;;;;4181:18:7;;;4154:7;4181:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;4065:151;718:62:18;;756:24;718:62;;2585:204:0;2670:4;-1:-1:-1;;;;;;2694:47:0;;-1:-1:-1;;;2694:47:0;;:87;;-1:-1:-1;;;;;;;;;;896:40:6;;;2745:36:0;2687:94;2585:204;-1:-1:-1;;2585:204:0:o;2127:123:7:-;2204:13;2237:5;2230:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2127:123;:::o;4363:169::-;4446:4;4463:39;682:10:2;4486:7:7;4495:6;4463:8;:39::i;:::-;-1:-1:-1;4520:4:7;4363:169;;;;:::o;5014:492::-;5154:4;5171:36;5181:6;5189:9;5200:6;5171:9;:36::i;:::-;-1:-1:-1;;;;;5247:19:7;;5220:24;5247:19;;;:11;:19;;;;;;;;682:10:2;5247:33:7;;;;;;;;5299:26;;;;5291:79;;;;-1:-1:-1;;;5291:79:7;;5709:2:19;5291:79:7;;;5691:21:19;5748:2;5728:18;;;5721:30;5787:34;5767:18;;;5760:62;-1:-1:-1;;;5838:18:19;;;5831:38;5886:19;;5291:79:7;;;;;;;;;5406:57;5415:6;682:10:2;5456:6:7;5437:16;:25;5406:8;:57::i;:::-;-1:-1:-1;5494:4:7;;5014:492;-1:-1:-1;;;;5014:492:7:o;4381:147:0:-;4062:7;4089:12;;;:6;:12;;;;;:22;;;2463:30;2474:4;682:10:2;2463::0;:30::i;:::-;4495:25:::1;4506:4;4512:7;4495:10;:25::i;:::-;4381:147:::0;;;:::o;2396:115:9:-;2456:7;2483:20;:18;:20::i;:::-;2476:27;;2396:115;:::o;5429:218:0:-;-1:-1:-1;;;;;5525:23:0;;682:10:2;5525:23:0;5517:83;;;;-1:-1:-1;;;5517:83:0;;6118:2:19;5517:83:0;;;6100:21:19;6157:2;6137:18;;;6130:30;6196:34;6176:18;;;6169:62;-1:-1:-1;;;6247:18:19;;;6240:45;6302:19;;5517:83:0;5916:411:19;5517:83:0;5613:26;5625:4;5631:7;5613:11;:26::i;:::-;5429:218;;:::o;5915:215:7:-;682:10:2;6003:4:7;6052:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;6052:34:7;;;;;;;;;;6003:4;;6020:80;;6043:7;;6052:47;;6089:10;;6052:47;:::i;:::-;6020:8;:80::i;1454:79:18:-;756:24;2463:30:0;756:24:18;682:10:2;2463::0;:30::i;:::-;1515:10:18::1;:8;:10::i;:::-;1454:79:::0;:::o;1088:109::-;616:24;2463:30:0;616:24:18;682:10:2;2463::0;:30::i;:::-;1172:17:18::1;1178:2;1182:6;1172:5;:17::i;493:91:8:-:0;549:27;682:10:2;569:6:8;549:5;:27::i;1205:158:18:-;686:25;2463:30:0;686:25:18;682:10:2;2463::0;:30::i;:::-;1322:33:18::1;::::0;-1:-1:-1;;;1322:33:18;;1337:10:::1;1322:33;::::0;::::1;6771:51:19::0;6838:18;;;6831:34;;;-1:-1:-1;;;;;1322:14:18;::::1;::::0;::::1;::::0;6744:18:19;;1322:33:18::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;1205:158:::0;;;:::o;903:368:8:-;980:24;1007:32;1017:7;682:10:2;4065:151:7;:::i;1007:32:8:-;980:59;;1078:6;1058:16;:26;;1050:75;;;;-1:-1:-1;;;1050:75:8;;7360:2:19;1050:75:8;;;7342:21:19;7399:2;7379:18;;;7372:30;7438:34;7418:18;;;7411:62;-1:-1:-1;;;7489:18:19;;;7482:34;7533:19;;1050:75:8;7158:400:19;1050:75:8;1161:58;1170:7;682:10:2;1212:6:8;1193:16;:25;1161:8;:58::i;:::-;1241:22;1247:7;1256:6;1241:5;:22::i;2138:128:9:-;-1:-1:-1;;;;;2234:14:9;;2207:7;2234:14;;;:7;:14;;;;;885::3;2234:24:9;793:114:3;1371:75:18;756:24;2463:30:0;756:24:18;682:10:2;2463::0;:30::i;:::-;1430:8:18::1;:6;:8::i;2881:139:0:-:0;2959:4;2983:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2983:29:0;;;;;;;;;;;;;;;2881:139::o;2369:127:7:-;2448:13;2481:7;2474:14;;;;;:::i;6633:413::-;682:10:2;6726:4:7;6770:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;6770:34:7;;;;;;;;;;6823:35;;;;6815:85;;;;-1:-1:-1;;;6815:85:7;;7765:2:19;6815:85:7;;;7747:21:19;7804:2;7784:18;;;7777:30;7843:34;7823:18;;;7816:62;-1:-1:-1;;;7894:18:19;;;7887:35;7939:19;;6815:85:7;7563:401:19;6815:85:7;6936:67;682:10:2;6959:7:7;6987:15;6968:16;:34;6936:8;:67::i;:::-;-1:-1:-1;7034:4:7;;6633:413;-1:-1:-1;;;6633:413:7:o;3827:175::-;3913:4;3930:42;682:10:2;3954:9:7;3965:6;3930:9;:42::i;1427:645:9:-;1671:8;1652:15;:27;;1644:69;;;;-1:-1:-1;;;1644:69:9;;8171:2:19;1644:69:9;;;8153:21:19;8210:2;8190:18;;;8183:30;8249:31;8229:18;;;8222:59;8298:18;;1644:69:9;7969:353:19;1644:69:9;1726:18;1768:16;1786:5;1793:7;1802:5;1809:16;1819:5;1809:9;:16::i;:::-;1757:79;;;;;;8614:25:19;;;;-1:-1:-1;;;;;8713:15:19;;;8693:18;;;8686:43;8765:15;;;;8745:18;;;8738:43;8797:18;;;8790:34;8840:19;;;8833:35;8884:19;;;8877:35;;;8586:19;;1757:79:9;;;;;;;;;;;;1747:90;;;;;;1726:111;;1850:12;1865:28;1882:10;1865:16;:28::i;:::-;1850:43;;1906:14;1923:28;1937:4;1943:1;1946;1949;1923:13;:28::i;:::-;1906:45;;1980:5;-1:-1:-1;;;;;1970:15:9;:6;-1:-1:-1;;;;;1970:15:9;;1962:58;;;;-1:-1:-1;;;1962:58:9;;9125:2:19;1962:58:9;;;9107:21:19;9164:2;9144:18;;;9137:30;9203:32;9183:18;;;9176:60;9253:18;;1962:58:9;8923:354:19;1962:58:9;2033:31;2042:5;2049:7;2058:5;2033:8;:31::i;:::-;1633:439;;;1427:645;;;;;;;:::o;4773:149:0:-;4062:7;4089:12;;;:6;:12;;;;;:22;;;2463:30;2474:4;682:10:2;2463::0;:30::i;:::-;4888:26:::1;4900:4;4906:7;4888:11;:26::i;10317:380:7:-:0;-1:-1:-1;;;;;10453:19:7;;10445:68;;;;-1:-1:-1;;;10445:68:7;;9484:2:19;10445:68:7;;;9466:21:19;9523:2;9503:18;;;9496:30;9562:34;9542:18;;;9535:62;-1:-1:-1;;;9613:18:19;;;9606:34;9657:19;;10445:68:7;9282:400:19;10445:68:7;-1:-1:-1;;;;;10532:21:7;;10524:68;;;;-1:-1:-1;;;10524:68:7;;9889:2:19;10524:68:7;;;9871:21:19;9928:2;9908:18;;;9901:30;9967:34;9947:18;;;9940:62;-1:-1:-1;;;10018:18:19;;;10011:32;10060:19;;10524:68:7;9687:398:19;10524:68:7;-1:-1:-1;;;;;10605:18:7;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;10657:32;;1750:25:19;;;10657:32:7;;1723:18:19;10657:32:7;;;;;;;10317:380;;;:::o;7536:733::-;-1:-1:-1;;;;;7676:20:7;;7668:70;;;;-1:-1:-1;;;7668:70:7;;10292:2:19;7668:70:7;;;10274:21:19;10331:2;10311:18;;;10304:30;10370:34;10350:18;;;10343:62;-1:-1:-1;;;10421:18:19;;;10414:35;10466:19;;7668:70:7;10090:401:19;7668:70:7;-1:-1:-1;;;;;7757:23:7;;7749:71;;;;-1:-1:-1;;;7749:71:7;;10698:2:19;7749:71:7;;;10680:21:19;10737:2;10717:18;;;10710:30;10776:34;10756:18;;;10749:62;-1:-1:-1;;;10827:18:19;;;10820:33;10870:19;;7749:71:7;10496:399:19;7749:71:7;7833:47;7854:6;7862:9;7873:6;7833:20;:47::i;:::-;-1:-1:-1;;;;;7917:17:7;;7893:21;7917:17;;;;;;;;;;;7953:23;;;;7945:74;;;;-1:-1:-1;;;7945:74:7;;11102:2:19;7945:74:7;;;11084:21:19;11141:2;11121:18;;;11114:30;11180:34;11160:18;;;11153:62;-1:-1:-1;;;11231:18:19;;;11224:36;11277:19;;7945:74:7;10900:402:19;7945:74:7;-1:-1:-1;;;;;8055:17:7;;;:9;:17;;;;;;;;;;;8075:22;;;8055:42;;8119:20;;;;;;;;:30;;8091:6;;8055:9;8119:30;;8091:6;;8119:30;:::i;:::-;;;;;;;;8184:9;-1:-1:-1;;;;;8167:35:7;8176:6;-1:-1:-1;;;;;8167:35:7;;8195:6;8167:35;;;;1750:25:19;;1738:2;1723:18;;1604:177;8167:35:7;;;;;;;;8215:46;4381:147:0;3310:497;3391:22;3399:4;3405:7;3391;:22::i;:::-;3386:414;;3579:41;3607:7;-1:-1:-1;;;;;3579:41:0;3617:2;3579:19;:41::i;:::-;3693:38;3721:4;3728:2;3693:19;:38::i;:::-;3484:270;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;3484:270:0;;;;;;;;;;-1:-1:-1;;;3430:358:0;;;;;;;:::i;6930:238::-;7014:22;7022:4;7028:7;7014;:22::i;:::-;7009:152;;7053:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;7053:29:0;;;;;;;;;:36;;-1:-1:-1;;7053:36:0;7085:4;7053:36;;;7136:12;682:10:2;;602:98;7136:12:0;-1:-1:-1;;;;;7109:40:0;7127:7;-1:-1:-1;;;;;7109:40:0;7121:4;7109:40;;;;;;;;;;6930:238;;:::o;3140:314:5:-;3193:7;3225:4;-1:-1:-1;;;;;3234:12:5;3217:29;;:66;;;;;3267:16;3250:13;:33;3217:66;3213:234;;;-1:-1:-1;3307:24:5;;3140:314::o;3213:234::-;-1:-1:-1;3643:73:5;;;3393:10;3643:73;;;;15493:25:19;;;;3405:12:5;15534:18:19;;;15527:34;3419:15:5;15577:18:19;;;15570:34;3687:13:5;15620:18:19;;;15613:34;3710:4:5;15663:19:19;;;;15656:61;;;;3643:73:5;;;;;;;;;;15465:19:19;;;;3643:73:5;;;3633:84;;;;;;2396:115:9:o;7300:239:0:-;7384:22;7392:4;7398:7;7384;:22::i;:::-;7380:152;;;7455:5;7423:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;7423:29:0;;;;;;;;;;:37;;-1:-1:-1;;7423:37:0;;;7480:40;682:10:2;;7423:12:0;;7480:40;;7455:5;7480:40;7300:239;;:::o;2129:120:15:-;1141:7;;;;1665:41;;;;-1:-1:-1;;;1665:41:15;;12300:2:19;1665:41:15;;;12282:21:19;12339:2;12319:18;;;12312:30;-1:-1:-1;;;12358:18:19;;;12351:50;12418:18;;1665:41:15;12098:344:19;1665:41:15;2188:7:::1;:15:::0;;-1:-1:-1;;2188:15:15::1;::::0;;2219:22:::1;682:10:2::0;2228:12:15::1;2219:22;::::0;-1:-1:-1;;;;;12611:32:19;;;12593:51;;12581:2;12566:18;2219:22:15::1;;;;;;;2129:120::o:0;8556:399:7:-;-1:-1:-1;;;;;8640:21:7;;8632:65;;;;-1:-1:-1;;;8632:65:7;;12857:2:19;8632:65:7;;;12839:21:19;12896:2;12876:18;;;12869:30;12935:33;12915:18;;;12908:61;12986:18;;8632:65:7;12655:355:19;8632:65:7;8710:49;8739:1;8743:7;8752:6;8710:20;:49::i;:::-;8788:6;8772:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;8805:18:7;;:9;:18;;;;;;;;;;:28;;8827:6;;8805:9;:28;;8827:6;;8805:28;:::i;:::-;;;;-1:-1:-1;;8849:37:7;;1750:25:19;;;-1:-1:-1;;;;;8849:37:7;;;8866:1;;8849:37;;1738:2:19;1723:18;8849:37:7;;;;;;;5429:218:0;;:::o;9288:591:7:-;-1:-1:-1;;;;;9372:21:7;;9364:67;;;;-1:-1:-1;;;9364:67:7;;13217:2:19;9364:67:7;;;13199:21:19;13256:2;13236:18;;;13229:30;13295:34;13275:18;;;13268:62;-1:-1:-1;;;13346:18:19;;;13339:31;13387:19;;9364:67:7;13015:397:19;9364:67:7;9444:49;9465:7;9482:1;9486:6;9444:20;:49::i;:::-;-1:-1:-1;;;;;9531:18:7;;9506:22;9531:18;;;;;;;;;;;9568:24;;;;9560:71;;;;-1:-1:-1;;;9560:71:7;;13619:2:19;9560:71:7;;;13601:21:19;13658:2;13638:18;;;13631:30;13697:34;13677:18;;;13670:62;-1:-1:-1;;;13748:18:19;;;13741:32;13790:19;;9560:71:7;13417:398:19;9560:71:7;-1:-1:-1;;;;;9667:18:7;;:9;:18;;;;;;;;;;9688:23;;;9667:44;;9733:12;:22;;9705:6;;9667:9;9733:22;;9705:6;;9733:22;:::i;:::-;;;;-1:-1:-1;;9773:37:7;;1750:25:19;;;9799:1:7;;-1:-1:-1;;;;;9773:37:7;;;;;1738:2:19;1723:18;9773:37:7;;;;;;;4381:147:0;;;:::o;1870:118:15:-;1141:7;;;;1395:9;1387:38;;;;-1:-1:-1;;;1387:38:15;;14152:2:19;1387:38:15;;;14134:21:19;14191:2;14171:18;;;14164:30;-1:-1:-1;;;14210:18:19;;;14203:46;14266:18;;1387:38:15;13950:340:19;1387:38:15;1930:7:::1;:14:::0;;-1:-1:-1;;1930:14:15::1;1940:4;1930:14;::::0;;1960:20:::1;1967:12;682:10:2::0;;602:98;2649:207:9;-1:-1:-1;;;;;2770:14:9;;2709:15;2770:14;;;:7;:14;;;;;885::3;;1022:1;1004:19;;;;885:14;2831:17:9;2726:130;2649:207;;;:::o;4367:167:5:-;4444:7;4471:55;4493:20;:18;:20::i;:::-;4515:10;9426:57:4;;-1:-1:-1;;;9426:57:4;;;15986:27:19;16029:11;;;16022:27;;;16065:12;;;16058:28;;;9389:7:4;;16102:12:19;;9426:57:4;;;;;;;;;;;;9416:68;;;;;;9409:75;;9296:196;;;;;7605:279;7733:7;7754:17;7773:18;7795:25;7806:4;7812:1;7815;7818;7795:10;:25::i;:::-;7753:67;;;;7831:18;7843:5;7831:11;:18::i;:::-;-1:-1:-1;7867:9:4;7605:279;-1:-1:-1;;;;;7605:279:4:o;1541:201:18:-;1141:7:15;;;;1395:9;1387:38;;;;-1:-1:-1;;;1387:38:15;;14152:2:19;1387:38:15;;;14134:21:19;14191:2;14171:18;;;14164:30;-1:-1:-1;;;14210:18:19;;;14203:46;14266:18;;1387:38:15;13950:340:19;1589:451:17;1664:13;1690:19;1722:10;1726:6;1722:1;:10;:::i;:::-;:14;;1735:1;1722:14;:::i;:::-;1712:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1712:25:17;;1690:47;;-1:-1:-1;;;1748:6:17;1755:1;1748:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1748:15:17;;;;;;;;;-1:-1:-1;;;1774:6:17;1781:1;1774:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1774:15:17;;;;;;;;-1:-1:-1;1805:9:17;1817:10;1821:6;1817:1;:10;:::i;:::-;:14;;1830:1;1817:14;:::i;:::-;1805:26;;1800:135;1837:1;1833;:5;1800:135;;;-1:-1:-1;;;1885:5:17;1893:3;1885:11;1872:25;;;;;;;:::i;:::-;;;;1860:6;1867:1;1860:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;1860:37:17;;;;;;;;-1:-1:-1;1922:1:17;1912:11;;;;;1840:3;;;:::i;:::-;;;1800:135;;;-1:-1:-1;1953:10:17;;1945:55;;;;-1:-1:-1;;;1945:55:17;;15075:2:19;1945:55:17;;;15057:21:19;;;15094:18;;;15087:30;15153:34;15133:18;;;15126:62;15205:18;;1945:55:17;14873:356:19;1945:55:17;2025:6;1589:451;-1:-1:-1;;;1589:451:17:o;5827:1639:4:-;5958:7;;6899:66;6886:79;;6882:163;;;-1:-1:-1;6998:1:4;;-1:-1:-1;7002:30:4;6982:51;;6882:163;7059:1;:7;;7064:2;7059:7;;:18;;;;;7070:1;:7;;7075:2;7070:7;;7059:18;7055:102;;;-1:-1:-1;7110:1:4;;-1:-1:-1;7114:30:4;7094:51;;7055:102;7271:24;;;7254:14;7271:24;;;;;;;;;16352:25:19;;;16425:4;16413:17;;16393:18;;;16386:45;;;;16447:18;;;16440:34;;;16490:18;;;16483:34;;;7271:24:4;;16324:19:19;;7271:24:4;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7271:24:4;;-1:-1:-1;;7271:24:4;;;-1:-1:-1;;;;;;;7310:20:4;;7306:103;;7363:1;7367:29;7347:50;;;;;;;7306:103;7429:6;-1:-1:-1;7437:20:4;;-1:-1:-1;5827:1639:4;;;;;;;;:::o;489:643::-;567:20;558:5;:29;;;;;;;;:::i;:::-;;554:571;;;489:643;:::o;554:571::-;665:29;656:5;:38;;;;;;;;:::i;:::-;;652:473;;;711:34;;-1:-1:-1;;;711:34:4;;16862:2:19;711:34:4;;;16844:21:19;16901:2;16881:18;;;16874:30;16940:26;16920:18;;;16913:54;16984:18;;711:34:4;16660:348:19;652:473:4;776:35;767:5;:44;;;;;;;;:::i;:::-;;763:362;;;828:41;;-1:-1:-1;;;828:41:4;;17215:2:19;828:41:4;;;17197:21:19;17254:2;17234:18;;;17227:30;17293:33;17273:18;;;17266:61;17344:18;;828:41:4;17013:355:19;763:362:4;900:30;891:5;:39;;;;;;;;:::i;:::-;;887:238;;;947:44;;-1:-1:-1;;;947:44:4;;17575:2:19;947:44:4;;;17557:21:19;17614:2;17594:18;;;17587:30;17653:34;17633:18;;;17626:62;-1:-1:-1;;;17704:18:19;;;17697:32;17746:19;;947:44:4;17373:398:19;887:238:4;1022:30;1013:5;:39;;;;;;;;:::i;:::-;;1009:116;;;1069:44;;-1:-1:-1;;;1069:44:4;;17978:2:19;1069:44:4;;;17960:21:19;18017:2;17997:18;;;17990:30;18056:34;18036:18;;;18029:62;-1:-1:-1;;;18107:18:19;;;18100:32;18149:19;;1069:44:4;17776:398:19;14:286;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:19;;209:43;;199:71;;266:1;263;256:12;497:258;569:1;579:113;593:6;590:1;587:13;579:113;;;669:11;;;663:18;650:11;;;643:39;615:2;608:10;579:113;;;710:6;707:1;704:13;701:48;;;-1:-1:-1;;745:1:19;727:16;;720:27;497:258::o;760:383::-;909:2;898:9;891:21;872:4;941:6;935:13;984:6;979:2;968:9;964:18;957:34;1000:66;1059:6;1054:2;1043:9;1039:18;1034:2;1026:6;1022:15;1000:66;:::i;:::-;1127:2;1106:15;-1:-1:-1;;1102:29:19;1087:45;;;;1134:2;1083:54;;760:383;-1:-1:-1;;760:383:19:o;1148:131::-;-1:-1:-1;;;;;1223:31:19;;1213:42;;1203:70;;1269:1;1266;1259:12;1284:315;1352:6;1360;1413:2;1401:9;1392:7;1388:23;1384:32;1381:52;;;1429:1;1426;1419:12;1381:52;1468:9;1455:23;1487:31;1512:5;1487:31;:::i;:::-;1537:5;1589:2;1574:18;;;;1561:32;;-1:-1:-1;;;1284:315:19:o;1786:456::-;1863:6;1871;1879;1932:2;1920:9;1911:7;1907:23;1903:32;1900:52;;;1948:1;1945;1938:12;1900:52;1987:9;1974:23;2006:31;2031:5;2006:31;:::i;:::-;2056:5;-1:-1:-1;2113:2:19;2098:18;;2085:32;2126:33;2085:32;2126:33;:::i;:::-;1786:456;;2178:7;;-1:-1:-1;;;2232:2:19;2217:18;;;;2204:32;;1786:456::o;2247:180::-;2306:6;2359:2;2347:9;2338:7;2334:23;2330:32;2327:52;;;2375:1;2372;2365:12;2327:52;-1:-1:-1;2398:23:19;;2247:180;-1:-1:-1;2247:180:19:o;2614:315::-;2682:6;2690;2743:2;2731:9;2722:7;2718:23;2714:32;2711:52;;;2759:1;2756;2749:12;2711:52;2795:9;2782:23;2772:33;;2855:2;2844:9;2840:18;2827:32;2868:31;2893:5;2868:31;:::i;:::-;2918:5;2908:15;;;2614:315;;;;;:::o;3643:247::-;3702:6;3755:2;3743:9;3734:7;3730:23;3726:32;3723:52;;;3771:1;3768;3761:12;3723:52;3810:9;3797:23;3829:31;3854:5;3829:31;:::i;3895:829::-;4006:6;4014;4022;4030;4038;4046;4054;4107:3;4095:9;4086:7;4082:23;4078:33;4075:53;;;4124:1;4121;4114:12;4075:53;4163:9;4150:23;4182:31;4207:5;4182:31;:::i;:::-;4232:5;-1:-1:-1;4289:2:19;4274:18;;4261:32;4302:33;4261:32;4302:33;:::i;:::-;4354:7;-1:-1:-1;4408:2:19;4393:18;;4380:32;;-1:-1:-1;4459:2:19;4444:18;;4431:32;;-1:-1:-1;4515:3:19;4500:19;;4487:33;4564:4;4551:18;;4539:31;;4529:59;;4584:1;4581;4574:12;4529:59;3895:829;;;;-1:-1:-1;3895:829:19;;;;4607:7;4661:3;4646:19;;4633:33;;-1:-1:-1;4713:3:19;4698:19;;;4685:33;;3895:829;-1:-1:-1;;3895:829:19:o;4729:388::-;4797:6;4805;4858:2;4846:9;4837:7;4833:23;4829:32;4826:52;;;4874:1;4871;4864:12;4826:52;4913:9;4900:23;4932:31;4957:5;4932:31;:::i;:::-;4982:5;-1:-1:-1;5039:2:19;5024:18;;5011:32;5052:33;5011:32;5052:33;:::i;5122:380::-;5201:1;5197:12;;;;5244;;;5265:61;;5319:4;5311:6;5307:17;5297:27;;5265:61;5372:2;5364:6;5361:14;5341:18;5338:38;5335:161;;;5418:10;5413:3;5409:20;5406:1;5399:31;5453:4;5450:1;5443:15;5481:4;5478:1;5471:15;6332:127;6393:10;6388:3;6384:20;6381:1;6374:31;6424:4;6421:1;6414:15;6448:4;6445:1;6438:15;6464:128;6504:3;6535:1;6531:6;6528:1;6525:13;6522:39;;;6541:18;;:::i;:::-;-1:-1:-1;6577:9:19;;6464:128::o;6876:277::-;6943:6;6996:2;6984:9;6975:7;6971:23;6967:32;6964:52;;;7012:1;7009;7002:12;6964:52;7044:9;7038:16;7097:5;7090:13;7083:21;7076:5;7073:32;7063:60;;7119:1;7116;7109:12;11307:786;11718:25;11713:3;11706:38;11688:3;11773:6;11767:13;11789:62;11844:6;11839:2;11834:3;11830:12;11823:4;11815:6;11811:17;11789:62;:::i;:::-;-1:-1:-1;;;11910:2:19;11870:16;;;11902:11;;;11895:40;11960:13;;11982:63;11960:13;12031:2;12023:11;;12016:4;12004:17;;11982:63;:::i;:::-;12065:17;12084:2;12061:26;;11307:786;-1:-1:-1;;;;11307:786:19:o;13820:125::-;13860:4;13888:1;13885;13882:8;13879:34;;;13893:18;;:::i;:::-;-1:-1:-1;13930:9:19;;13820:125::o;14295:168::-;14335:7;14401:1;14397;14393:6;14389:14;14386:1;14383:21;14378:1;14371:9;14364:17;14360:45;14357:71;;;14408:18;;:::i;:::-;-1:-1:-1;14448:9:19;;14295:168::o;14468:127::-;14529:10;14524:3;14520:20;14517:1;14510:31;14560:4;14557:1;14550:15;14584:4;14581:1;14574:15;14600:127;14661:10;14656:3;14652:20;14649:1;14642:31;14692:4;14689:1;14682:15;14716:4;14713:1;14706:15;14732:136;14771:3;14799:5;14789:39;;14808:18;;:::i;:::-;-1:-1:-1;;;14844:18:19;;14732:136::o;16528:127::-;16589:10;16584:3;16580:20;16577:1;16570:31;16620:4;16617:1;16610:15;16644:4;16641:1;16634:15

Swarm Source

ipfs://1cd88dc81bcea0dba8aeb39b90469e6b357d3d17599a8eafad0c351c41f2eda7
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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