ERC-20
Overview
Max Total Supply
100,000,000 GLDS
Holders
26
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
0.000000000027504388 GLDSValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
Glades
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2025-01-22 */ // File: @openzeppelin/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/token/ERC20/extensions/ERC20Burnable.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.20; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys a `value` amount of tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 value) public virtual { _burn(_msgSender(), value); } /** * @dev Destroys a `value` amount of tokens from `account`, deducting from * the caller's allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `value`. */ function burnFrom(address account, uint256 value) public virtual { _spendAllowance(account, _msgSender(), value); _burn(account, value); } } // File: @openzeppelin/[email protected]/utils/Pausable.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { bool private _paused; /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File: @openzeppelin/[email protected]/token/ERC20/extensions/ERC20Pausable.sol // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Pausable.sol) pragma solidity ^0.8.20; /** * @dev ERC-20 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. * * IMPORTANT: This contract does not include public pause and unpause functions. In * addition to inheriting this contract, you must define both functions, invoking the * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will * make the contract pause mechanism of the contract unreachable, and thus unusable. */ abstract contract ERC20Pausable is ERC20, Pausable { /** * @dev See {ERC20-_update}. * * Requirements: * * - the contract must not be paused. */ function _update(address from, address to, uint256 value) internal virtual override whenNotPaused { super._update(from, to, value); } } // File: @openzeppelin/[email protected]/access/IAccessControl.sol // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; } // File: @openzeppelin/[email protected]/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/[email protected]/utils/introspection/ERC165.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/[email protected]/access/AccessControl.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } } // File: @openzeppelin/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/utils/structs/EnumerableSet.sol // OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; assembly ("memory-safe") { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly ("memory-safe") { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly ("memory-safe") { result := store } return result; } } // File: contracts/Blacklistable.sol /** * Copyright (c) 2018-2020 CENTRE SECZ * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ pragma solidity 0.8.28; /** * @title Blacklistable Token * @dev Allows accounts to be blacklisted by a "blacklister" role */ abstract contract Blacklistable is Context { mapping(address => bool) internal blacklisted; event Blacklisted(address indexed _account); event Unblacklisted(address indexed _account); /** * @dev Throws if argument account is blacklisted * @param _account The address to check */ modifier notBlacklisted(address _account) { require( !blacklisted[_account], "Blacklistable: account is blacklisted" ); _; } /** * @dev Checks if account is blacklisted * @param _account The address to check */ function isBlacklisted(address _account) external view returns (bool) { return blacklisted[_account]; } /** * @dev Adds account to blacklist * @param _account The address to blacklist */ function _blacklist(address _account) internal virtual { blacklisted[_account] = true; emit Blacklisted(_account); } /** * @dev Removes account from blacklist * @param _account The address to remove from the blacklist */ function _unblacklist(address _account) internal virtual { blacklisted[_account] = false; emit Unblacklisted(_account); } } // File: contracts/Glades.sol pragma solidity ^0.8.28; contract Glades is ERC20, ERC20Burnable, ERC20Pausable, AccessControl, ERC20Permit, Blacklistable { using EnumerableSet for EnumerableSet.AddressSet; bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); bytes32 public constant BLACKLISTER_ROLE = keccak256("BLACKLISTER_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant TAX_ROLE = keccak256("TAX_ROLE"); address public taxReceiver; uint16 public buyTaxBps; uint16 public sellTaxBps; uint16 public transferTaxBps; uint16 public buyLimit; // Track which addresses do not incur tax mapping(address => bool) public excludedFromTax; // Track which pairs should be taxed (i.e., recognized as swap pairs) EnumerableSet.AddressSet private swapV2Pairs; event TaxReceiverSet(address indexed receiver); event TaxesSet(uint16 buyTaxBps, uint16 sellTaxBps, uint16 transferTaxBps); event ExcludedFromTax(address indexed target); event IncludedInTax(address indexed target); event NewTaxableSwapPair(address indexed pair); constructor() ERC20("Glades", "GLDS") ERC20Permit("Glades") { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(PAUSER_ROLE, msg.sender); _grantRole(BLACKLISTER_ROLE, msg.sender); _grantRole(MINTER_ROLE, msg.sender); _grantRole(TAX_ROLE, msg.sender); buyLimit = 2; // Mint initial supply to deployer _mint(msg.sender, 100000000 * 10 ** decimals()); } function pause() public onlyRole(PAUSER_ROLE) { _pause(); } function unpause() public onlyRole(PAUSER_ROLE) { _unpause(); } function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) { _mint(to, amount); } function blacklist(address account) public onlyRole(BLACKLISTER_ROLE) { _blacklist(account); } function unblacklist(address account) public onlyRole(BLACKLISTER_ROLE) { _unblacklist(account); } // ------------------------------------------------------------------------ // Override transfer(...) to apply buy/sell/transfer tax logic // ------------------------------------------------------------------------ function transfer(address to, uint256 amount) public override returns (bool) { _taxedTransfer(msg.sender, to, amount); return true; } // ------------------------------------------------------------------------ // Override transferFrom(...) to also apply buy/sell/transfer tax logic // ------------------------------------------------------------------------ function transferFrom(address from, address to, uint256 amount) public override returns (bool) { // Standard ERC20 allowance check uint256 currentAllowance = allowance(from, msg.sender); require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); _approve(from, msg.sender, currentAllowance - amount); _taxedTransfer(from, to, amount); return true; } // ------------------------------------------------------------------------ // Private function that unifies the logic for transfer and transferFrom // ------------------------------------------------------------------------ function _taxedTransfer(address from, address to, uint256 amount) private { // If the recipient (or sender) is excluded from tax, skip any checks or taxes if (excludedFromTax[from] || excludedFromTax[to]) { _transfer(from, to, amount); return; } // Check if this is a sell (to a swap pair), apply sell tax if (swapV2Pairs.contains(to)) { if (sellTaxBps > 0) { _transferTaxed(from, to, amount, sellTaxBps); } else { _transfer(from, to, amount); } // Check if this is a buy (from a swap pair), apply buy limit + buy tax } else if (swapV2Pairs.contains(from)) { // Enforce X% limit of the total supply on each buy require( amount <= (totalSupply() * buyLimit) / 100, "GLDS: Buy exceeds buy limit % of total supply" ); if (buyTaxBps > 0) { _transferTaxed(from, to, amount, buyTaxBps); } else { _transfer(from, to, amount); } // Otherwise, apply transfer tax if any } else if (transferTaxBps > 0) { _transferTaxed(from, to, amount, transferTaxBps); // If no condition matches, just do a normal transfer } else { _transfer(from, to, amount); } } // ------------------------------------------------------------------------ // Internal function to handle the actual taxed transfer // ------------------------------------------------------------------------ function _transferTaxed( address from, address to, uint256 amount, uint16 taxBps ) private { uint256 taxAmount = (amount * taxBps) / 10000; uint256 leftAmount = amount - taxAmount; require(taxReceiver != address(0), "GLDS: taxReceiver is the zero address"); // First transfer the tax to the taxReceiver _transfer(from, taxReceiver, taxAmount); // Then transfer the remainder to the intended recipient _transfer(from, to, leftAmount); } // ----------------------------------------- // Tax & Swap Pair Configuration // ----------------------------------------- function setTaxReceiver(address receiver) external onlyRole(TAX_ROLE) { require(receiver != address(0), "GLDS: Cannot set tax receiver to the zero address!"); taxReceiver = receiver; emit TaxReceiverSet(receiver); } function setTaxes(uint16 buyTax, uint16 sellTax, uint16 transferTax) external onlyRole(TAX_ROLE) { require(buyTax <= 2000, "GLDS: buy tax is too high!"); require(sellTax <= 2000, "GLDS: sell tax is too high!"); require(transferTax <= 2000, "GLDS: transfer tax is too high!"); buyTaxBps = buyTax; sellTaxBps = sellTax; transferTaxBps = transferTax; emit TaxesSet(buyTax, sellTax, transferTax); } function excludeFromTax(address target) external onlyRole(TAX_ROLE) { excludedFromTax[target] = true; emit ExcludedFromTax(target); } function includeInTax(address target) external onlyRole(TAX_ROLE) { excludedFromTax[target] = false; emit IncludedInTax(target); } function addTaxableSwapPair(address pairAddress) external onlyRole(TAX_ROLE) { require(!swapV2Pairs.contains(pairAddress), "GLDS: SwapV2Pair already added"); swapV2Pairs.add(pairAddress); emit NewTaxableSwapPair(pairAddress); } function isTaxablePair(address pair) public view returns (bool) { return swapV2Pairs.contains(pair); } function setBuyLimit(uint16 newBuyLimit) external onlyRole(TAX_ROLE) { require(newBuyLimit <= 100, "GLDS: Max buy limit is too high!"); require(newBuyLimit > 0, "GLDS: Max buy limit is too low!"); buyLimit = newBuyLimit; } // ----------------------------------------- // Required overrides // ----------------------------------------- // Make sure that pausable checks and blacklisting checks still apply function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Pausable) { super._update(from, to, value); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","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":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_account","type":"address"}],"name":"Blacklisted","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"}],"name":"ExcludedFromTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"}],"name":"IncludedInTax","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"}],"name":"NewTaxableSwapPair","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"}],"name":"TaxReceiverSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"buyTaxBps","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"sellTaxBps","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"transferTaxBps","type":"uint16"}],"name":"TaxesSet","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":"_account","type":"address"}],"name":"Unblacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BLACKLISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TAX_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pairAddress","type":"address"}],"name":"addTaxableSwapPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"blacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyLimit","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyTaxBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"excludeFromTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"excludedFromTax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"includeInTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"isTaxablePair","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellTaxBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"newBuyLimit","type":"uint16"}],"name":"setBuyLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"setTaxReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"buyTax","type":"uint16"},{"internalType":"uint16","name":"sellTax","type":"uint16"},{"internalType":"uint16","name":"transferTax","type":"uint16"}],"name":"setTaxes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","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":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferTaxBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unblacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610160604052348015610010575f5ffd5b506040518060400160405280600681526020017f476c616465730000000000000000000000000000000000000000000000000000815250806040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600681526020017f476c6164657300000000000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f474c44530000000000000000000000000000000000000000000000000000000081525081600390816100f99190610af1565b5080600490816101099190610af1565b5050505f60055f6101000a81548160ff02191690831515021790555061013960078361030260201b90919060201c565b610120818152505061015560088261030260201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a0818152505061019261034f60201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050506101e25f5f1b336103a960201b60201c565b506102137f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336103a960201b60201c565b506102447f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e9336103a960201b60201c565b506102757f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336103a960201b60201c565b506102a67f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac336103a960201b60201c565b506002600b601a6101000a81548161ffff021916908361ffff1602179055506102fd336102d761049f60201b60201c565b600a6102e39190610d28565b6305f5e1006102f29190610d72565b6104a760201b60201c565b61101d565b5f6020835110156103235761031c8361052c60201b60201c565b9050610349565b826103338361059160201b60201c565b5f0190816103419190610af1565b5060ff5f1b90505b92915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e05161010051463060405160200161038e959493929190610e19565b60405160208183030381529060405280519060200120905090565b5f6103ba838361059a60201b60201c565b61049557600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506104326105fe60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610499565b5f90505b92915050565b5f6012905090565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610517575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161050e9190610e6a565b60405180910390fd5b6105285f838361060560201b60201c565b5050565b5f5f829050601f8151111561057857826040517f305a27a900000000000000000000000000000000000000000000000000000000815260040161056f9190610ee9565b60405180910390fd5b80518161058490610f36565b5f1c175f1b915050919050565b5f819050919050565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b61061683838361061b60201b60201c565b505050565b61062961063f60201b60201c565b61063a83838361068660201b60201c565b505050565b61064d61089f60201b60201c565b15610684576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106d6578060025f8282546106ca9190610f9c565b925050819055506107a4565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561075f578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161075693929190610fcf565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036107eb578060025f8282540392505081905550610835565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516108929190611004565b60405180910390a3505050565b5f60055f9054906101000a900460ff16905090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061092f57607f821691505b602082108103610942576109416108eb565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026109a47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610969565b6109ae8683610969565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6109f26109ed6109e8846109c6565b6109cf565b6109c6565b9050919050565b5f819050919050565b610a0b836109d8565b610a1f610a17826109f9565b848454610975565b825550505050565b5f5f905090565b610a36610a27565b610a41818484610a02565b505050565b5b81811015610a6457610a595f82610a2e565b600181019050610a47565b5050565b601f821115610aa957610a7a81610948565b610a838461095a565b81016020851015610a92578190505b610aa6610a9e8561095a565b830182610a46565b50505b505050565b5f82821c905092915050565b5f610ac95f1984600802610aae565b1980831691505092915050565b5f610ae18383610aba565b9150826002028217905092915050565b610afa826108b4565b67ffffffffffffffff811115610b1357610b126108be565b5b610b1d8254610918565b610b28828285610a68565b5f60209050601f831160018114610b59575f8415610b47578287015190505b610b518582610ad6565b865550610bb8565b601f198416610b6786610948565b5f5b82811015610b8e57848901518255600182019150602085019450602081019050610b69565b86831015610bab5784890151610ba7601f891682610aba565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b6001851115610c4257808604811115610c1e57610c1d610bc0565b5b6001851615610c2d5780820291505b8081029050610c3b85610bed565b9450610c02565b94509492505050565b5f82610c5a5760019050610d15565b81610c67575f9050610d15565b8160018114610c7d5760028114610c8757610cb6565b6001915050610d15565b60ff841115610c9957610c98610bc0565b5b8360020a915084821115610cb057610caf610bc0565b5b50610d15565b5060208310610133831016604e8410600b8410161715610ceb5782820a905083811115610ce657610ce5610bc0565b5b610d15565b610cf88484846001610bf9565b92509050818404811115610d0f57610d0e610bc0565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610d32826109c6565b9150610d3d83610d1c565b9250610d6a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484610c4b565b905092915050565b5f610d7c826109c6565b9150610d87836109c6565b9250828202610d95816109c6565b91508282048414831517610dac57610dab610bc0565b5b5092915050565b5f819050919050565b610dc581610db3565b82525050565b610dd4816109c6565b82525050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610e0382610dda565b9050919050565b610e1381610df9565b82525050565b5f60a082019050610e2c5f830188610dbc565b610e396020830187610dbc565b610e466040830186610dbc565b610e536060830185610dcb565b610e606080830184610e0a565b9695505050505050565b5f602082019050610e7d5f830184610e0a565b92915050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610ebb826108b4565b610ec58185610e83565b9350610ed5818560208601610e93565b610ede81610ea1565b840191505092915050565b5f6020820190508181035f830152610f018184610eb1565b905092915050565b5f81519050919050565b5f819050602082019050919050565b5f610f2d8251610db3565b80915050919050565b5f610f4082610f09565b82610f4a84610f13565b9050610f5581610f22565b92506020821015610f9557610f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802610969565b831692505b5050919050565b5f610fa6826109c6565b9150610fb1836109c6565b9250828201905080821115610fc957610fc8610bc0565b5b92915050565b5f606082019050610fe25f830186610e0a565b610fef6020830185610dcb565b610ffc6040830184610dcb565b949350505050565b5f6020820190506110175f830184610dcb565b92915050565b60805160a05160c05160e051610100516101205161014051613e2261106e5f395f61211701525f6120dc01525f6126d001525f6126af01525f611ba901525f611bff01525f611c280152613e225ff3fe608060405234801561000f575f5ffd5b5060043610610288575f3560e01c80637ecebe001161015a578063cd8de42c116100cc578063e17c4c7411610085578063e17c4c74146107c6578063e63ab1e9146107e2578063e6ef73d614610800578063f515e6f21461081e578063f9f92be41461083c578063fe575a871461085857610288565b8063cd8de42c14610706578063cffd129c14610722578063d505accf14610740578063d53913931461075c578063d547741f1461077a578063dd62ed3e1461079657610288565b8063989763ef1161011e578063989763ef1461061c578063a217fddf1461064c578063a9059cbb1461066a578063b8a09b711461069a578063c473413a146106ca578063c4e48398146106e857610288565b80637ecebe00146105705780638456cb59146105a057806384b0196e146105aa57806391d14854146105ce57806395d89b41146105fe57610288565b806336568abe116101fe5780635c975abb116101b75780635c975abb146104b257806360d1259e146104d057806370a08231146104ec57806375e3661e1461051c5780637747b3321461053857806379cc67901461055457610288565b806336568abe1461041a5780633f4ba83a1461043657806340c10f191461044057806342966c681461045c57806344be2eae14610478578063589210d91461049457610288565b806323b872dd1161025057806323b872dd14610346578063248a9ca3146103765780632f2ff15d146103a6578063313ce567146103c257806332cde664146103e05780633644e515146103fc57610288565b806301ffc9a71461028c57806306fdde03146102bc57806308249db8146102da578063095ea7b3146102f857806318160ddd14610328575b5f5ffd5b6102a660048036038101906102a19190612eb8565b610888565b6040516102b39190612efd565b60405180910390f35b6102c4610901565b6040516102d19190612f86565b60405180910390f35b6102e2610991565b6040516102ef9190612fbe565b60405180910390f35b610312600480360381019061030d9190613064565b6109b5565b60405161031f9190612efd565b60405180910390f35b6103306109d7565b60405161033d91906130b1565b60405180910390f35b610360600480360381019061035b91906130ca565b6109e0565b60405161036d9190612efd565b60405180910390f35b610390600480360381019061038b9190613144565b610a5e565b60405161039d9190612fbe565b60405180910390f35b6103c060048036038101906103bb919061316f565b610a7b565b005b6103ca610a9d565b6040516103d791906131c8565b60405180910390f35b6103fa60048036038101906103f59190613218565b610aa5565b005b610404610c42565b6040516104119190612fbe565b60405180910390f35b610434600480360381019061042f919061316f565b610c50565b005b61043e610ccb565b005b61045a60048036038101906104559190613064565b610d00565b005b61047660048036038101906104719190613268565b610d39565b005b610492600480360381019061048d9190613293565b610d4d565b005b61049c610e27565b6040516104a991906132cd565b60405180910390f35b6104ba610e3b565b6040516104c79190612efd565b60405180910390f35b6104ea60048036038101906104e59190613293565b610e50565b005b61050660048036038101906105019190613293565b610f16565b60405161051391906130b1565b60405180910390f35b61053660048036038101906105319190613293565b610f5b565b005b610552600480360381019061054d91906132e6565b610f92565b005b61056e60048036038101906105699190613064565b61106b565b005b61058a60048036038101906105859190613293565b61108b565b60405161059791906130b1565b60405180910390f35b6105a861109c565b005b6105b26110d1565b6040516105c59796959493929190613411565b60405180910390f35b6105e860048036038101906105e3919061316f565b611176565b6040516105f59190612efd565b60405180910390f35b6106066111da565b6040516106139190612f86565b60405180910390f35b61063660048036038101906106319190613293565b61126a565b6040516106439190612efd565b60405180910390f35b610654611287565b6040516106619190612fbe565b60405180910390f35b610684600480360381019061067f9190613064565b61128d565b6040516106919190612efd565b60405180910390f35b6106b460048036038101906106af9190613293565b6112a3565b6040516106c19190612efd565b60405180910390f35b6106d26112bf565b6040516106df91906132cd565b60405180910390f35b6106f06112d3565b6040516106fd91906132cd565b60405180910390f35b610720600480360381019061071b9190613293565b6112e7565b005b61072a611406565b60405161073791906132cd565b60405180910390f35b61075a600480360381019061075591906134bd565b61141a565b005b61076461155f565b6040516107719190612fbe565b60405180910390f35b610794600480360381019061078f919061316f565b611583565b005b6107b060048036038101906107ab919061355a565b6115a5565b6040516107bd91906130b1565b60405180910390f35b6107e060048036038101906107db9190613293565b611627565b005b6107ea6116ec565b6040516107f79190612fbe565b60405180910390f35b610808611710565b6040516108159190613598565b60405180910390f35b610826611735565b6040516108339190612fbe565b60405180910390f35b61085660048036038101906108519190613293565b611759565b005b610872600480360381019061086d9190613293565b611790565b60405161087f9190612efd565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108fa57506108f9826117e2565b5b9050919050565b606060038054610910906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461093c906135de565b80156109875780601f1061095e57610100808354040283529160200191610987565b820191905f5260205f20905b81548152906001019060200180831161096a57829003601f168201915b5050505050905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac81565b5f5f6109bf61184b565b90506109cc818585611852565b600191505092915050565b5f600254905090565b5f5f6109ec85336115a5565b905082811015610a31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a289061367e565b60405180910390fd5b610a4785338584610a4291906136c9565b611852565b610a52858585611864565b60019150509392505050565b5f60065f8381526020019081526020015f20600101549050919050565b610a8482610a5e565b610a8d81611aa8565b610a978383611abc565b50505050565b5f6012905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610acf81611aa8565b6107d08461ffff161115610b18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0f90613746565b60405180910390fd5b6107d08361ffff161115610b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b58906137ae565b60405180910390fd5b6107d08261ffff161115610baa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba190613816565b60405180910390fd5b83600b60146101000a81548161ffff021916908361ffff16021790555082600b60166101000a81548161ffff021916908361ffff16021790555081600b60186101000a81548161ffff021916908361ffff1602179055507f540dec552b2a7a44d3d6174e189be8d0b3e89bc5c82bc74c93a3b251afd123db848484604051610c3493929190613834565b60405180910390a150505050565b5f610c4b611ba6565b905090565b610c5861184b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610cbc576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cc68282611c5c565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610cf581611aa8565b610cfd611d46565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610d2a81611aa8565b610d348383611da7565b505050565b610d4a610d4461184b565b82611e26565b50565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610d7781611aa8565b610d8b82600d611ea590919063ffffffff16565b15610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc2906138b3565b60405180910390fd5b610ddf82600d611ed290919063ffffffff16565b508173ffffffffffffffffffffffffffffffffffffffff167f0847e23332122e80466494f0dcd8617569de17c0a7abb702e7b77c20e4a68fbd60405160405180910390a25050565b600b601a9054906101000a900461ffff1681565b5f60055f9054906101000a900460ff16905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610e7a81611aa8565b6001600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f80da454365b13711a276446e1f98b60c9e938b703654280adf3b288a15cc40a660405160405180910390a25050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e9610f8581611aa8565b610f8e82611eff565b5050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610fbc81611aa8565b60648261ffff161115611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ffb9061391b565b60405180910390fd5b5f8261ffff161161104a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104190613983565b60405180910390fd5b81600b601a6101000a81548161ffff021916908361ffff1602179055505050565b61107d8261107761184b565b83611f99565b6110878282611e26565b5050565b5f6110958261202b565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6110c681611aa8565b6110ce612071565b50565b5f6060805f5f5f60606110e26120d3565b6110ea61210e565b46305f5f1b5f67ffffffffffffffff811115611109576111086139a1565b5b6040519080825280602002602001820160405280156111375781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6060600480546111e9906135de565b80601f0160208091040260200160405190810160405280929190818152602001828054611215906135de565b80156112605780601f1061123757610100808354040283529160200191611260565b820191905f5260205f20905b81548152906001019060200180831161124357829003601f168201915b5050505050905090565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f5f1b81565b5f611299338484611864565b6001905092915050565b5f6112b882600d611ea590919063ffffffff16565b9050919050565b600b60149054906101000a900461ffff1681565b600b60189054906101000a900461ffff1681565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61131181611aa8565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361137f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137690613a3e565b60405180910390fd5b81600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167fb637765305c2a6e716ace8b4c731e205863b495f7cc0c7810a3af93dd2808a3060405160405180910390a25050565b600b60169054906101000a900461ffff1681565b8342111561145f57836040517f6279130200000000000000000000000000000000000000000000000000000000815260040161145691906130b1565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861148d8c612149565b896040516020016114a396959493929190613a5c565b6040516020818303038152906040528051906020012090505f6114c58261219c565b90505f6114d4828787876121b5565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461154857808a6040517f4b800e4600000000000000000000000000000000000000000000000000000000815260040161153f929190613abb565b60405180910390fd5b6115538a8a8a611852565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61158c82610a5e565b61159581611aa8565b61159f8383611c5c565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61165181611aa8565b5f600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167fac77091f326d74b3968d96338bee7ba39f7eaa8107f38905a3589d4f0e735bf560405160405180910390a25050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e981565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e961178381611aa8565b61178c826121e3565b5050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b61185f838383600161227e565b505050565b600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16806118ff5750600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b156119145761190f83838361244d565b611aa3565b61192882600d611ea590919063ffffffff16565b1561197b575f600b60169054906101000a900461ffff1661ffff16111561196a57611965838383600b60169054906101000a900461ffff1661253d565b611976565b61197583838361244d565b5b611aa2565b61198f83600d611ea590919063ffffffff16565b15611a57576064600b601a9054906101000a900461ffff1661ffff166119b36109d7565b6119bd9190613ae2565b6119c79190613b50565b811115611a09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0090613bf0565b60405180910390fd5b5f600b60149054906101000a900461ffff1661ffff161115611a4657611a41838383600b60149054906101000a900461ffff1661253d565b611a52565b611a5183838361244d565b5b611aa1565b5f600b60189054906101000a900461ffff1661ffff161115611a9457611a8f838383600b60189054906101000a900461ffff1661253d565b611aa0565b611a9f83838361244d565b5b5b5b5b505050565b611ab981611ab461184b565b61263a565b50565b5f611ac78383611176565b611b9c57600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611b3961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611ba0565b5f90505b92915050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611c2157507f000000000000000000000000000000000000000000000000000000000000000046145b15611c4e577f00000000000000000000000000000000000000000000000000000000000000009050611c59565b611c5661268b565b90505b90565b5f611c678383611176565b15611d3c575f60065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611cd961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611d40565b5f90505b92915050565b611d4e612720565b5f60055f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611d9061184b565b604051611d9d9190613598565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e17575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611e0e9190613598565b60405180910390fd5b611e225f8383612760565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e96575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611e8d9190613598565b60405180910390fd5b611ea1825f83612760565b5050565b5f611eca835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612770565b905092915050565b5f611ef7835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612790565b905092915050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f7534c63860313c46c473e4e98328f37017e9674e2162faf1a3ad7a96236c3b7b60405160405180910390a250565b5f611fa484846115a5565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146120255781811015612016578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161200d93929190613c0e565b60405180910390fd5b61202484848484035f61227e565b5b50505050565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6120796127f7565b600160055f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586120bc61184b565b6040516120c99190613598565b60405180910390a1565b606061210960077f000000000000000000000000000000000000000000000000000000000000000061283890919063ffffffff16565b905090565b606061214460087f000000000000000000000000000000000000000000000000000000000000000061283890919063ffffffff16565b905090565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f6121ae6121a8611ba6565b836128e5565b9050919050565b5f5f5f5f6121c588888888612925565b9250925092506121d58282612a0c565b829350505050949350505050565b6001600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85560405160405180910390a250565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122ee575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122e59190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361235e575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016123559190613598565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612447578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161243e91906130b1565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124bd575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016124b49190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361252d575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016125249190613598565b60405180910390fd5b612538838383612760565b505050565b5f6127108261ffff16846125519190613ae2565b61255b9190613b50565b90505f818461256a91906136c9565b90505f73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036125fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f290613cb3565b60405180910390fd5b61262786600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168461244d565b61263286868361244d565b505050505050565b6126448282611176565b6126875780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161267e929190613cd1565b60405180910390fd5b5050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001612705959493929190613cf8565b60405160208183030381529060405280519060200120905090565b612728610e3b565b61275e576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61276b838383612b6e565b505050565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f61279b8383612770565b6127ed57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f2081905550600190506127f1565b5f90505b92915050565b6127ff610e3b565b15612836576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b606060ff5f1b83146128545761284d83612b86565b90506128df565b818054612860906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461288c906135de565b80156128d75780601f106128ae576101008083540402835291602001916128d7565b820191905f5260205f20905b8154815290600101906020018083116128ba57829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f5f5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612961575f600385925092509250612a02565b5f6001888888886040515f81526020016040526040516129849493929190613d49565b6020604051602081039080840390855afa1580156129a4573d5f5f3e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129f5575f60015f5f1b93509350935050612a02565b805f5f5f1b935093509350505b9450945094915050565b5f6003811115612a1f57612a1e613d8c565b5b826003811115612a3257612a31613d8c565b5b0315612b6a5760016003811115612a4c57612a4b613d8c565b5b826003811115612a5f57612a5e613d8c565b5b03612a96576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612aaa57612aa9613d8c565b5b826003811115612abd57612abc613d8c565b5b03612b0157805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612af891906130b1565b60405180910390fd5b600380811115612b1457612b13613d8c565b5b826003811115612b2757612b26613d8c565b5b03612b6957806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612b609190612fbe565b60405180910390fd5b5b5050565b612b766127f7565b612b81838383612bf8565b505050565b60605f612b9283612e11565b90505f602067ffffffffffffffff811115612bb057612baf6139a1565b5b6040519080825280601f01601f191660200182016040528015612be25781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612c48578060025f828254612c3c9190613db9565b92505081905550612d16565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612cd1578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612cc893929190613c0e565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d5d578060025f8282540392505081905550612da7565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612e0491906130b1565b60405180910390a3505050565b5f5f60ff835f1c169050601f811115612e56576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612e9781612e63565b8114612ea1575f5ffd5b50565b5f81359050612eb281612e8e565b92915050565b5f60208284031215612ecd57612ecc612e5f565b5b5f612eda84828501612ea4565b91505092915050565b5f8115159050919050565b612ef781612ee3565b82525050565b5f602082019050612f105f830184612eee565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612f5882612f16565b612f628185612f20565b9350612f72818560208601612f30565b612f7b81612f3e565b840191505092915050565b5f6020820190508181035f830152612f9e8184612f4e565b905092915050565b5f819050919050565b612fb881612fa6565b82525050565b5f602082019050612fd15f830184612faf565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61300082612fd7565b9050919050565b61301081612ff6565b811461301a575f5ffd5b50565b5f8135905061302b81613007565b92915050565b5f819050919050565b61304381613031565b811461304d575f5ffd5b50565b5f8135905061305e8161303a565b92915050565b5f5f6040838503121561307a57613079612e5f565b5b5f6130878582860161301d565b925050602061309885828601613050565b9150509250929050565b6130ab81613031565b82525050565b5f6020820190506130c45f8301846130a2565b92915050565b5f5f5f606084860312156130e1576130e0612e5f565b5b5f6130ee8682870161301d565b93505060206130ff8682870161301d565b925050604061311086828701613050565b9150509250925092565b61312381612fa6565b811461312d575f5ffd5b50565b5f8135905061313e8161311a565b92915050565b5f6020828403121561315957613158612e5f565b5b5f61316684828501613130565b91505092915050565b5f5f6040838503121561318557613184612e5f565b5b5f61319285828601613130565b92505060206131a38582860161301d565b9150509250929050565b5f60ff82169050919050565b6131c2816131ad565b82525050565b5f6020820190506131db5f8301846131b9565b92915050565b5f61ffff82169050919050565b6131f7816131e1565b8114613201575f5ffd5b50565b5f81359050613212816131ee565b92915050565b5f5f5f6060848603121561322f5761322e612e5f565b5b5f61323c86828701613204565b935050602061324d86828701613204565b925050604061325e86828701613204565b9150509250925092565b5f6020828403121561327d5761327c612e5f565b5b5f61328a84828501613050565b91505092915050565b5f602082840312156132a8576132a7612e5f565b5b5f6132b58482850161301d565b91505092915050565b6132c7816131e1565b82525050565b5f6020820190506132e05f8301846132be565b92915050565b5f602082840312156132fb576132fa612e5f565b5b5f61330884828501613204565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61334581613311565b82525050565b61335481612ff6565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61338c81613031565b82525050565b5f61339d8383613383565b60208301905092915050565b5f602082019050919050565b5f6133bf8261335a565b6133c98185613364565b93506133d483613374565b805f5b838110156134045781516133eb8882613392565b97506133f6836133a9565b9250506001810190506133d7565b5085935050505092915050565b5f60e0820190506134245f83018a61333c565b81810360208301526134368189612f4e565b9050818103604083015261344a8188612f4e565b905061345960608301876130a2565b613466608083018661334b565b61347360a0830185612faf565b81810360c083015261348581846133b5565b905098975050505050505050565b61349c816131ad565b81146134a6575f5ffd5b50565b5f813590506134b781613493565b92915050565b5f5f5f5f5f5f5f60e0888a0312156134d8576134d7612e5f565b5b5f6134e58a828b0161301d565b97505060206134f68a828b0161301d565b96505060406135078a828b01613050565b95505060606135188a828b01613050565b94505060806135298a828b016134a9565b93505060a061353a8a828b01613130565b92505060c061354b8a828b01613130565b91505092959891949750929550565b5f5f604083850312156135705761356f612e5f565b5b5f61357d8582860161301d565b925050602061358e8582860161301d565b9150509250929050565b5f6020820190506135ab5f83018461334b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806135f557607f821691505b602082108103613608576136076135b1565b5b50919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320615f8201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b5f613668602883612f20565b91506136738261360e565b604082019050919050565b5f6020820190508181035f8301526136958161365c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6136d382613031565b91506136de83613031565b92508282039050818111156136f6576136f561369c565b5b92915050565b7f474c44533a206275792074617820697320746f6f2068696768210000000000005f82015250565b5f613730601a83612f20565b915061373b826136fc565b602082019050919050565b5f6020820190508181035f83015261375d81613724565b9050919050565b7f474c44533a2073656c6c2074617820697320746f6f20686967682100000000005f82015250565b5f613798601b83612f20565b91506137a382613764565b602082019050919050565b5f6020820190508181035f8301526137c58161378c565b9050919050565b7f474c44533a207472616e736665722074617820697320746f6f206869676821005f82015250565b5f613800601f83612f20565b915061380b826137cc565b602082019050919050565b5f6020820190508181035f83015261382d816137f4565b9050919050565b5f6060820190506138475f8301866132be565b61385460208301856132be565b61386160408301846132be565b949350505050565b7f474c44533a205377617056325061697220616c726561647920616464656400005f82015250565b5f61389d601e83612f20565b91506138a882613869565b602082019050919050565b5f6020820190508181035f8301526138ca81613891565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f2068696768215f82015250565b5f613905602083612f20565b9150613910826138d1565b602082019050919050565b5f6020820190508181035f830152613932816138f9565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f206c6f7721005f82015250565b5f61396d601f83612f20565b915061397882613939565b602082019050919050565b5f6020820190508181035f83015261399a81613961565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f474c44533a2043616e6e6f74207365742074617820726563656976657220746f5f8201527f20746865207a65726f2061646472657373210000000000000000000000000000602082015250565b5f613a28603283612f20565b9150613a33826139ce565b604082019050919050565b5f6020820190508181035f830152613a5581613a1c565b9050919050565b5f60c082019050613a6f5f830189612faf565b613a7c602083018861334b565b613a89604083018761334b565b613a9660608301866130a2565b613aa360808301856130a2565b613ab060a08301846130a2565b979650505050505050565b5f604082019050613ace5f83018561334b565b613adb602083018461334b565b9392505050565b5f613aec82613031565b9150613af783613031565b9250828202613b0581613031565b91508282048414831517613b1c57613b1b61369c565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613b5a82613031565b9150613b6583613031565b925082613b7557613b74613b23565b5b828204905092915050565b7f474c44533a20427579206578636565647320627579206c696d69742025206f665f8201527f20746f74616c20737570706c7900000000000000000000000000000000000000602082015250565b5f613bda602d83612f20565b9150613be582613b80565b604082019050919050565b5f6020820190508181035f830152613c0781613bce565b9050919050565b5f606082019050613c215f83018661334b565b613c2e60208301856130a2565b613c3b60408301846130a2565b949350505050565b7f474c44533a20746178526563656976657220697320746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f613c9d602583612f20565b9150613ca882613c43565b604082019050919050565b5f6020820190508181035f830152613cca81613c91565b9050919050565b5f604082019050613ce45f83018561334b565b613cf16020830184612faf565b9392505050565b5f60a082019050613d0b5f830188612faf565b613d186020830187612faf565b613d256040830186612faf565b613d3260608301856130a2565b613d3f608083018461334b565b9695505050505050565b5f608082019050613d5c5f830187612faf565b613d6960208301866131b9565b613d766040830185612faf565b613d836060830184612faf565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f613dc382613031565b9150613dce83613031565b9250828201905080821115613de657613de561369c565b5b9291505056fea2646970667358221220d7ae364ebf38f1292ad96706abfb172fe0c3b90d5b165210e3b69f8aacc4dccd64736f6c634300081c0033
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610288575f3560e01c80637ecebe001161015a578063cd8de42c116100cc578063e17c4c7411610085578063e17c4c74146107c6578063e63ab1e9146107e2578063e6ef73d614610800578063f515e6f21461081e578063f9f92be41461083c578063fe575a871461085857610288565b8063cd8de42c14610706578063cffd129c14610722578063d505accf14610740578063d53913931461075c578063d547741f1461077a578063dd62ed3e1461079657610288565b8063989763ef1161011e578063989763ef1461061c578063a217fddf1461064c578063a9059cbb1461066a578063b8a09b711461069a578063c473413a146106ca578063c4e48398146106e857610288565b80637ecebe00146105705780638456cb59146105a057806384b0196e146105aa57806391d14854146105ce57806395d89b41146105fe57610288565b806336568abe116101fe5780635c975abb116101b75780635c975abb146104b257806360d1259e146104d057806370a08231146104ec57806375e3661e1461051c5780637747b3321461053857806379cc67901461055457610288565b806336568abe1461041a5780633f4ba83a1461043657806340c10f191461044057806342966c681461045c57806344be2eae14610478578063589210d91461049457610288565b806323b872dd1161025057806323b872dd14610346578063248a9ca3146103765780632f2ff15d146103a6578063313ce567146103c257806332cde664146103e05780633644e515146103fc57610288565b806301ffc9a71461028c57806306fdde03146102bc57806308249db8146102da578063095ea7b3146102f857806318160ddd14610328575b5f5ffd5b6102a660048036038101906102a19190612eb8565b610888565b6040516102b39190612efd565b60405180910390f35b6102c4610901565b6040516102d19190612f86565b60405180910390f35b6102e2610991565b6040516102ef9190612fbe565b60405180910390f35b610312600480360381019061030d9190613064565b6109b5565b60405161031f9190612efd565b60405180910390f35b6103306109d7565b60405161033d91906130b1565b60405180910390f35b610360600480360381019061035b91906130ca565b6109e0565b60405161036d9190612efd565b60405180910390f35b610390600480360381019061038b9190613144565b610a5e565b60405161039d9190612fbe565b60405180910390f35b6103c060048036038101906103bb919061316f565b610a7b565b005b6103ca610a9d565b6040516103d791906131c8565b60405180910390f35b6103fa60048036038101906103f59190613218565b610aa5565b005b610404610c42565b6040516104119190612fbe565b60405180910390f35b610434600480360381019061042f919061316f565b610c50565b005b61043e610ccb565b005b61045a60048036038101906104559190613064565b610d00565b005b61047660048036038101906104719190613268565b610d39565b005b610492600480360381019061048d9190613293565b610d4d565b005b61049c610e27565b6040516104a991906132cd565b60405180910390f35b6104ba610e3b565b6040516104c79190612efd565b60405180910390f35b6104ea60048036038101906104e59190613293565b610e50565b005b61050660048036038101906105019190613293565b610f16565b60405161051391906130b1565b60405180910390f35b61053660048036038101906105319190613293565b610f5b565b005b610552600480360381019061054d91906132e6565b610f92565b005b61056e60048036038101906105699190613064565b61106b565b005b61058a60048036038101906105859190613293565b61108b565b60405161059791906130b1565b60405180910390f35b6105a861109c565b005b6105b26110d1565b6040516105c59796959493929190613411565b60405180910390f35b6105e860048036038101906105e3919061316f565b611176565b6040516105f59190612efd565b60405180910390f35b6106066111da565b6040516106139190612f86565b60405180910390f35b61063660048036038101906106319190613293565b61126a565b6040516106439190612efd565b60405180910390f35b610654611287565b6040516106619190612fbe565b60405180910390f35b610684600480360381019061067f9190613064565b61128d565b6040516106919190612efd565b60405180910390f35b6106b460048036038101906106af9190613293565b6112a3565b6040516106c19190612efd565b60405180910390f35b6106d26112bf565b6040516106df91906132cd565b60405180910390f35b6106f06112d3565b6040516106fd91906132cd565b60405180910390f35b610720600480360381019061071b9190613293565b6112e7565b005b61072a611406565b60405161073791906132cd565b60405180910390f35b61075a600480360381019061075591906134bd565b61141a565b005b61076461155f565b6040516107719190612fbe565b60405180910390f35b610794600480360381019061078f919061316f565b611583565b005b6107b060048036038101906107ab919061355a565b6115a5565b6040516107bd91906130b1565b60405180910390f35b6107e060048036038101906107db9190613293565b611627565b005b6107ea6116ec565b6040516107f79190612fbe565b60405180910390f35b610808611710565b6040516108159190613598565b60405180910390f35b610826611735565b6040516108339190612fbe565b60405180910390f35b61085660048036038101906108519190613293565b611759565b005b610872600480360381019061086d9190613293565b611790565b60405161087f9190612efd565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108fa57506108f9826117e2565b5b9050919050565b606060038054610910906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461093c906135de565b80156109875780601f1061095e57610100808354040283529160200191610987565b820191905f5260205f20905b81548152906001019060200180831161096a57829003601f168201915b5050505050905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac81565b5f5f6109bf61184b565b90506109cc818585611852565b600191505092915050565b5f600254905090565b5f5f6109ec85336115a5565b905082811015610a31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a289061367e565b60405180910390fd5b610a4785338584610a4291906136c9565b611852565b610a52858585611864565b60019150509392505050565b5f60065f8381526020019081526020015f20600101549050919050565b610a8482610a5e565b610a8d81611aa8565b610a978383611abc565b50505050565b5f6012905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610acf81611aa8565b6107d08461ffff161115610b18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0f90613746565b60405180910390fd5b6107d08361ffff161115610b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b58906137ae565b60405180910390fd5b6107d08261ffff161115610baa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba190613816565b60405180910390fd5b83600b60146101000a81548161ffff021916908361ffff16021790555082600b60166101000a81548161ffff021916908361ffff16021790555081600b60186101000a81548161ffff021916908361ffff1602179055507f540dec552b2a7a44d3d6174e189be8d0b3e89bc5c82bc74c93a3b251afd123db848484604051610c3493929190613834565b60405180910390a150505050565b5f610c4b611ba6565b905090565b610c5861184b565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610cbc576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cc68282611c5c565b505050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a610cf581611aa8565b610cfd611d46565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610d2a81611aa8565b610d348383611da7565b505050565b610d4a610d4461184b565b82611e26565b50565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610d7781611aa8565b610d8b82600d611ea590919063ffffffff16565b15610dcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc2906138b3565b60405180910390fd5b610ddf82600d611ed290919063ffffffff16565b508173ffffffffffffffffffffffffffffffffffffffff167f0847e23332122e80466494f0dcd8617569de17c0a7abb702e7b77c20e4a68fbd60405160405180910390a25050565b600b601a9054906101000a900461ffff1681565b5f60055f9054906101000a900460ff16905090565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610e7a81611aa8565b6001600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f80da454365b13711a276446e1f98b60c9e938b703654280adf3b288a15cc40a660405160405180910390a25050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e9610f8581611aa8565b610f8e82611eff565b5050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac610fbc81611aa8565b60648261ffff161115611004576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ffb9061391b565b60405180910390fd5b5f8261ffff161161104a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104190613983565b60405180910390fd5b81600b601a6101000a81548161ffff021916908361ffff1602179055505050565b61107d8261107761184b565b83611f99565b6110878282611e26565b5050565b5f6110958261202b565b9050919050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6110c681611aa8565b6110ce612071565b50565b5f6060805f5f5f60606110e26120d3565b6110ea61210e565b46305f5f1b5f67ffffffffffffffff811115611109576111086139a1565b5b6040519080825280602002602001820160405280156111375781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b6060600480546111e9906135de565b80601f0160208091040260200160405190810160405280929190818152602001828054611215906135de565b80156112605780601f1061123757610100808354040283529160200191611260565b820191905f5260205f20905b81548152906001019060200180831161124357829003601f168201915b5050505050905090565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f5f1b81565b5f611299338484611864565b6001905092915050565b5f6112b882600d611ea590919063ffffffff16565b9050919050565b600b60149054906101000a900461ffff1681565b600b60189054906101000a900461ffff1681565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61131181611aa8565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361137f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137690613a3e565b60405180910390fd5b81600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167fb637765305c2a6e716ace8b4c731e205863b495f7cc0c7810a3af93dd2808a3060405160405180910390a25050565b600b60169054906101000a900461ffff1681565b8342111561145f57836040517f6279130200000000000000000000000000000000000000000000000000000000815260040161145691906130b1565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988888861148d8c612149565b896040516020016114a396959493929190613a5c565b6040516020818303038152906040528051906020012090505f6114c58261219c565b90505f6114d4828787876121b5565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461154857808a6040517f4b800e4600000000000000000000000000000000000000000000000000000000815260040161153f929190613abb565b60405180910390fd5b6115538a8a8a611852565b50505050505050505050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61158c82610a5e565b61159581611aa8565b61159f8383611c5c565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b7f6a6feb6ad361b4660d183a90f4efcf4c0fb807f2ebf050bc5820f4e9c7c7e4ac61165181611aa8565b5f600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167fac77091f326d74b3968d96338bee7ba39f7eaa8107f38905a3589d4f0e735bf560405160405180910390a25050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e981565b7f98db8a220cd0f09badce9f22d0ba7e93edb3d404448cc3560d391ab096ad16e961178381611aa8565b61178c826121e3565b5050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff169050919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b61185f838383600161227e565b505050565b600c5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16806118ff5750600c5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b156119145761190f83838361244d565b611aa3565b61192882600d611ea590919063ffffffff16565b1561197b575f600b60169054906101000a900461ffff1661ffff16111561196a57611965838383600b60169054906101000a900461ffff1661253d565b611976565b61197583838361244d565b5b611aa2565b61198f83600d611ea590919063ffffffff16565b15611a57576064600b601a9054906101000a900461ffff1661ffff166119b36109d7565b6119bd9190613ae2565b6119c79190613b50565b811115611a09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a0090613bf0565b60405180910390fd5b5f600b60149054906101000a900461ffff1661ffff161115611a4657611a41838383600b60149054906101000a900461ffff1661253d565b611a52565b611a5183838361244d565b5b611aa1565b5f600b60189054906101000a900461ffff1661ffff161115611a9457611a8f838383600b60189054906101000a900461ffff1661253d565b611aa0565b611a9f83838361244d565b5b5b5b5b505050565b611ab981611ab461184b565b61263a565b50565b5f611ac78383611176565b611b9c57600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611b3961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611ba0565b5f90505b92915050565b5f7f0000000000000000000000003d5dc167c4657565e8045c22040d242b25b9b1a673ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611c2157507f000000000000000000000000000000000000000000000000000000000000000146145b15611c4e577ff65d8fc27a5476ab4c899088df99f4835cd92c88d0523a84096ca599b787ed319050611c59565b611c5661268b565b90505b90565b5f611c678383611176565b15611d3c575f60065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611cd961184b565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611d40565b5f90505b92915050565b611d4e612720565b5f60055f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611d9061184b565b604051611d9d9190613598565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e17575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611e0e9190613598565b60405180910390fd5b611e225f8383612760565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e96575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611e8d9190613598565b60405180910390fd5b611ea1825f83612760565b5050565b5f611eca835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612770565b905092915050565b5f611ef7835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612790565b905092915050565b5f600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167f7534c63860313c46c473e4e98328f37017e9674e2162faf1a3ad7a96236c3b7b60405160405180910390a250565b5f611fa484846115a5565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146120255781811015612016578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161200d93929190613c0e565b60405180910390fd5b61202484848484035f61227e565b5b50505050565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6120796127f7565b600160055f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586120bc61184b565b6040516120c99190613598565b60405180910390a1565b606061210960077f476c61646573000000000000000000000000000000000000000000000000000661283890919063ffffffff16565b905090565b606061214460087f310000000000000000000000000000000000000000000000000000000000000161283890919063ffffffff16565b905090565b5f60095f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f815480929190600101919050559050919050565b5f6121ae6121a8611ba6565b836128e5565b9050919050565b5f5f5f5f6121c588888888612925565b9250925092506121d58282612a0c565b829350505050949350505050565b6001600a5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85560405160405180910390a250565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122ee575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122e59190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361235e575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016123559190613598565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612447578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161243e91906130b1565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036124bd575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016124b49190613598565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361252d575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016125249190613598565b60405180910390fd5b612538838383612760565b505050565b5f6127108261ffff16846125519190613ae2565b61255b9190613b50565b90505f818461256a91906136c9565b90505f73ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036125fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f290613cb3565b60405180910390fd5b61262786600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168461244d565b61263286868361244d565b505050505050565b6126448282611176565b6126875780826040517fe2517d3f00000000000000000000000000000000000000000000000000000000815260040161267e929190613cd1565b60405180910390fd5b5050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f4ef23e2235d6064549416ca0a4fdb6b85e980452d2c17f1de3f0efd649d1b60c7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001612705959493929190613cf8565b60405160208183030381529060405280519060200120905090565b612728610e3b565b61275e576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61276b838383612b6e565b505050565b5f5f836001015f8481526020019081526020015f20541415905092915050565b5f61279b8383612770565b6127ed57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f2081905550600190506127f1565b5f90505b92915050565b6127ff610e3b565b15612836576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b606060ff5f1b83146128545761284d83612b86565b90506128df565b818054612860906135de565b80601f016020809104026020016040519081016040528092919081815260200182805461288c906135de565b80156128d75780601f106128ae576101008083540402835291602001916128d7565b820191905f5260205f20905b8154815290600101906020018083116128ba57829003601f168201915b505050505090505b92915050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f5f5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612961575f600385925092509250612a02565b5f6001888888886040515f81526020016040526040516129849493929190613d49565b6020604051602081039080840390855afa1580156129a4573d5f5f3e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036129f5575f60015f5f1b93509350935050612a02565b805f5f5f1b935093509350505b9450945094915050565b5f6003811115612a1f57612a1e613d8c565b5b826003811115612a3257612a31613d8c565b5b0315612b6a5760016003811115612a4c57612a4b613d8c565b5b826003811115612a5f57612a5e613d8c565b5b03612a96576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612aaa57612aa9613d8c565b5b826003811115612abd57612abc613d8c565b5b03612b0157805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612af891906130b1565b60405180910390fd5b600380811115612b1457612b13613d8c565b5b826003811115612b2757612b26613d8c565b5b03612b6957806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612b609190612fbe565b60405180910390fd5b5b5050565b612b766127f7565b612b81838383612bf8565b505050565b60605f612b9283612e11565b90505f602067ffffffffffffffff811115612bb057612baf6139a1565b5b6040519080825280601f01601f191660200182016040528015612be25781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612c48578060025f828254612c3c9190613db9565b92505081905550612d16565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015612cd1578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612cc893929190613c0e565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d5d578060025f8282540392505081905550612da7565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612e0491906130b1565b60405180910390a3505050565b5f5f60ff835f1c169050601f811115612e56576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612e9781612e63565b8114612ea1575f5ffd5b50565b5f81359050612eb281612e8e565b92915050565b5f60208284031215612ecd57612ecc612e5f565b5b5f612eda84828501612ea4565b91505092915050565b5f8115159050919050565b612ef781612ee3565b82525050565b5f602082019050612f105f830184612eee565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612f5882612f16565b612f628185612f20565b9350612f72818560208601612f30565b612f7b81612f3e565b840191505092915050565b5f6020820190508181035f830152612f9e8184612f4e565b905092915050565b5f819050919050565b612fb881612fa6565b82525050565b5f602082019050612fd15f830184612faf565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61300082612fd7565b9050919050565b61301081612ff6565b811461301a575f5ffd5b50565b5f8135905061302b81613007565b92915050565b5f819050919050565b61304381613031565b811461304d575f5ffd5b50565b5f8135905061305e8161303a565b92915050565b5f5f6040838503121561307a57613079612e5f565b5b5f6130878582860161301d565b925050602061309885828601613050565b9150509250929050565b6130ab81613031565b82525050565b5f6020820190506130c45f8301846130a2565b92915050565b5f5f5f606084860312156130e1576130e0612e5f565b5b5f6130ee8682870161301d565b93505060206130ff8682870161301d565b925050604061311086828701613050565b9150509250925092565b61312381612fa6565b811461312d575f5ffd5b50565b5f8135905061313e8161311a565b92915050565b5f6020828403121561315957613158612e5f565b5b5f61316684828501613130565b91505092915050565b5f5f6040838503121561318557613184612e5f565b5b5f61319285828601613130565b92505060206131a38582860161301d565b9150509250929050565b5f60ff82169050919050565b6131c2816131ad565b82525050565b5f6020820190506131db5f8301846131b9565b92915050565b5f61ffff82169050919050565b6131f7816131e1565b8114613201575f5ffd5b50565b5f81359050613212816131ee565b92915050565b5f5f5f6060848603121561322f5761322e612e5f565b5b5f61323c86828701613204565b935050602061324d86828701613204565b925050604061325e86828701613204565b9150509250925092565b5f6020828403121561327d5761327c612e5f565b5b5f61328a84828501613050565b91505092915050565b5f602082840312156132a8576132a7612e5f565b5b5f6132b58482850161301d565b91505092915050565b6132c7816131e1565b82525050565b5f6020820190506132e05f8301846132be565b92915050565b5f602082840312156132fb576132fa612e5f565b5b5f61330884828501613204565b91505092915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b61334581613311565b82525050565b61335481612ff6565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61338c81613031565b82525050565b5f61339d8383613383565b60208301905092915050565b5f602082019050919050565b5f6133bf8261335a565b6133c98185613364565b93506133d483613374565b805f5b838110156134045781516133eb8882613392565b97506133f6836133a9565b9250506001810190506133d7565b5085935050505092915050565b5f60e0820190506134245f83018a61333c565b81810360208301526134368189612f4e565b9050818103604083015261344a8188612f4e565b905061345960608301876130a2565b613466608083018661334b565b61347360a0830185612faf565b81810360c083015261348581846133b5565b905098975050505050505050565b61349c816131ad565b81146134a6575f5ffd5b50565b5f813590506134b781613493565b92915050565b5f5f5f5f5f5f5f60e0888a0312156134d8576134d7612e5f565b5b5f6134e58a828b0161301d565b97505060206134f68a828b0161301d565b96505060406135078a828b01613050565b95505060606135188a828b01613050565b94505060806135298a828b016134a9565b93505060a061353a8a828b01613130565b92505060c061354b8a828b01613130565b91505092959891949750929550565b5f5f604083850312156135705761356f612e5f565b5b5f61357d8582860161301d565b925050602061358e8582860161301d565b9150509250929050565b5f6020820190506135ab5f83018461334b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806135f557607f821691505b602082108103613608576136076135b1565b5b50919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320615f8201527f6c6c6f77616e6365000000000000000000000000000000000000000000000000602082015250565b5f613668602883612f20565b91506136738261360e565b604082019050919050565b5f6020820190508181035f8301526136958161365c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6136d382613031565b91506136de83613031565b92508282039050818111156136f6576136f561369c565b5b92915050565b7f474c44533a206275792074617820697320746f6f2068696768210000000000005f82015250565b5f613730601a83612f20565b915061373b826136fc565b602082019050919050565b5f6020820190508181035f83015261375d81613724565b9050919050565b7f474c44533a2073656c6c2074617820697320746f6f20686967682100000000005f82015250565b5f613798601b83612f20565b91506137a382613764565b602082019050919050565b5f6020820190508181035f8301526137c58161378c565b9050919050565b7f474c44533a207472616e736665722074617820697320746f6f206869676821005f82015250565b5f613800601f83612f20565b915061380b826137cc565b602082019050919050565b5f6020820190508181035f83015261382d816137f4565b9050919050565b5f6060820190506138475f8301866132be565b61385460208301856132be565b61386160408301846132be565b949350505050565b7f474c44533a205377617056325061697220616c726561647920616464656400005f82015250565b5f61389d601e83612f20565b91506138a882613869565b602082019050919050565b5f6020820190508181035f8301526138ca81613891565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f2068696768215f82015250565b5f613905602083612f20565b9150613910826138d1565b602082019050919050565b5f6020820190508181035f830152613932816138f9565b9050919050565b7f474c44533a204d617820627579206c696d697420697320746f6f206c6f7721005f82015250565b5f61396d601f83612f20565b915061397882613939565b602082019050919050565b5f6020820190508181035f83015261399a81613961565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f474c44533a2043616e6e6f74207365742074617820726563656976657220746f5f8201527f20746865207a65726f2061646472657373210000000000000000000000000000602082015250565b5f613a28603283612f20565b9150613a33826139ce565b604082019050919050565b5f6020820190508181035f830152613a5581613a1c565b9050919050565b5f60c082019050613a6f5f830189612faf565b613a7c602083018861334b565b613a89604083018761334b565b613a9660608301866130a2565b613aa360808301856130a2565b613ab060a08301846130a2565b979650505050505050565b5f604082019050613ace5f83018561334b565b613adb602083018461334b565b9392505050565b5f613aec82613031565b9150613af783613031565b9250828202613b0581613031565b91508282048414831517613b1c57613b1b61369c565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613b5a82613031565b9150613b6583613031565b925082613b7557613b74613b23565b5b828204905092915050565b7f474c44533a20427579206578636565647320627579206c696d69742025206f665f8201527f20746f74616c20737570706c7900000000000000000000000000000000000000602082015250565b5f613bda602d83612f20565b9150613be582613b80565b604082019050919050565b5f6020820190508181035f830152613c0781613bce565b9050919050565b5f606082019050613c215f83018661334b565b613c2e60208301856130a2565b613c3b60408301846130a2565b949350505050565b7f474c44533a20746178526563656976657220697320746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f613c9d602583612f20565b9150613ca882613c43565b604082019050919050565b5f6020820190508181035f830152613cca81613c91565b9050919050565b5f604082019050613ce45f83018561334b565b613cf16020830184612faf565b9392505050565b5f60a082019050613d0b5f830188612faf565b613d186020830187612faf565b613d256040830186612faf565b613d3260608301856130a2565b613d3f608083018461334b565b9695505050505050565b5f608082019050613d5c5f830187612faf565b613d6960208301866131b9565b613d766040830185612faf565b613d836060830184612faf565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f613dc382613031565b9150613dce83613031565b9250828201905080821115613de657613de561369c565b5b9291505056fea2646970667358221220d7ae364ebf38f1292ad96706abfb172fe0c3b90d5b165210e3b69f8aacc4dccd64736f6c634300081c0033
Deployed Bytecode Sourcemap
166387:7826:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35670:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13035:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166766:56;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;15328:190;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14137:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;169100:432;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36950:122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37382:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;13988:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172398:466;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;150192:114;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;38519:251;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;168031:77;;;:::i;:::-;;168116:107;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;23014:89;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;173197:259;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166960:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;25506:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172872:156;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14299:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;168347:112;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;173588:240;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;23432:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;149934:145;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;167950:73;;;:::i;:::-;;144578:580;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;35966:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13245:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;167038:47;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35278:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;168697:156;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173464:116;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166864:23;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166925:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;172143:247;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166894:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;149180:695;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166697:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37813:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14867:142;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;173036:153;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;166549:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166831:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;166618:72;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;168231:108;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;165614:121;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;35670:204;35755:4;35794:32;35779:47;;;:11;:47;;;;:87;;;;35830:36;35854:11;35830:23;:36::i;:::-;35779:87;35772:94;;35670:204;;;:::o;13035:91::-;13080:13;13113:5;13106:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13035:91;:::o;166766:56::-;166801:21;166766:56;:::o;15328:190::-;15401:4;15418:13;15434:12;:10;:12::i;:::-;15418:28;;15457:31;15466:5;15473:7;15482:5;15457:8;:31::i;:::-;15506:4;15499:11;;;15328:190;;;;:::o;14137:99::-;14189:7;14216:12;;14209:19;;14137:99;:::o;169100:432::-;169189:4;169249:24;169276:27;169286:4;169292:10;169276:9;:27::i;:::-;169249:54;;169342:6;169322:16;:26;;169314:79;;;;;;;;;;;;:::i;:::-;;;;;;;;;169404:53;169413:4;169419:10;169450:6;169431:16;:25;;;;:::i;:::-;169404:8;:53::i;:::-;169470:32;169485:4;169491:2;169495:6;169470:14;:32::i;:::-;169520:4;169513:11;;;169100:432;;;;;:::o;36950:122::-;37015:7;37042:6;:12;37049:4;37042:12;;;;;;;;;;;:22;;;37035:29;;36950:122;;;:::o;37382:138::-;37456:18;37469:4;37456:12;:18::i;:::-;35562:16;35573:4;35562:10;:16::i;:::-;37487:25:::1;37498:4;37504:7;37487:10;:25::i;:::-;;37382:138:::0;;;:::o;13988:84::-;14037:5;14062:2;14055:9;;13988:84;:::o;172398:466::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;172524:4:::1;172514:6;:14;;;;172506:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;172589:4;172578:7;:15;;;;172570:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;172659:4;172644:11;:19;;;;172636:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;172724:6;172712:9;;:18;;;;;;;;;;;;;;;;;;172754:7;172741:10;;:20;;;;;;;;;;;;;;;;;;172789:11;172772:14;;:28;;;;;;;;;;;;;;;;;;172818:38;172827:6;172835:7;172844:11;172818:38;;;;;;;;:::i;:::-;;;;;;;;172398:466:::0;;;;:::o;150192:114::-;150251:7;150278:20;:18;:20::i;:::-;150271:27;;150192:114;:::o;38519:251::-;38635:12;:10;:12::i;:::-;38613:34;;:18;:34;;;38609:104;;38671:30;;;;;;;;;;;;;;38609:104;38725:37;38737:4;38743:18;38725:11;:37::i;:::-;;38519:251;;:::o;168031:77::-;166587:24;35562:16;35573:4;35562:10;:16::i;:::-;168090:10:::1;:8;:10::i;:::-;168031:77:::0;:::o;168116:107::-;166735:24;35562:16;35573:4;35562:10;:16::i;:::-;168198:17:::1;168204:2;168208:6;168198:5;:17::i;:::-;168116:107:::0;;;:::o;23014:89::-;23069:26;23075:12;:10;:12::i;:::-;23089:5;23069;:26::i;:::-;23014:89;:::o;173197:259::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;173294:33:::1;173315:11;173294;:20;;:33;;;;:::i;:::-;173293:34;173285:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;173373:28;173389:11;173373;:15;;:28;;;;:::i;:::-;;173436:11;173417:31;;;;;;;;;;;;173197:259:::0;;:::o;166960:22::-;;;;;;;;;;;;;:::o;25506:86::-;25553:4;25577:7;;;;;;;;;;;25570:14;;25506:86;:::o;172872:156::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;172977:4:::1;172951:15;:23;172967:6;172951:23;;;;;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;173013:6;172997:23;;;;;;;;;;;;172872:156:::0;;:::o;14299:118::-;14364:7;14391:9;:18;14401:7;14391:18;;;;;;;;;;;;;;;;14384:25;;14299:118;;;:::o;168347:112::-;166661:29;35562:16;35573:4;35562:10;:16::i;:::-;168430:21:::1;168443:7;168430:12;:21::i;:::-;168347:112:::0;;:::o;173588:240::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;173691:3:::1;173676:11;:18;;;;173668:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;173757:1;173743:11;:15;;;173735:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;173809:11;173798:8;;:22;;;;;;;;;;;;;;;;;;173588:240:::0;;:::o;23432:161::-;23508:45;23524:7;23533:12;:10;:12::i;:::-;23547:5;23508:15;:45::i;:::-;23564:21;23570:7;23579:5;23564;:21::i;:::-;23432:161;;:::o;149934:145::-;150025:7;150052:19;150065:5;150052:12;:19::i;:::-;150045:26;;149934:145;;;:::o;167950:73::-;166587:24;35562:16;35573:4;35562:10;:16::i;:::-;168007:8:::1;:6;:8::i;:::-;167950:73:::0;:::o;144578:580::-;144681:13;144709:18;144742:21;144778:15;144808:25;144848:12;144875:27;144983:13;:11;:13::i;:::-;145011:16;:14;:16::i;:::-;145042:13;145078:4;145106:1;145098:10;;145137:1;145123:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;144930:220;;;;;;;;;;;;;;;;;;;;;144578:580;;;;;;;:::o;35966:138::-;36043:4;36067:6;:12;36074:4;36067:12;;;;;;;;;;;:20;;:29;36088:7;36067:29;;;;;;;;;;;;;;;;;;;;;;;;;36060:36;;35966:138;;;;:::o;13245:95::-;13292:13;13325:7;13318:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13245:95;:::o;167038:47::-;;;;;;;;;;;;;;;;;;;;;;:::o;35278:49::-;35323:4;35278:49;;;:::o;168697:156::-;168768:4;168785:38;168800:10;168812:2;168816:6;168785:14;:38::i;:::-;168841:4;168834:11;;168697:156;;;;:::o;173464:116::-;173522:4;173546:26;173567:4;173546:11;:20;;:26;;;;:::i;:::-;173539:33;;173464:116;;;:::o;166864:23::-;;;;;;;;;;;;;:::o;166925:28::-;;;;;;;;;;;;;:::o;172143:247::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;172252:1:::1;172232:22;;:8;:22;;::::0;172224:85:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;172334:8;172320:11;;:22;;;;;;;;;;;;;;;;;;172373:8;172358:24;;;;;;;;;;;;172143:247:::0;;:::o;166894:24::-;;;;;;;;;;;;;:::o;149180:695::-;149410:8;149392:15;:26;149388:99;;;149466:8;149442:33;;;;;;;;;;;:::i;:::-;;;;;;;;149388:99;149499:18;148499:95;149558:5;149565:7;149574:5;149581:16;149591:5;149581:9;:16::i;:::-;149599:8;149530:78;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;149520:89;;;;;;149499:110;;149622:12;149637:28;149654:10;149637:16;:28::i;:::-;149622:43;;149678:14;149695:28;149709:4;149715:1;149718;149721;149695:13;:28::i;:::-;149678:45;;149748:5;149738:15;;:6;:15;;;149734:90;;149798:6;149806:5;149777:35;;;;;;;;;;;;:::i;:::-;;;;;;;;149734:90;149836:31;149845:5;149852:7;149861:5;149836:8;:31::i;:::-;149377:498;;;149180:695;;;;;;;:::o;166697:62::-;166735:24;166697:62;:::o;37813:140::-;37888:18;37901:4;37888:12;:18::i;:::-;35562:16;35573:4;35562:10;:16::i;:::-;37919:26:::1;37931:4;37937:7;37919:11;:26::i;:::-;;37813:140:::0;;;:::o;14867:142::-;14947:7;14974:11;:18;14986:5;14974:18;;;;;;;;;;;;;;;:27;14993:7;14974:27;;;;;;;;;;;;;;;;14967:34;;14867:142;;;;:::o;173036:153::-;166801:21;35562:16;35573:4;35562:10;:16::i;:::-;173139:5:::1;173113:15;:23;173129:6;173113:23;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;173174:6;173160:21;;;;;;;;;;;;173036:153:::0;;:::o;166549:62::-;166587:24;166549:62;:::o;166831:26::-;;;;;;;;;;;;;:::o;166618:72::-;166661:29;166618:72;:::o;168231:108::-;166661:29;35562:16;35573:4;35562:10;:16::i;:::-;168312:19:::1;168323:7;168312:10;:19::i;:::-;168231:108:::0;;:::o;165614:121::-;165678:4;165704:11;:21;165716:8;165704:21;;;;;;;;;;;;;;;;;;;;;;;;;165697:28;;165614:121;;;:::o;33000:148::-;33076:4;33115:25;33100:40;;;:11;:40;;;;33093:47;;33000:148;;;:::o;4322:98::-;4375:7;4402:10;4395:17;;4322:98;:::o;20187:130::-;20272:37;20281:5;20288:7;20297:5;20304:4;20272:8;:37::i;:::-;20187:130;;;:::o;169780:1433::-;169957:15;:21;169973:4;169957:21;;;;;;;;;;;;;;;;;;;;;;;;;:44;;;;169982:15;:19;169998:2;169982:19;;;;;;;;;;;;;;;;;;;;;;;;;169957:44;169953:125;;;170018:27;170028:4;170034:2;170038:6;170018:9;:27::i;:::-;170060:7;;169953:125;170163:24;170184:2;170163:11;:20;;:24;;;;:::i;:::-;170159:1047;;;170221:1;170208:10;;;;;;;;;;;:14;;;170204:167;;;170243:44;170258:4;170264:2;170268:6;170276:10;;;;;;;;;;;170243:14;:44::i;:::-;170204:167;;;170328:27;170338:4;170344:2;170348:6;170328:9;:27::i;:::-;170204:167;170159:1047;;;170475:26;170496:4;170475:11;:20;;:26;;;;:::i;:::-;170471:735;;;170648:3;170636:8;;;;;;;;;;;170620:24;;:13;:11;:13::i;:::-;:24;;;;:::i;:::-;170619:32;;;;:::i;:::-;170609:6;:42;;170583:149;;;;;;;;;;;;:::i;:::-;;;;;;;;;170765:1;170753:9;;;;;;;;;;;:13;;;170749:165;;;170787:43;170802:4;170808:2;170812:6;170820:9;;;;;;;;;;;170787:14;:43::i;:::-;170749:165;;;170871:27;170881:4;170887:2;170891:6;170871:9;:27::i;:::-;170749:165;170471:735;;;171003:1;170986:14;;;;;;;;;;;:18;;;170982:224;;;171021:48;171036:4;171042:2;171046:6;171054:14;;;;;;;;;;;171021;:48::i;:::-;170982:224;;;171167:27;171177:4;171183:2;171187:6;171167:9;:27::i;:::-;170982:224;170471:735;170159:1047;169780:1433;;;;:::o;36319:105::-;36386:30;36397:4;36403:12;:10;:12::i;:::-;36386:10;:30::i;:::-;36319:105;:::o;39396:324::-;39473:4;39495:22;39503:4;39509:7;39495;:22::i;:::-;39490:223;;39566:4;39534:6;:12;39541:4;39534:12;;;;;;;;;;;:20;;:29;39555:7;39534:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;39617:12;:10;:12::i;:::-;39590:40;;39608:7;39590:40;;39602:4;39590:40;;;;;;;;;;39652:4;39645:11;;;;39490:223;39696:5;39689:12;;39396:324;;;;;:::o;143245:268::-;143298:7;143339:11;143322:28;;143330:4;143322:28;;;:63;;;;;143371:14;143354:13;:31;143322:63;143318:188;;;143409:22;143402:29;;;;143318:188;143471:23;:21;:23::i;:::-;143464:30;;143245:268;;:::o;39964:325::-;40042:4;40063:22;40071:4;40077:7;40063;:22::i;:::-;40059:223;;;40134:5;40102:6;:12;40109:4;40102:12;;;;;;;;;;;:20;;:29;40123:7;40102:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;40186:12;:10;:12::i;:::-;40159:40;;40177:7;40159:40;;40171:4;40159:40;;;;;;;;;;40221:4;40214:11;;;;40059:223;40265:5;40258:12;;39964:325;;;;;:::o;26407:120::-;25370:16;:14;:16::i;:::-;26476:5:::1;26466:7;;:15;;;;;;;;;;;;;;;;;;26497:22;26506:12;:10;:12::i;:::-;26497:22;;;;;;:::i;:::-;;;;;;;;26407:120::o:0;18882:213::-;18972:1;18953:21;;:7;:21;;;18949:93;;19027:1;18998:32;;;;;;;;;;;:::i;:::-;;;;;;;;18949:93;19052:35;19068:1;19072:7;19081:5;19052:7;:35::i;:::-;18882:213;;:::o;19423:211::-;19513:1;19494:21;;:7;:21;;;19490:91;;19566:1;19539:30;;;;;;;;;;;:::i;:::-;;;;;;;;19490:91;19591:35;19599:7;19616:1;19620:5;19591:7;:35::i;:::-;19423:211;;:::o;159458:167::-;159538:4;159562:55;159572:3;:10;;159608:5;159592:23;;159584:32;;159562:9;:55::i;:::-;159555:62;;159458:167;;;;:::o;158886:152::-;158956:4;158980:50;158985:3;:10;;159021:5;159005:23;;158997:32;;158980:4;:50::i;:::-;158973:57;;158886:152;;;;:::o;166149:150::-;166243:5;166219:11;:21;166231:8;166219:21;;;;;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;166280:8;166266:23;;;;;;;;;;;;166149:150;:::o;21919:487::-;22019:24;22046:25;22056:5;22063:7;22046:9;:25::i;:::-;22019:52;;22106:17;22086:16;:37;22082:317;;22163:5;22144:16;:24;22140:132;;;22223:7;22232:16;22250:5;22196:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;22140:132;22315:57;22324:5;22331:7;22359:5;22340:16;:24;22366:5;22315:8;:57::i;:::-;22082:317;22008:398;21919:487;;;:::o;146678:109::-;146738:7;146765;:14;146773:5;146765:14;;;;;;;;;;;;;;;;146758:21;;146678:109;;;:::o;26148:118::-;25111:19;:17;:19::i;:::-;26218:4:::1;26208:7;;:14;;;;;;;;;;;;;;;;;;26238:20;26245:12;:10;:12::i;:::-;26238:20;;;;;;:::i;:::-;;;;;;;;26148:118::o:0;145487:128::-;145533:13;145566:41;145593:13;145566:5;:26;;:41;;;;:::i;:::-;145559:48;;145487:128;:::o;145950:137::-;145999:13;146032:47;146062:16;146032:8;:29;;:47;;;;:::i;:::-;146025:54;;145950:137;:::o;146908:402::-;146968:7;147275;:14;147283:5;147275:14;;;;;;;;;;;;;;;;:16;;;;;;;;;;;;147268:23;;146908:402;;;:::o;144344:178::-;144421:7;144448:66;144481:20;:18;:20::i;:::-;144503:10;144448:32;:66::i;:::-;144441:73;;144344:178;;;:::o;51330:264::-;51415:7;51436:17;51455:18;51475:16;51495:25;51506:4;51512:1;51515;51518;51495:10;:25::i;:::-;51435:85;;;;;;51531:28;51543:5;51550:8;51531:11;:28::i;:::-;51577:9;51570:16;;;;;51330:264;;;;;;:::o;165859:145::-;165951:4;165927:11;:21;165939:8;165927:21;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;165985:8;165973:21;;;;;;;;;;;;165859:145;:::o;21184:443::-;21314:1;21297:19;;:5;:19;;;21293:91;;21369:1;21340:32;;;;;;;;;;;:::i;:::-;;;;;;;;21293:91;21417:1;21398:21;;:7;:21;;;21394:92;;21471:1;21443:31;;;;;;;;;;;:::i;:::-;;;;;;;;21394:92;21526:5;21496:11;:18;21508:5;21496:18;;;;;;;;;;;;;;;:27;21515:7;21496:27;;;;;;;;;;;;;;;:35;;;;21546:9;21542:78;;;21593:7;21577:31;;21586:5;21577:31;;;21602:5;21577:31;;;;;;:::i;:::-;;;;;;;;21542:78;21184:443;;;;:::o;16762:308::-;16862:1;16846:18;;:4;:18;;;16842:88;;16915:1;16888:30;;;;;;;;;;;:::i;:::-;;;;;;;;16842:88;16958:1;16944:16;;:2;:16;;;16940:88;;17013:1;16984:32;;;;;;;;;;;:::i;:::-;;;;;;;;16940:88;17038:24;17046:4;17052:2;17056:5;17038:7;:24::i;:::-;16762:308;;;:::o;171445:550::-;171588:17;171628:5;171618:6;171609:15;;:6;:15;;;;:::i;:::-;171608:25;;;;:::i;:::-;171588:45;;171644:18;171674:9;171665:6;:18;;;;:::i;:::-;171644:39;;171727:1;171704:25;;:11;;;;;;;;;;;:25;;;171696:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;171838:39;171848:4;171854:11;;;;;;;;;;;171867:9;171838;:39::i;:::-;171956:31;171966:4;171972:2;171976:10;171956:9;:31::i;:::-;171577:418;;171445:550;;;;:::o;36560:201::-;36649:22;36657:4;36663:7;36649;:22::i;:::-;36644:110;;36728:7;36737:4;36695:47;;;;;;;;;;;;:::i;:::-;;;;;;;;36644:110;36560:201;;:::o;143521:181::-;143576:7;141437:95;143635:11;143648:14;143664:13;143687:4;143613:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;143603:91;;;;;;143596:98;;143521:181;:::o;25874:130::-;25938:8;:6;:8::i;:::-;25933:64;;25970:15;;;;;;;;;;;;;;25933:64;25874:130::o;174040:170::-;174172:30;174186:4;174192:2;174196:5;174172:13;:30::i;:::-;174040:170;;;:::o;154739:131::-;154812:4;154861:1;154836:3;:14;;:21;154851:5;154836:21;;;;;;;;;;;;:26;;154829:33;;154739:131;;;;:::o;152661:416::-;152724:4;152746:21;152756:3;152761:5;152746:9;:21::i;:::-;152741:329;;152784:3;:11;;152801:5;152784:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;152969:3;:11;;:18;;;;152945:3;:14;;:21;152960:5;152945:21;;;;;;;;;;;:42;;;;153009:4;153002:11;;;;152741:329;153053:5;153046:12;;152661:416;;;;;:::o;25665:132::-;25731:8;:6;:8::i;:::-;25727:63;;;25763:15;;;;;;;;;;;;;;25727:63;25665:132::o;137702:273::-;137796:13;135676:66;137855:17;;137845:5;137826:46;137822:146;;137896:15;137905:5;137896:8;:15::i;:::-;137889:22;;;;137822:146;137951:5;137944:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137702:273;;;;;:::o;129510:382::-;129603:14;129687:4;129681:11;129718:10;129713:3;129706:23;129766:15;129759:4;129754:3;129750:14;129743:39;129819:10;129812:4;129807:3;129803:14;129796:34;129869:4;129864:3;129854:20;129844:30;;129655:230;129510:382;;;;:::o;49614:1577::-;49745:17;49764:16;49782:14;50709:66;50704:1;50696:10;;:79;50692:166;;;50808:1;50812:30;50844:1;50792:54;;;;;;;;50692:166;50955:14;50972:24;50982:4;50988:1;50991;50994;50972:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50955:41;;51029:1;51011:20;;:6;:20;;;51007:115;;51064:1;51068:29;51107:1;51099:10;;51048:62;;;;;;;;;51007:115;51142:6;51150:20;51180:1;51172:10;;51134:49;;;;;;;49614:1577;;;;;;;;;:::o;51732:542::-;51828:20;51819:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;51815:452;51865:7;51815:452;51926:29;51917:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;51913:354;;51979:23;;;;;;;;;;;;;;51913:354;52033:35;52024:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;52020:247;;52128:8;52120:17;;52092:46;;;;;;;;;;;:::i;:::-;;;;;;;;52020:247;52169:30;52160:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;52156:111;;52246:8;52223:32;;;;;;;;;;;:::i;:::-;;;;;;;;52156:111;51732:542;;;:::o;27638:147::-;25111:19;:17;:19::i;:::-;27747:30:::1;27761:4;27767:2;27771:5;27747:13;:30::i;:::-;27638:147:::0;;;:::o;136385:387::-;136444:13;136470:11;136484:16;136495:4;136484:10;:16::i;:::-;136470:30;;136590:17;136621:2;136610:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136590:34;;136687:3;136682;136675:16;136728:4;136721;136716:3;136712:14;136705:28;136761:3;136754:10;;;;136385:387;;;:::o;17394:1135::-;17500:1;17484:18;;:4;:18;;;17480:552;;17638:5;17622:12;;:21;;;;;;;:::i;:::-;;;;;;;;17480:552;;;17676:19;17698:9;:15;17708:4;17698:15;;;;;;;;;;;;;;;;17676:37;;17746:5;17732:11;:19;17728:117;;;17804:4;17810:11;17823:5;17779:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;17728:117;18000:5;17986:11;:19;17968:9;:15;17978:4;17968:15;;;;;;;;;;;;;;;:37;;;;17661:371;17480:552;18062:1;18048:16;;:2;:16;;;18044:435;;18230:5;18214:12;;:21;;;;;;;;;;;18044:435;;;18447:5;18430:9;:13;18440:2;18430:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;18044:435;18511:2;18496:25;;18505:4;18496:25;;;18515:5;18496:25;;;;;;:::i;:::-;;;;;;;;17394:1135;;;:::o;136849:251::-;136910:7;136930:14;136983:4;136974;136947:33;;:40;136930:57;;137011:2;137002:6;:11;136998:71;;;137037:20;;;;;;;;;;;;;;136998:71;137086:6;137079:13;;;136849:251;;;:::o;88:117:1:-;197:1;194;187:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:139::-;1887:6;1882:3;1877;1871:23;1928:1;1919:6;1914:3;1910:16;1903:27;1798:139;;;:::o;1943:102::-;1984:6;2035:2;2031:7;2026:2;2019:5;2015:14;2011:28;2001:38;;1943:102;;;:::o;2051:377::-;2139:3;2167:39;2200:5;2167:39;:::i;:::-;2222:71;2286:6;2281:3;2222:71;:::i;:::-;2215:78;;2302:65;2360:6;2355:3;2348:4;2341:5;2337:16;2302:65;:::i;:::-;2392:29;2414:6;2392:29;:::i;:::-;2387:3;2383:39;2376:46;;2143:285;2051:377;;;;:::o;2434:313::-;2547:4;2585:2;2574:9;2570:18;2562:26;;2634:9;2628:4;2624:20;2620:1;2609:9;2605:17;2598:47;2662:78;2735:4;2726:6;2662:78;:::i;:::-;2654:86;;2434:313;;;;:::o;2753:77::-;2790:7;2819:5;2808:16;;2753:77;;;:::o;2836:118::-;2923:24;2941:5;2923:24;:::i;:::-;2918:3;2911:37;2836:118;;:::o;2960:222::-;3053:4;3091:2;3080:9;3076:18;3068:26;;3104:71;3172:1;3161:9;3157:17;3148:6;3104:71;:::i;:::-;2960:222;;;;:::o;3188:126::-;3225:7;3265:42;3258:5;3254:54;3243:65;;3188:126;;;:::o;3320:96::-;3357:7;3386:24;3404:5;3386:24;:::i;:::-;3375:35;;3320:96;;;:::o;3422:122::-;3495:24;3513:5;3495:24;:::i;:::-;3488:5;3485:35;3475:63;;3534:1;3531;3524:12;3475:63;3422:122;:::o;3550:139::-;3596:5;3634:6;3621:20;3612:29;;3650:33;3677:5;3650:33;:::i;:::-;3550:139;;;;:::o;3695:77::-;3732:7;3761:5;3750:16;;3695:77;;;:::o;3778:122::-;3851:24;3869:5;3851:24;:::i;:::-;3844:5;3841:35;3831:63;;3890:1;3887;3880:12;3831:63;3778:122;:::o;3906:139::-;3952:5;3990:6;3977:20;3968:29;;4006:33;4033:5;4006:33;:::i;:::-;3906:139;;;;:::o;4051:474::-;4119:6;4127;4176:2;4164:9;4155:7;4151:23;4147:32;4144:119;;;4182:79;;:::i;:::-;4144:119;4302:1;4327:53;4372:7;4363:6;4352:9;4348:22;4327:53;:::i;:::-;4317:63;;4273:117;4429:2;4455:53;4500:7;4491:6;4480:9;4476:22;4455:53;:::i;:::-;4445:63;;4400:118;4051:474;;;;;:::o;4531:118::-;4618:24;4636:5;4618:24;:::i;:::-;4613:3;4606:37;4531:118;;:::o;4655:222::-;4748:4;4786:2;4775:9;4771:18;4763:26;;4799:71;4867:1;4856:9;4852:17;4843:6;4799:71;:::i;:::-;4655:222;;;;:::o;4883:619::-;4960:6;4968;4976;5025:2;5013:9;5004:7;5000:23;4996:32;4993:119;;;5031:79;;:::i;:::-;4993:119;5151:1;5176:53;5221:7;5212:6;5201:9;5197:22;5176:53;:::i;:::-;5166:63;;5122:117;5278:2;5304:53;5349:7;5340:6;5329:9;5325:22;5304:53;:::i;:::-;5294:63;;5249:118;5406:2;5432:53;5477:7;5468:6;5457:9;5453:22;5432:53;:::i;:::-;5422:63;;5377:118;4883:619;;;;;:::o;5508:122::-;5581:24;5599:5;5581:24;:::i;:::-;5574:5;5571:35;5561:63;;5620:1;5617;5610:12;5561:63;5508:122;:::o;5636:139::-;5682:5;5720:6;5707:20;5698:29;;5736:33;5763:5;5736:33;:::i;:::-;5636:139;;;;:::o;5781:329::-;5840:6;5889:2;5877:9;5868:7;5864:23;5860:32;5857:119;;;5895:79;;:::i;:::-;5857:119;6015:1;6040:53;6085:7;6076:6;6065:9;6061:22;6040:53;:::i;:::-;6030:63;;5986:117;5781:329;;;;:::o;6116:474::-;6184:6;6192;6241:2;6229:9;6220:7;6216:23;6212:32;6209:119;;;6247:79;;:::i;:::-;6209:119;6367:1;6392:53;6437:7;6428:6;6417:9;6413:22;6392:53;:::i;:::-;6382:63;;6338:117;6494:2;6520:53;6565:7;6556:6;6545:9;6541:22;6520:53;:::i;:::-;6510:63;;6465:118;6116:474;;;;;:::o;6596:86::-;6631:7;6671:4;6664:5;6660:16;6649:27;;6596:86;;;:::o;6688:112::-;6771:22;6787:5;6771:22;:::i;:::-;6766:3;6759:35;6688:112;;:::o;6806:214::-;6895:4;6933:2;6922:9;6918:18;6910:26;;6946:67;7010:1;6999:9;6995:17;6986:6;6946:67;:::i;:::-;6806:214;;;;:::o;7026:89::-;7062:7;7102:6;7095:5;7091:18;7080:29;;7026:89;;;:::o;7121:120::-;7193:23;7210:5;7193:23;:::i;:::-;7186:5;7183:34;7173:62;;7231:1;7228;7221:12;7173:62;7121:120;:::o;7247:137::-;7292:5;7330:6;7317:20;7308:29;;7346:32;7372:5;7346:32;:::i;:::-;7247:137;;;;:::o;7390:613::-;7464:6;7472;7480;7529:2;7517:9;7508:7;7504:23;7500:32;7497:119;;;7535:79;;:::i;:::-;7497:119;7655:1;7680:52;7724:7;7715:6;7704:9;7700:22;7680:52;:::i;:::-;7670:62;;7626:116;7781:2;7807:52;7851:7;7842:6;7831:9;7827:22;7807:52;:::i;:::-;7797:62;;7752:117;7908:2;7934:52;7978:7;7969:6;7958:9;7954:22;7934:52;:::i;:::-;7924:62;;7879:117;7390:613;;;;;:::o;8009:329::-;8068:6;8117:2;8105:9;8096:7;8092:23;8088:32;8085:119;;;8123:79;;:::i;:::-;8085:119;8243:1;8268:53;8313:7;8304:6;8293:9;8289:22;8268:53;:::i;:::-;8258:63;;8214:117;8009:329;;;;:::o;8344:::-;8403:6;8452:2;8440:9;8431:7;8427:23;8423:32;8420:119;;;8458:79;;:::i;:::-;8420:119;8578:1;8603:53;8648:7;8639:6;8628:9;8624:22;8603:53;:::i;:::-;8593:63;;8549:117;8344:329;;;;:::o;8679:115::-;8764:23;8781:5;8764:23;:::i;:::-;8759:3;8752:36;8679:115;;:::o;8800:218::-;8891:4;8929:2;8918:9;8914:18;8906:26;;8942:69;9008:1;8997:9;8993:17;8984:6;8942:69;:::i;:::-;8800:218;;;;:::o;9024:327::-;9082:6;9131:2;9119:9;9110:7;9106:23;9102:32;9099:119;;;9137:79;;:::i;:::-;9099:119;9257:1;9282:52;9326:7;9317:6;9306:9;9302:22;9282:52;:::i;:::-;9272:62;;9228:116;9024:327;;;;:::o;9357:149::-;9393:7;9433:66;9426:5;9422:78;9411:89;;9357:149;;;:::o;9512:115::-;9597:23;9614:5;9597:23;:::i;:::-;9592:3;9585:36;9512:115;;:::o;9633:118::-;9720:24;9738:5;9720:24;:::i;:::-;9715:3;9708:37;9633:118;;:::o;9757:114::-;9824:6;9858:5;9852:12;9842:22;;9757:114;;;:::o;9877:184::-;9976:11;10010:6;10005:3;9998:19;10050:4;10045:3;10041:14;10026:29;;9877:184;;;;:::o;10067:132::-;10134:4;10157:3;10149:11;;10187:4;10182:3;10178:14;10170:22;;10067:132;;;:::o;10205:108::-;10282:24;10300:5;10282:24;:::i;:::-;10277:3;10270:37;10205:108;;:::o;10319:179::-;10388:10;10409:46;10451:3;10443:6;10409:46;:::i;:::-;10487:4;10482:3;10478:14;10464:28;;10319:179;;;;:::o;10504:113::-;10574:4;10606;10601:3;10597:14;10589:22;;10504:113;;;:::o;10653:732::-;10772:3;10801:54;10849:5;10801:54;:::i;:::-;10871:86;10950:6;10945:3;10871:86;:::i;:::-;10864:93;;10981:56;11031:5;10981:56;:::i;:::-;11060:7;11091:1;11076:284;11101:6;11098:1;11095:13;11076:284;;;11177:6;11171:13;11204:63;11263:3;11248:13;11204:63;:::i;:::-;11197:70;;11290:60;11343:6;11290:60;:::i;:::-;11280:70;;11136:224;11123:1;11120;11116:9;11111:14;;11076:284;;;11080:14;11376:3;11369:10;;10777:608;;;10653:732;;;;:::o;11391:1215::-;11740:4;11778:3;11767:9;11763:19;11755:27;;11792:69;11858:1;11847:9;11843:17;11834:6;11792:69;:::i;:::-;11908:9;11902:4;11898:20;11893:2;11882:9;11878:18;11871:48;11936:78;12009:4;12000:6;11936:78;:::i;:::-;11928:86;;12061:9;12055:4;12051:20;12046:2;12035:9;12031:18;12024:48;12089:78;12162:4;12153:6;12089:78;:::i;:::-;12081:86;;12177:72;12245:2;12234:9;12230:18;12221:6;12177:72;:::i;:::-;12259:73;12327:3;12316:9;12312:19;12303:6;12259:73;:::i;:::-;12342;12410:3;12399:9;12395:19;12386:6;12342:73;:::i;:::-;12463:9;12457:4;12453:20;12447:3;12436:9;12432:19;12425:49;12491:108;12594:4;12585:6;12491:108;:::i;:::-;12483:116;;11391:1215;;;;;;;;;;:::o;12612:118::-;12683:22;12699:5;12683:22;:::i;:::-;12676:5;12673:33;12663:61;;12720:1;12717;12710:12;12663:61;12612:118;:::o;12736:135::-;12780:5;12818:6;12805:20;12796:29;;12834:31;12859:5;12834:31;:::i;:::-;12736:135;;;;:::o;12877:1199::-;12988:6;12996;13004;13012;13020;13028;13036;13085:3;13073:9;13064:7;13060:23;13056:33;13053:120;;;13092:79;;:::i;:::-;13053:120;13212:1;13237:53;13282:7;13273:6;13262:9;13258:22;13237:53;:::i;:::-;13227:63;;13183:117;13339:2;13365:53;13410:7;13401:6;13390:9;13386:22;13365:53;:::i;:::-;13355:63;;13310:118;13467:2;13493:53;13538:7;13529:6;13518:9;13514:22;13493:53;:::i;:::-;13483:63;;13438:118;13595:2;13621:53;13666:7;13657:6;13646:9;13642:22;13621:53;:::i;:::-;13611:63;;13566:118;13723:3;13750:51;13793:7;13784:6;13773:9;13769:22;13750:51;:::i;:::-;13740:61;;13694:117;13850:3;13877:53;13922:7;13913:6;13902:9;13898:22;13877:53;:::i;:::-;13867:63;;13821:119;13979:3;14006:53;14051:7;14042:6;14031:9;14027:22;14006:53;:::i;:::-;13996:63;;13950:119;12877:1199;;;;;;;;;;:::o;14082:474::-;14150:6;14158;14207:2;14195:9;14186:7;14182:23;14178:32;14175:119;;;14213:79;;:::i;:::-;14175:119;14333:1;14358:53;14403:7;14394:6;14383:9;14379:22;14358:53;:::i;:::-;14348:63;;14304:117;14460:2;14486:53;14531:7;14522:6;14511:9;14507:22;14486:53;:::i;:::-;14476:63;;14431:118;14082:474;;;;;:::o;14562:222::-;14655:4;14693:2;14682:9;14678:18;14670:26;;14706:71;14774:1;14763:9;14759:17;14750:6;14706:71;:::i;:::-;14562:222;;;;:::o;14790:180::-;14838:77;14835:1;14828:88;14935:4;14932:1;14925:15;14959:4;14956:1;14949:15;14976:320;15020:6;15057:1;15051:4;15047:12;15037:22;;15104:1;15098:4;15094:12;15125:18;15115:81;;15181:4;15173:6;15169:17;15159:27;;15115:81;15243:2;15235:6;15232:14;15212:18;15209:38;15206:84;;15262:18;;:::i;:::-;15206:84;15027:269;14976:320;;;:::o;15302:227::-;15442:34;15438:1;15430:6;15426:14;15419:58;15511:10;15506:2;15498:6;15494:15;15487:35;15302:227;:::o;15535:366::-;15677:3;15698:67;15762:2;15757:3;15698:67;:::i;:::-;15691:74;;15774:93;15863:3;15774:93;:::i;:::-;15892:2;15887:3;15883:12;15876:19;;15535:366;;;:::o;15907:419::-;16073:4;16111:2;16100:9;16096:18;16088:26;;16160:9;16154:4;16150:20;16146:1;16135:9;16131:17;16124:47;16188:131;16314:4;16188:131;:::i;:::-;16180:139;;15907:419;;;:::o;16332:180::-;16380:77;16377:1;16370:88;16477:4;16474:1;16467:15;16501:4;16498:1;16491:15;16518:194;16558:4;16578:20;16596:1;16578:20;:::i;:::-;16573:25;;16612:20;16630:1;16612:20;:::i;:::-;16607:25;;16656:1;16653;16649:9;16641:17;;16680:1;16674:4;16671:11;16668:37;;;16685:18;;:::i;:::-;16668:37;16518:194;;;;:::o;16718:176::-;16858:28;16854:1;16846:6;16842:14;16835:52;16718:176;:::o;16900:366::-;17042:3;17063:67;17127:2;17122:3;17063:67;:::i;:::-;17056:74;;17139:93;17228:3;17139:93;:::i;:::-;17257:2;17252:3;17248:12;17241:19;;16900:366;;;:::o;17272:419::-;17438:4;17476:2;17465:9;17461:18;17453:26;;17525:9;17519:4;17515:20;17511:1;17500:9;17496:17;17489:47;17553:131;17679:4;17553:131;:::i;:::-;17545:139;;17272:419;;;:::o;17697:177::-;17837:29;17833:1;17825:6;17821:14;17814:53;17697:177;:::o;17880:366::-;18022:3;18043:67;18107:2;18102:3;18043:67;:::i;:::-;18036:74;;18119:93;18208:3;18119:93;:::i;:::-;18237:2;18232:3;18228:12;18221:19;;17880:366;;;:::o;18252:419::-;18418:4;18456:2;18445:9;18441:18;18433:26;;18505:9;18499:4;18495:20;18491:1;18480:9;18476:17;18469:47;18533:131;18659:4;18533:131;:::i;:::-;18525:139;;18252:419;;;:::o;18677:181::-;18817:33;18813:1;18805:6;18801:14;18794:57;18677:181;:::o;18864:366::-;19006:3;19027:67;19091:2;19086:3;19027:67;:::i;:::-;19020:74;;19103:93;19192:3;19103:93;:::i;:::-;19221:2;19216:3;19212:12;19205:19;;18864:366;;;:::o;19236:419::-;19402:4;19440:2;19429:9;19425:18;19417:26;;19489:9;19483:4;19479:20;19475:1;19464:9;19460:17;19453:47;19517:131;19643:4;19517:131;:::i;:::-;19509:139;;19236:419;;;:::o;19661:430::-;19804:4;19842:2;19831:9;19827:18;19819:26;;19855:69;19921:1;19910:9;19906:17;19897:6;19855:69;:::i;:::-;19934:70;20000:2;19989:9;19985:18;19976:6;19934:70;:::i;:::-;20014;20080:2;20069:9;20065:18;20056:6;20014:70;:::i;:::-;19661:430;;;;;;:::o;20097:180::-;20237:32;20233:1;20225:6;20221:14;20214:56;20097:180;:::o;20283:366::-;20425:3;20446:67;20510:2;20505:3;20446:67;:::i;:::-;20439:74;;20522:93;20611:3;20522:93;:::i;:::-;20640:2;20635:3;20631:12;20624:19;;20283:366;;;:::o;20655:419::-;20821:4;20859:2;20848:9;20844:18;20836:26;;20908:9;20902:4;20898:20;20894:1;20883:9;20879:17;20872:47;20936:131;21062:4;20936:131;:::i;:::-;20928:139;;20655:419;;;:::o;21080:182::-;21220:34;21216:1;21208:6;21204:14;21197:58;21080:182;:::o;21268:366::-;21410:3;21431:67;21495:2;21490:3;21431:67;:::i;:::-;21424:74;;21507:93;21596:3;21507:93;:::i;:::-;21625:2;21620:3;21616:12;21609:19;;21268:366;;;:::o;21640:419::-;21806:4;21844:2;21833:9;21829:18;21821:26;;21893:9;21887:4;21883:20;21879:1;21868:9;21864:17;21857:47;21921:131;22047:4;21921:131;:::i;:::-;21913:139;;21640:419;;;:::o;22065:181::-;22205:33;22201:1;22193:6;22189:14;22182:57;22065:181;:::o;22252:366::-;22394:3;22415:67;22479:2;22474:3;22415:67;:::i;:::-;22408:74;;22491:93;22580:3;22491:93;:::i;:::-;22609:2;22604:3;22600:12;22593:19;;22252:366;;;:::o;22624:419::-;22790:4;22828:2;22817:9;22813:18;22805:26;;22877:9;22871:4;22867:20;22863:1;22852:9;22848:17;22841:47;22905:131;23031:4;22905:131;:::i;:::-;22897:139;;22624:419;;;:::o;23049:180::-;23097:77;23094:1;23087:88;23194:4;23191:1;23184:15;23218:4;23215:1;23208:15;23235:237;23375:34;23371:1;23363:6;23359:14;23352:58;23444:20;23439:2;23431:6;23427:15;23420:45;23235:237;:::o;23478:366::-;23620:3;23641:67;23705:2;23700:3;23641:67;:::i;:::-;23634:74;;23717:93;23806:3;23717:93;:::i;:::-;23835:2;23830:3;23826:12;23819:19;;23478:366;;;:::o;23850:419::-;24016:4;24054:2;24043:9;24039:18;24031:26;;24103:9;24097:4;24093:20;24089:1;24078:9;24074:17;24067:47;24131:131;24257:4;24131:131;:::i;:::-;24123:139;;23850:419;;;:::o;24275:775::-;24508:4;24546:3;24535:9;24531:19;24523:27;;24560:71;24628:1;24617:9;24613:17;24604:6;24560:71;:::i;:::-;24641:72;24709:2;24698:9;24694:18;24685:6;24641:72;:::i;:::-;24723;24791:2;24780:9;24776:18;24767:6;24723:72;:::i;:::-;24805;24873:2;24862:9;24858:18;24849:6;24805:72;:::i;:::-;24887:73;24955:3;24944:9;24940:19;24931:6;24887:73;:::i;:::-;24970;25038:3;25027:9;25023:19;25014:6;24970:73;:::i;:::-;24275:775;;;;;;;;;:::o;25056:332::-;25177:4;25215:2;25204:9;25200:18;25192:26;;25228:71;25296:1;25285:9;25281:17;25272:6;25228:71;:::i;:::-;25309:72;25377:2;25366:9;25362:18;25353:6;25309:72;:::i;:::-;25056:332;;;;;:::o;25394:410::-;25434:7;25457:20;25475:1;25457:20;:::i;:::-;25452:25;;25491:20;25509:1;25491:20;:::i;:::-;25486:25;;25546:1;25543;25539:9;25568:30;25586:11;25568:30;:::i;:::-;25557:41;;25747:1;25738:7;25734:15;25731:1;25728:22;25708:1;25701:9;25681:83;25658:139;;25777:18;;:::i;:::-;25658:139;25442:362;25394:410;;;;:::o;25810:180::-;25858:77;25855:1;25848:88;25955:4;25952:1;25945:15;25979:4;25976:1;25969:15;25996:185;26036:1;26053:20;26071:1;26053:20;:::i;:::-;26048:25;;26087:20;26105:1;26087:20;:::i;:::-;26082:25;;26126:1;26116:35;;26131:18;;:::i;:::-;26116:35;26173:1;26170;26166:9;26161:14;;25996:185;;;;:::o;26187:232::-;26327:34;26323:1;26315:6;26311:14;26304:58;26396:15;26391:2;26383:6;26379:15;26372:40;26187:232;:::o;26425:366::-;26567:3;26588:67;26652:2;26647:3;26588:67;:::i;:::-;26581:74;;26664:93;26753:3;26664:93;:::i;:::-;26782:2;26777:3;26773:12;26766:19;;26425:366;;;:::o;26797:419::-;26963:4;27001:2;26990:9;26986:18;26978:26;;27050:9;27044:4;27040:20;27036:1;27025:9;27021:17;27014:47;27078:131;27204:4;27078:131;:::i;:::-;27070:139;;26797:419;;;:::o;27222:442::-;27371:4;27409:2;27398:9;27394:18;27386:26;;27422:71;27490:1;27479:9;27475:17;27466:6;27422:71;:::i;:::-;27503:72;27571:2;27560:9;27556:18;27547:6;27503:72;:::i;:::-;27585;27653:2;27642:9;27638:18;27629:6;27585:72;:::i;:::-;27222:442;;;;;;:::o;27670:224::-;27810:34;27806:1;27798:6;27794:14;27787:58;27879:7;27874:2;27866:6;27862:15;27855:32;27670:224;:::o;27900:366::-;28042:3;28063:67;28127:2;28122:3;28063:67;:::i;:::-;28056:74;;28139:93;28228:3;28139:93;:::i;:::-;28257:2;28252:3;28248:12;28241:19;;27900:366;;;:::o;28272:419::-;28438:4;28476:2;28465:9;28461:18;28453:26;;28525:9;28519:4;28515:20;28511:1;28500:9;28496:17;28489:47;28553:131;28679:4;28553:131;:::i;:::-;28545:139;;28272:419;;;:::o;28697:332::-;28818:4;28856:2;28845:9;28841:18;28833:26;;28869:71;28937:1;28926:9;28922:17;28913:6;28869:71;:::i;:::-;28950:72;29018:2;29007:9;29003:18;28994:6;28950:72;:::i;:::-;28697:332;;;;;:::o;29035:664::-;29240:4;29278:3;29267:9;29263:19;29255:27;;29292:71;29360:1;29349:9;29345:17;29336:6;29292:71;:::i;:::-;29373:72;29441:2;29430:9;29426:18;29417:6;29373:72;:::i;:::-;29455;29523:2;29512:9;29508:18;29499:6;29455:72;:::i;:::-;29537;29605:2;29594:9;29590:18;29581:6;29537:72;:::i;:::-;29619:73;29687:3;29676:9;29672:19;29663:6;29619:73;:::i;:::-;29035:664;;;;;;;;:::o;29705:545::-;29878:4;29916:3;29905:9;29901:19;29893:27;;29930:71;29998:1;29987:9;29983:17;29974:6;29930:71;:::i;:::-;30011:68;30075:2;30064:9;30060:18;30051:6;30011:68;:::i;:::-;30089:72;30157:2;30146:9;30142:18;30133:6;30089:72;:::i;:::-;30171;30239:2;30228:9;30224:18;30215:6;30171:72;:::i;:::-;29705:545;;;;;;;:::o;30256:180::-;30304:77;30301:1;30294:88;30401:4;30398:1;30391:15;30425:4;30422:1;30415:15;30442:191;30482:3;30501:20;30519:1;30501:20;:::i;:::-;30496:25;;30535:20;30553:1;30535:20;:::i;:::-;30530:25;;30578:1;30575;30571:9;30564:16;;30599:3;30596:1;30593:10;30590:36;;;30606:18;;:::i;:::-;30590:36;30442:191;;;;:::o
Swarm Source
ipfs://d7ae364ebf38f1292ad96706abfb172fe0c3b90d5b165210e3b69f8aacc4dccd
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.