ETH Price: $3,479.50 (+0.92%)

Token

Hommies (HOMMIES)
 

Overview

Max Total Supply

665,000,000 HOMMIES

Holders

1,356

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Balance
118,549 HOMMIES

Value
$0.00
0xf30E00D8D824930b8ae2F13e38244a3b8d11A6d7
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Hommiestoken is an erc-20 token that aims to solve real-world problems for the middle class around the world.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
Hommies

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-01-29
*/

/*                                                                                                                                                                                                                                                        
HHHHHHHHH     HHHHHHHHH                                                                   iiii                                       
H:::::::H     H:::::::H                                                                  i::::i                                      
H:::::::H     H:::::::H                                                                   iiii                                       
HH::::::H     H::::::HH                                                                                                              
  H:::::H     H:::::H     ooooooooooo      mmmmmmm    mmmmmmm      mmmmmmm    mmmmmmm   iiiiiii     eeeeeeeeeeee        ssssssssss   
  H:::::H     H:::::H   oo:::::::::::oo  mm:::::::m  m:::::::mm  mm:::::::m  m:::::::mm i:::::i   ee::::::::::::ee    ss::::::::::s  
  H::::::HHHHH::::::H  o:::::::::::::::om::::::::::mm::::::::::mm::::::::::mm::::::::::m i::::i  e::::::eeeee:::::eess:::::::::::::s 
  H:::::::::::::::::H  o:::::ooooo:::::om::::::::::::::::::::::mm::::::::::::::::::::::m i::::i e::::::e     e:::::es::::::ssss:::::s
  H:::::::::::::::::H  o::::o     o::::om:::::mmm::::::mmm:::::mm:::::mmm::::::mmm:::::m i::::i e:::::::eeeee::::::e s:::::s  ssssss 
  H::::::HHHHH::::::H  o::::o     o::::om::::m   m::::m   m::::mm::::m   m::::m   m::::m i::::i e:::::::::::::::::e    s::::::s      
  H:::::H     H:::::H  o::::o     o::::om::::m   m::::m   m::::mm::::m   m::::m   m::::m i::::i e::::::eeeeeeeeeee        s::::::s   
  H:::::H     H:::::H  o::::o     o::::om::::m   m::::m   m::::mm::::m   m::::m   m::::m i::::i e:::::::e           ssssss   s:::::s 
HH::::::H     H::::::HHo:::::ooooo:::::om::::m   m::::m   m::::mm::::m   m::::m   m::::mi::::::ie::::::::e          s:::::ssss::::::s
H:::::::H     H:::::::Ho:::::::::::::::om::::m   m::::m   m::::mm::::m   m::::m   m::::mi::::::i e::::::::eeeeeeee  s::::::::::::::s 
H:::::::H     H:::::::H oo:::::::::::oo m::::m   m::::m   m::::mm::::m   m::::m   m::::mi::::::i  ee:::::::::::::e   s:::::::::::ss  
HHHHHHHHH     HHHHHHHHH   ooooooooooo   mmmmmm   mmmmmm   mmmmmmmmmmmm   mmmmmm   mmmmmmiiiiiiii    eeeeeeeeeeeeee    sssssssssss    
*/
// File: @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol

pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

// File: @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol

pragma solidity >=0.6.2;


interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

// File: @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol

pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

// File: @uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol

pragma solidity >=0.5.0;

interface IUniswapV2Factory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint) external view returns (address pair);
    function allPairsLength() external view returns (uint);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;


/**
 * @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);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: @openzeppelin/contracts/access/IAccessControl.sol


// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @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.
     */
    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 `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

// File: @openzeppelin/contracts/utils/Nonces.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)
pragma solidity ^0.8.20;

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

    mapping(address account => uint256) private _nonces;

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

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

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

// File: @openzeppelin/contracts/interfaces/IERC5267.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.20;

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

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

// File: @openzeppelin/contracts/utils/StorageSlot.sol


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

pragma solidity ^0.8.20;

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

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/ShortStrings.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol)

pragma solidity ^0.8.20;


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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/math/SignedMath.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

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

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

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

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

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

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

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

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

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

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

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

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

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;



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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)

pragma solidity ^0.8.20;


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

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

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

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

// File: @openzeppelin/contracts/utils/cryptography/EIP712.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol)

pragma solidity ^0.8.20;




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

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

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

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol


// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
        unchecked {
            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

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

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

// File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol


// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

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

// File: @openzeppelin/contracts/security/Pausable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;


/**
 * @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 Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

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

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

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        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: @openzeppelin/contracts/access/AccessControl.sol


// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;




/**
 * @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:
 *
 * ```solidity
 * 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}:
 *
 * ```solidity
 * 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. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @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 virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @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 virtual 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.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual 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.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual 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 `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @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 Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;


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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;


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

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

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

// File: @openzeppelin/contracts/token/ERC20/ERC20.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;





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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

        emit Transfer(from, to, value);
    }

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

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

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

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

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

// File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Permit.sol)

pragma solidity ^0.8.20;






/**
 * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
    bytes32 private constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

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

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

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

    /**
     * @inheritdoc IERC20Permit
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        if (block.timestamp > deadline) {
            revert ERC2612ExpiredSignature(deadline);
        }

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

        bytes32 hash = _hashTypedDataV4(structHash);

        address signer = ECDSA.recover(hash, v, r, s);
        if (signer != owner) {
            revert ERC2612InvalidSigner(signer, owner);
        }

        _approve(owner, spender, value);
    }

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

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

// File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol


// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.20;



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

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

// File: contracts/Hommies.sol


pragma solidity ^0.8.20;








// Import the Uniswap V2 interfaces




contract Hommies is
    ERC20,
    ERC20Burnable,
    Ownable,
    ERC20Permit,
    AccessControl,
    Pausable
{
    uint8 public buyTax = 4;
    uint8 public sellTax = 8;
    uint8 public transferTax = 0;

    uint256 public initialSupply = 700000000;
    uint256 public maxSupply = 10000000000;

    address public rewardWallet;
    address public revenueWallet;
    address public uniswapPair;

    uint256 public revenueThreshold = 10000000;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    IUniswapV2Router02 public uniswapRouter;
    IUniswapV2Factory private uniswapFactory;
    IUniswapV2Pair private uniswapV2Pair;

    constructor(
        address _rewardWallet,
        address _revenueWallet,
        address _minterWallet
    ) ERC20("Hommies", "HOMMIES") Ownable(msg.sender) ERC20Permit("Hommies") {
        require(_rewardWallet != address(0), "Invalid Reward Wallet Address");
        require(_revenueWallet != address(0), "Invalid Revenue Wallet Address");

        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, _minterWallet);

        rewardWallet = _rewardWallet;
        revenueWallet = _revenueWallet;

        uniswapRouter = IUniswapV2Router02(
            0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
        ); //Uniswap Router Address
        uniswapFactory = IUniswapV2Factory(
            0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
        ); //Uniswap Factory Address
        uniswapPair = uniswapFactory.createPair(
            address(this),
            uniswapRouter.WETH()
        );
        uniswapV2Pair = IUniswapV2Pair(uniswapPair);
        _mint(msg.sender, initialSupply * 10**decimals());
    }

    function mint(address to, uint256 amount) public whenNotPaused {
        require(hasRole(MINTER_ROLE, msg.sender), "Caller is not a minter");
        require(to != address(0), "Invalid Wallet Address");
        require(
            totalSupply() + amount <= maxSupply * 10**decimals(),
            "ERC20: max supply exceeded"
        );
        _mint(to, amount);
    }

    function setRewardWallet(address _rewardWallet) public {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            "Caller is not an admin"
        );
        require(_rewardWallet != address(0), "Invalid Wallet Address");
        rewardWallet = _rewardWallet;
    }

    function setRevenueWallet(address _revenueWallet) public {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            "Caller is not an admin"
        );
        require(_revenueWallet != address(0), "Invalid Wallet Address");
        revenueWallet = _revenueWallet;
    }

    function setThresholdLimit(uint256 _limit) public {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            "Caller is not an admin"
        );
        revenueThreshold = _limit;
    }

    function setTaxes(
        uint8 _buyTax,
        uint8 _sellTax,
        uint8 _transferTax
    ) external {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            "Caller is not an admin"
        );
        buyTax = _buyTax;
        sellTax = _sellTax;
        transferTax = _transferTax;
    }

    function transfer(address recipient, uint amount)
        public
        override
        whenNotPaused
        returns (bool)
    {
        require(recipient != address(0), "Invalid Address");
        require(amount > 0, "Amount should be greater than zero.");
        return _taxedTransfer(msg.sender, recipient, amount);
    }

    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) public override whenNotPaused returns (bool) {
        require(sender != address(0), "Invalid Address");
        require(recipient != address(0), "Invalid Address");
        uint256 currentAllowance = allowance(sender, msg.sender);
        require(
            currentAllowance >= amount,
            "ERC20: transfer amount exceeds allowance"
        );
        require(amount > 0, "Amount should be greater than zero.");
        _taxedTransfer(sender, recipient, amount);
        return true;
    }

    function _taxedTransfer(
        address sender,
        address recipient,
        uint amount
    ) internal whenNotPaused returns (bool) {
        require(sender != address(0), "Invalid Address");
        require(recipient != address(0), "Invalid Address");
        require(
            amount > 0,
            "Amount should be greater than zero for transaction."
        );

        uint256 totalTax = 0;
        uint8 taxRate = transferTax;
        uint256 amountAfterTax = amount;

        if (sender == uniswapPair && recipient != address(uniswapRouter)) {
            //Buy Transaction
            taxRate = buyTax;
        } else if (recipient == uniswapPair) {
            //Sell Transaction
            taxRate = sellTax;
        } else {
            //Other Transaction
            taxRate = transferTax;
        }

        totalTax = calculateTax(amount, taxRate);
        amountAfterTax -= totalTax;
        uint256 rewardTax = totalTax / 2;
        uint256 revenueTax = totalTax / 2;

        super._transfer(sender, address(this), revenueTax);
        super._transfer(sender, rewardWallet, rewardTax);
        super._transfer(sender, recipient, amountAfterTax);

        uint256 currentContractBalance = getContractBalance();
        uint256 minAmountBack = 0;
        if (currentContractBalance > revenueThreshold * 10**decimals()) {
            minAmountBack = getMinAmountBack(
                revenueThreshold * 10**decimals(),
                1000
            ); //Swap with max 10% slippage
        }
        uint256 minExpectedWETH = 1e17; //0.1 ETH
        if (
            (currentContractBalance > revenueThreshold * 10**decimals()) &&
            (minAmountBack > minExpectedWETH)
        ) {
            swapTokensForEth(revenueThreshold * 10**decimals(), minAmountBack);
        }
        return true;
    }

    function calculateTax(uint256 amount, uint8 _taxRate)
        private
        pure
        returns (uint256)
    {
        return (amount * _taxRate) / 100;
    }

    function getContractBalance() public view returns (uint256) {
        return balanceOf(address(this));
    }

    function swapTokensForEth(uint256 _tokenAmount, uint256 _minAmountBack)
        private
        whenNotPaused
    {
        IERC20(address(this)).approve(address(uniswapRouter), _tokenAmount);

        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapRouter.WETH();

        // Make the swap
        uniswapRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
            _tokenAmount,
            _minAmountBack,
            path,
            revenueWallet,
            block.timestamp
        );
    }

    function getMinAmountBack(uint256 amountIn, uint256 slippage)
        private
        view
        returns (uint256 minAmountOut)
    {
        require(slippage <= 10000, "Slippage too high"); // Slippage cannot be more than 100%

        (uint112 reserve0, uint112 reserve1, ) = uniswapV2Pair.getReserves();
        address token0 = uniswapV2Pair.token0();
        address token1 = uniswapV2Pair.token1();

        uint256 rawAmountOut;
        if (address(this) == token0) {
            // Sorting tokens according to their addresses
            rawAmountOut = uniswapRouter.getAmountOut(
                amountIn,
                reserve0,
                reserve1
            );
        } else if (address(this) == token1) {
            rawAmountOut = uniswapRouter.getAmountOut(
                amountIn,
                reserve1,
                reserve0
            );
        } else {
            revert("Invalid token");
        }
        uint256 slippageAmount = (rawAmountOut * slippage) / 10000;
        minAmountOut = rawAmountOut - slippageAmount;
    }

    function pauseContract() public whenNotPaused returns (bool) {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            "Caller is not an admin"
        );
        _pause();
        return true;
    }

    function unpauseContract() public whenPaused returns (bool) {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            "Caller is not an admin"
        );
        _unpause();
        return true;
    }

    function withdrawTokens(address _tokenContract) external whenNotPaused {
        require(
            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
            "Caller is not an admin"
        );
        IERC20 token = IERC20(_tokenContract);
        uint256 tokenBalance = token.balanceOf(address(this));
        require(token.transfer(revenueWallet, tokenBalance), "Transfer failed");
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_rewardWallet","type":"address"},{"internalType":"address","name":"_revenueWallet","type":"address"},{"internalType":"address","name":"_minterWallet","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyTax","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"initialSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"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":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revenueThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revenueWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellTax","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_revenueWallet","type":"address"}],"name":"setRevenueWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardWallet","type":"address"}],"name":"setRewardWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_buyTax","type":"uint8"},{"internalType":"uint8","name":"_sellTax","type":"uint8"},{"internalType":"uint8","name":"_transferTax","type":"uint8"}],"name":"setTaxes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setThresholdLimit","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":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferTax","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenContract","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]

610160604052600a805463ffffff001916620804001790556329b92700600b556402540be400600c55629896806010553480156200003b575f80fd5b5060405162003377380380620033778339810160408190526200005e9162000793565b60405180604001604052806007815260200166486f6d6d69657360c81b81525080604051806040016040528060018152602001603160f81b8152503360405180604001604052806007815260200166486f6d6d69657360c81b81525060405180604001604052806007815260200166484f4d4d49455360c81b8152508160039081620000eb919062000878565b506004620000fa828262000878565b5050506001600160a01b0381166200012c57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b620001378162000492565b5062000145826006620004e3565b6101205262000156816007620004e3565b61014052815160208084019190912060e052815190820120610100524660a052620001e360e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c05250600a805460ff191690556001600160a01b0383166200024f5760405162461bcd60e51b815260206004820152601d60248201527f496e76616c6964205265776172642057616c6c65742041646472657373000000604482015260640162000123565b6001600160a01b038216620002a75760405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420526576656e75652057616c6c657420416464726573730000604482015260640162000123565b620002b35f336200051b565b50620002e07f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6826200051b565b50600d80546001600160a01b03199081166001600160a01b0386811691909117909255600e805482169285169290921790915560118054737a250d5630b4cf539739df2c5dacb4c659f2488d908316811790915560128054735c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f931683179055604080516315ab88c960e31b8152905163c9c65396923092909163ad5c4648916004808201926020929091908290030181865afa15801562000397573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620003bd919062000944565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303815f875af115801562000408573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200042e919062000944565b600f80546001600160a01b03929092166001600160a01b0319928316811790915560138054909216179055620004893362000467601290565b6200047490600a62000a74565b600b5462000483919062000a84565b620005ca565b50505062000b26565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f6020835110156200050257620004fa8362000606565b905062000515565b816200050f848262000878565b5060ff90505b92915050565b5f8281526009602090815260408083206001600160a01b038516845290915281205460ff16620005c2575f8381526009602090815260408083206001600160a01b03861684529091529020805460ff19166001179055620005793390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600162000515565b505f62000515565b6001600160a01b038216620005f55760405163ec442f0560e01b81525f600482015260240162000123565b620006025f838362000648565b5050565b5f80829050601f8151111562000633578260405163305a27a960e01b815260040162000123919062000a9e565b8051620006408262000aec565b179392505050565b6001600160a01b03831662000676578060025f8282546200066a919062000b10565b90915550620006e89050565b6001600160a01b0383165f9081526020819052604090205481811015620006ca5760405163391434e360e21b81526001600160a01b0385166004820152602481018290526044810183905260640162000123565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216620007065760028054829003905562000724565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516200076a91815260200190565b60405180910390a3505050565b80516001600160a01b03811681146200078e575f80fd5b919050565b5f805f60608486031215620007a6575f80fd5b620007b18462000777565b9250620007c16020850162000777565b9150620007d16040850162000777565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200080357607f821691505b6020821081036200082257634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200087357805f5260205f20601f840160051c810160208510156200084f5750805b601f840160051c820191505b8181101562000870575f81556001016200085b565b50505b505050565b81516001600160401b03811115620008945762000894620007da565b620008ac81620008a58454620007ee565b8462000828565b602080601f831160018114620008e2575f8415620008ca5750858301515b5f19600386901b1c1916600185901b1785556200093c565b5f85815260208120601f198616915b828110156200091257888601518255948401946001909101908401620008f1565b50858210156200093057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f6020828403121562000955575f80fd5b620009608262000777565b9392505050565b634e487b7160e01b5f52601160045260245ffd5b600181815b80851115620009bb57815f19048211156200099f576200099f62000967565b80851615620009ad57918102915b93841c939080029062000980565b509250929050565b5f82620009d35750600162000515565b81620009e157505f62000515565b8160018114620009fa576002811462000a055762000a25565b600191505062000515565b60ff84111562000a195762000a1962000967565b50506001821b62000515565b5060208310610133831016604e8410600b841016171562000a4a575081810a62000515565b62000a5683836200097b565b805f190482111562000a6c5762000a6c62000967565b029392505050565b5f6200096060ff841683620009c3565b808202811582820484141762000515576200051562000967565b5f602080835283518060208501525f5b8181101562000acc5785810183015185820160400152820162000aae565b505f604082860101526040601f19601f8301168501019250505092915050565b8051602080830151919081101562000822575f1960209190910360031b1b16919050565b8082018082111562000515576200051562000967565b60805160a05160c05160e0516101005161012051610140516127ff62000b785f395f61164801525f61161b01525f6113bc01525f61139401525f6112ef01525f61131901525f61134301526127ff5ff3fe608060405234801561000f575f80fd5b5060043610610281575f3560e01c8063715018a611610156578063a9059cbb116100ca578063d547741f11610084578063d547741f1461058f578063d5abeb01146105a2578063dd62ed3e146105ab578063f2fde38b146105be578063fb235f34146105d1578063fb75b2c7146105e4575f80fd5b8063a9059cbb14610514578063b33712c514610527578063c816841b1461052f578063cc1776d314610542578063d505accf14610555578063d539139314610568575f80fd5b806384b0196e1161011b57806384b0196e146104b35780638da5cb5b146104ce57806391d14854146104df57806395d89b41146104f257806396804ba6146104fa578063a217fddf1461050d575f80fd5b8063715018a61461045e578063735de9f71461046657806379cc6790146104795780637ecebe001461048c5780638124f7ac1461049f575f80fd5b8063378dc3dc116101f857806349df728c116101b257806349df728c146103df5780634f7041a5146103f25780635958621e146104045780635c975abb146104175780636f9fb98a1461042257806370a0823114610436575f80fd5b8063378dc3dc146103745780633b6238651461037d57806340c10f191461038657806342966c6814610399578063439766ce146103ac57806344478425146103b4575f80fd5b806323b872dd1161024957806323b872dd146102fc578063248a9ca31461030f5780632f2ff15d14610331578063313ce567146103445780633644e5151461035957806336568abe14610361575f80fd5b806301ffc9a71461028557806306fdde03146102ad578063095ea7b3146102c25780630d2cf31f146102d557806318160ddd146102ea575b5f80fd5b610298610293366004612142565b6105f7565b60405190151581526020015b60405180910390f35b6102b561062d565b6040516102a491906121ac565b6102986102d03660046121d2565b6106bd565b6102e86102e3366004612211565b6106d4565b005b6002545b6040519081526020016102a4565b61029861030a366004612251565b610745565b6102ee61031d36600461228f565b5f9081526009602052604090206001015490565b6102e861033f3660046122a6565b61083e565b60125b60405160ff90911681526020016102a4565b6102ee610868565b6102e861036f3660046122a6565b610876565b6102ee600b5481565b6102ee60105481565b6102e86103943660046121d2565b6108ae565b6102e86103a736600461228f565b6109d4565b6102986109e1565b600e546103c7906001600160a01b031681565b6040516001600160a01b0390911681526020016102a4565b6102e86103ed3660046122d4565b610a1e565b600a5461034790610100900460ff1681565b6102e86104123660046122d4565b610b6a565b600a5460ff16610298565b305f908152602081905260409020546102ee565b6102ee6104443660046122d4565b6001600160a01b03165f9081526020819052604090205490565b6102e8610bd8565b6011546103c7906001600160a01b031681565b6102e86104873660046121d2565b610beb565b6102ee61049a3660046122d4565b610c00565b600a54610347906301000000900460ff1681565b6104bb610c1d565b6040516102a497969594939291906122ef565b6005546001600160a01b03166103c7565b6102986104ed3660046122a6565b610c5f565b6102b5610c89565b6102e861050836600461228f565b610c98565b6102ee5f81565b6102986105223660046121d2565b610cc3565b610298610d23565b600f546103c7906001600160a01b031681565b600a546103479062010000900460ff1681565b6102e8610563366004612386565b610d5a565b6102ee7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102e861059d3660046122a6565b610e90565b6102ee600c5481565b6102ee6105b93660046123ef565b610eb4565b6102e86105cc3660046122d4565b610ede565b6102e86105df3660046122d4565b610f18565b600d546103c7906001600160a01b031681565b5f6001600160e01b03198216637965db0b60e01b148061062757506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606003805461063c9061241b565b80601f01602080910402602001604051908101604052809291908181526020018280546106689061241b565b80156106b35780601f1061068a576101008083540402835291602001916106b3565b820191905f5260205f20905b81548152906001019060200180831161069657829003601f168201915b5050505050905090565b5f336106ca818585610f86565b5060019392505050565b6106de5f33610c5f565b6107035760405162461bcd60e51b81526004016106fa90612453565b60405180910390fd5b600a805462ffff00191661010060ff9586160262ff000019161762010000938516939093029290921763ff000000191663010000009190931602919091179055565b5f61074e610f93565b6001600160a01b0384166107745760405162461bcd60e51b81526004016106fa90612483565b6001600160a01b03831661079a5760405162461bcd60e51b81526004016106fa90612483565b5f6107a58533610eb4565b9050828110156108085760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084016106fa565b5f83116108275760405162461bcd60e51b81526004016106fa906124ac565b610832858585610fd9565b50600195945050505050565b5f8281526009602052604090206001015461085881611248565b6108628383611252565b50505050565b5f6108716112e3565b905090565b6001600160a01b038116331461089f5760405163334bd91960e11b815260040160405180910390fd5b6108a9828261140c565b505050565b6108b6610f93565b6108e07f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610c5f565b6109255760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b4b73a32b960511b60448201526064016106fa565b6001600160a01b03821661094b5760405162461bcd60e51b81526004016106fa906124ef565b6109576012600a612613565b600c546109649190612621565b8161096e60025490565b6109789190612638565b11156109c65760405162461bcd60e51b815260206004820152601a60248201527f45524332303a206d617820737570706c7920657863656564656400000000000060448201526064016106fa565b6109d08282611477565b5050565b6109de33826114ab565b50565b5f6109ea610f93565b6109f45f33610c5f565b610a105760405162461bcd60e51b81526004016106fa90612453565b610a186114df565b50600190565b610a26610f93565b610a305f33610c5f565b610a4c5760405162461bcd60e51b81526004016106fa90612453565b6040516370a0823160e01b815230600482015281905f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610a92573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab6919061264b565b600e5460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810183905291925083169063a9059cbb906044016020604051808303815f875af1158015610b08573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2c9190612662565b6108a95760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016106fa565b610b745f33610c5f565b610b905760405162461bcd60e51b81526004016106fa90612453565b6001600160a01b038116610bb65760405162461bcd60e51b81526004016106fa906124ef565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b610be0611539565b610be95f611566565b565b610bf68233836115b7565b6109d082826114ab565b6001600160a01b0381165f90815260086020526040812054610627565b5f6060805f805f6060610c2e611614565b610c36611641565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f9182526009602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60606004805461063c9061241b565b610ca25f33610c5f565b610cbe5760405162461bcd60e51b81526004016106fa90612453565b601055565b5f610ccc610f93565b6001600160a01b038316610cf25760405162461bcd60e51b81526004016106fa90612483565b5f8211610d115760405162461bcd60e51b81526004016106fa906124ac565b610d1c338484610fd9565b9392505050565b5f610d2c61166e565b610d365f33610c5f565b610d525760405162461bcd60e51b81526004016106fa90612453565b610a186116b7565b83421115610d7e5760405163313c898160e11b8152600481018590526024016106fa565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610dc98c6001600160a01b03165f90815260086020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f610e23826116f0565b90505f610e328287878761171c565b9050896001600160a01b0316816001600160a01b031614610e79576040516325c0072360e11b81526001600160a01b0380831660048301528b1660248201526044016106fa565b610e848a8a8a610f86565b50505050505050505050565b5f82815260096020526040902060010154610eaa81611248565b610862838361140c565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b610ee6611539565b6001600160a01b038116610f0f57604051631e4fbdf760e01b81525f60048201526024016106fa565b6109de81611566565b610f225f33610c5f565b610f3e5760405162461bcd60e51b81526004016106fa90612453565b6001600160a01b038116610f645760405162461bcd60e51b81526004016106fa906124ef565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6108a98383836001611748565b600a5460ff1615610be95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106fa565b5f610fe2610f93565b6001600160a01b0384166110085760405162461bcd60e51b81526004016106fa90612483565b6001600160a01b03831661102e5760405162461bcd60e51b81526004016106fa90612483565b5f82116110995760405162461bcd60e51b815260206004820152603360248201527f416d6f756e742073686f756c642062652067726561746572207468616e207a656044820152723937903337b9103a3930b739b0b1ba34b7b71760691b60648201526084016106fa565b600a54600f545f9160ff6301000000909104169084906001600160a01b0388811691161480156110d757506011546001600160a01b03878116911614155b156110ee57600a54610100900460ff169150611127565b600f546001600160a01b039081169087160361111757600a5462010000900460ff169150611127565b600a546301000000900460ff1691505b611131858361181a565b925061113d8382612681565b90505f61114b600285612694565b90505f611159600286612694565b9050611166893083611834565b600d5461117e908a906001600160a01b031684611834565b611189898985611834565b305f90815260208190526040812054906111a56012600a612613565b6010546111b29190612621565b8211156111e0576111dd6111c86012600a612613565b6010546111d59190612621565b6103e8611891565b90505b67016345785d8a00006111f56012600a612613565b6010546112029190612621565b8311801561120f57508082115b15611236576112366112236012600a612613565b6010546112309190612621565b83611b9d565b5060019b9a5050505050505050505050565b6109de8133611d56565b5f61125d8383610c5f565b6112dc575f8381526009602090815260408083206001600160a01b03861684529091529020805460ff191660011790556112943390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610627565b505f610627565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561133b57507f000000000000000000000000000000000000000000000000000000000000000046145b1561136557507f000000000000000000000000000000000000000000000000000000000000000090565b610871604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f6114178383610c5f565b156112dc575f8381526009602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610627565b6001600160a01b0382166114a05760405163ec442f0560e01b81525f60048201526024016106fa565b6109d05f8383611d8f565b6001600160a01b0382166114d457604051634b637e8f60e11b81525f60048201526024016106fa565b6109d0825f83611d8f565b6114e7610f93565b600a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861151c3390565b6040516001600160a01b03909116815260200160405180910390a1565b6005546001600160a01b03163314610be95760405163118cdaa760e01b81523360048201526024016106fa565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f6115c28484610eb4565b90505f198114610862578181101561160657604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016106fa565b61086284848484035f611748565b60606108717f00000000000000000000000000000000000000000000000000000000000000006006611eb5565b60606108717f00000000000000000000000000000000000000000000000000000000000000006007611eb5565b600a5460ff16610be95760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106fa565b6116bf61166e565b600a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3361151c565b5f6106276116fc6112e3565b8360405161190160f01b8152600281019290925260228201526042902090565b5f805f8061172c88888888611f5e565b92509250925061173c8282612026565b50909695505050505050565b6001600160a01b0384166117715760405163e602df0560e01b81525f60048201526024016106fa565b6001600160a01b03831661179a57604051634a1406b160e11b81525f60048201526024016106fa565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561086257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161180c91815260200190565b60405180910390a350505050565b5f606461182a60ff841685612621565b610d1c9190612694565b6001600160a01b03831661185d57604051634b637e8f60e11b81525f60048201526024016106fa565b6001600160a01b0382166118865760405163ec442f0560e01b81525f60048201526024016106fa565b6108a9838383611d8f565b5f6127108211156118d85760405162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b60448201526064016106fa565b5f8060135f9054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561192a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061194e91906126c9565b50915091505f60135f9054906101000a90046001600160a01b03166001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119c89190612715565b90505f60135f9054906101000a90046001600160a01b03166001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a3f9190612715565b90505f6001600160a01b0383163003611adc57601154604051630153543560e21b8152600481018a90526001600160701b038088166024830152861660448201526001600160a01b039091169063054d50d4906064015b602060405180830381865afa158015611ab1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ad5919061264b565b9050611b6c565b6001600160a01b0382163003611b3457601154604051630153543560e21b8152600481018a90526001600160701b038087166024830152871660448201526001600160a01b039091169063054d50d490606401611a96565b60405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106fa565b5f612710611b7a8984612621565b611b849190612694565b9050611b908183612681565b9998505050505050505050565b611ba5610f93565b60115460405163095ea7b360e01b81526001600160a01b03909116600482015260248101839052309063095ea7b3906044016020604051808303815f875af1158015611bf3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c179190612662565b506040805160028082526060820183525f9260208301908036833701905050905030815f81518110611c4b57611c4b612730565b6001600160a01b03928316602091820292909201810191909152601154604080516315ab88c960e31b81529051919093169263ad5c46489260048083019391928290030181865afa158015611ca2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cc69190612715565b81600181518110611cd957611cd9612730565b6001600160a01b039283166020918202929092010152601154600e5460405163791ac94760e01b81529183169263791ac94792611d2492889288928892909116904290600401612744565b5f604051808303815f87803b158015611d3b575f80fd5b505af1158015611d4d573d5f803e3d5ffd5b50505050505050565b611d608282610c5f565b6109d05760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016106fa565b6001600160a01b038316611db9578060025f828254611dae9190612638565b90915550611e299050565b6001600160a01b0383165f9081526020819052604090205481811015611e0b5760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016106fa565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216611e4557600280548290039055611e63565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611ea891815260200190565b60405180910390a3505050565b606060ff8314611ecf57611ec8836120de565b9050610627565b818054611edb9061241b565b80601f0160208091040260200160405190810160405280929190818152602001828054611f079061241b565b8015611f525780601f10611f2957610100808354040283529160200191611f52565b820191905f5260205f20905b815481529060010190602001808311611f3557829003601f168201915b50505050509050610627565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611f9757505f9150600390508261201c565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611fe8573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661201357505f92506001915082905061201c565b92505f91508190505b9450945094915050565b5f826003811115612039576120396127b5565b03612042575050565b6001826003811115612056576120566127b5565b036120745760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115612088576120886127b5565b036120a95760405163fce698f760e01b8152600481018290526024016106fa565b60038260038111156120bd576120bd6127b5565b036109d0576040516335e2f38360e21b8152600481018290526024016106fa565b60605f6120ea8361211b565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f81111561062757604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215612152575f80fd5b81356001600160e01b031981168114610d1c575f80fd5b5f81518084525f5b8181101561218d57602081850181015186830182015201612171565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610d1c6020830184612169565b6001600160a01b03811681146109de575f80fd5b5f80604083850312156121e3575f80fd5b82356121ee816121be565b946020939093013593505050565b803560ff8116811461220c575f80fd5b919050565b5f805f60608486031215612223575f80fd5b61222c846121fc565b925061223a602085016121fc565b9150612248604085016121fc565b90509250925092565b5f805f60608486031215612263575f80fd5b833561226e816121be565b9250602084013561227e816121be565b929592945050506040919091013590565b5f6020828403121561229f575f80fd5b5035919050565b5f80604083850312156122b7575f80fd5b8235915060208301356122c9816121be565b809150509250929050565b5f602082840312156122e4575f80fd5b8135610d1c816121be565b60ff60f81b881681525f602060e0602084015261230f60e084018a612169565b8381036040850152612321818a612169565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b8181101561237457835183529284019291840191600101612358565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a03121561239c575f80fd5b87356123a7816121be565b965060208801356123b7816121be565b955060408801359450606088013593506123d3608089016121fc565b925060a0880135915060c0880135905092959891949750929550565b5f8060408385031215612400575f80fd5b823561240b816121be565b915060208301356122c9816121be565b600181811c9082168061242f57607f821691505b60208210810361244d57634e487b7160e01b5f52602260045260245ffd5b50919050565b60208082526016908201527521b0b63632b91034b9903737ba1030b71030b236b4b760511b604082015260600190565b6020808252600f908201526e496e76616c6964204164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e742073686f756c642062652067726561746572207468616e207a6560408201526239379760e91b606082015260800190565b602080825260169082015275496e76616c69642057616c6c6574204164647265737360501b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b600181815b8085111561256d57815f19048211156125535761255361251f565b8085161561256057918102915b93841c9390800290612538565b509250929050565b5f8261258357506001610627565b8161258f57505f610627565b81600181146125a557600281146125af576125cb565b6001915050610627565b60ff8411156125c0576125c061251f565b50506001821b610627565b5060208310610133831016604e8410600b84101617156125ee575081810a610627565b6125f88383612533565b805f190482111561260b5761260b61251f565b029392505050565b5f610d1c60ff841683612575565b80820281158282048414176106275761062761251f565b808201808211156106275761062761251f565b5f6020828403121561265b575f80fd5b5051919050565b5f60208284031215612672575f80fd5b81518015158114610d1c575f80fd5b818103818111156106275761062761251f565b5f826126ae57634e487b7160e01b5f52601260045260245ffd5b500490565b80516001600160701b038116811461220c575f80fd5b5f805f606084860312156126db575f80fd5b6126e4846126b3565b92506126f2602085016126b3565b9150604084015163ffffffff8116811461270a575f80fd5b809150509250925092565b5f60208284031215612725575f80fd5b8151610d1c816121be565b634e487b7160e01b5f52603260045260245ffd5b5f60a08201878352602087602085015260a0604085015281875180845260c0860191506020890193505f5b818110156127945784516001600160a01b03168352938301939183019160010161276f565b50506001600160a01b03969096166060850152505050608001529392505050565b634e487b7160e01b5f52602160045260245ffdfea26469706673582212200a20798adad5c2326881a81590ea34b6343270527e3a9e27c839dc9006843b0964736f6c63430008160033000000000000000000000000a4679cf4b3e070b0bce6314e896218ab52904ad30000000000000000000000008787e1ea6e4e49f72d6ea0f0db923fed62788690000000000000000000000000572aea54f7c75cff6098ca3413f47ffc243d99ed

Deployed Bytecode

0x608060405234801561000f575f80fd5b5060043610610281575f3560e01c8063715018a611610156578063a9059cbb116100ca578063d547741f11610084578063d547741f1461058f578063d5abeb01146105a2578063dd62ed3e146105ab578063f2fde38b146105be578063fb235f34146105d1578063fb75b2c7146105e4575f80fd5b8063a9059cbb14610514578063b33712c514610527578063c816841b1461052f578063cc1776d314610542578063d505accf14610555578063d539139314610568575f80fd5b806384b0196e1161011b57806384b0196e146104b35780638da5cb5b146104ce57806391d14854146104df57806395d89b41146104f257806396804ba6146104fa578063a217fddf1461050d575f80fd5b8063715018a61461045e578063735de9f71461046657806379cc6790146104795780637ecebe001461048c5780638124f7ac1461049f575f80fd5b8063378dc3dc116101f857806349df728c116101b257806349df728c146103df5780634f7041a5146103f25780635958621e146104045780635c975abb146104175780636f9fb98a1461042257806370a0823114610436575f80fd5b8063378dc3dc146103745780633b6238651461037d57806340c10f191461038657806342966c6814610399578063439766ce146103ac57806344478425146103b4575f80fd5b806323b872dd1161024957806323b872dd146102fc578063248a9ca31461030f5780632f2ff15d14610331578063313ce567146103445780633644e5151461035957806336568abe14610361575f80fd5b806301ffc9a71461028557806306fdde03146102ad578063095ea7b3146102c25780630d2cf31f146102d557806318160ddd146102ea575b5f80fd5b610298610293366004612142565b6105f7565b60405190151581526020015b60405180910390f35b6102b561062d565b6040516102a491906121ac565b6102986102d03660046121d2565b6106bd565b6102e86102e3366004612211565b6106d4565b005b6002545b6040519081526020016102a4565b61029861030a366004612251565b610745565b6102ee61031d36600461228f565b5f9081526009602052604090206001015490565b6102e861033f3660046122a6565b61083e565b60125b60405160ff90911681526020016102a4565b6102ee610868565b6102e861036f3660046122a6565b610876565b6102ee600b5481565b6102ee60105481565b6102e86103943660046121d2565b6108ae565b6102e86103a736600461228f565b6109d4565b6102986109e1565b600e546103c7906001600160a01b031681565b6040516001600160a01b0390911681526020016102a4565b6102e86103ed3660046122d4565b610a1e565b600a5461034790610100900460ff1681565b6102e86104123660046122d4565b610b6a565b600a5460ff16610298565b305f908152602081905260409020546102ee565b6102ee6104443660046122d4565b6001600160a01b03165f9081526020819052604090205490565b6102e8610bd8565b6011546103c7906001600160a01b031681565b6102e86104873660046121d2565b610beb565b6102ee61049a3660046122d4565b610c00565b600a54610347906301000000900460ff1681565b6104bb610c1d565b6040516102a497969594939291906122ef565b6005546001600160a01b03166103c7565b6102986104ed3660046122a6565b610c5f565b6102b5610c89565b6102e861050836600461228f565b610c98565b6102ee5f81565b6102986105223660046121d2565b610cc3565b610298610d23565b600f546103c7906001600160a01b031681565b600a546103479062010000900460ff1681565b6102e8610563366004612386565b610d5a565b6102ee7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102e861059d3660046122a6565b610e90565b6102ee600c5481565b6102ee6105b93660046123ef565b610eb4565b6102e86105cc3660046122d4565b610ede565b6102e86105df3660046122d4565b610f18565b600d546103c7906001600160a01b031681565b5f6001600160e01b03198216637965db0b60e01b148061062757506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606003805461063c9061241b565b80601f01602080910402602001604051908101604052809291908181526020018280546106689061241b565b80156106b35780601f1061068a576101008083540402835291602001916106b3565b820191905f5260205f20905b81548152906001019060200180831161069657829003601f168201915b5050505050905090565b5f336106ca818585610f86565b5060019392505050565b6106de5f33610c5f565b6107035760405162461bcd60e51b81526004016106fa90612453565b60405180910390fd5b600a805462ffff00191661010060ff9586160262ff000019161762010000938516939093029290921763ff000000191663010000009190931602919091179055565b5f61074e610f93565b6001600160a01b0384166107745760405162461bcd60e51b81526004016106fa90612483565b6001600160a01b03831661079a5760405162461bcd60e51b81526004016106fa90612483565b5f6107a58533610eb4565b9050828110156108085760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084016106fa565b5f83116108275760405162461bcd60e51b81526004016106fa906124ac565b610832858585610fd9565b50600195945050505050565b5f8281526009602052604090206001015461085881611248565b6108628383611252565b50505050565b5f6108716112e3565b905090565b6001600160a01b038116331461089f5760405163334bd91960e11b815260040160405180910390fd5b6108a9828261140c565b505050565b6108b6610f93565b6108e07f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610c5f565b6109255760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba10309036b4b73a32b960511b60448201526064016106fa565b6001600160a01b03821661094b5760405162461bcd60e51b81526004016106fa906124ef565b6109576012600a612613565b600c546109649190612621565b8161096e60025490565b6109789190612638565b11156109c65760405162461bcd60e51b815260206004820152601a60248201527f45524332303a206d617820737570706c7920657863656564656400000000000060448201526064016106fa565b6109d08282611477565b5050565b6109de33826114ab565b50565b5f6109ea610f93565b6109f45f33610c5f565b610a105760405162461bcd60e51b81526004016106fa90612453565b610a186114df565b50600190565b610a26610f93565b610a305f33610c5f565b610a4c5760405162461bcd60e51b81526004016106fa90612453565b6040516370a0823160e01b815230600482015281905f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610a92573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab6919061264b565b600e5460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810183905291925083169063a9059cbb906044016020604051808303815f875af1158015610b08573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2c9190612662565b6108a95760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016106fa565b610b745f33610c5f565b610b905760405162461bcd60e51b81526004016106fa90612453565b6001600160a01b038116610bb65760405162461bcd60e51b81526004016106fa906124ef565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b610be0611539565b610be95f611566565b565b610bf68233836115b7565b6109d082826114ab565b6001600160a01b0381165f90815260086020526040812054610627565b5f6060805f805f6060610c2e611614565b610c36611641565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f9182526009602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60606004805461063c9061241b565b610ca25f33610c5f565b610cbe5760405162461bcd60e51b81526004016106fa90612453565b601055565b5f610ccc610f93565b6001600160a01b038316610cf25760405162461bcd60e51b81526004016106fa90612483565b5f8211610d115760405162461bcd60e51b81526004016106fa906124ac565b610d1c338484610fd9565b9392505050565b5f610d2c61166e565b610d365f33610c5f565b610d525760405162461bcd60e51b81526004016106fa90612453565b610a186116b7565b83421115610d7e5760405163313c898160e11b8152600481018590526024016106fa565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610dc98c6001600160a01b03165f90815260086020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f610e23826116f0565b90505f610e328287878761171c565b9050896001600160a01b0316816001600160a01b031614610e79576040516325c0072360e11b81526001600160a01b0380831660048301528b1660248201526044016106fa565b610e848a8a8a610f86565b50505050505050505050565b5f82815260096020526040902060010154610eaa81611248565b610862838361140c565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b610ee6611539565b6001600160a01b038116610f0f57604051631e4fbdf760e01b81525f60048201526024016106fa565b6109de81611566565b610f225f33610c5f565b610f3e5760405162461bcd60e51b81526004016106fa90612453565b6001600160a01b038116610f645760405162461bcd60e51b81526004016106fa906124ef565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6108a98383836001611748565b600a5460ff1615610be95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106fa565b5f610fe2610f93565b6001600160a01b0384166110085760405162461bcd60e51b81526004016106fa90612483565b6001600160a01b03831661102e5760405162461bcd60e51b81526004016106fa90612483565b5f82116110995760405162461bcd60e51b815260206004820152603360248201527f416d6f756e742073686f756c642062652067726561746572207468616e207a656044820152723937903337b9103a3930b739b0b1ba34b7b71760691b60648201526084016106fa565b600a54600f545f9160ff6301000000909104169084906001600160a01b0388811691161480156110d757506011546001600160a01b03878116911614155b156110ee57600a54610100900460ff169150611127565b600f546001600160a01b039081169087160361111757600a5462010000900460ff169150611127565b600a546301000000900460ff1691505b611131858361181a565b925061113d8382612681565b90505f61114b600285612694565b90505f611159600286612694565b9050611166893083611834565b600d5461117e908a906001600160a01b031684611834565b611189898985611834565b305f90815260208190526040812054906111a56012600a612613565b6010546111b29190612621565b8211156111e0576111dd6111c86012600a612613565b6010546111d59190612621565b6103e8611891565b90505b67016345785d8a00006111f56012600a612613565b6010546112029190612621565b8311801561120f57508082115b15611236576112366112236012600a612613565b6010546112309190612621565b83611b9d565b5060019b9a5050505050505050505050565b6109de8133611d56565b5f61125d8383610c5f565b6112dc575f8381526009602090815260408083206001600160a01b03861684529091529020805460ff191660011790556112943390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610627565b505f610627565b5f306001600160a01b037f0000000000000000000000008a370c951f34e295b2655b47bb0985dd08d8f7181614801561133b57507f000000000000000000000000000000000000000000000000000000000000000146145b1561136557507fe4cc1470bd97352610bdb51204e47c09b329b8c2b62a55a8a7db17b689cc2ff290565b610871604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f02fa15c817decb6d4886fa91737cc6ae3a5b7b4777ed3b8eff6cbd85d4dcc5ce918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f6114178383610c5f565b156112dc575f8381526009602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610627565b6001600160a01b0382166114a05760405163ec442f0560e01b81525f60048201526024016106fa565b6109d05f8383611d8f565b6001600160a01b0382166114d457604051634b637e8f60e11b81525f60048201526024016106fa565b6109d0825f83611d8f565b6114e7610f93565b600a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861151c3390565b6040516001600160a01b03909116815260200160405180910390a1565b6005546001600160a01b03163314610be95760405163118cdaa760e01b81523360048201526024016106fa565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f6115c28484610eb4565b90505f198114610862578181101561160657604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016106fa565b61086284848484035f611748565b60606108717f486f6d6d696573000000000000000000000000000000000000000000000000076006611eb5565b60606108717f31000000000000000000000000000000000000000000000000000000000000016007611eb5565b600a5460ff16610be95760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106fa565b6116bf61166e565b600a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3361151c565b5f6106276116fc6112e3565b8360405161190160f01b8152600281019290925260228201526042902090565b5f805f8061172c88888888611f5e565b92509250925061173c8282612026565b50909695505050505050565b6001600160a01b0384166117715760405163e602df0560e01b81525f60048201526024016106fa565b6001600160a01b03831661179a57604051634a1406b160e11b81525f60048201526024016106fa565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561086257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161180c91815260200190565b60405180910390a350505050565b5f606461182a60ff841685612621565b610d1c9190612694565b6001600160a01b03831661185d57604051634b637e8f60e11b81525f60048201526024016106fa565b6001600160a01b0382166118865760405163ec442f0560e01b81525f60048201526024016106fa565b6108a9838383611d8f565b5f6127108211156118d85760405162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b60448201526064016106fa565b5f8060135f9054906101000a90046001600160a01b03166001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561192a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061194e91906126c9565b50915091505f60135f9054906101000a90046001600160a01b03166001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119c89190612715565b90505f60135f9054906101000a90046001600160a01b03166001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a3f9190612715565b90505f6001600160a01b0383163003611adc57601154604051630153543560e21b8152600481018a90526001600160701b038088166024830152861660448201526001600160a01b039091169063054d50d4906064015b602060405180830381865afa158015611ab1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ad5919061264b565b9050611b6c565b6001600160a01b0382163003611b3457601154604051630153543560e21b8152600481018a90526001600160701b038087166024830152871660448201526001600160a01b039091169063054d50d490606401611a96565b60405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106fa565b5f612710611b7a8984612621565b611b849190612694565b9050611b908183612681565b9998505050505050505050565b611ba5610f93565b60115460405163095ea7b360e01b81526001600160a01b03909116600482015260248101839052309063095ea7b3906044016020604051808303815f875af1158015611bf3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c179190612662565b506040805160028082526060820183525f9260208301908036833701905050905030815f81518110611c4b57611c4b612730565b6001600160a01b03928316602091820292909201810191909152601154604080516315ab88c960e31b81529051919093169263ad5c46489260048083019391928290030181865afa158015611ca2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cc69190612715565b81600181518110611cd957611cd9612730565b6001600160a01b039283166020918202929092010152601154600e5460405163791ac94760e01b81529183169263791ac94792611d2492889288928892909116904290600401612744565b5f604051808303815f87803b158015611d3b575f80fd5b505af1158015611d4d573d5f803e3d5ffd5b50505050505050565b611d608282610c5f565b6109d05760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016106fa565b6001600160a01b038316611db9578060025f828254611dae9190612638565b90915550611e299050565b6001600160a01b0383165f9081526020819052604090205481811015611e0b5760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016106fa565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216611e4557600280548290039055611e63565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611ea891815260200190565b60405180910390a3505050565b606060ff8314611ecf57611ec8836120de565b9050610627565b818054611edb9061241b565b80601f0160208091040260200160405190810160405280929190818152602001828054611f079061241b565b8015611f525780601f10611f2957610100808354040283529160200191611f52565b820191905f5260205f20905b815481529060010190602001808311611f3557829003601f168201915b50505050509050610627565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611f9757505f9150600390508261201c565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611fe8573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661201357505f92506001915082905061201c565b92505f91508190505b9450945094915050565b5f826003811115612039576120396127b5565b03612042575050565b6001826003811115612056576120566127b5565b036120745760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115612088576120886127b5565b036120a95760405163fce698f760e01b8152600481018290526024016106fa565b60038260038111156120bd576120bd6127b5565b036109d0576040516335e2f38360e21b8152600481018290526024016106fa565b60605f6120ea8361211b565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f81111561062757604051632cd44ac360e21b815260040160405180910390fd5b5f60208284031215612152575f80fd5b81356001600160e01b031981168114610d1c575f80fd5b5f81518084525f5b8181101561218d57602081850181015186830182015201612171565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f610d1c6020830184612169565b6001600160a01b03811681146109de575f80fd5b5f80604083850312156121e3575f80fd5b82356121ee816121be565b946020939093013593505050565b803560ff8116811461220c575f80fd5b919050565b5f805f60608486031215612223575f80fd5b61222c846121fc565b925061223a602085016121fc565b9150612248604085016121fc565b90509250925092565b5f805f60608486031215612263575f80fd5b833561226e816121be565b9250602084013561227e816121be565b929592945050506040919091013590565b5f6020828403121561229f575f80fd5b5035919050565b5f80604083850312156122b7575f80fd5b8235915060208301356122c9816121be565b809150509250929050565b5f602082840312156122e4575f80fd5b8135610d1c816121be565b60ff60f81b881681525f602060e0602084015261230f60e084018a612169565b8381036040850152612321818a612169565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b8181101561237457835183529284019291840191600101612358565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a03121561239c575f80fd5b87356123a7816121be565b965060208801356123b7816121be565b955060408801359450606088013593506123d3608089016121fc565b925060a0880135915060c0880135905092959891949750929550565b5f8060408385031215612400575f80fd5b823561240b816121be565b915060208301356122c9816121be565b600181811c9082168061242f57607f821691505b60208210810361244d57634e487b7160e01b5f52602260045260245ffd5b50919050565b60208082526016908201527521b0b63632b91034b9903737ba1030b71030b236b4b760511b604082015260600190565b6020808252600f908201526e496e76616c6964204164647265737360881b604082015260600190565b60208082526023908201527f416d6f756e742073686f756c642062652067726561746572207468616e207a6560408201526239379760e91b606082015260800190565b602080825260169082015275496e76616c69642057616c6c6574204164647265737360501b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b600181815b8085111561256d57815f19048211156125535761255361251f565b8085161561256057918102915b93841c9390800290612538565b509250929050565b5f8261258357506001610627565b8161258f57505f610627565b81600181146125a557600281146125af576125cb565b6001915050610627565b60ff8411156125c0576125c061251f565b50506001821b610627565b5060208310610133831016604e8410600b84101617156125ee575081810a610627565b6125f88383612533565b805f190482111561260b5761260b61251f565b029392505050565b5f610d1c60ff841683612575565b80820281158282048414176106275761062761251f565b808201808211156106275761062761251f565b5f6020828403121561265b575f80fd5b5051919050565b5f60208284031215612672575f80fd5b81518015158114610d1c575f80fd5b818103818111156106275761062761251f565b5f826126ae57634e487b7160e01b5f52601260045260245ffd5b500490565b80516001600160701b038116811461220c575f80fd5b5f805f606084860312156126db575f80fd5b6126e4846126b3565b92506126f2602085016126b3565b9150604084015163ffffffff8116811461270a575f80fd5b809150509250925092565b5f60208284031215612725575f80fd5b8151610d1c816121be565b634e487b7160e01b5f52603260045260245ffd5b5f60a08201878352602087602085015260a0604085015281875180845260c0860191506020890193505f5b818110156127945784516001600160a01b03168352938301939183019160010161276f565b50506001600160a01b03969096166060850152505050608001529392505050565b634e487b7160e01b5f52602160045260245ffdfea26469706673582212200a20798adad5c2326881a81590ea34b6343270527e3a9e27c839dc9006843b0964736f6c63430008160033

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

000000000000000000000000a4679cf4b3e070b0bce6314e896218ab52904ad30000000000000000000000008787e1ea6e4e49f72d6ea0f0db923fed62788690000000000000000000000000572aea54f7c75cff6098ca3413f47ffc243d99ed

-----Decoded View---------------
Arg [0] : _rewardWallet (address): 0xA4679CF4b3e070B0BcE6314e896218ab52904Ad3
Arg [1] : _revenueWallet (address): 0x8787E1EA6E4e49f72d6ea0f0db923fed62788690
Arg [2] : _minterWallet (address): 0x572aea54F7c75Cff6098CA3413F47ffC243D99ed

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000a4679cf4b3e070b0bce6314e896218ab52904ad3
Arg [1] : 0000000000000000000000008787e1ea6e4e49f72d6ea0f0db923fed62788690
Arg [2] : 000000000000000000000000572aea54f7c75cff6098ca3413f47ffc243d99ed


Deployed Bytecode Sourcemap

108855:9048:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82219:204;;;;;;:::i;:::-;;:::i;:::-;;;470:14:1;;463:22;445:41;;433:2;418:18;82219:204:0;;;;;;;;95577:91;;;:::i;:::-;;;;;;;:::i;97870:190::-;;;;;;:::i;:::-;;:::i;111830:335::-;;;;;;:::i;:::-;;:::i;:::-;;96679:99;96758:12;;96679:99;;;2240:25:1;;;2228:2;2213:18;96679:99:0;2094:177:1;112519:615:0;;;;;;:::i;:::-;;:::i;83499:122::-;;;;;;:::i;:::-;83564:7;83591:12;;;:6;:12;;;;;:22;;;;83499:122;83931:138;;;;;;:::i;:::-;;:::i;96530:84::-;96604:2;96530:84;;;3596:4:1;3584:17;;;3566:36;;3554:2;3539:18;96530:84:0;3424:184:1;107430:114:0;;;:::i;85068:251::-;;;;;;:::i;:::-;;:::i;109079:40::-;;;;;;109277:42;;;;;;110605:378;;;;;;:::i;:::-;;:::i;108146:89::-;;;;;;:::i;:::-;;:::i;117024:232::-;;;:::i;109207:28::-;;;;;-1:-1:-1;;;;;109207:28:0;;;;;;-1:-1:-1;;;;;3962:32:1;;;3944:51;;3932:2;3917:18;109207:28:0;3798:203:1;117505:395:0;;;;;;:::i;:::-;;:::i;108981:23::-;;;;;;;;;;;;110991:297;;;;;;:::i;:::-;;:::i;78728:86::-;78799:7;;;;78728:86;;115215:110;115311:4;115266:7;96933:18;;;;;;;;;;;115215:110;107430:114;96841:118;;;;;;:::i;:::-;-1:-1:-1;;;;;96933:18:0;96906:7;96933:18;;;;;;;;;;;;96841:118;89190:103;;;:::i;109399:39::-;;;;;-1:-1:-1;;;;;109399:39:0;;;108564:161;;;;;;:::i;:::-;;:::i;107172:145::-;;;;;;:::i;:::-;;:::i;109042:28::-;;;;;;;;;;;;55912:580;;;:::i;:::-;;;;;;;;;;;;;:::i;88515:87::-;88588:6;;-1:-1:-1;;;;;88588:6:0;88515:87;;82515:138;;;;;;:::i;:::-;;:::i;95787:95::-;;;:::i;111606:216::-;;;;;;:::i;:::-;;:::i;81827:49::-;;81872:4;81827:49;;112173:338;;;;;;:::i;:::-;;:::i;117264:233::-;;;:::i;109242:26::-;;;;;-1:-1:-1;;;;;109242:26:0;;;109011:24;;;;;;;;;;;;106418:695;;;;;;:::i;:::-;;:::i;109328:62::-;;109366:24;109328:62;;84362:140;;;;;;:::i;:::-;;:::i;109126:38::-;;;;;;97409:142;;;;;;:::i;:::-;;:::i;89448:220::-;;;;;;:::i;:::-;;:::i;111296:302::-;;;;;;:::i;:::-;;:::i;109173:27::-;;;;;-1:-1:-1;;;;;109173:27:0;;;82219:204;82304:4;-1:-1:-1;;;;;;82328:47:0;;-1:-1:-1;;;82328:47:0;;:87;;-1:-1:-1;;;;;;;;;;12604:40:0;;;82379:36;82321:94;82219:204;-1:-1:-1;;82219:204:0:o;95577:91::-;95622:13;95655:5;95648:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95577:91;:::o;97870:190::-;97943:4;76814:10;97999:31;76814:10;98015:7;98024:5;97999:8;:31::i;:::-;-1:-1:-1;98048:4:0;;97870:190;-1:-1:-1;;;97870:190:0:o;111830:335::-;111975:39;81872:4;112003:10;111975:7;:39::i;:::-;111953:111;;;;-1:-1:-1;;;111953:111:0;;;;;;;:::i;:::-;;;;;;;;;112075:6;:16;;-1:-1:-1;;112102:18:0;112075:16;;;;;;-1:-1:-1;;112102:18:0;;;;;;;;;;;;;;-1:-1:-1;;112131:26:0;;;;;;;;;;;;;111830:335::o;112519:615::-;112662:4;78333:19;:17;:19::i;:::-;-1:-1:-1;;;;;112687:20:0;::::1;112679:48;;;;-1:-1:-1::0;;;112679:48:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;112746:23:0;::::1;112738:51;;;;-1:-1:-1::0;;;112738:51:0::1;;;;;;;:::i;:::-;112800:24;112827:29;112837:6;112845:10;112827:9;:29::i;:::-;112800:56;;112909:6;112889:16;:26;;112867:116;;;::::0;-1:-1:-1;;;112867:116:0;;8170:2:1;112867:116:0::1;::::0;::::1;8152:21:1::0;8209:2;8189:18;;;8182:30;8248:34;8228:18;;;8221:62;-1:-1:-1;;;8299:18:1;;;8292:38;8347:19;;112867:116:0::1;7968:404:1::0;112867:116:0::1;113011:1;113002:6;:10;112994:58;;;;-1:-1:-1::0;;;112994:58:0::1;;;;;;;:::i;:::-;113063:41;113078:6;113086:9;113097:6;113063:14;:41::i;:::-;-1:-1:-1::0;113122:4:0::1;::::0;112519:615;-1:-1:-1;;;;;112519:615:0:o;83931:138::-;83564:7;83591:12;;;:6;:12;;;;;:22;;;82111:16;82122:4;82111:10;:16::i;:::-;84036:25:::1;84047:4;84053:7;84036:10;:25::i;:::-;;83931:138:::0;;;:::o;107430:114::-;107489:7;107516:20;:18;:20::i;:::-;107509:27;;107430:114;:::o;85068:251::-;-1:-1:-1;;;;;85162:34:0;;76814:10;85162:34;85158:104;;85220:30;;-1:-1:-1;;;85220:30:0;;;;;;;;;;;85158:104;85274:37;85286:4;85292:18;85274:11;:37::i;:::-;;85068:251;;:::o;110605:378::-;78333:19;:17;:19::i;:::-;110687:32:::1;109366:24;110708:10;110687:7;:32::i;:::-;110679:67;;;::::0;-1:-1:-1;;;110679:67:0;;8983:2:1;110679:67:0::1;::::0;::::1;8965:21:1::0;9022:2;9002:18;;;8995:30;-1:-1:-1;;;9041:18:1;;;9034:52;9103:18;;110679:67:0::1;8781:346:1::0;110679:67:0::1;-1:-1:-1::0;;;;;110765:16:0;::::1;110757:51;;;;-1:-1:-1::0;;;110757:51:0::1;;;;;;;:::i;:::-;110879:14;96604:2:::0;110879::::1;:14;:::i;:::-;110867:9;;:26;;;;:::i;:::-;110857:6;110841:13;96758:12:::0;;;96679:99;110841:13:::1;:22;;;;:::i;:::-;:52;;110819:128;;;::::0;-1:-1:-1;;;110819:128:0;;11497:2:1;110819:128:0::1;::::0;::::1;11479:21:1::0;11536:2;11516:18;;;11509:30;11575:28;11555:18;;;11548:56;11621:18;;110819:128:0::1;11295:350:1::0;110819:128:0::1;110958:17;110964:2;110968:6;110958:5;:17::i;:::-;110605:378:::0;;:::o;108146:89::-;108201:26;76814:10;108221:5;108201;:26::i;:::-;108146:89;:::o;117024:232::-;117079:4;78333:19;:17;:19::i;:::-;117118:39:::1;81872:4;117146:10;117118:7;:39::i;:::-;117096:111;;;;-1:-1:-1::0;;;117096:111:0::1;;;;;;;:::i;:::-;117218:8;:6;:8::i;:::-;-1:-1:-1::0;117244:4:0::1;117024:232:::0;:::o;117505:395::-;78333:19;:17;:19::i;:::-;117609:39:::1;81872:4;117637:10;117609:7;:39::i;:::-;117587:111;;;;-1:-1:-1::0;;;117587:111:0::1;;;;;;;:::i;:::-;117780:30;::::0;-1:-1:-1;;;117780:30:0;;117804:4:::1;117780:30;::::0;::::1;3944:51:1::0;117731:14:0;;117709:12:::1;::::0;-1:-1:-1;;;;;117780:15:0;::::1;::::0;::::1;::::0;3917:18:1;;117780:30:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117844:13;::::0;117829:43:::1;::::0;-1:-1:-1;;;117829:43:0;;-1:-1:-1;;;;;117844:13:0;;::::1;117829:43;::::0;::::1;12013:51:1::0;12080:18;;;12073:34;;;117757:53:0;;-1:-1:-1;117829:14:0;::::1;::::0;::::1;::::0;11986:18:1;;117829:43:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;117821:71;;;::::0;-1:-1:-1;;;117821:71:0;;12602:2:1;117821:71:0::1;::::0;::::1;12584:21:1::0;12641:2;12621:18;;;12614:30;-1:-1:-1;;;12660:18:1;;;12653:45;12715:18;;117821:71:0::1;12400:339:1::0;110991:297:0;111079:39;81872:4;111107:10;111079:7;:39::i;:::-;111057:111;;;;-1:-1:-1;;;111057:111:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;111187:27:0;;111179:62;;;;-1:-1:-1;;;111179:62:0;;;;;;;:::i;:::-;111252:12;:28;;-1:-1:-1;;;;;;111252:28:0;-1:-1:-1;;;;;111252:28:0;;;;;;;;;;110991:297::o;89190:103::-;88401:13;:11;:13::i;:::-;89255:30:::1;89282:1;89255:18;:30::i;:::-;89190:103::o:0;108564:161::-;108640:45;108656:7;76814:10;108679:5;108640:15;:45::i;:::-;108696:21;108702:7;108711:5;108696;:21::i;107172:145::-;-1:-1:-1;;;;;16714:14:0;;107263:7;16714:14;;;:7;:14;;;;;;107290:19;16627:109;55912:580;56015:13;56043:18;56076:21;56112:15;56142:25;56182:12;56209:27;56317:13;:11;:13::i;:::-;56345:16;:14;:16::i;:::-;56457;;;56440:1;56457:16;;;;;;;;;-1:-1:-1;;;56264:220:0;;;-1:-1:-1;56264:220:0;;-1:-1:-1;56376:13:0;;-1:-1:-1;56412:4:0;;-1:-1:-1;56440:1:0;-1:-1:-1;56457:16:0;-1:-1:-1;56264:220:0;-1:-1:-1;55912:580:0:o;82515:138::-;82592:4;82616:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;82616:29:0;;;;;;;;;;;;;;;82515:138::o;95787:95::-;95834:13;95867:7;95860:14;;;;;:::i;111606:216::-;111689:39;81872:4;111717:10;111689:7;:39::i;:::-;111667:111;;;;-1:-1:-1;;;111667:111:0;;;;;;;:::i;:::-;111789:16;:25;111606:216::o;112173:338::-;112298:4;78333:19;:17;:19::i;:::-;-1:-1:-1;;;;;112328:23:0;::::1;112320:51;;;;-1:-1:-1::0;;;112320:51:0::1;;;;;;;:::i;:::-;112399:1;112390:6;:10;112382:58;;;;-1:-1:-1::0;;;112382:58:0::1;;;;;;;:::i;:::-;112458:45;112473:10;112485:9;112496:6;112458:14;:45::i;:::-;112451:52:::0;112173:338;-1:-1:-1;;;112173:338:0:o;117264:233::-;117318:4;78592:16;:14;:16::i;:::-;117357:39:::1;81872:4;117385:10;117357:7;:39::i;:::-;117335:111;;;;-1:-1:-1::0;;;117335:111:0::1;;;;;;;:::i;:::-;117457:10;:8;:10::i;106418:695::-:0;106648:8;106630:15;:26;106626:99;;;106680:33;;-1:-1:-1;;;106680:33:0;;;;;2240:25:1;;;2213:18;;106680:33:0;2094:177:1;106626:99:0;106737:18;105738:95;106796:5;106803:7;106812:5;106819:16;106829:5;-1:-1:-1;;;;;17224:14:0;16917:7;17224:14;;;:7;:14;;;;;:16;;;;;;;;;16857:402;106819:16;106768:78;;;;;;13163:25:1;;;;-1:-1:-1;;;;;13262:15:1;;;13242:18;;;13235:43;13314:15;;;;13294:18;;;13287:43;13346:18;;;13339:34;13389:19;;;13382:35;13433:19;;;13426:35;;;13135:19;;106768:78:0;;;;;;;;;;;;106758:89;;;;;;106737:110;;106860:12;106875:28;106892:10;106875:16;:28::i;:::-;106860:43;;106916:14;106933:28;106947:4;106953:1;106956;106959;106933:13;:28::i;:::-;106916:45;;106986:5;-1:-1:-1;;;;;106976:15:0;:6;-1:-1:-1;;;;;106976:15:0;;106972:90;;107015:35;;-1:-1:-1;;;107015:35:0;;-1:-1:-1;;;;;13702:15:1;;;107015:35:0;;;13684:34:1;13754:15;;13734:18;;;13727:43;13619:18;;107015:35:0;13472:304:1;106972:90:0;107074:31;107083:5;107090:7;107099:5;107074:8;:31::i;:::-;106615:498;;;106418:695;;;;;;;:::o;84362:140::-;83564:7;83591:12;;;:6;:12;;;;;:22;;;82111:16;82122:4;82111:10;:16::i;:::-;84468:26:::1;84480:4;84486:7;84468:11;:26::i;97409:142::-:0;-1:-1:-1;;;;;97516:18:0;;;97489:7;97516:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;97409:142::o;89448:220::-;88401:13;:11;:13::i;:::-;-1:-1:-1;;;;;89533:22:0;::::1;89529:93;;89579:31;::::0;-1:-1:-1;;;89579:31:0;;89607:1:::1;89579:31;::::0;::::1;3944:51:1::0;3917:18;;89579:31:0::1;3798:203:1::0;89529:93:0::1;89632:28;89651:8;89632:18;:28::i;111296:302::-:0;111386:39;81872:4;111414:10;111386:7;:39::i;:::-;111364:111;;;;-1:-1:-1;;;111364:111:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;111494:28:0;;111486:63;;;;-1:-1:-1;;;111486:63:0;;;;;;;:::i;:::-;111560:13;:30;;-1:-1:-1;;;;;;111560:30:0;-1:-1:-1;;;;;111560:30:0;;;;;;;;;;111296:302::o;102697:130::-;102782:37;102791:5;102798:7;102807:5;102814:4;102782:8;:37::i;78887:108::-;78799:7;;;;78957:9;78949:38;;;;-1:-1:-1;;;78949:38:0;;13983:2:1;78949:38:0;;;13965:21:1;14022:2;14002:18;;;13995:30;-1:-1:-1;;;14041:18:1;;;14034:46;14097:18;;78949:38:0;13781:340:1;113142:1889:0;113280:4;78333:19;:17;:19::i;:::-;-1:-1:-1;;;;;113305:20:0;::::1;113297:48;;;;-1:-1:-1::0;;;113297:48:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;113364:23:0;::::1;113356:51;;;;-1:-1:-1::0;;;113356:51:0::1;;;;;;;:::i;:::-;113449:1;113440:6;:10;113418:111;;;::::0;-1:-1:-1;;;113418:111:0;;14328:2:1;113418:111:0::1;::::0;::::1;14310:21:1::0;14367:2;14347:18;;;14340:30;14406:34;14386:18;;;14379:62;-1:-1:-1;;;14457:18:1;;;14450:49;14516:19;;113418:111:0::1;14126:415:1::0;113418:111:0::1;113589:11;::::0;113669::::1;::::0;113542:16:::1;::::0;113589:11:::1;::::0;;;::::1;;::::0;113636:6;;-1:-1:-1;;;;;113659:21:0;;::::1;113669:11:::0;::::1;113659:21;:60:::0;::::1;;;-1:-1:-1::0;113705:13:0::1;::::0;-1:-1:-1;;;;;113684:35:0;;::::1;113705:13:::0;::::1;113684:35;;113659:60;113655:339;;;113777:6;::::0;::::1;::::0;::::1;;;::::0;-1:-1:-1;113655:339:0::1;;;113818:11;::::0;-1:-1:-1;;;;;113818:11:0;;::::1;113805:24:::0;;::::1;::::0;113801:193:::1;;113888:7;::::0;;;::::1;;;::::0;-1:-1:-1;113801:193:0::1;;;113971:11;::::0;;;::::1;;;::::0;-1:-1:-1;113801:193:0::1;114017:29;114030:6;114038:7;114017:12;:29::i;:::-;114006:40:::0;-1:-1:-1;114057:26:0::1;114006:40:::0;114057:26;::::1;:::i;:::-;::::0;-1:-1:-1;114094:17:0::1;114114:12;114125:1;114114:8:::0;:12:::1;:::i;:::-;114094:32:::0;-1:-1:-1;114137:18:0::1;114158:12;114169:1;114158:8:::0;:12:::1;:::i;:::-;114137:33;;114183:50;114199:6;114215:4;114222:10;114183:15;:50::i;:::-;114268:12;::::0;114244:48:::1;::::0;114260:6;;-1:-1:-1;;;;;114268:12:0::1;114282:9:::0;114244:15:::1;:48::i;:::-;114303:50;114319:6;114327:9;114338:14;114303:15;:50::i;:::-;115311:4:::0;114366:30:::1;96933:18:::0;;;;;;;;;;;;114514:14:::1;96604:2:::0;114514::::1;:14;:::i;:::-;114495:16;;:33;;;;:::i;:::-;114470:22;:58;114466:242;;;114561:106;114615:14;96604:2:::0;114615::::1;:14;:::i;:::-;114596:16;;:33;;;;:::i;:::-;114648:4;114561:16;:106::i;:::-;114545:122;;114466:242;114744:4;114832:14;96604:2:::0;114832::::1;:14;:::i;:::-;114813:16;;:33;;;;:::i;:::-;114788:22;:58;114787:110;;;;;114881:15;114865:13;:31;114787:110;114769:233;;;114924:66;114960:14;96604:2:::0;114960::::1;:14;:::i;:::-;114941:16;;:33;;;;:::i;:::-;114976:13;114924:16;:66::i;:::-;-1:-1:-1::0;115019:4:0::1;::::0;113142:1889;-1:-1:-1;;;;;;;;;;;113142:1889:0:o;82868:105::-;82935:30;82946:4;76814:10;82935;:30::i;85945:324::-;86022:4;86044:22;86052:4;86058:7;86044;:22::i;:::-;86039:223;;86083:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;86083:29:0;;;;;;;;;:36;;-1:-1:-1;;86083:36:0;86115:4;86083:36;;;86166:12;76814:10;;76734:98;86166:12;-1:-1:-1;;;;;86139:40:0;86157:7;-1:-1:-1;;;;;86139:40:0;86151:4;86139:40;;;;;;;;;;-1:-1:-1;86201:4:0;86194:11;;86039:223;-1:-1:-1;86245:5:0;86238:12;;54579:268;54632:7;54664:4;-1:-1:-1;;;;;54673:11:0;54656:28;;:63;;;;;54705:14;54688:13;:31;54656:63;54652:188;;;-1:-1:-1;54743:22:0;;54579:268::o;54652:188::-;54805:23;54947:80;;;52771:95;54947:80;;;19230:25:1;54969:11:0;19271:18:1;;;19264:34;;;;54982:14:0;19314:18:1;;;19307:34;54998:13:0;19357:18:1;;;19350:34;55021:4:0;19400:19:1;;;19393:61;54910:7:0;;19202:19:1;;54947:80:0;;;;;;;;;;;;54937:91;;;;;;54930:98;;54855:181;;86513:325;86591:4;86612:22;86620:4;86626:7;86612;:22::i;:::-;86608:223;;;86683:5;86651:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;86651:29:0;;;;;;;;;;:37;;-1:-1:-1;;86651:37:0;;;86708:40;76814:10;;86651:12;;86708:40;;86683:5;86708:40;-1:-1:-1;86770:4:0;86763:11;;101392:213;-1:-1:-1;;;;;101463:21:0;;101459:93;;101508:32;;-1:-1:-1;;;101508:32:0;;101537:1;101508:32;;;3944:51:1;3917:18;;101508:32:0;3798:203:1;101459:93:0;101562:35;101578:1;101582:7;101591:5;101562:7;:35::i;101933:211::-;-1:-1:-1;;;;;102004:21:0;;102000:91;;102049:30;;-1:-1:-1;;;102049:30:0;;102076:1;102049:30;;;3944:51:1;3917:18;;102049:30:0;3798:203:1;102000:91:0;102101:35;102109:7;102126:1;102130:5;102101:7;:35::i;79324:118::-;78333:19;:17;:19::i;:::-;79384:7:::1;:14:::0;;-1:-1:-1;;79384:14:0::1;79394:4;79384:14;::::0;;79414:20:::1;79421:12;76814:10:::0;;76734:98;79421:12:::1;79414:20;::::0;-1:-1:-1;;;;;3962:32:1;;;3944:51;;3932:2;3917:18;79414:20:0::1;;;;;;;79324:118::o:0;88680:166::-;88588:6;;-1:-1:-1;;;;;88588:6:0;76814:10;88740:23;88736:103;;88787:40;;-1:-1:-1;;;88787:40:0;;76814:10;88787:40;;;3944:51:1;3917:18;;88787:40:0;3798:203:1;89828:191:0;89921:6;;;-1:-1:-1;;;;;89938:17:0;;;-1:-1:-1;;;;;;89938:17:0;;;;;;;89971:40;;89921:6;;;89938:17;89921:6;;89971:40;;89902:16;;89971:40;89891:128;89828:191;:::o;104413:487::-;104513:24;104540:25;104550:5;104557:7;104540:9;:25::i;:::-;104513:52;;-1:-1:-1;;104580:16:0;:37;104576:317;;104657:5;104638:16;:24;104634:132;;;104690:60;;-1:-1:-1;;;104690:60:0;;-1:-1:-1;;;;;15121:32:1;;104690:60:0;;;15103:51:1;15170:18;;;15163:34;;;15213:18;;;15206:34;;;15076:18;;104690:60:0;14901:345:1;104634:132:0;104809:57;104818:5;104825:7;104853:5;104834:16;:24;104860:5;104809:8;:57::i;56821:128::-;56867:13;56900:41;:5;56927:13;56900:26;:41::i;57284:137::-;57333:13;57366:47;:8;57396:16;57366:29;:47::i;79072:108::-;78799:7;;;;79131:41;;;;-1:-1:-1;;;79131:41:0;;15453:2:1;79131:41:0;;;15435:21:1;15492:2;15472:18;;;15465:30;-1:-1:-1;;;15511:18:1;;;15504:50;15571:18;;79131:41:0;15251:344:1;79583:120:0;78592:16;:14;:16::i;:::-;79642:7:::1;:15:::0;;-1:-1:-1;;79642:15:0::1;::::0;;79673:22:::1;76814:10:::0;79682:12:::1;76734:98:::0;55678:178;55755:7;55782:66;55815:20;:18;:20::i;:::-;55837:10;50583:4;50577:11;-1:-1:-1;;;50602:23:0;;50655:4;50646:14;;50639:39;;;;50708:4;50699:14;;50692:34;50765:4;50750:20;;;50378:410;64418:264;64503:7;64524:17;64543:18;64563:16;64583:25;64594:4;64600:1;64603;64606;64583:10;:25::i;:::-;64523:85;;;;;;64619:28;64631:5;64638:8;64619:11;:28::i;:::-;-1:-1:-1;64665:9:0;;64418:264;-1:-1:-1;;;;;;64418:264:0:o;103678:443::-;-1:-1:-1;;;;;103791:19:0;;103787:91;;103834:32;;-1:-1:-1;;;103834:32:0;;103863:1;103834:32;;;3944:51:1;3917:18;;103834:32:0;3798:203:1;103787:91:0;-1:-1:-1;;;;;103892:21:0;;103888:92;;103937:31;;-1:-1:-1;;;103937:31:0;;103965:1;103937:31;;;3944:51:1;3917:18;;103937:31:0;3798:203:1;103888:92:0;-1:-1:-1;;;;;103990:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;104036:78;;;;104087:7;-1:-1:-1;;;;;104071:31:0;104080:5;-1:-1:-1;;;;;104071:31:0;;104096:5;104071:31;;;;2240:25:1;;2228:2;2213:18;;2094:177;104071:31:0;;;;;;;;103678:443;;;;:::o;115039:168::-;115142:7;115196:3;115175:17;;;;:6;:17;:::i;:::-;115174:25;;;;:::i;99272:308::-;-1:-1:-1;;;;;99356:18:0;;99352:88;;99398:30;;-1:-1:-1;;;99398:30:0;;99425:1;99398:30;;;3944:51:1;3917:18;;99398:30:0;3798:203:1;99352:88:0;-1:-1:-1;;;;;99454:16:0;;99450:88;;99494:32;;-1:-1:-1;;;99494:32:0;;99523:1;99494:32;;;3944:51:1;3917:18;;99494:32:0;3798:203:1;99450:88:0;99548:24;99556:4;99562:2;99566:5;99548:7;:24::i;115919:1097::-;116030:20;116088:5;116076:8;:17;;116068:47;;;;-1:-1:-1;;;116068:47:0;;15802:2:1;116068:47:0;;;15784:21:1;15841:2;15821:18;;;15814:30;-1:-1:-1;;;15860:18:1;;;15853:47;15917:18;;116068:47:0;15600:341:1;116068:47:0;116166:16;116184;116206:13;;;;;;;;;-1:-1:-1;;;;;116206:13:0;-1:-1:-1;;;;;116206:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116165:68;;;;;116244:14;116261:13;;;;;;;;;-1:-1:-1;;;;;116261:13:0;-1:-1:-1;;;;;116261:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116244:39;;116294:14;116311:13;;;;;;;;;-1:-1:-1;;;;;116311:13:0;-1:-1:-1;;;;;116311:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116294:39;-1:-1:-1;116346:20:0;-1:-1:-1;;;;;116381:23:0;;116389:4;116381:23;116377:508;;116496:13;;:122;;-1:-1:-1;;;116496:122:0;;;;;17052:25:1;;;-1:-1:-1;;;;;17162:15:1;;;17142:18;;;17135:43;17214:15;;17194:18;;;17187:43;-1:-1:-1;;;;;116496:13:0;;;;:26;;17025:18:1;;116496:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116481:137;;116377:508;;;-1:-1:-1;;;;;116640:23:0;;116648:4;116640:23;116636:249;;116695:13;;:122;;-1:-1:-1;;;116695:122:0;;;;;17052:25:1;;;-1:-1:-1;;;;;17162:15:1;;;17142:18;;;17135:43;17214:15;;17194:18;;;17187:43;-1:-1:-1;;;;;116695:13:0;;;;:26;;17025:18:1;;116695:122:0;16850:386:1;116636:249:0;116850:23;;-1:-1:-1;;;116850:23:0;;17443:2:1;116850:23:0;;;17425:21:1;17482:2;17462:18;;;17455:30;-1:-1:-1;;;17501:18:1;;;17494:43;17554:18;;116850:23:0;17241:337:1;116636:249:0;116895:22;116948:5;116921:23;116936:8;116921:12;:23;:::i;:::-;116920:33;;;;:::i;:::-;116895:58;-1:-1:-1;116979:29:0;116895:58;116979:12;:29;:::i;:::-;116964:44;115919:1097;-1:-1:-1;;;;;;;;;115919:1097:0:o;115333:578::-;78333:19;:17;:19::i;:::-;115499:13:::1;::::0;115461:67:::1;::::0;-1:-1:-1;;;115461:67:0;;-1:-1:-1;;;;;115499:13:0;;::::1;115461:67;::::0;::::1;12013:51:1::0;12080:18;;;12073:34;;;115476:4:0::1;::::0;115461:29:::1;::::0;11986:18:1;;115461:67:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;115565:16:0::1;::::0;;115579:1:::1;115565:16:::0;;;;;::::1;::::0;;115541:21:::1;::::0;115565:16:::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;115565:16:0::1;115541:40;;115610:4;115592;115597:1;115592:7;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;115592:23:0;;::::1;:7;::::0;;::::1;::::0;;;;;;:23;;;;115636:13:::1;::::0;:20:::1;::::0;;-1:-1:-1;;;115636:20:0;;;;:13;;;::::1;::::0;:18:::1;::::0;:20:::1;::::0;;::::1;::::0;115592:7;;115636:20;;;;;:13;:20:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115626:4;115631:1;115626:7;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;115626:30:0;;::::1;:7;::::0;;::::1;::::0;;;;;:30;115695:13:::1;::::0;115849::::1;::::0;115695:208:::1;::::0;-1:-1:-1;;;115695:208:0;;:13;;::::1;::::0;:64:::1;::::0;:208:::1;::::0;115774:12;;115801:14;;115830:4;;115849:13;;::::1;::::0;115877:15:::1;::::0;115695:208:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;115450:461;115333:578:::0;;:::o;83109:201::-;83198:22;83206:4;83212:7;83198;:22::i;:::-;83193:110;;83244:47;;-1:-1:-1;;;83244:47:0;;-1:-1:-1;;;;;12031:32:1;;83244:47:0;;;12013:51:1;12080:18;;;12073:34;;;11986:18;;83244:47:0;11839:274:1;99904:1135:0;-1:-1:-1;;;;;99994:18:0;;99990:552;;100148:5;100132:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;99990:552:0;;-1:-1:-1;99990:552:0;;-1:-1:-1;;;;;100208:15:0;;100186:19;100208:15;;;;;;;;;;;100242:19;;;100238:117;;;100289:50;;-1:-1:-1;;;100289:50:0;;-1:-1:-1;;;;;15121:32:1;;100289:50:0;;;15103:51:1;15170:18;;;15163:34;;;15213:18;;;15206:34;;;15076:18;;100289:50:0;14901:345:1;100238:117:0;-1:-1:-1;;;;;100478:15:0;;:9;:15;;;;;;;;;;100496:19;;;;100478:37;;99990:552;-1:-1:-1;;;;;100558:16:0;;100554:435;;100724:12;:21;;;;;;;100554:435;;;-1:-1:-1;;;;;100940:13:0;;:9;:13;;;;;;;;;;:22;;;;;;100554:435;101021:2;-1:-1:-1;;;;;101006:25:0;101015:4;-1:-1:-1;;;;;101006:25:0;;101025:5;101006:25;;;;2240::1;;2228:2;2213:18;;2094:177;101006:25:0;;;;;;;;99904:1135;;;:::o;25967:273::-;26061:13;23913:66;26091:46;;26087:146;;26161:15;26170:5;26161:8;:15::i;:::-;26154:22;;;;26087:146;26216:5;26209:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62723:1556;62854:7;;;63797:66;63784:79;;63780:166;;;-1:-1:-1;63896:1:0;;-1:-1:-1;63900:30:0;;-1:-1:-1;63932:1:0;63880:54;;63780:166;64060:24;;;64043:14;64060:24;;;;;;;;;19692:25:1;;;19765:4;19753:17;;19733:18;;;19726:45;;;;19787:18;;;19780:34;;;19830:18;;;19823:34;;;64060:24:0;;19664:19:1;;64060:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;64060:24:0;;-1:-1:-1;;64060:24:0;;;-1:-1:-1;;;;;;;64099:20:0;;64095:115;;-1:-1:-1;64152:1:0;;-1:-1:-1;64156:29:0;;-1:-1:-1;64152:1:0;;-1:-1:-1;64136:62:0;;64095:115;64230:6;-1:-1:-1;64238:20:0;;-1:-1:-1;64238:20:0;;-1:-1:-1;62723:1556:0;;;;;;;;;:::o;64820:542::-;64916:20;64907:5;:29;;;;;;;;:::i;:::-;;64903:452;;64820:542;;:::o;64903:452::-;65014:29;65005:5;:38;;;;;;;;:::i;:::-;;65001:354;;65067:23;;-1:-1:-1;;;65067:23:0;;;;;;;;;;;65001:354;65121:35;65112:5;:44;;;;;;;;:::i;:::-;;65108:247;;65180:46;;-1:-1:-1;;;65180:46:0;;;;;2240:25:1;;;2213:18;;65180:46:0;2094:177:1;65108:247:0;65257:30;65248:5;:39;;;;;;;;:::i;:::-;;65244:111;;65311:32;;-1:-1:-1;;;65311:32:0;;;;;2240:25:1;;;2213:18;;65311:32:0;2094:177:1;24622:415:0;24681:13;24707:11;24721:16;24732:4;24721:10;:16::i;:::-;24847:14;;;24858:2;24847:14;;;;;;;;;24707:30;;-1:-1:-1;24827:17:0;;24847:14;;;;;;;;;-1:-1:-1;;;24940:16:0;;;-1:-1:-1;24986:4:0;24977:14;;24970:28;;;;-1:-1:-1;24940:16:0;24622:415::o;25114:251::-;25175:7;25248:4;25212:40;;25276:2;25267:11;;25263:71;;;25302:20;;-1:-1:-1;;;25302:20:0;;;;;;;;;;;14:286:1;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:1;;209:43;;199:71;;266:1;263;256:12;497:423;539:3;577:5;571:12;604:6;599:3;592:19;629:1;639:162;653:6;650:1;647:13;639:162;;;715:4;771:13;;;767:22;;761:29;743:11;;;739:20;;732:59;668:12;639:162;;;643:3;846:1;839:4;830:6;825:3;821:16;817:27;810:38;909:4;902:2;898:7;893:2;885:6;881:15;877:29;872:3;868:39;864:50;857:57;;;497:423;;;;:::o;925:220::-;1074:2;1063:9;1056:21;1037:4;1094:45;1135:2;1124:9;1120:18;1112:6;1094:45;:::i;1150:131::-;-1:-1:-1;;;;;1225:31:1;;1215:42;;1205:70;;1271:1;1268;1261:12;1286:315;1354:6;1362;1415:2;1403:9;1394:7;1390:23;1386:32;1383:52;;;1431:1;1428;1421:12;1383:52;1470:9;1457:23;1489:31;1514:5;1489:31;:::i;:::-;1539:5;1591:2;1576:18;;;;1563:32;;-1:-1:-1;;;1286:315:1:o;1606:156::-;1672:20;;1732:4;1721:16;;1711:27;;1701:55;;1752:1;1749;1742:12;1701:55;1606:156;;;:::o;1767:322::-;1838:6;1846;1854;1907:2;1895:9;1886:7;1882:23;1878:32;1875:52;;;1923:1;1920;1913:12;1875:52;1946:27;1963:9;1946:27;:::i;:::-;1936:37;;1992:36;2024:2;2013:9;2009:18;1992:36;:::i;:::-;1982:46;;2047:36;2079:2;2068:9;2064:18;2047:36;:::i;:::-;2037:46;;1767:322;;;;;:::o;2276:456::-;2353:6;2361;2369;2422:2;2410:9;2401:7;2397:23;2393:32;2390:52;;;2438:1;2435;2428:12;2390:52;2477:9;2464:23;2496:31;2521:5;2496:31;:::i;:::-;2546:5;-1:-1:-1;2603:2:1;2588:18;;2575:32;2616:33;2575:32;2616:33;:::i;:::-;2276:456;;2668:7;;-1:-1:-1;;;2722:2:1;2707:18;;;;2694:32;;2276:456::o;2737:180::-;2796:6;2849:2;2837:9;2828:7;2824:23;2820:32;2817:52;;;2865:1;2862;2855:12;2817:52;-1:-1:-1;2888:23:1;;2737:180;-1:-1:-1;2737:180:1:o;3104:315::-;3172:6;3180;3233:2;3221:9;3212:7;3208:23;3204:32;3201:52;;;3249:1;3246;3239:12;3201:52;3285:9;3272:23;3262:33;;3345:2;3334:9;3330:18;3317:32;3358:31;3383:5;3358:31;:::i;:::-;3408:5;3398:15;;;3104:315;;;;;:::o;4006:247::-;4065:6;4118:2;4106:9;4097:7;4093:23;4089:32;4086:52;;;4134:1;4131;4124:12;4086:52;4173:9;4160:23;4192:31;4217:5;4192:31;:::i;4492:1259::-;4898:3;4893;4889:13;4881:6;4877:26;4866:9;4859:45;4840:4;4923:2;4961:3;4956:2;4945:9;4941:18;4934:31;4988:46;5029:3;5018:9;5014:19;5006:6;4988:46;:::i;:::-;5082:9;5074:6;5070:22;5065:2;5054:9;5050:18;5043:50;5116:33;5142:6;5134;5116:33;:::i;:::-;5180:2;5165:18;;5158:34;;;-1:-1:-1;;;;;5229:32:1;;5223:3;5208:19;;5201:61;5249:3;5278:19;;5271:35;;;5343:22;;;5337:3;5322:19;;5315:51;5415:13;;5437:22;;;5487:2;5513:15;;;;-1:-1:-1;5475:15:1;;;;-1:-1:-1;5556:169:1;5570:6;5567:1;5564:13;5556:169;;;5631:13;;5619:26;;5700:15;;;;5665:12;;;;5592:1;5585:9;5556:169;;;-1:-1:-1;5742:3:1;;4492:1259;-1:-1:-1;;;;;;;;;;;;4492:1259:1:o;5756:734::-;5867:6;5875;5883;5891;5899;5907;5915;5968:3;5956:9;5947:7;5943:23;5939:33;5936:53;;;5985:1;5982;5975:12;5936:53;6024:9;6011:23;6043:31;6068:5;6043:31;:::i;:::-;6093:5;-1:-1:-1;6150:2:1;6135:18;;6122:32;6163:33;6122:32;6163:33;:::i;:::-;6215:7;-1:-1:-1;6269:2:1;6254:18;;6241:32;;-1:-1:-1;6320:2:1;6305:18;;6292:32;;-1:-1:-1;6343:37:1;6375:3;6360:19;;6343:37;:::i;:::-;6333:47;;6427:3;6416:9;6412:19;6399:33;6389:43;;6479:3;6468:9;6464:19;6451:33;6441:43;;5756:734;;;;;;;;;;:::o;6495:388::-;6563:6;6571;6624:2;6612:9;6603:7;6599:23;6595:32;6592:52;;;6640:1;6637;6630:12;6592:52;6679:9;6666:23;6698:31;6723:5;6698:31;:::i;:::-;6748:5;-1:-1:-1;6805:2:1;6790:18;;6777:32;6818:33;6777:32;6818:33;:::i;6888:380::-;6967:1;6963:12;;;;7010;;;7031:61;;7085:4;7077:6;7073:17;7063:27;;7031:61;7138:2;7130:6;7127:14;7107:18;7104:38;7101:161;;7184:10;7179:3;7175:20;7172:1;7165:31;7219:4;7216:1;7209:15;7247:4;7244:1;7237:15;7101:161;;6888:380;;;:::o;7273:346::-;7475:2;7457:21;;;7514:2;7494:18;;;7487:30;-1:-1:-1;;;7548:2:1;7533:18;;7526:52;7610:2;7595:18;;7273:346::o;7624:339::-;7826:2;7808:21;;;7865:2;7845:18;;;7838:30;-1:-1:-1;;;7899:2:1;7884:18;;7877:45;7954:2;7939:18;;7624:339::o;8377:399::-;8579:2;8561:21;;;8618:2;8598:18;;;8591:30;8657:34;8652:2;8637:18;;8630:62;-1:-1:-1;;;8723:2:1;8708:18;;8701:33;8766:3;8751:19;;8377:399::o;9132:346::-;9334:2;9316:21;;;9373:2;9353:18;;;9346:30;-1:-1:-1;;;9407:2:1;9392:18;;9385:52;9469:2;9454:18;;9132:346::o;9483:127::-;9544:10;9539:3;9535:20;9532:1;9525:31;9575:4;9572:1;9565:15;9599:4;9596:1;9589:15;9615:416;9704:1;9741:5;9704:1;9755:270;9776:7;9766:8;9763:21;9755:270;;;9835:4;9831:1;9827:6;9823:17;9817:4;9814:27;9811:53;;;9844:18;;:::i;:::-;9894:7;9884:8;9880:22;9877:55;;;9914:16;;;;9877:55;9993:22;;;;9953:15;;;;9755:270;;;9759:3;9615:416;;;;;:::o;10036:806::-;10085:5;10115:8;10105:80;;-1:-1:-1;10156:1:1;10170:5;;10105:80;10204:4;10194:76;;-1:-1:-1;10241:1:1;10255:5;;10194:76;10286:4;10304:1;10299:59;;;;10372:1;10367:130;;;;10279:218;;10299:59;10329:1;10320:10;;10343:5;;;10367:130;10404:3;10394:8;10391:17;10388:43;;;10411:18;;:::i;:::-;-1:-1:-1;;10467:1:1;10453:16;;10482:5;;10279:218;;10581:2;10571:8;10568:16;10562:3;10556:4;10553:13;10549:36;10543:2;10533:8;10530:16;10525:2;10519:4;10516:12;10512:35;10509:77;10506:159;;;-1:-1:-1;10618:19:1;;;10650:5;;10506:159;10697:34;10722:8;10716:4;10697:34;:::i;:::-;10767:6;10763:1;10759:6;10755:19;10746:7;10743:32;10740:58;;;10778:18;;:::i;:::-;10816:20;;10036:806;-1:-1:-1;;;10036:806:1:o;10847:140::-;10905:5;10934:47;10975:4;10965:8;10961:19;10955:4;10934:47;:::i;10992:168::-;11065:9;;;11096;;11113:15;;;11107:22;;11093:37;11083:71;;11134:18;;:::i;11165:125::-;11230:9;;;11251:10;;;11248:36;;;11264:18;;:::i;11650:184::-;11720:6;11773:2;11761:9;11752:7;11748:23;11744:32;11741:52;;;11789:1;11786;11779:12;11741:52;-1:-1:-1;11812:16:1;;11650:184;-1:-1:-1;11650:184:1:o;12118:277::-;12185:6;12238:2;12226:9;12217:7;12213:23;12209:32;12206:52;;;12254:1;12251;12244:12;12206:52;12286:9;12280:16;12339:5;12332:13;12325:21;12318:5;12315:32;12305:60;;12361:1;12358;12351:12;14546:128;14613:9;;;14634:11;;;14631:37;;;14648:18;;:::i;14679:217::-;14719:1;14745;14735:132;;14789:10;14784:3;14780:20;14777:1;14770:31;14824:4;14821:1;14814:15;14852:4;14849:1;14842:15;14735:132;-1:-1:-1;14881:9:1;;14679:217::o;15946:188::-;16025:13;;-1:-1:-1;;;;;16067:42:1;;16057:53;;16047:81;;16124:1;16121;16114:12;16139:450;16226:6;16234;16242;16295:2;16283:9;16274:7;16270:23;16266:32;16263:52;;;16311:1;16308;16301:12;16263:52;16334:40;16364:9;16334:40;:::i;:::-;16324:50;;16393:49;16438:2;16427:9;16423:18;16393:49;:::i;:::-;16383:59;;16485:2;16474:9;16470:18;16464:25;16529:10;16522:5;16518:22;16511:5;16508:33;16498:61;;16555:1;16552;16545:12;16498:61;16578:5;16568:15;;;16139:450;;;;;:::o;16594:251::-;16664:6;16717:2;16705:9;16696:7;16692:23;16688:32;16685:52;;;16733:1;16730;16723:12;16685:52;16765:9;16759:16;16784:31;16809:5;16784:31;:::i;17583:127::-;17644:10;17639:3;17635:20;17632:1;17625:31;17675:4;17672:1;17665:15;17699:4;17696:1;17689:15;17715:972;17969:4;18017:3;18006:9;18002:19;18048:6;18037:9;18030:25;18074:2;18112:6;18107:2;18096:9;18092:18;18085:34;18155:3;18150:2;18139:9;18135:18;18128:31;18179:6;18214;18208:13;18245:6;18237;18230:22;18283:3;18272:9;18268:19;18261:26;;18322:2;18314:6;18310:15;18296:29;;18343:1;18353:195;18367:6;18364:1;18361:13;18353:195;;;18432:13;;-1:-1:-1;;;;;18428:39:1;18416:52;;18523:15;;;;18488:12;;;;18464:1;18382:9;18353:195;;;-1:-1:-1;;;;;;;18604:32:1;;;;18599:2;18584:18;;18577:60;-1:-1:-1;;;18668:3:1;18653:19;18646:35;18565:3;17715:972;-1:-1:-1;;;17715:972:1:o;19868:127::-;19929:10;19924:3;19920:20;19917:1;19910:31;19960:4;19957:1;19950:15;19984:4;19981:1;19974:15

Swarm Source

ipfs://0a20798adad5c2326881a81590ea34b6343270527e3a9e27c839dc9006843b09
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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