ERC-20
Overview
Max Total Supply
10,000,000,000 INSP
Holders
258
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
7,448,000 INSPValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
INSPAD
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-12-05 */ // SPDX-License-Identifier: MIT // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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.1.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; /** * @dev Interface for the optional metadata functions from the ERC-20 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/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/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 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 ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-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 ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 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/token/ERC20/ERC20.sol // OpenZeppelin Contracts (last updated v5.1.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 ERC-20 * applications. */ 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}. * * Skips emitting an {Approval} event indicating an allowance update. This is not * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. * * 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: * * ```solidity * 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/IERC20Permit.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. * * Adds the {permit} method, which can be used to change an account's ERC-20 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/utils/cryptography/ECDSA.sol // OpenZeppelin Contracts (last updated v5.1.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 recovered, RecoverError err, bytes32 errArg) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly ("memory-safe") { 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[ERC-2098 short signatures] */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { 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 recovered, RecoverError err, bytes32 errArg) { // 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/utils/Panic.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } } // File: @openzeppelin/contracts/utils/math/SafeCast.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { 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 success flag (no overflow). */ function tryAdd( uint256 a, uint256 b ) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub( uint256 a, uint256 b ) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul( uint256 a, uint256 b ) internal pure returns (bool success, uint256 result) { 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 success flag (no division by zero). */ function tryDiv( uint256 a, uint256 b ) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod( uint256 a, uint256 b ) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary( bool condition, uint256 a, uint256 b ) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(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. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * 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²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + 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²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic( ternary( denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW ) ); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. 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²⁵⁶ / 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²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. 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⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // 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²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, 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; } } /** * @dev 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) { return mulDiv(x, y, denominator) + SafeCast.toUint( unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0 ); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp( uint256 b, uint256 e, uint256 m ) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp( uint256 b, uint256 e, uint256 m ) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall( gas(), 0x05, dataPtr, mload(result), dataPtr, mLen ) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev 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 + SafeCast.toUint( unsignedRoundsUp(rounding) && result * result < a ); } } /** * @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; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 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 + SafeCast.toUint( unsignedRoundsUp(rounding) && 1 << result < value ); } } /** * @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 + SafeCast.toUint( unsignedRoundsUp(rounding) && 10 ** result < value ); } } /** * @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; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 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 + SafeCast.toUint( unsignedRoundsUp(rounding) && 1 << (result << 3) < value ); } } /** * @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/math/SignedMath.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary( bool condition, int256 a, int256 b ) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(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 { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v5.1.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; assembly ("memory-safe") { ptr := add(buffer, add(32, length)) } while (true) { ptr--; assembly ("memory-safe") { 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 Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal * representation, according to EIP-55. */ function toChecksumHexString( address addr ) internal pure returns (string memory) { bytes memory buffer = bytes(toHexString(addr)); // hash the hex part of buffer (skip length + 2 bytes, length 40) uint256 hashValue; assembly ("memory-safe") { hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) } for (uint256 i = 41; i > 1; --i) { // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { // case shift by xoring with 0x20 buffer[i] ^= 0x20; } hashValue >>= 4; } return string(buffer); } /** * @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.1.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[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an ERC-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) { assembly ("memory-safe") { 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 ERC-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 ERC-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 (ERC-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) { assembly ("memory-safe") { 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/StorageSlot.sol // OpenZeppelin Contracts (last updated v5.1.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 ERC-1967 implementation slot: * ```solidity * contract ERC1967 { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. * 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; * } * } * ``` * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct Int256Slot { int256 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) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot( bytes32 slot ) internal pure returns (BooleanSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot( bytes32 slot ) internal pure returns (Bytes32Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot( bytes32 slot ) internal pure returns (Uint256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Int256Slot` with member `value` located at `slot`. */ function getInt256Slot( bytes32 slot ) internal pure returns (Int256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `StringSlot` with member `value` located at `slot`. */ function getStringSlot( bytes32 slot ) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { 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) { assembly ("memory-safe") { r.slot := store.slot } } /** * @dev Returns a `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot( bytes32 slot ) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { 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) { assembly ("memory-safe") { r.slot := store.slot } } } // File: @openzeppelin/contracts/utils/ShortStrings.sol // OpenZeppelin Contracts (last updated v5.1.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); assembly ("memory-safe") { 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/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/cryptography/EIP712.sol // OpenZeppelin Contracts (last updated v5.1.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/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/token/ERC20/extensions/ERC20Permit.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612]. * * Adds the {permit} method, which can be used to change an account's ERC-20 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 ERC-20 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/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/interfaces/IERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * 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[ERC 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/interfaces/IERC165.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; // File: @openzeppelin/contracts/interfaces/IERC1363.sol // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall( address from, address to, uint256 value ) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall( address from, address to, uint256 value, bytes calldata data ) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall( address spender, uint256 value ) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall( address spender, uint256 value, bytes calldata data ) external returns (bool); } // File: @openzeppelin/contracts/utils/Errors.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); } // File: @openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall( address target, bytes memory data ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}( data ); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall( address target, bytes memory data ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall( address target, bytes memory data ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult( bool success, bytes memory returndata ) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } } // File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance( address spender, uint256 currentAllowance, uint256 requestedDecrease ); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeCall(token.transferFrom, (from, to, value)) ); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance( IERC20 token, address spender, uint256 requestedDecrease ) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance( spender, currentAllowance, requestedDecrease ); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove( IERC20 token, address spender, uint256 value ) internal { bytes memory approvalCall = abi.encodeCall( token.approve, (spender, value) ); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn( token, abi.encodeCall(token.approve, (spender, 0)) ); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed( IERC1363 token, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed( IERC1363 token, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call( gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20 ) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if ( returnSize == 0 ? address(token).code.length == 0 : returnValue != 1 ) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool( IERC20 token, bytes memory data ) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call( gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20 ) returnSize := returndatasize() returnValue := mload(0) } return success && ( returnSize == 0 ? address(token).code.length > 0 : returnValue == 1 ); } } // 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: @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: INSPAD.sol // Compatible with OpenZeppelin Contracts ^5.0.0 pragma solidity 0.8.28; contract INSPAD is ERC20, ERC20Permit, Ownable { using SafeERC20 for IERC20; uint256 public marketingTaxBuy; uint256 public marketingTaxSell; uint256 public marketingTaxTransfer; uint256 public immutable denominator; address public marketingWallet; bool private swapping; uint256 public swapTokensAtAmount; bool public isSwapBackEnabled; IUniswapV2Router02 public immutable uniswapV2Router; address public immutable uniswapV2Pair; mapping(address => bool) private _isExcludedFromFees; mapping(address => bool) private _isAutomatedMarketMakerPair; modifier inSwap() { swapping = true; _; swapping = false; } event UpdateBuyTax(uint256 marketingTaxBuy); event UpdateSellTax(uint256 marketingTaxSell); event UpdateTransferTax(uint256 marketingTaxTransfer); event UpdateMarketingWallet(address indexed marketingWallet); event UpdateSwapTokensAtAmount(uint256 swapTokensAtAmount); event UpdateSwapBackStatus(bool status); event UpdateExcludeFromFees(address indexed account, bool isExcluded); event UpdateAutomatedMarketMakerPair(address indexed pair, bool status); constructor() ERC20("INSPAD", "INSP") ERC20Permit("INSPAD") Ownable(getOwnerAddress()) { _mint(owner(), 10_000_000_000 * (10 ** uint256(decimals()))); marketingTaxBuy = 200; marketingTaxSell = 200; marketingTaxTransfer = 200; denominator = 10_000; marketingWallet = getMarketingAddress(); swapTokensAtAmount = (totalSupply() * 1) / 10_000; isSwapBackEnabled = true; uniswapV2Router = IUniswapV2Router02(getRouterAddress()); uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair( address(this), uniswapV2Router.WETH() ); _approve(address(this), address(uniswapV2Router), type(uint256).max); address DEAD = address(0xdead); address ZERO = address(0x0); _isExcludedFromFees[address(owner())] = true; _isExcludedFromFees[address(this)] = true; _isExcludedFromFees[address(uniswapV2Router)] = true; _isExcludedFromFees[address(DEAD)] = true; _isExcludedFromFees[address(ZERO)] = true; _isAutomatedMarketMakerPair[address(uniswapV2Pair)] = true; } receive() external payable {} fallback() external payable {} function isContract(address account) internal view returns (bool) { return account.code.length > 0; } function getOwnerAddress() internal view returns (address) { if (block.chainid == 56 || block.chainid == 1) { return 0xc91A5F4fB6Ff46b047a3E713254CDCb5d748C4f9; } return address(_msgSender()); } function getMarketingAddress() internal view returns (address) { if (block.chainid == 56 || block.chainid == 1) { return 0xf6c2758cB55824BBE85CC02D6EF5BF610610E189; } return address(_msgSender()); } function getRouterAddress() public view returns (address) { if (block.chainid == 56) { return 0x10ED43C718714eb63d5aA57B78B54704E256024E; } else if (block.chainid == 97) { return 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; } else if (block.chainid == 1 || block.chainid == 5) { return 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; } else { revert("Cannot found router on this network"); } } function claimStuckTokens(address _token, address _to) external onlyOwner { require(_token != address(this), "Cannot claim native tokens"); if (_token == address(0)) { payable(_to).transfer(address(this).balance); return; } IERC20 token = IERC20(_token); uint256 balance = token.balanceOf(address(this)); token.safeTransfer(_to, balance); } function setBuyTax(uint256 _marketingTaxBuy) external onlyOwner { require( _marketingTaxBuy != marketingTaxBuy, "Buy Tax already on that percentage" ); require( _marketingTaxBuy <= 1_000, "Marketing Tax buy cannot be more than 10%" ); marketingTaxBuy = _marketingTaxBuy; emit UpdateBuyTax(_marketingTaxBuy); } function setSellTax(uint256 _marketingTaxSell) external onlyOwner { require( _marketingTaxSell != marketingTaxSell, "Sell Tax already on that percentage" ); require( _marketingTaxSell <= 1_000, "Marketing Tax sell cannot be more than 10%" ); marketingTaxSell = _marketingTaxSell; emit UpdateSellTax(_marketingTaxSell); } function setTransferTax(uint256 _marketingTaxTransfer) external onlyOwner { require( _marketingTaxTransfer != marketingTaxTransfer, "Transfer Tax already on that percentage" ); require( _marketingTaxTransfer <= 1_000, "Marketing Tax transfer cannot be more than 10%" ); marketingTaxTransfer = _marketingTaxTransfer; emit UpdateTransferTax(_marketingTaxTransfer); } function setMarketingWallet(address _marketingWallet) external onlyOwner { require( _marketingWallet != marketingWallet, "Marketing wallet is already that address" ); require( _marketingWallet != address(0), "Marketing wallet cannot be zero address" ); require( !isContract(_marketingWallet), "Marketing wallet cannot be contract" ); marketingWallet = _marketingWallet; emit UpdateMarketingWallet(_marketingWallet); } function setSwapTokensAtAmount(uint256 _amount) external onlyOwner { require( swapTokensAtAmount != _amount, "SwapTokensAtAmount already on that amount" ); require(_amount >= 1, "Amount must be equal or greater than 1 Wei"); swapTokensAtAmount = _amount; emit UpdateSwapTokensAtAmount(_amount); } function toggleSwapBack(bool _status) external onlyOwner { require(isSwapBackEnabled != _status, "SwapBack already on status"); isSwapBackEnabled = _status; emit UpdateSwapBackStatus(_status); } function setExcludeFromFees( address _account, bool _isExcluded ) external onlyOwner { require( _isExcludedFromFees[_account] != _isExcluded, "Account already on that status" ); _isExcludedFromFees[_account] = _isExcluded; emit UpdateExcludeFromFees(_account, _isExcluded); } function isExcludedFromFees(address _account) external view returns (bool) { return _isExcludedFromFees[_account]; } function setAutomatedMarketMakerPair( address _pair, bool _status ) external onlyOwner { require( _isAutomatedMarketMakerPair[_pair] != _status, "Pair already on that status" ); require(_pair != uniswapV2Pair, "Cannot change status of uniswap pair"); _isAutomatedMarketMakerPair[_pair] = _status; emit UpdateAutomatedMarketMakerPair(_pair, _status); } function isAutomatedMarketMakerPair( address _pair ) external view returns (bool) { return _isAutomatedMarketMakerPair[_pair]; } function _update( address sender, address recipient, uint256 amount ) internal override { if (sender == address(0) || recipient == address(0) || amount == 0) { super._update(sender, recipient, amount); return; } uint256 contractTokenBalance = balanceOf(address(this)); bool canSwap = contractTokenBalance >= swapTokensAtAmount; if ( canSwap && !swapping && _isAutomatedMarketMakerPair[recipient] && isSwapBackEnabled && sender != owner() && recipient != owner() ) { swapBack(); } bool takeFee = true; if (_isExcludedFromFees[sender] || _isExcludedFromFees[recipient]) { takeFee = false; } if (takeFee) { uint256 marketingTax = 0; if (_isAutomatedMarketMakerPair[sender]) { marketingTax = (marketingTaxBuy * amount) / denominator; } else if (_isAutomatedMarketMakerPair[recipient]) { marketingTax = (marketingTaxSell * amount) / denominator; } else { marketingTax = (marketingTaxTransfer * amount) / denominator; } uint256 contractTax = marketingTax; if (contractTax > 0) { amount -= contractTax; super._update(sender, address(this), contractTax); } } super._update(sender, recipient, amount); } function swapBack() internal inSwap { address[] memory pathWallet = new address[](2); pathWallet[0] = address(this); pathWallet[1] = uniswapV2Router.WETH(); uint256 contractTokenBalance = balanceOf(address(this)); uint256 marketingTokenAmount = contractTokenBalance; if (marketingTokenAmount > 0) { try uniswapV2Router .swapExactTokensForETHSupportingFeeOnTransferTokens( marketingTokenAmount, 0, pathWallet, address(marketingWallet), block.timestamp ) {} catch {} } } function manualSwapBack() external { uint256 contractTokenBalance = balanceOf(address(this)); require(contractTokenBalance > 0, "Cant Swap Back 0 Token!"); swapBack(); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"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":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","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":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":true,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"UpdateAutomatedMarketMakerPair","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketingTaxBuy","type":"uint256"}],"name":"UpdateBuyTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"UpdateExcludeFromFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketingWallet","type":"address"}],"name":"UpdateMarketingWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketingTaxSell","type":"uint256"}],"name":"UpdateSellTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"UpdateSwapBackStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"swapTokensAtAmount","type":"uint256"}],"name":"UpdateSwapTokensAtAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketingTaxTransfer","type":"uint256"}],"name":"UpdateTransferTax","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_SEPARATOR","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":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"claimStuckTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"denominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"getRouterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"}],"name":"isAutomatedMarketMakerPair","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isExcludedFromFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSwapBackEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manualSwapBack","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"marketingTaxBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingTaxSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingTaxTransfer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"setAutomatedMarketMakerPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketingTaxBuy","type":"uint256"}],"name":"setBuyTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_isExcluded","type":"bool"}],"name":"setExcludeFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marketingWallet","type":"address"}],"name":"setMarketingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketingTaxSell","type":"uint256"}],"name":"setSellTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setSwapTokensAtAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_marketingTaxTransfer","type":"uint256"}],"name":"setTransferTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapTokensAtAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_status","type":"bool"}],"name":"toggleSwapBack","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101c0604052348015610010575f5ffd5b5061001961045d565b60405180604001604052806006815260200165125394d4105160d21b81525080604051806040016040528060018152602001603160f81b81525060405180604001604052806006815260200165125394d4105160d21b815250604051806040016040528060048152602001630494e53560e41b815250816003908161009e9190610c89565b5060046100ab8282610c89565b506100bb91508390506005610490565b610120526100ca816006610490565b61014052815160208084019190912060e052815190820120610100524660a05261015660e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506001600160a01b03811661018e57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b610197816104c2565b506101cd6101ad6008546001600160a01b031690565b6101b96012600a610e3a565b6101c8906402540be400610e4c565b610513565b60c86009819055600a819055600b55612710610160526101eb61054b565b600c80546001600160a01b0319166001600160a01b039290921691909117905561271061021760025490565b610222906001610e4c565b61022c9190610e63565b600d55600e805460ff19166001179055610244610579565b6001600160a01b03166101808190526040805163c45a015560e01b8152905163c45a0155916004808201926020929091908290030181865afa15801561028c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b09190610e82565b6001600160a01b031663c9c6539630610180516001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102fe573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103229190610e82565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303815f875af115801561036c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103909190610e82565b6001600160a01b03166101a052610180516103ae9030905f1961063d565b61dead5f6001600f826103c96008546001600160a01b031690565b6001600160a01b03908116825260208083019390935260409182015f908120805495151560ff19968716179055308152600f84528281208054861660019081179091556101805183168252838220805487168217905596821681528281208054861688179055948116855281852080548516871790556101a051168452601090915290912080549091169091179055610faa565b5f466038148061046d5750466001145b1561048b575073c91a5f4fb6ff46b047a3e713254cdcb5d748c4f990565b503390565b5f6020835110156104ab576104a48361064f565b90506104bc565b816104b68482610c89565b5060ff90505b92915050565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b03821661053c5760405163ec442f0560e01b81525f6004820152602401610185565b6105475f838361068c565b5050565b5f466038148061055b5750466001145b1561048b575073f6c2758cb55824bbe85cc02d6ef5bf610610e18990565b5f4660380361059b57507310ed43c718714eb63d5aa57b78b54704e256024e90565b466061036105bc575073d99d1c33f9fc3444f8101754abc46c52416550d190565b46600114806105cb5750466005145b156105e95750737a250d5630b4cf539739df2c5dacb4c659f2488d90565b60405162461bcd60e51b815260206004820152602360248201527f43616e6e6f7420666f756e6420726f75746572206f6e2074686973206e6574776044820152626f726b60e81b6064820152608401610185565b61064a8383836001610877565b505050565b5f5f829050601f81511115610679578260405163305a27a960e01b81526004016101859190610ea8565b805161068482610edd565b179392505050565b6001600160a01b03831615806106a957506001600160a01b038216155b806106b2575080155b156106c25761064a83838361094a565b305f90815260208190526040902054600d54811080159081906106ef5750600c54600160a01b900460ff16155b801561071257506001600160a01b0384165f9081526010602052604090205460ff165b80156107205750600e5460ff165b801561073a57506008546001600160a01b03868116911614155b801561075457506008546001600160a01b03858116911614155b1561076157610761610a70565b6001600160a01b0385165f908152600f602052604090205460019060ff16806107a157506001600160a01b0385165f908152600f602052604090205460ff165b156107a957505f5b8015610864576001600160a01b0386165f9081526010602052604081205460ff16156107f25761016051856009546107e19190610e4c565b6107eb9190610e63565b9050610843565b6001600160a01b0386165f9081526010602052604090205460ff1615610824576101605185600a546107e19190610e4c565b6101605185600b546108369190610e4c565b6108409190610e63565b90505b808015610861576108548187610f00565b955061086188308361094a565b50505b61086f86868661094a565b505050505050565b6001600160a01b0384166108a05760405163e602df0560e01b81525f6004820152602401610185565b6001600160a01b0383166108c957604051634a1406b160e11b81525f6004820152602401610185565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561094457826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161093b91815260200190565b60405180910390a35b50505050565b6001600160a01b038316610974578060025f8282546109699190610f13565b909155506109e49050565b6001600160a01b0383165f90815260208190526040902054818110156109c65760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610185565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610a0057600280548290039055610a1e565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610a6391815260200190565b60405180910390a3505050565b600c805460ff60a01b1916600160a01b1790556040805160028082526060820183525f9260208301908036833701905050905030815f81518110610ab657610ab6610f26565b60200260200101906001600160a01b031690816001600160a01b031681525050610180516001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b15573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b399190610e82565b81600181518110610b4c57610b4c610f26565b6001600160a01b0392909216602092830291909101820152305f908152908190526040902054808015610be05761018051600c5460405163791ac94760e01b81526001600160a01b039283169263791ac94792610bb69286925f928a929116904290600401610f3a565b5f604051808303815f87803b158015610bcd575f5ffd5b505af1925050508015610bde575060015b505b5050600c805460ff60a01b1916905550565b634e487b7160e01b5f52604160045260245ffd5b600181811c90821680610c1a57607f821691505b602082108103610c3857634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561064a57805f5260205f20601f840160051c81016020851015610c635750805b601f840160051c820191505b81811015610c82575f8155600101610c6f565b5050505050565b81516001600160401b03811115610ca257610ca2610bf2565b610cb681610cb08454610c06565b84610c3e565b6020601f821160018114610ce8575f8315610cd15750848201515b5f19600385901b1c1916600184901b178455610c82565b5f84815260208120601f198516915b82811015610d175787850151825560209485019460019092019101610cf7565b5084821015610d3457868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b6001815b6001841115610d9257808504811115610d7657610d76610d43565b6001841615610d8457908102905b60019390931c928002610d5b565b935093915050565b5f82610da8575060016104bc565b81610db457505f6104bc565b8160018114610dca5760028114610dd457610df0565b60019150506104bc565b60ff841115610de557610de5610d43565b50506001821b6104bc565b5060208310610133831016604e8410600b8410161715610e13575081810a6104bc565b610e1f5f198484610d57565b805f1904821115610e3257610e32610d43565b029392505050565b5f610e458383610d9a565b9392505050565b80820281158282048414176104bc576104bc610d43565b5f82610e7d57634e487b7160e01b5f52601260045260245ffd5b500490565b5f60208284031215610e92575f5ffd5b81516001600160a01b0381168114610e45575f5ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80516020808301519190811015610c38575f1960209190910360031b1b16919050565b818103818111156104bc576104bc610d43565b808201808211156104bc576104bc610d43565b634e487b7160e01b5f52603260045260245ffd5b5f60a0820187835286602084015260a0604084015280865180835260c0850191506020880192505f5b81811015610f8a5783516001600160a01b0316835260209384019390920191600101610f63565b50506001600160a01b039590951660608401525050608001529392505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051612ac76110435f395f81816103b40152610ed101525f81816102c901528181611a6c0152611b5d01525f81816105e70152818161200501528181612065015261209401525f611c9201525f611c6501525f61198801525f61196001525f6118bb01525f6118e501525f61190f0152612ac75ff3fe60806040526004361061025d575f3560e01c80637ecebe001161013d578063a8eb226d116100be578063d63cad2211610078578063dd62ed3e11610060578063dd62ed3e146106f6578063e2f456051461073a578063f2fde38b1461074f57005b8063d63cad22146106b8578063dc1052e2146106d757005b8063afa4f3b2116100a6578063afa4f3b214610666578063d505accf14610685578063d54f7d5e146106a457005b8063a8eb226d14610628578063a9059cbb1461064757005b80638cd09d501161010f57806395d89b41116100f757806395d89b41146105c257806396ce0795146105d65780639a7a23d61461060957005b80638cd09d50146105865780638da5cb5b146105a557005b80637ecebe001461050c57806384b0196e1461052b57806384ec44d2146105525780638b5259031461056757005b806349bd5a5e116101df57806370a0823111610199578063721e623311610181578063721e6233146104a157806375f0a874146104b65780637949a403146104d557005b806370a0823114610459578063715018a61461048d57005b806352dfc8d0116101c757806352dfc8d01461040d5780635d098b381461042657806366eb37851461044557005b806349bd5a5e146103a35780634fbee193146103d657005b80631f88a23e11610230578063313ce56711610218578063313ce5671461035f5780633644e5151461037a57806342d0b0bc1461038e57005b80631f88a23e1461032157806323b872dd1461034057005b806306fdde031461025f578063095ea7b3146102895780631694505e146102b857806318160ddd14610303575b005b34801561026a575f5ffd5b5061027361076e565b6040516102809190612621565b60405180910390f35b348015610294575f5ffd5b506102a86102a336600461264e565b6107fe565b6040519015158152602001610280565b3480156102c3575f5ffd5b506102eb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610280565b34801561030e575f5ffd5b506002545b604051908152602001610280565b34801561032c575f5ffd5b5061025d61033b36600461268c565b610817565b34801561034b575f5ffd5b506102a861035a3660046126a5565b6108e4565b34801561036a575f5ffd5b5060405160128152602001610280565b348015610385575f5ffd5b50610313610907565b348015610399575f5ffd5b50610313600a5481565b3480156103ae575f5ffd5b506102eb7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e1575f5ffd5b506102a86103f03660046126e3565b6001600160a01b03165f908152600f602052604090205460ff1690565b348015610418575f5ffd5b50600e546102a89060ff1681565b348015610431575f5ffd5b5061025d6104403660046126e3565b610915565b348015610450575f5ffd5b5061025d610afc565b348015610464575f5ffd5b506103136104733660046126e3565b6001600160a01b03165f9081526020819052604090205490565b348015610498575f5ffd5b5061025d610b63565b3480156104ac575f5ffd5b5061031360095481565b3480156104c1575f5ffd5b50600c546102eb906001600160a01b031681565b3480156104e0575f5ffd5b506102a86104ef3660046126e3565b6001600160a01b03165f9081526010602052604090205460ff1690565b348015610517575f5ffd5b506103136105263660046126e3565b610b76565b348015610536575f5ffd5b5061053f610b93565b60405161028097969594939291906126fe565b34801561055d575f5ffd5b50610313600b5481565b348015610572575f5ffd5b5061025d6105813660046127b0565b610bf1565b348015610591575f5ffd5b5061025d6105a03660046127b0565b610d1d565b3480156105b0575f5ffd5b506008546001600160a01b03166102eb565b3480156105cd575f5ffd5b50610273610e49565b3480156105e1575f5ffd5b506103137f000000000000000000000000000000000000000000000000000000000000000081565b348015610614575f5ffd5b5061025d6106233660046127c7565b610e58565b348015610633575f5ffd5b5061025d6106423660046127fa565b610ff2565b348015610652575f5ffd5b506102a861066136600461264e565b611137565b348015610671575f5ffd5b5061025d6106803660046127b0565b611144565b348015610690575f5ffd5b5061025d61069f366004612831565b61126f565b3480156106af575f5ffd5b506102eb6113d7565b3480156106c3575f5ffd5b5061025d6106d23660046127c7565b6114b5565b3480156106e2575f5ffd5b5061025d6106f13660046127b0565b6115a1565b348015610701575f5ffd5b506103136107103660046127fa565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b348015610745575f5ffd5b50610313600d5481565b34801561075a575f5ffd5b5061025d6107693660046126e3565b6116cd565b60606003805461077d906128a2565b80601f01602080910402602001604051908101604052809291908181526020018280546107a9906128a2565b80156107f45780601f106107cb576101008083540402835291602001916107f4565b820191905f5260205f20905b8154815290600101906020018083116107d757829003601f168201915b5050505050905090565b5f3361080b818585611720565b60019150505b92915050565b61081f61172d565b600e5481151560ff90911615150361087e5760405162461bcd60e51b815260206004820152601a60248201527f537761704261636b20616c7265616479206f6e2073746174757300000000000060448201526064015b60405180910390fd5b600e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215159081179091556040519081527fc2385a9c5843e4cd7e987e979b22e4d4748ec5dbbfc325ee4023a8c1914809b7906020015b60405180910390a150565b5f336108f1858285611773565b6108fc858585611820565b506001949350505050565b5f6109106118af565b905090565b61091d61172d565b600c546001600160a01b03908116908216036109a15760405162461bcd60e51b815260206004820152602860248201527f4d61726b6574696e672077616c6c657420697320616c7265616479207468617460448201527f20616464726573730000000000000000000000000000000000000000000000006064820152608401610875565b6001600160a01b038116610a1d5760405162461bcd60e51b815260206004820152602760248201527f4d61726b6574696e672077616c6c65742063616e6e6f74206265207a65726f2060448201527f61646472657373000000000000000000000000000000000000000000000000006064820152608401610875565b6001600160a01b0381163b15610a9b5760405162461bcd60e51b815260206004820152602360248201527f4d61726b6574696e672077616c6c65742063616e6e6f7420626520636f6e747260448201527f61637400000000000000000000000000000000000000000000000000000000006064820152608401610875565b600c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f335aad0eda24dacfa324b3d651daa091864338cf7d4af9d5087ba1c5ee1174f0905f90a250565b305f9081526020819052604090205480610b585760405162461bcd60e51b815260206004820152601760248201527f43616e742053776170204261636b203020546f6b656e210000000000000000006044820152606401610875565b610b606119d8565b50565b610b6b61172d565b610b745f611bf5565b565b6001600160a01b0381165f90815260076020526040812054610811565b5f6060805f5f5f6060610ba4611c5e565b610bac611c8b565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b610bf961172d565b600b548103610c705760405162461bcd60e51b815260206004820152602760248201527f5472616e736665722054617820616c7265616479206f6e20746861742070657260448201527f63656e74616765000000000000000000000000000000000000000000000000006064820152608401610875565b6103e8811115610ce85760405162461bcd60e51b815260206004820152602e60248201527f4d61726b6574696e6720546178207472616e736665722063616e6e6f7420626560448201527f206d6f7265207468616e203130250000000000000000000000000000000000006064820152608401610875565b600b8190556040518181527f929d0bf4c90b61d2b4908b85d6756d928390ce6787bdfe9b1f1427a9bc5c3482906020016108d9565b610d2561172d565b600a548103610d9c5760405162461bcd60e51b815260206004820152602360248201527f53656c6c2054617820616c7265616479206f6e20746861742070657263656e7460448201527f61676500000000000000000000000000000000000000000000000000000000006064820152608401610875565b6103e8811115610e145760405162461bcd60e51b815260206004820152602a60248201527f4d61726b6574696e67205461782073656c6c2063616e6e6f74206265206d6f7260448201527f65207468616e20313025000000000000000000000000000000000000000000006064820152608401610875565b600a8190556040518181527fc9d5952b1f3c1b1a0194027998b195d38e356b5cdcdb07d02335a1bde8f67e70906020016108d9565b60606004805461077d906128a2565b610e6061172d565b6001600160a01b0382165f9081526010602052604090205481151560ff909116151503610ecf5760405162461bcd60e51b815260206004820152601b60248201527f5061697220616c7265616479206f6e20746861742073746174757300000000006044820152606401610875565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603610f755760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f74206368616e676520737461747573206f6620756e69737761702060448201527f70616972000000000000000000000000000000000000000000000000000000006064820152608401610875565b6001600160a01b0382165f8181526010602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527fb6f1aed3b1ced30ce666a8b7f2e12b02aed514cdab677738640be9937f13320591015b60405180910390a25050565b610ffa61172d565b306001600160a01b038316036110525760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420636c61696d206e617469766520746f6b656e730000000000006044820152606401610875565b6001600160a01b038216611097576040516001600160a01b038216904780156108fc02915f818181858888f19350505050158015611092573d5f5f3e3d5ffd5b505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282905f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156110f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111a91906128f3565b90506111306001600160a01b0383168483611cb8565b50505b5050565b5f3361080b818585611820565b61114c61172d565b80600d54036111c35760405162461bcd60e51b815260206004820152602960248201527f53776170546f6b656e734174416d6f756e7420616c7265616479206f6e20746860448201527f617420616d6f756e7400000000000000000000000000000000000000000000006064820152608401610875565b600181101561123a5760405162461bcd60e51b815260206004820152602a60248201527f416d6f756e74206d75737420626520657175616c206f7220677265617465722060448201527f7468616e203120576569000000000000000000000000000000000000000000006064820152608401610875565b600d8190556040518181527fe82283d0f679a15d3811ecbaa8b6a8afb1b110e22daa33b359c37bcae5a11e48906020016108d9565b834211156112ac576040517f6279130200000000000000000000000000000000000000000000000000000000815260048101859052602401610875565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886112f78c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61135182611d38565b90505f61136082878787611d7f565b9050896001600160a01b0316816001600160a01b0316146113c0576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b166024820152604401610875565b6113cb8a8a8a611720565b50505050505050505050565b5f466038036113f957507310ed43c718714eb63d5aa57b78b54704e256024e90565b4660610361141a575073d99d1c33f9fc3444f8101754abc46c52416550d190565b46600114806114295750466005145b156114475750737a250d5630b4cf539739df2c5dacb4c659f2488d90565b60405162461bcd60e51b815260206004820152602360248201527f43616e6e6f7420666f756e6420726f75746572206f6e2074686973206e65747760448201527f6f726b00000000000000000000000000000000000000000000000000000000006064820152608401610875565b6114bd61172d565b6001600160a01b0382165f908152600f602052604090205481151560ff90911615150361152c5760405162461bcd60e51b815260206004820152601e60248201527f4163636f756e7420616c7265616479206f6e20746861742073746174757300006044820152606401610875565b6001600160a01b0382165f818152600f602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527fee48373bc01f03d5728ce4cf0b4e1c35d75d7da201d5b5d5013a94e50941efe19101610fe6565b6115a961172d565b60095481036116205760405162461bcd60e51b815260206004820152602260248201527f4275792054617820616c7265616479206f6e20746861742070657263656e746160448201527f67650000000000000000000000000000000000000000000000000000000000006064820152608401610875565b6103e88111156116985760405162461bcd60e51b815260206004820152602960248201527f4d61726b6574696e6720546178206275792063616e6e6f74206265206d6f726560448201527f207468616e2031302500000000000000000000000000000000000000000000006064820152608401610875565b60098190556040518181527f2d16b529cd6f4d8d1af62fe74e0801442778f50967ec8b5994f628052c59c73a906020016108d9565b6116d561172d565b6001600160a01b038116611717576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b610b6081611bf5565b6110928383836001611dab565b6008546001600160a01b03163314610b74576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610875565b6001600160a01b038381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146111305781811015611812576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024810182905260448101839052606401610875565b61113084848484035f611dab565b6001600160a01b038316611862576040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b6001600160a01b0382166118a4576040517fec442f050000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b611092838383611eaf565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561190757507f000000000000000000000000000000000000000000000000000000000000000046145b1561193157507f000000000000000000000000000000000000000000000000000000000000000090565b610910604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b600c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040805160028082526060820183525f9260208301908036833701905050905030815f81518110611a4a57611a4a61290a565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ac6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aea9190612937565b81600181518110611afd57611afd61290a565b6001600160a01b0392909216602092830291909101820152305f908152908190526040902054808015611bc857600c546040517f791ac9470000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263791ac94792611b9e9286925f928a9291909116904290600401612952565b5f604051808303815f87803b158015611bb5575f5ffd5b505af1925050508015611bc6575060015b505b5050600c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b600880546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60606109107f00000000000000000000000000000000000000000000000000000000000000006005612102565b60606109107f00000000000000000000000000000000000000000000000000000000000000006006612102565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526110929084906121ab565b5f610811611d446118af565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f5f5f5f611d8f88888888612230565b925092509250611d9f8282612316565b50909695505050505050565b6001600160a01b038416611ded576040517fe602df050000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b6001600160a01b038316611e2f576040517f94280d620000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561113057826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611ea191815260200190565b60405180910390a350505050565b6001600160a01b0383161580611ecc57506001600160a01b038216155b80611ed5575080155b15611ee557611092838383612419565b305f90815260208190526040902054600d5481108015908190611f235750600c5474010000000000000000000000000000000000000000900460ff16155b8015611f4657506001600160a01b0384165f9081526010602052604090205460ff165b8015611f545750600e5460ff165b8015611f6e57506008546001600160a01b03868116911614155b8015611f8857506008546001600160a01b03858116911614155b15611f9557611f956119d8565b6001600160a01b0385165f908152600f602052604090205460019060ff1680611fd557506001600160a01b0385165f908152600f602052604090205460ff165b15611fdd57505f5b80156120ef576001600160a01b0386165f9081526010602052604081205460ff1615612043577f00000000000000000000000000000000000000000000000000000000000000008560095461203291906129ef565b61203c9190612a06565b90506120ce565b6001600160a01b0386165f9081526010602052604090205460ff1615612092577f000000000000000000000000000000000000000000000000000000000000000085600a5461203291906129ef565b7f000000000000000000000000000000000000000000000000000000000000000085600b546120c191906129ef565b6120cb9190612a06565b90505b8080156120ec576120df8187612a3e565b95506120ec883083612419565b50505b6120fa868686612419565b505050505050565b606060ff831461211c5761211583612558565b9050610811565b818054612128906128a2565b80601f0160208091040260200160405190810160405280929190818152602001828054612154906128a2565b801561219f5780601f106121765761010080835404028352916020019161219f565b820191905f5260205f20905b81548152906001019060200180831161218257829003601f168201915b50505050509050610811565b5f5f60205f8451602086015f885af1806121ca576040513d5f823e3d81fd5b50505f513d915081156121e15780600114156121ee565b6001600160a01b0384163b155b15611130576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610875565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561226957505f9150600390508261230c565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156122ba573d5f5f3e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b03811661230357505f92506001915082905061230c565b92505f91508190505b9450945094915050565b5f82600381111561232957612329612a51565b03612332575050565b600182600381111561234657612346612a51565b0361237d576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561239157612391612a51565b036123cb576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610875565b60038260038111156123df576123df612a51565b03611133576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610875565b6001600160a01b038316612443578060025f8282546124389190612a7e565b909155506124cc9050565b6001600160a01b0383165f90815260208190526040902054818110156124ae576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024810182905260448101839052606401610875565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b0382166124e857600280548290039055612506565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161254b91815260200190565b60405180910390a3505050565b60605f61256483612595565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f811115610811576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61263360208301846125d5565b9392505050565b6001600160a01b0381168114610b60575f5ffd5b5f5f6040838503121561265f575f5ffd5b823561266a8161263a565b946020939093013593505050565b80358015158114612687575f5ffd5b919050565b5f6020828403121561269c575f5ffd5b61263382612678565b5f5f5f606084860312156126b7575f5ffd5b83356126c28161263a565b925060208401356126d28161263a565b929592945050506040919091013590565b5f602082840312156126f3575f5ffd5b81356126338161263a565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201525f61273860e08301896125d5565b828103604084015261274a81896125d5565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b8181101561279f578351835260209384019390920191600101612781565b50909b9a5050505050505050505050565b5f602082840312156127c0575f5ffd5b5035919050565b5f5f604083850312156127d8575f5ffd5b82356127e38161263a565b91506127f160208401612678565b90509250929050565b5f5f6040838503121561280b575f5ffd5b82356128168161263a565b915060208301356128268161263a565b809150509250929050565b5f5f5f5f5f5f5f60e0888a031215612847575f5ffd5b87356128528161263a565b965060208801356128628161263a565b95506040880135945060608801359350608088013560ff81168114612885575f5ffd5b9699959850939692959460a0840135945060c09093013592915050565b600181811c908216806128b657607f821691505b6020821081036128ed577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215612903575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215612947575f5ffd5b81516126338161263a565b5f60a0820187835286602084015260a0604084015280865180835260c0850191506020880192505f5b818110156129a25783516001600160a01b031683526020938401939092019160010161297b565b50506001600160a01b039590951660608401525050608001529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082028115828204841417610811576108116129c2565b5f82612a39577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b81810381811115610811576108116129c2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80820180821115610811576108116129c256fea2646970667358221220101259a872be53a5ee472c96f2303dd6bbe9535ad95566d6693ab772f3a318ba64736f6c634300081c0033
Deployed Bytecode
0x60806040526004361061025d575f3560e01c80637ecebe001161013d578063a8eb226d116100be578063d63cad2211610078578063dd62ed3e11610060578063dd62ed3e146106f6578063e2f456051461073a578063f2fde38b1461074f57005b8063d63cad22146106b8578063dc1052e2146106d757005b8063afa4f3b2116100a6578063afa4f3b214610666578063d505accf14610685578063d54f7d5e146106a457005b8063a8eb226d14610628578063a9059cbb1461064757005b80638cd09d501161010f57806395d89b41116100f757806395d89b41146105c257806396ce0795146105d65780639a7a23d61461060957005b80638cd09d50146105865780638da5cb5b146105a557005b80637ecebe001461050c57806384b0196e1461052b57806384ec44d2146105525780638b5259031461056757005b806349bd5a5e116101df57806370a0823111610199578063721e623311610181578063721e6233146104a157806375f0a874146104b65780637949a403146104d557005b806370a0823114610459578063715018a61461048d57005b806352dfc8d0116101c757806352dfc8d01461040d5780635d098b381461042657806366eb37851461044557005b806349bd5a5e146103a35780634fbee193146103d657005b80631f88a23e11610230578063313ce56711610218578063313ce5671461035f5780633644e5151461037a57806342d0b0bc1461038e57005b80631f88a23e1461032157806323b872dd1461034057005b806306fdde031461025f578063095ea7b3146102895780631694505e146102b857806318160ddd14610303575b005b34801561026a575f5ffd5b5061027361076e565b6040516102809190612621565b60405180910390f35b348015610294575f5ffd5b506102a86102a336600461264e565b6107fe565b6040519015158152602001610280565b3480156102c3575f5ffd5b506102eb7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b6040516001600160a01b039091168152602001610280565b34801561030e575f5ffd5b506002545b604051908152602001610280565b34801561032c575f5ffd5b5061025d61033b36600461268c565b610817565b34801561034b575f5ffd5b506102a861035a3660046126a5565b6108e4565b34801561036a575f5ffd5b5060405160128152602001610280565b348015610385575f5ffd5b50610313610907565b348015610399575f5ffd5b50610313600a5481565b3480156103ae575f5ffd5b506102eb7f000000000000000000000000c3ccc0a80650a82e7e6ac994b06a5939177e63f781565b3480156103e1575f5ffd5b506102a86103f03660046126e3565b6001600160a01b03165f908152600f602052604090205460ff1690565b348015610418575f5ffd5b50600e546102a89060ff1681565b348015610431575f5ffd5b5061025d6104403660046126e3565b610915565b348015610450575f5ffd5b5061025d610afc565b348015610464575f5ffd5b506103136104733660046126e3565b6001600160a01b03165f9081526020819052604090205490565b348015610498575f5ffd5b5061025d610b63565b3480156104ac575f5ffd5b5061031360095481565b3480156104c1575f5ffd5b50600c546102eb906001600160a01b031681565b3480156104e0575f5ffd5b506102a86104ef3660046126e3565b6001600160a01b03165f9081526010602052604090205460ff1690565b348015610517575f5ffd5b506103136105263660046126e3565b610b76565b348015610536575f5ffd5b5061053f610b93565b60405161028097969594939291906126fe565b34801561055d575f5ffd5b50610313600b5481565b348015610572575f5ffd5b5061025d6105813660046127b0565b610bf1565b348015610591575f5ffd5b5061025d6105a03660046127b0565b610d1d565b3480156105b0575f5ffd5b506008546001600160a01b03166102eb565b3480156105cd575f5ffd5b50610273610e49565b3480156105e1575f5ffd5b506103137f000000000000000000000000000000000000000000000000000000000000271081565b348015610614575f5ffd5b5061025d6106233660046127c7565b610e58565b348015610633575f5ffd5b5061025d6106423660046127fa565b610ff2565b348015610652575f5ffd5b506102a861066136600461264e565b611137565b348015610671575f5ffd5b5061025d6106803660046127b0565b611144565b348015610690575f5ffd5b5061025d61069f366004612831565b61126f565b3480156106af575f5ffd5b506102eb6113d7565b3480156106c3575f5ffd5b5061025d6106d23660046127c7565b6114b5565b3480156106e2575f5ffd5b5061025d6106f13660046127b0565b6115a1565b348015610701575f5ffd5b506103136107103660046127fa565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b348015610745575f5ffd5b50610313600d5481565b34801561075a575f5ffd5b5061025d6107693660046126e3565b6116cd565b60606003805461077d906128a2565b80601f01602080910402602001604051908101604052809291908181526020018280546107a9906128a2565b80156107f45780601f106107cb576101008083540402835291602001916107f4565b820191905f5260205f20905b8154815290600101906020018083116107d757829003601f168201915b5050505050905090565b5f3361080b818585611720565b60019150505b92915050565b61081f61172d565b600e5481151560ff90911615150361087e5760405162461bcd60e51b815260206004820152601a60248201527f537761704261636b20616c7265616479206f6e2073746174757300000000000060448201526064015b60405180910390fd5b600e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215159081179091556040519081527fc2385a9c5843e4cd7e987e979b22e4d4748ec5dbbfc325ee4023a8c1914809b7906020015b60405180910390a150565b5f336108f1858285611773565b6108fc858585611820565b506001949350505050565b5f6109106118af565b905090565b61091d61172d565b600c546001600160a01b03908116908216036109a15760405162461bcd60e51b815260206004820152602860248201527f4d61726b6574696e672077616c6c657420697320616c7265616479207468617460448201527f20616464726573730000000000000000000000000000000000000000000000006064820152608401610875565b6001600160a01b038116610a1d5760405162461bcd60e51b815260206004820152602760248201527f4d61726b6574696e672077616c6c65742063616e6e6f74206265207a65726f2060448201527f61646472657373000000000000000000000000000000000000000000000000006064820152608401610875565b6001600160a01b0381163b15610a9b5760405162461bcd60e51b815260206004820152602360248201527f4d61726b6574696e672077616c6c65742063616e6e6f7420626520636f6e747260448201527f61637400000000000000000000000000000000000000000000000000000000006064820152608401610875565b600c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f335aad0eda24dacfa324b3d651daa091864338cf7d4af9d5087ba1c5ee1174f0905f90a250565b305f9081526020819052604090205480610b585760405162461bcd60e51b815260206004820152601760248201527f43616e742053776170204261636b203020546f6b656e210000000000000000006044820152606401610875565b610b606119d8565b50565b610b6b61172d565b610b745f611bf5565b565b6001600160a01b0381165f90815260076020526040812054610811565b5f6060805f5f5f6060610ba4611c5e565b610bac611c8b565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b610bf961172d565b600b548103610c705760405162461bcd60e51b815260206004820152602760248201527f5472616e736665722054617820616c7265616479206f6e20746861742070657260448201527f63656e74616765000000000000000000000000000000000000000000000000006064820152608401610875565b6103e8811115610ce85760405162461bcd60e51b815260206004820152602e60248201527f4d61726b6574696e6720546178207472616e736665722063616e6e6f7420626560448201527f206d6f7265207468616e203130250000000000000000000000000000000000006064820152608401610875565b600b8190556040518181527f929d0bf4c90b61d2b4908b85d6756d928390ce6787bdfe9b1f1427a9bc5c3482906020016108d9565b610d2561172d565b600a548103610d9c5760405162461bcd60e51b815260206004820152602360248201527f53656c6c2054617820616c7265616479206f6e20746861742070657263656e7460448201527f61676500000000000000000000000000000000000000000000000000000000006064820152608401610875565b6103e8811115610e145760405162461bcd60e51b815260206004820152602a60248201527f4d61726b6574696e67205461782073656c6c2063616e6e6f74206265206d6f7260448201527f65207468616e20313025000000000000000000000000000000000000000000006064820152608401610875565b600a8190556040518181527fc9d5952b1f3c1b1a0194027998b195d38e356b5cdcdb07d02335a1bde8f67e70906020016108d9565b60606004805461077d906128a2565b610e6061172d565b6001600160a01b0382165f9081526010602052604090205481151560ff909116151503610ecf5760405162461bcd60e51b815260206004820152601b60248201527f5061697220616c7265616479206f6e20746861742073746174757300000000006044820152606401610875565b7f000000000000000000000000c3ccc0a80650a82e7e6ac994b06a5939177e63f76001600160a01b0316826001600160a01b031603610f755760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f74206368616e676520737461747573206f6620756e69737761702060448201527f70616972000000000000000000000000000000000000000000000000000000006064820152608401610875565b6001600160a01b0382165f8181526010602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527fb6f1aed3b1ced30ce666a8b7f2e12b02aed514cdab677738640be9937f13320591015b60405180910390a25050565b610ffa61172d565b306001600160a01b038316036110525760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f7420636c61696d206e617469766520746f6b656e730000000000006044820152606401610875565b6001600160a01b038216611097576040516001600160a01b038216904780156108fc02915f818181858888f19350505050158015611092573d5f5f3e3d5ffd5b505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282905f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156110f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111a91906128f3565b90506111306001600160a01b0383168483611cb8565b50505b5050565b5f3361080b818585611820565b61114c61172d565b80600d54036111c35760405162461bcd60e51b815260206004820152602960248201527f53776170546f6b656e734174416d6f756e7420616c7265616479206f6e20746860448201527f617420616d6f756e7400000000000000000000000000000000000000000000006064820152608401610875565b600181101561123a5760405162461bcd60e51b815260206004820152602a60248201527f416d6f756e74206d75737420626520657175616c206f7220677265617465722060448201527f7468616e203120576569000000000000000000000000000000000000000000006064820152608401610875565b600d8190556040518181527fe82283d0f679a15d3811ecbaa8b6a8afb1b110e22daa33b359c37bcae5a11e48906020016108d9565b834211156112ac576040517f6279130200000000000000000000000000000000000000000000000000000000815260048101859052602401610875565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886112f78c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61135182611d38565b90505f61136082878787611d7f565b9050896001600160a01b0316816001600160a01b0316146113c0576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b166024820152604401610875565b6113cb8a8a8a611720565b50505050505050505050565b5f466038036113f957507310ed43c718714eb63d5aa57b78b54704e256024e90565b4660610361141a575073d99d1c33f9fc3444f8101754abc46c52416550d190565b46600114806114295750466005145b156114475750737a250d5630b4cf539739df2c5dacb4c659f2488d90565b60405162461bcd60e51b815260206004820152602360248201527f43616e6e6f7420666f756e6420726f75746572206f6e2074686973206e65747760448201527f6f726b00000000000000000000000000000000000000000000000000000000006064820152608401610875565b6114bd61172d565b6001600160a01b0382165f908152600f602052604090205481151560ff90911615150361152c5760405162461bcd60e51b815260206004820152601e60248201527f4163636f756e7420616c7265616479206f6e20746861742073746174757300006044820152606401610875565b6001600160a01b0382165f818152600f602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527fee48373bc01f03d5728ce4cf0b4e1c35d75d7da201d5b5d5013a94e50941efe19101610fe6565b6115a961172d565b60095481036116205760405162461bcd60e51b815260206004820152602260248201527f4275792054617820616c7265616479206f6e20746861742070657263656e746160448201527f67650000000000000000000000000000000000000000000000000000000000006064820152608401610875565b6103e88111156116985760405162461bcd60e51b815260206004820152602960248201527f4d61726b6574696e6720546178206275792063616e6e6f74206265206d6f726560448201527f207468616e2031302500000000000000000000000000000000000000000000006064820152608401610875565b60098190556040518181527f2d16b529cd6f4d8d1af62fe74e0801442778f50967ec8b5994f628052c59c73a906020016108d9565b6116d561172d565b6001600160a01b038116611717576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b610b6081611bf5565b6110928383836001611dab565b6008546001600160a01b03163314610b74576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610875565b6001600160a01b038381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146111305781811015611812576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024810182905260448101839052606401610875565b61113084848484035f611dab565b6001600160a01b038316611862576040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b6001600160a01b0382166118a4576040517fec442f050000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b611092838383611eaf565b5f306001600160a01b037f000000000000000000000000d37ae8c16449e7ef858652e02555c51d2572552b1614801561190757507f000000000000000000000000000000000000000000000000000000000000000146145b1561193157507f6d5cb72f8e6852ece22cd59ac79eba38c6ec69dc28def0c18aead2bc2807ea9490565b610910604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f5753b514d56869ba79477f60f3a8aff52f2443c4da433ee38b5fefc09f595ff9918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b600c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040805160028082526060820183525f9260208301908036833701905050905030815f81518110611a4a57611a4a61290a565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ac6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aea9190612937565b81600181518110611afd57611afd61290a565b6001600160a01b0392909216602092830291909101820152305f908152908190526040902054808015611bc857600c546040517f791ac9470000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81169263791ac94792611b9e9286925f928a9291909116904290600401612952565b5f604051808303815f87803b158015611bb5575f5ffd5b505af1925050508015611bc6575060015b505b5050600c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550565b600880546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60606109107f494e5350414400000000000000000000000000000000000000000000000000066005612102565b60606109107f31000000000000000000000000000000000000000000000000000000000000016006612102565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526110929084906121ab565b5f610811611d446118af565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f5f5f5f611d8f88888888612230565b925092509250611d9f8282612316565b50909695505050505050565b6001600160a01b038416611ded576040517fe602df050000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b6001600160a01b038316611e2f576040517f94280d620000000000000000000000000000000000000000000000000000000081525f6004820152602401610875565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561113057826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611ea191815260200190565b60405180910390a350505050565b6001600160a01b0383161580611ecc57506001600160a01b038216155b80611ed5575080155b15611ee557611092838383612419565b305f90815260208190526040902054600d5481108015908190611f235750600c5474010000000000000000000000000000000000000000900460ff16155b8015611f4657506001600160a01b0384165f9081526010602052604090205460ff165b8015611f545750600e5460ff165b8015611f6e57506008546001600160a01b03868116911614155b8015611f8857506008546001600160a01b03858116911614155b15611f9557611f956119d8565b6001600160a01b0385165f908152600f602052604090205460019060ff1680611fd557506001600160a01b0385165f908152600f602052604090205460ff165b15611fdd57505f5b80156120ef576001600160a01b0386165f9081526010602052604081205460ff1615612043577f00000000000000000000000000000000000000000000000000000000000027108560095461203291906129ef565b61203c9190612a06565b90506120ce565b6001600160a01b0386165f9081526010602052604090205460ff1615612092577f000000000000000000000000000000000000000000000000000000000000271085600a5461203291906129ef565b7f000000000000000000000000000000000000000000000000000000000000271085600b546120c191906129ef565b6120cb9190612a06565b90505b8080156120ec576120df8187612a3e565b95506120ec883083612419565b50505b6120fa868686612419565b505050505050565b606060ff831461211c5761211583612558565b9050610811565b818054612128906128a2565b80601f0160208091040260200160405190810160405280929190818152602001828054612154906128a2565b801561219f5780601f106121765761010080835404028352916020019161219f565b820191905f5260205f20905b81548152906001019060200180831161218257829003601f168201915b50505050509050610811565b5f5f60205f8451602086015f885af1806121ca576040513d5f823e3d81fd5b50505f513d915081156121e15780600114156121ee565b6001600160a01b0384163b155b15611130576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610875565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561226957505f9150600390508261230c565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156122ba573d5f5f3e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001519150506001600160a01b03811661230357505f92506001915082905061230c565b92505f91508190505b9450945094915050565b5f82600381111561232957612329612a51565b03612332575050565b600182600381111561234657612346612a51565b0361237d576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561239157612391612a51565b036123cb576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610875565b60038260038111156123df576123df612a51565b03611133576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610875565b6001600160a01b038316612443578060025f8282546124389190612a7e565b909155506124cc9050565b6001600160a01b0383165f90815260208190526040902054818110156124ae576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024810182905260448101839052606401610875565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b0382166124e857600280548290039055612506565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161254b91815260200190565b60405180910390a3505050565b60605f61256483612595565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f811115610811576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61263360208301846125d5565b9392505050565b6001600160a01b0381168114610b60575f5ffd5b5f5f6040838503121561265f575f5ffd5b823561266a8161263a565b946020939093013593505050565b80358015158114612687575f5ffd5b919050565b5f6020828403121561269c575f5ffd5b61263382612678565b5f5f5f606084860312156126b7575f5ffd5b83356126c28161263a565b925060208401356126d28161263a565b929592945050506040919091013590565b5f602082840312156126f3575f5ffd5b81356126338161263a565b7fff000000000000000000000000000000000000000000000000000000000000008816815260e060208201525f61273860e08301896125d5565b828103604084015261274a81896125d5565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b8181101561279f578351835260209384019390920191600101612781565b50909b9a5050505050505050505050565b5f602082840312156127c0575f5ffd5b5035919050565b5f5f604083850312156127d8575f5ffd5b82356127e38161263a565b91506127f160208401612678565b90509250929050565b5f5f6040838503121561280b575f5ffd5b82356128168161263a565b915060208301356128268161263a565b809150509250929050565b5f5f5f5f5f5f5f60e0888a031215612847575f5ffd5b87356128528161263a565b965060208801356128628161263a565b95506040880135945060608801359350608088013560ff81168114612885575f5ffd5b9699959850939692959460a0840135945060c09093013592915050565b600181811c908216806128b657607f821691505b6020821081036128ed577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215612903575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215612947575f5ffd5b81516126338161263a565b5f60a0820187835286602084015260a0604084015280865180835260c0850191506020880192505f5b818110156129a25783516001600160a01b031683526020938401939092019160010161297b565b50506001600160a01b039590951660608401525050608001529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082028115828204841417610811576108116129c2565b5f82612a39577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b81810381811115610811576108116129c2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80820180821115610811576108116129c256fea2646970667358221220101259a872be53a5ee472c96f2303dd6bbe9535ad95566d6693ab772f3a318ba64736f6c634300081c0033
Deployed Bytecode Sourcemap
168512:10355:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13231:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;15549:215;;;;;;;;;;-1:-1:-1;15549:215:0;;;;;:::i;:::-;;:::i;:::-;;;1288:14:1;;1281:22;1263:41;;1251:2;1236:18;15549:215:0;1123:187:1;168910:51:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1506:55:1;;;1488:74;;1476:2;1461:18;168910:51:0;1315:253:1;14333:99:0;;;;;;;;;;-1:-1:-1;14412:12:0;;14333:99;;;1719:25:1;;;1707:2;1692:18;14333:99:0;1573:177:1;174927:228:0;;;;;;;;;;-1:-1:-1;174927:228:0;;;;;:::i;:::-;;:::i;16374:283::-;;;;;;;;;;-1:-1:-1;16374:283:0;;;;;:::i;:::-;;:::i;14184:84::-;;;;;;;;;;-1:-1:-1;14184:84:0;;14258:2;2760:36:1;;2748:2;2733:18;14184:84:0;2618:184:1;135208:114:0;;;;;;;;;;;;;:::i;168638:31::-;;;;;;;;;;;;;;;;168968:38;;;;;;;;;;;;;;;175540:130;;;;;;;;;;-1:-1:-1;175540:130:0;;;;;:::i;:::-;-1:-1:-1;;;;;175633:29:0;175609:4;175633:29;;;:19;:29;;;;;;;;;175540:130;168872:29;;;;;;;;;;-1:-1:-1;168872:29:0;;;;;;;;173959:576;;;;;;;;;;-1:-1:-1;173959:576:0;;;;;:::i;:::-;;:::i;178659:205::-;;;;;;;;;;;;;:::i;14495:118::-;;;;;;;;;;-1:-1:-1;14495:118:0;;;;;:::i;:::-;-1:-1:-1;;;;;14587:18:0;14560:7;14587:18;;;;;;;;;;;;14495:118;137695:103;;;;;;;;;;;;;:::i;168601:30::-;;;;;;;;;;;;;;;;168765;;;;;;;;;;-1:-1:-1;168765:30:0;;;;-1:-1:-1;;;;;168765:30:0;;;176140:156;;;;;;;;;;-1:-1:-1;176140:156:0;;;;;:::i;:::-;-1:-1:-1;;;;;176254:34:0;176230:4;176254:34;;;:27;:34;;;;;;;;;176140:156;134934:161;;;;;;;;;;-1:-1:-1;134934:161:0;;;;;:::i;:::-;;:::i;129439:580::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;168676:35::-;;;;;;;;;;;;;;;;173472:479;;;;;;;;;;-1:-1:-1;173472:479:0;;;;;:::i;:::-;;:::i;173029:435::-;;;;;;;;;;-1:-1:-1;173029:435:0;;;;;:::i;:::-;;:::i;137020:87::-;;;;;;;;;;-1:-1:-1;137093:6:0;;-1:-1:-1;;;;;137093:6:0;137020:87;;13441:95;;;;;;;;;;;;;:::i;168720:36::-;;;;;;;;;;;;;;;175678:454;;;;;;;;;;-1:-1:-1;175678:454:0;;;;;:::i;:::-;;:::i;172160:429::-;;;;;;;;;;-1:-1:-1;172160:429:0;;;;;:::i;:::-;;:::i;14818:182::-;;;;;;;;;;-1:-1:-1;14818:182:0;;;;;:::i;:::-;;:::i;174543:376::-;;;;;;;;;;-1:-1:-1;174543:376:0;;;;;:::i;:::-;;:::i;134039:836::-;;;;;;;;;;-1:-1:-1;134039:836:0;;;;;:::i;:::-;;:::i;171662:490::-;;;;;;;;;;;;;:::i;175163:369::-;;;;;;;;;;-1:-1:-1;175163:369:0;;;;;:::i;:::-;;:::i;172597:424::-;;;;;;;;;;-1:-1:-1;172597:424:0;;;;;:::i;:::-;;:::i;15063:167::-;;;;;;;;;;-1:-1:-1;15063:167:0;;;;;:::i;:::-;-1:-1:-1;;;;;15195:18:0;;;15168:7;15195:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;15063:167;168832:33;;;;;;;;;;;;;;;;137953:220;;;;;;;;;;-1:-1:-1;137953:220:0;;;;;:::i;:::-;;:::i;13231:91::-;13276:13;13309:5;13302:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13231:91;:::o;15549:215::-;15647:4;4502:10;15703:31;4502:10;15719:7;15728:5;15703:8;:31::i;:::-;15752:4;15745:11;;;15549:215;;;;;:::o;174927:228::-;136906:13;:11;:13::i;:::-;175003:17:::1;::::0;:28;::::1;;:17;::::0;;::::1;:28;;::::0;174995:67:::1;;;::::0;-1:-1:-1;;;174995:67:0;;7421:2:1;174995:67:0::1;::::0;::::1;7403:21:1::0;7460:2;7440:18;;;7433:30;7499:28;7479:18;;;7472:56;7545:18;;174995:67:0::1;;;;;;;;;175075:17;:27:::0;;;::::1;::::0;::::1;;::::0;;::::1;::::0;;;175118:29:::1;::::0;1263:41:1;;;175118:29:0::1;::::0;1251:2:1;1236:18;175118:29:0::1;;;;;;;;174927:228:::0;:::o;16374:283::-;16495:4;4502:10;16553:37;16569:4;4502:10;16584:5;16553:15;:37::i;:::-;16601:26;16611:4;16617:2;16621:5;16601:9;:26::i;:::-;-1:-1:-1;16645:4:0;;16374:283;-1:-1:-1;;;;16374:283:0:o;135208:114::-;135267:7;135294:20;:18;:20::i;:::-;135287:27;;135208:114;:::o;173959:576::-;136906:13;:11;:13::i;:::-;174085:15:::1;::::0;-1:-1:-1;;;;;174085:15:0;;::::1;174065:35:::0;;::::1;::::0;174043:125:::1;;;::::0;-1:-1:-1;;;174043:125:0;;7776:2:1;174043:125:0::1;::::0;::::1;7758:21:1::0;7815:2;7795:18;;;7788:30;7854:34;7834:18;;;7827:62;7925:10;7905:18;;;7898:38;7953:19;;174043:125:0::1;7574:404:1::0;174043:125:0::1;-1:-1:-1::0;;;;;174201:30:0;::::1;174179:119;;;::::0;-1:-1:-1;;;174179:119:0;;8185:2:1;174179:119:0::1;::::0;::::1;8167:21:1::0;8224:2;8204:18;;;8197:30;8263:34;8243:18;;;8236:62;8334:9;8314:18;;;8307:37;8361:19;;174179:119:0::1;7983:403:1::0;174179:119:0::1;-1:-1:-1::0;;;;;171125:19:0;;;:23;174309:114:::1;;;::::0;-1:-1:-1;;;174309:114:0;;8593:2:1;174309:114:0::1;::::0;::::1;8575:21:1::0;8632:2;8612:18;;;8605:30;8671:34;8651:18;;;8644:62;8742:5;8722:18;;;8715:33;8765:19;;174309:114:0::1;8391:399:1::0;174309:114:0::1;174436:15;:34:::0;;;::::1;-1:-1:-1::0;;;;;174436:34:0;::::1;::::0;;::::1;::::0;;;174488:39:::1;::::0;::::1;::::0;-1:-1:-1;;174488:39:0::1;173959:576:::0;:::o;178659:205::-;178754:4;178705:28;14587:18;;;;;;;;;;;178781:24;178773:60;;;;-1:-1:-1;;;178773:60:0;;8997:2:1;178773:60:0;;;8979:21:1;9036:2;9016:18;;;9009:30;9075:25;9055:18;;;9048:53;9118:18;;178773:60:0;8795:347:1;178773:60:0;178846:10;:8;:10::i;:::-;178694:170;178659:205::o;137695:103::-;136906:13;:11;:13::i;:::-;137760:30:::1;137787:1;137760:18;:30::i;:::-;137695:103::o:0;134934:161::-;-1:-1:-1;;;;;131618:14:0;;135041:7;131618:14;;;:7;:14;;;;;;135068:19;131531:109;129439:580;129542:13;129570:18;129603:21;129639:15;129669:25;129709:12;129736:27;129844:13;:11;:13::i;:::-;129872:16;:14;:16::i;:::-;129984;;;129967:1;129984:16;;;;;;;;;129791:220;;;;-1:-1:-1;129791:220:0;;-1:-1:-1;129903:13:0;;-1:-1:-1;129939:4:0;;-1:-1:-1;129967:1:0;-1:-1:-1;129984:16:0;-1:-1:-1;129791:220:0;-1:-1:-1;129439:580:0:o;173472:479::-;136906:13;:11;:13::i;:::-;173604:20:::1;;173579:21;:45:::0;173557:134:::1;;;::::0;-1:-1:-1;;;173557:134:0;;9538:2:1;173557:134:0::1;::::0;::::1;9520:21:1::0;9577:2;9557:18;;;9550:30;9616:34;9596:18;;;9589:62;9687:9;9667:18;;;9660:37;9714:19;;173557:134:0::1;9336:403:1::0;173557:134:0::1;173749:5;173724:21;:30;;173702:126;;;::::0;-1:-1:-1;;;173702:126:0;;9946:2:1;173702:126:0::1;::::0;::::1;9928:21:1::0;9985:2;9965:18;;;9958:30;10024:34;10004:18;;;9997:62;10095:16;10075:18;;;10068:44;10129:19;;173702:126:0::1;9744:410:1::0;173702:126:0::1;173841:20;:44:::0;;;173903:40:::1;::::0;1719:25:1;;;173903:40:0::1;::::0;1707:2:1;1692:18;173903:40:0::1;1573:177:1::0;173029:435:0;136906:13;:11;:13::i;:::-;173149:16:::1;;173128:17;:37:::0;173106:122:::1;;;::::0;-1:-1:-1;;;173106:122:0;;10361:2:1;173106:122:0::1;::::0;::::1;10343:21:1::0;10400:2;10380:18;;;10373:30;10439:34;10419:18;;;10412:62;10510:5;10490:18;;;10483:33;10533:19;;173106:122:0::1;10159:399:1::0;173106:122:0::1;173282:5;173261:17;:26;;173239:118;;;::::0;-1:-1:-1;;;173239:118:0;;10765:2:1;173239:118:0::1;::::0;::::1;10747:21:1::0;10804:2;10784:18;;;10777:30;10843:34;10823:18;;;10816:62;10914:12;10894:18;;;10887:40;10944:19;;173239:118:0::1;10563:406:1::0;173239:118:0::1;173370:16;:36:::0;;;173424:32:::1;::::0;1719:25:1;;;173424:32:0::1;::::0;1707:2:1;1692:18;173424:32:0::1;1573:177:1::0;13441:95:0;13488:13;13521:7;13514:14;;;;;:::i;175678:454::-;136906:13;:11;:13::i;:::-;-1:-1:-1;;;;;175821:34:0;::::1;;::::0;;;:27:::1;:34;::::0;;;;;:45;::::1;;:34;::::0;;::::1;:45;;::::0;175799:122:::1;;;::::0;-1:-1:-1;;;175799:122:0;;11176:2:1;175799:122:0::1;::::0;::::1;11158:21:1::0;11215:2;11195:18;;;11188:30;11254:29;11234:18;;;11227:57;11301:18;;175799:122:0::1;10974:351:1::0;175799:122:0::1;175949:13;-1:-1:-1::0;;;;;175940:22:0::1;:5;-1:-1:-1::0;;;;;175940:22:0::1;::::0;175932:71:::1;;;::::0;-1:-1:-1;;;175932:71:0;;11532:2:1;175932:71:0::1;::::0;::::1;11514:21:1::0;11571:2;11551:18;;;11544:30;11610:34;11590:18;;;11583:62;11681:6;11661:18;;;11654:34;11705:19;;175932:71:0::1;11330:400:1::0;175932:71:0::1;-1:-1:-1::0;;;;;176016:34:0;::::1;;::::0;;;:27:::1;:34;::::0;;;;;;;;:44;;;::::1;::::0;::::1;;::::0;;::::1;::::0;;;176078:46;;1263:41:1;;;176078:46:0::1;::::0;1236:18:1;176078:46:0::1;;;;;;;;175678:454:::0;;:::o;172160:429::-;136906:13;:11;:13::i;:::-;172271:4:::1;-1:-1:-1::0;;;;;172253:23:0;::::1;::::0;172245:62:::1;;;::::0;-1:-1:-1;;;172245:62:0;;11937:2:1;172245:62:0::1;::::0;::::1;11919:21:1::0;11976:2;11956:18;;;11949:30;12015:28;11995:18;;;11988:56;12061:18;;172245:62:0::1;11735:350:1::0;172245:62:0::1;-1:-1:-1::0;;;;;172324:20:0;::::1;172320:118;;172361:44;::::0;-1:-1:-1;;;;;172361:21:0;::::1;::::0;172383::::1;172361:44:::0;::::1;;;::::0;::::1;::::0;;;172383:21;172361;:44;::::1;;;;;;;;;;;;;;;;;;;;172160:429:::0;;:::o;172320:118::-:1;172508:30;::::0;;;;172532:4:::1;172508:30;::::0;::::1;1488:74:1::0;172472:6:0;;172450:12:::1;::::0;-1:-1:-1;;;;;172508:15:0;::::1;::::0;::::1;::::0;1461:18:1;;172508:30:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;172490:48:::0;-1:-1:-1;172549:32:0::1;-1:-1:-1::0;;;;;172549:18:0;::::1;172568:3:::0;172490:48;172549:18:::1;:32::i;:::-;172234:355;;136930:1;172160:429:::0;;:::o;14818:182::-;14887:4;4502:10;14943:27;4502:10;14960:2;14964:5;14943:9;:27::i;174543:376::-;136906:13;:11;:13::i;:::-;174665:7:::1;174643:18;;:29:::0;174621:120:::1;;;::::0;-1:-1:-1;;;174621:120:0;;12481:2:1;174621:120:0::1;::::0;::::1;12463:21:1::0;12520:2;12500:18;;;12493:30;12559:34;12539:18;;;12532:62;12630:11;12610:18;;;12603:39;12659:19;;174621:120:0::1;12279:405:1::0;174621:120:0::1;174771:1;174760:7;:12;;174752:67;;;::::0;-1:-1:-1;;;174752:67:0;;12891:2:1;174752:67:0::1;::::0;::::1;12873:21:1::0;12930:2;12910:18;;;12903:30;12969:34;12949:18;;;12942:62;13040:12;13020:18;;;13013:40;13070:19;;174752:67:0::1;12689:406:1::0;174752:67:0::1;174832:18;:28:::0;;;174878:33:::1;::::0;1719:25:1;;;174878:33:0::1;::::0;1707:2:1;1692:18;174878:33:0::1;1573:177:1::0;134039:836:0;134269:8;134251:15;:26;134247:99;;;134301:33;;;;;;;;1719:25:1;;;1692:18;;134301:33:0;1573:177:1;134247:99:0;134358:18;133334:119;134466:5;134490:7;134516:5;134540:16;134550:5;-1:-1:-1;;;;;132128:14:0;131821:7;132128:14;;;:7;:14;;;;;:16;;;;;;;;;131761:402;134540:16;134403:195;;;;;;13387:25:1;;;;-1:-1:-1;;;;;13448:55:1;;;13428:18;;;13421:83;13540:55;;;;13520:18;;;13513:83;13612:18;;;13605:34;13655:19;;;13648:35;13699:19;;;13692:35;;;13359:19;;134403:195:0;;;;;;;;;;;;134379:230;;;;;;134358:251;;134622:12;134637:28;134654:10;134637:16;:28::i;:::-;134622:43;;134678:14;134695:28;134709:4;134715:1;134718;134721;134695:13;:28::i;:::-;134678:45;;134748:5;-1:-1:-1;;;;;134738:15:0;:6;-1:-1:-1;;;;;134738:15:0;;134734:90;;134777:35;;;;;-1:-1:-1;;;;;13930:55:1;;;134777:35:0;;;13912:74:1;14022:55;;14002:18;;;13995:83;13885:18;;134777:35:0;13738:346:1;134734:90:0;134836:31;134845:5;134852:7;134861:5;134836:8;:31::i;:::-;134236:639;;;134039:836;;;;;;;:::o;171662:490::-;171711:7;171735:13;171752:2;171735:19;171731:414;;-1:-1:-1;171778:42:0;;171662:490::o;171731:414::-;171842:13;171859:2;171842:19;171838:307;;-1:-1:-1;171885:42:0;;171662:490::o;171838:307::-;171949:13;171966:1;171949:18;:40;;;;171971:13;171988:1;171971:18;171949:40;171945:200;;;-1:-1:-1;172013:42:0;;171662:490::o;171945:200::-;172088:45;;-1:-1:-1;;;172088:45:0;;14291:2:1;172088:45:0;;;14273:21:1;14330:2;14310:18;;;14303:30;14369:34;14349:18;;;14342:62;14440:5;14420:18;;;14413:33;14463:19;;172088:45:0;14089:399:1;175163:369:0;136906:13;:11;:13::i;:::-;-1:-1:-1;;;;;175304:29:0;::::1;;::::0;;;:19:::1;:29;::::0;;;;;:44;::::1;;:29;::::0;;::::1;:44;;::::0;175282:124:::1;;;::::0;-1:-1:-1;;;175282:124:0;;14695:2:1;175282:124:0::1;::::0;::::1;14677:21:1::0;14734:2;14714:18;;;14707:30;14773:32;14753:18;;;14746:60;14823:18;;175282:124:0::1;14493:354:1::0;175282:124:0::1;-1:-1:-1::0;;;;;175419:29:0;::::1;;::::0;;;:19:::1;:29;::::0;;;;;;;;:43;;;::::1;::::0;::::1;;::::0;;::::1;::::0;;;175480:44;;1263:41:1;;;175480:44:0::1;::::0;1236:18:1;175480:44:0::1;1123:187:1::0;172597:424:0;136906:13;:11;:13::i;:::-;172714:15:::1;;172694:16;:35:::0;172672:119:::1;;;::::0;-1:-1:-1;;;172672:119:0;;15054:2:1;172672:119:0::1;::::0;::::1;15036:21:1::0;15093:2;15073:18;;;15066:30;15132:34;15112:18;;;15105:62;15203:4;15183:18;;;15176:32;15225:19;;172672:119:0::1;14852:398:1::0;172672:119:0::1;172844:5;172824:16;:25;;172802:116;;;::::0;-1:-1:-1;;;172802:116:0;;15457:2:1;172802:116:0::1;::::0;::::1;15439:21:1::0;15496:2;15476:18;;;15469:30;15535:34;15515:18;;;15508:62;15606:11;15586:18;;;15579:39;15635:19;;172802:116:0::1;15255:405:1::0;172802:116:0::1;172931:15;:34:::0;;;172983:30:::1;::::0;1719:25:1;;;172983:30:0::1;::::0;1707:2:1;1692:18;172983:30:0::1;1573:177:1::0;137953:220:0;136906:13;:11;:13::i;:::-;-1:-1:-1;;;;;138038:22:0;::::1;138034:93;;138084:31;::::0;::::1;::::0;;138112:1:::1;138084:31;::::0;::::1;1488:74:1::0;1461:18;;138084:31:0::1;1315:253:1::0;138034:93:0::1;138137:28;138156:8;138137:18;:28::i;20467:130::-:0;20552:37;20561:5;20568:7;20577:5;20584:4;20552:8;:37::i;137185:166::-;137093:6;;-1:-1:-1;;;;;137093:6:0;4502:10;137245:23;137241:103;;137292:40;;;;;4502:10;137292:40;;;1488:74:1;1461:18;;137292:40:0;1315:253:1;22242:603:0;-1:-1:-1;;;;;15195:18:0;;;22376:24;15195:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;22463:17;22443:37;;22439:399;;22520:5;22501:16;:24;22497:214;;;22553:142;;;;;-1:-1:-1;;;;;15885:55:1;;22553:142:0;;;15867:74:1;15957:18;;;15950:34;;;16000:18;;;15993:34;;;15840:18;;22553:142:0;15665:368:1;22497:214:0;22754:57;22763:5;22770:7;22798:5;22779:16;:24;22805:5;22754:8;:57::i;17042:308::-;-1:-1:-1;;;;;17126:18:0;;17122:88;;17168:30;;;;;17195:1;17168:30;;;1488:74:1;1461:18;;17168:30:0;1315:253:1;17122:88:0;-1:-1:-1;;;;;17224:16:0;;17220:88;;17264:32;;;;;17293:1;17264:32;;;1488:74:1;1461:18;;17264:32:0;1315:253:1;17220:88:0;17318:24;17326:4;17332:2;17336:5;17318:7;:24::i;127908:268::-;127961:7;127993:4;-1:-1:-1;;;;;128002:11:0;127985:28;;:63;;;;;128034:14;128017:13;:31;127985:63;127981:188;;;-1:-1:-1;128072:22:0;;127908:268::o;127981:188::-;128134:23;128307:204;;;126076:119;128307:204;;;18828:25:1;128372:11:0;18869:18:1;;;18862:34;;;;128406:14:0;18912:18:1;;;18905:34;128443:13:0;18955:18:1;;;18948:34;128487:4:0;18998:19:1;;;18991:84;128239:7:0;;18800:19:1;;128307:204:0;;;;;;;;;;;;128279:247;;;;;;128259:267;;128184:350;;177899:752;169172:8;:15;;;;;;;;177976:16:::1;::::0;;177990:1:::1;177976:16:::0;;;;;::::1;::::0;;-1:-1:-1;;177976:16:0::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;177976:16:0::1;177946:46;;178027:4;178003:10;178014:1;178003:13;;;;;;;;:::i;:::-;;;;;;:29;-1:-1:-1::0;;;;;178003:29:0::1;;;-1:-1:-1::0;;;;;178003:29:0::1;;;::::0;::::1;178059:15;-1:-1:-1::0;;;;;178059:20:0::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;178043:10;178054:1;178043:13;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;178043:38:0;;;::::1;:13;::::0;;::::1;::::0;;;;;;:38;178143:4:::1;178094:28;14587:18:::0;;;;;;;;;;;;178230:24;;178226:418:::1;;178527:15;::::0;178292:316:::1;::::0;;;;-1:-1:-1;;;;;178292:15:0::1;:88:::0;::::1;::::0;::::1;::::0;:316:::1;::::0;178407:20;;178454:1:::1;::::0;178482:10;;178527:15;;;::::1;::::0;178570::::1;::::0;178292:316:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;178271:362:::0;::::1;-1:-1:-1::0;;169210:8:0;:16;;;;;;-1:-1:-1;177899:752:0:o;138333:191::-;138426:6;;;-1:-1:-1;;;;;138443:17:0;;;;;;;;;;;138476:40;;138426:6;;;138443:17;138426:6;;138476:40;;138407:16;;138476:40;138396:128;138333:191;:::o;130348:128::-;130394:13;130427:41;:5;130454:13;130427:26;:41::i;130811:137::-;130860:13;130893:47;:8;130923:16;130893:29;:47::i;152941:162::-;153051:43;;;-1:-1:-1;;;;;17685:55:1;;153051:43:0;;;17667:74:1;17757:18;;;;17750:34;;;153051:43:0;;;;;;;;;;17640:18:1;;;;153051:43:0;;;;;;;;;;;;;;153024:71;;153044:5;;153024:19;:71::i;129176:207::-;129269:7;129309:66;129342:20;:18;:20::i;:::-;129364:10;114122:4;114116:11;114153:10;114141:23;;114194:4;114185:14;;114178:39;;;;114247:4;114238:14;;114231:34;114304:4;114289:20;;;113920:407;34272:370;34400:7;34421:17;34440:18;34460:16;34480:88;34505:4;34524:1;34540;34556;34480:10;:88::i;:::-;34420:148;;;;;;34579:28;34591:5;34598:8;34579:11;:28::i;:::-;-1:-1:-1;34625:9:0;;34272:370;-1:-1:-1;;;;;;34272:370:0:o;21464:486::-;-1:-1:-1;;;;;21620:19:0;;21616:91;;21663:32;;;;;21692:1;21663:32;;;1488:74:1;1461:18;;21663:32:0;1315:253:1;21616:91:0;-1:-1:-1;;;;;21721:21:0;;21717:92;;21766:31;;;;;21794:1;21766:31;;;1488:74:1;1461:18;;21766:31:0;1315:253:1;21717:92:0;-1:-1:-1;;;;;21819:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;21865:78;;;;21916:7;-1:-1:-1;;;;;21900:31:0;21909:5;-1:-1:-1;;;;;21900:31:0;;21925:5;21900:31;;;;1719:25:1;;1707:2;1692:18;;1573:177;21900:31:0;;;;;;;;21464:486;;;;:::o;176304:1587::-;-1:-1:-1;;;;;176439:20:0;;;;:47;;-1:-1:-1;;;;;;176463:23:0;;;176439:47;:62;;;-1:-1:-1;176490:11:0;;176439:62;176435:156;;;176518:40;176532:6;176540:9;176551:6;176518:13;:40::i;176435:156::-;176652:4;176603:28;14587:18;;;;;;;;;;;176710;;176686:42;;;;;;;176759:33;;-1:-1:-1;176784:8:0;;;;;;;176783:9;176759:33;:88;;;;-1:-1:-1;;;;;;176809:38:0;;;;;;:27;:38;;;;;;;;176759:88;:122;;;;-1:-1:-1;176864:17:0;;;;176759:122;:156;;;;-1:-1:-1;137093:6:0;;-1:-1:-1;;;;;176898:17:0;;;137093:6;;176898:17;;176759:156;:193;;;;-1:-1:-1;137093:6:0;;-1:-1:-1;;;;;176932:20:0;;;137093:6;;176932:20;;176759:193;176741:260;;;176979:10;:8;:10::i;:::-;-1:-1:-1;;;;;177049:27:0;;177013:12;177049:27;;;:19;:27;;;;;;177028:4;;177049:27;;;:61;;-1:-1:-1;;;;;;177080:30:0;;;;;;:19;:30;;;;;;;;177049:61;177045:109;;;-1:-1:-1;177137:5:0;177045:109;177170:7;177166:665;;;-1:-1:-1;;;;;177239:35:0;;177194:20;177239:35;;;:27;:35;;;;;;;;177235:373;;;177339:11;177329:6;177311:15;;:24;;;;:::i;:::-;177310:40;;;;:::i;:::-;177295:55;;177235:373;;;-1:-1:-1;;;;;177376:38:0;;;;;;:27;:38;;;;;;;;177372:236;;;177480:11;177470:6;177451:16;;:25;;;;:::i;177372:236::-;177581:11;177571:6;177548:20;;:29;;;;:::i;:::-;177547:45;;;;:::i;:::-;177532:60;;177372:236;177646:12;177679:15;;177675:145;;177715:21;177725:11;177715:21;;:::i;:::-;;;177755:49;177769:6;177785:4;177792:11;177755:13;:49::i;:::-;177179:652;;177166:665;177843:40;177857:6;177865:9;177876:6;177843:13;:40::i;:::-;176424:1467;;;176304:1587;;;:::o;122313:298::-;122432:13;120246:66;122462:46;;122458:146;;122532:15;122541:5;122532:8;:15::i;:::-;122525:22;;;;122458:146;122587:5;122580:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159970:896;160051:18;160080:19;160340:4;160320:1;160296:4;160290:11;160266:4;160260;160256:15;160236:1;160212:5;160188;160165:194;160413:7;160403:180;;160458:4;160452:11;160504:16;160501:1;160496:3;160481:40;160551:16;160546:3;160539:29;160403:180;-1:-1:-1;;160662:1:0;160656:8;160611:16;;-1:-1:-1;160705:15:0;;:68;;160757:11;160772:1;160757:16;;160705:68;;;-1:-1:-1;;;;;160723:26:0;;;:31;160705:68;160687:172;;;160807:40;;;;;-1:-1:-1;;;;;1506:55:1;;160807:40:0;;;1488:74:1;1461:18;;160807:40:0;1315:253:1;32487:1646:0;32645:17;;;33641:66;33615:92;;33597:203;;;-1:-1:-1;33750:1:0;;-1:-1:-1;33754:30:0;;-1:-1:-1;33786:1:0;33734:54;;33597:203;33914:24;;;33897:14;33914:24;;;;;;;;;19313:25:1;;;19386:4;19374:17;;19354:18;;;19347:45;;;;19408:18;;;19401:34;;;19451:18;;;19444:34;;;33914:24:0;;19285:19:1;;33914:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;33914:24:0;;;;;;-1:-1:-1;;;;;;;33953:20:0;;33949:115;;-1:-1:-1;34006:1:0;;-1:-1:-1;34010:29:0;;-1:-1:-1;34006:1:0;;-1:-1:-1;33990:62:0;;33949:115;34084:6;-1:-1:-1;34092:20:0;;-1:-1:-1;34092:20:0;;-1:-1:-1;32487:1646:0;;;;;;;;;:::o;34780:542::-;34876:20;34867:5;:29;;;;;;;;:::i;:::-;;34863:452;;34780:542;;:::o;34863:452::-;34974:29;34965:5;:38;;;;;;;;:::i;:::-;;34961:354;;35027:23;;;;;;;;;;;;;;34961:354;35081:35;35072:5;:44;;;;;;;;:::i;:::-;;35068:247;;35140:46;;;;;;;;1719:25:1;;;1692:18;;35140:46:0;1573:177:1;35068:247:0;35217:30;35208:5;:39;;;;;;;;:::i;:::-;;35204:111;;35271:32;;;;;;;;1719:25:1;;;1692:18;;35271:32:0;1573:177:1;17674:1135:0;-1:-1:-1;;;;;17764:18:0;;17760:552;;17918:5;17902:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;17760:552:0;;-1:-1:-1;17760:552:0;;-1:-1:-1;;;;;17978:15:0;;17956:19;17978:15;;;;;;;;;;;18012:19;;;18008:117;;;18059:50;;;;;-1:-1:-1;;;;;15885:55:1;;18059:50:0;;;15867:74:1;15957:18;;;15950:34;;;16000:18;;;15993:34;;;15840:18;;18059:50:0;15665:368:1;18008:117:0;-1:-1:-1;;;;;18248:15:0;;:9;:15;;;;;;;;;;18266:19;;;;18248:37;;17760:552;-1:-1:-1;;;;;18328:16:0;;18324:435;;18494:12;:21;;;;;;;18324:435;;;-1:-1:-1;;;;;18710:13:0;;:9;:13;;;;;;;;;;:22;;;;;;18324:435;18791:2;-1:-1:-1;;;;;18776:25:0;18785:4;-1:-1:-1;;;;;18776:25:0;;18795:5;18776:25;;;;1719::1;;1707:2;1692:18;;1573:177;18776:25:0;;;;;;;;17674:1135;;;:::o;120971:387::-;121030:13;121056:11;121070:16;121081:4;121070:10;:16::i;:::-;121196:14;;;121207:2;121196:14;;;;;;;;;121056:30;;-1:-1:-1;121176:17:0;;121196:14;;;;;;;;;-1:-1:-1;;;121261:16:0;;;-1:-1:-1;121307:4:0;121298:14;;121291:28;;;;-1:-1:-1;121261:16:0;120971:387::o;121435:251::-;121496:7;121569:4;121533:40;;121597:2;121588:11;;121584:71;;;121623:20;;;;;;;;;;;;;;14:348:1;56:3;94:5;88:12;121:6;116:3;109:19;177:6;170:4;163:5;159:16;152:4;147:3;143:14;137:47;229:1;222:4;213:6;208:3;204:16;200:27;193:38;351:4;281:66;276:2;268:6;264:15;260:88;255:3;251:98;247:109;240:116;;;14:348;;;;:::o;367:220::-;516:2;505:9;498:21;479:4;536:45;577:2;566:9;562:18;554:6;536:45;:::i;:::-;528:53;367:220;-1:-1:-1;;;367:220:1:o;592:154::-;-1:-1:-1;;;;;671:5:1;667:54;660:5;657:65;647:93;;736:1;733;726:12;751:367;819:6;827;880:2;868:9;859:7;855:23;851:32;848:52;;;896:1;893;886:12;848:52;935:9;922:23;954:31;979:5;954:31;:::i;:::-;1004:5;1082:2;1067:18;;;;1054:32;;-1:-1:-1;;;751:367:1:o;1755:160::-;1820:20;;1876:13;;1869:21;1859:32;;1849:60;;1905:1;1902;1895:12;1849:60;1755:160;;;:::o;1920:180::-;1976:6;2029:2;2017:9;2008:7;2004:23;2000:32;1997:52;;;2045:1;2042;2035:12;1997:52;2068:26;2084:9;2068:26;:::i;2105:508::-;2182:6;2190;2198;2251:2;2239:9;2230:7;2226:23;2222:32;2219:52;;;2267:1;2264;2257:12;2219:52;2306:9;2293:23;2325:31;2350:5;2325:31;:::i;:::-;2375:5;-1:-1:-1;2432:2:1;2417:18;;2404:32;2445:33;2404:32;2445:33;:::i;:::-;2105:508;;2497:7;;-1:-1:-1;;;2577:2:1;2562:18;;;;2549:32;;2105:508::o;3220:247::-;3279:6;3332:2;3320:9;3311:7;3307:23;3303:32;3300:52;;;3348:1;3345;3338:12;3300:52;3387:9;3374:23;3406:31;3431:5;3406:31;:::i;3472:1314::-;3869:66;3861:6;3857:79;3846:9;3839:98;3973:3;3968:2;3957:9;3953:18;3946:31;3820:4;4000:46;4041:3;4030:9;4026:19;4018:6;4000:46;:::i;:::-;4094:9;4086:6;4082:22;4077:2;4066:9;4062:18;4055:50;4128:33;4154:6;4146;4128:33;:::i;:::-;4192:2;4177:18;;4170:34;;;-1:-1:-1;;;;;4241:55:1;;4235:3;4220:19;;4213:84;4328:3;4313:19;;4306:35;;;4378:22;;;4372:3;4357:19;;4350:51;4450:13;;4472:22;;;4522:2;4548:15;;;;-1:-1:-1;4510:15:1;;;;-1:-1:-1;4591:169:1;4605:6;4602:1;4599:13;4591:169;;;4666:13;;4654:26;;4709:2;4735:15;;;;4700:12;;;;4627:1;4620:9;4591:169;;;-1:-1:-1;4777:3:1;;3472:1314;-1:-1:-1;;;;;;;;;;;3472:1314:1:o;4791:226::-;4850:6;4903:2;4891:9;4882:7;4878:23;4874:32;4871:52;;;4919:1;4916;4909:12;4871:52;-1:-1:-1;4964:23:1;;4791:226;-1:-1:-1;4791:226:1:o;5022:315::-;5087:6;5095;5148:2;5136:9;5127:7;5123:23;5119:32;5116:52;;;5164:1;5161;5154:12;5116:52;5203:9;5190:23;5222:31;5247:5;5222:31;:::i;:::-;5272:5;-1:-1:-1;5296:35:1;5327:2;5312:18;;5296:35;:::i;:::-;5286:45;;5022:315;;;;;:::o;5342:388::-;5410:6;5418;5471:2;5459:9;5450:7;5446:23;5442:32;5439:52;;;5487:1;5484;5477:12;5439:52;5526:9;5513:23;5545:31;5570:5;5545:31;:::i;:::-;5595:5;-1:-1:-1;5652:2:1;5637:18;;5624:32;5665:33;5624:32;5665:33;:::i;:::-;5717:7;5707:17;;;5342:388;;;;;:::o;5735:1037::-;5846:6;5854;5862;5870;5878;5886;5894;5947:3;5935:9;5926:7;5922:23;5918:33;5915:53;;;5964:1;5961;5954:12;5915:53;6003:9;5990:23;6022:31;6047:5;6022:31;:::i;:::-;6072:5;-1:-1:-1;6129:2:1;6114:18;;6101:32;6142:33;6101:32;6142:33;:::i;:::-;6194:7;-1:-1:-1;6274:2:1;6259:18;;6246:32;;-1:-1:-1;6377:2:1;6362:18;;6349:32;;-1:-1:-1;6459:3:1;6444:19;;6431:33;6508:4;6495:18;;6483:31;;6473:59;;6528:1;6525;6518:12;6473:59;5735:1037;;;;-1:-1:-1;5735:1037:1;;;;6551:7;6631:3;6616:19;;6603:33;;-1:-1:-1;6735:3:1;6720:19;;;6707:33;;5735:1037;-1:-1:-1;;5735:1037:1:o;6777:437::-;6856:1;6852:12;;;;6899;;;6920:61;;6974:4;6966:6;6962:17;6952:27;;6920:61;7027:2;7019:6;7016:14;6996:18;6993:38;6990:218;;7064:77;7061:1;7054:88;7165:4;7162:1;7155:15;7193:4;7190:1;7183:15;6990:218;;6777:437;;;:::o;12090:184::-;12160:6;12213:2;12201:9;12192:7;12188:23;12184:32;12181:52;;;12229:1;12226;12219:12;12181:52;-1:-1:-1;12252:16:1;;12090:184;-1:-1:-1;12090:184:1:o;16038:::-;16090:77;16087:1;16080:88;16187:4;16184:1;16177:15;16211:4;16208:1;16201:15;16227:251;16297:6;16350:2;16338:9;16329:7;16325:23;16321:32;16318:52;;;16366:1;16363;16356:12;16318:52;16398:9;16392:16;16417:31;16442:5;16417:31;:::i;16483:1005::-;16745:4;16793:3;16782:9;16778:19;16824:6;16813:9;16806:25;16867:6;16862:2;16851:9;16847:18;16840:34;16910:3;16905:2;16894:9;16890:18;16883:31;16934:6;16969;16963:13;17000:6;16992;16985:22;17038:3;17027:9;17023:19;17016:26;;17077:2;17069:6;17065:15;17051:29;;17098:1;17108:218;17122:6;17119:1;17116:13;17108:218;;;17187:13;;-1:-1:-1;;;;;17183:62:1;17171:75;;17275:2;17301:15;;;;17266:12;;;;17144:1;17137:9;17108:218;;;-1:-1:-1;;;;;;;17382:55:1;;;;17377:2;17362:18;;17355:83;-1:-1:-1;;17469:3:1;17454:19;17447:35;17343:3;16483:1005;-1:-1:-1;;;16483:1005:1:o;17795:184::-;17847:77;17844:1;17837:88;17944:4;17941:1;17934:15;17968:4;17965:1;17958:15;17984:168;18057:9;;;18088;;18105:15;;;18099:22;;18085:37;18075:71;;18126:18;;:::i;18157:274::-;18197:1;18223;18213:189;;18258:77;18255:1;18248:88;18359:4;18356:1;18349:15;18387:4;18384:1;18377:15;18213:189;-1:-1:-1;18416:9:1;;18157:274::o;18436:128::-;18503:9;;;18524:11;;;18521:37;;;18538:18;;:::i;19489:184::-;19541:77;19538:1;19531:88;19638:4;19635:1;19628:15;19662:4;19659:1;19652:15;19678:125;19743:9;;;19764:10;;;19761:36;;;19777:18;;:::i
Swarm Source
ipfs://101259a872be53a5ee472c96f2303dd6bbe9535ad95566d6693ab772f3a318ba
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.