ERC-20
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 HOMMIESValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Hommies
Compiler Version
v0.8.22+commit.4fc1097e
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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.