ERC-20
Overview
Max Total Supply
1,690.33769814 wAIPG
Holders
7
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
WrappedAIPG
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-06-06 */ // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } } // File: @openzeppelin/contracts/access/IAccessControl.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; } // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: @openzeppelin/contracts/utils/introspection/ERC165.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/contracts/access/AccessControl.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } } // File: @openzeppelin/contracts/security/Pausable.sol // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } } // File: @openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } } // File: @openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } } // File: @openzeppelin/contracts/utils/StorageSlot.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } } // File: @openzeppelin/contracts/utils/ShortStrings.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol) pragma solidity ^0.8.20; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using * {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } } // File: @openzeppelin/contracts/interfaces/IERC5267.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); } // File: @openzeppelin/contracts/utils/cryptography/EIP712.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * @custom:oz-upgrades-unsafe-allow state-variable-immutable */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {IERC-5267}. */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: By default this function reads _name which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Name() internal view returns (string memory) { return _name.toStringWithFallback(_nameFallback); } /** * @dev The version parameter for the EIP712 domain. * * NOTE: By default this function reads _version which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Version() internal view returns (string memory) { return _version.toStringWithFallback(_versionFallback); } } // File: @openzeppelin/contracts/utils/cryptography/draft-EIP712.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; // EIP-712 is Final as of 2022-08-11. This file is deprecated. // File: wAIPG_final.sol pragma solidity ^0.8.20; // Importing necessary OpenZeppelin contracts for ERC20 token, access control, pausing functionality, and EIP712 standard // WrappedAIPG is an ERC20 token with additional features like access control and pausability contract WrappedAIPG is ERC20, AccessControl, Pausable, EIP712 { // Role definition for minters using a unique hash bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); // Hash for the minting function to ensure correct function is called with EIP712 bytes32 private constant MINT_TYPEHASH = keccak256("MintRequest(address to,uint256 amount,uint256 uuid,uint256 deadline)"); // Account that will collect transaction fees address public feeAccount; // Initial fee percentage set at 3% uint256 public feePercent = 3; // Maximum fee percentage allowed uint256 public constant MAX_FEE = 5; // Mapping to store used UUIDs mapping(bytes32 => bool) private usedUUIDs; // Struct to define the mint request parameters struct MintRequest { address to; uint256 amount; uint256 uuid; uint256 deadline; } // Constructor to initialize the ERC20 token and set initial roles and fee account constructor() ERC20("Wrapped AI Power Grid", "wAIPG") EIP712("WrappedAIPowerGrid", "1") { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); // Granting admin role to the contract deployer _grantRole(MINTER_ROLE, msg.sender); // Granting minter role to the contract deployer feeAccount = msg.sender; // Setting the fee account to the contract deployer initially } // Function to set the fee account, only accessible by admin function setFeeAccount(address _feeAccount) external onlyRole(DEFAULT_ADMIN_ROLE) { feeAccount = _feeAccount; } // Function to set the fee percentage, only accessible by admin and with checks for maximum fee limit function setFeePercent(uint256 _feePercent) external onlyRole(DEFAULT_ADMIN_ROLE) { require(_feePercent <= MAX_FEE, "Fee percent too high"); feePercent = _feePercent; } // Function to transfer tokens with fee deduction function transfer(address recipient, uint256 amount) public override returns (bool) { uint256 fee = (amount * feePercent) / 100; uint256 amountAfterFee = amount - fee; super.transfer(feeAccount, fee); // Transfer the fee super.transfer(recipient, amountAfterFee); // Transfer the net amount return true; } // Function to mint tokens using a signed request, ensuring it's within the deadline and the signature is valid function mint(MintRequest calldata request, uint8 v, bytes32 r, bytes32 s) public { require(block.timestamp <= request.deadline, "Expired deadline"); bytes32 structHash = keccak256(abi.encode(MINT_TYPEHASH, request.to, request.amount, request.uuid, request.deadline)); bytes32 digest = _hashTypedDataV4(structHash); address signer = ecrecover(digest, v, r, s); require(hasRole(MINTER_ROLE, signer), "Invalid signature or unauthorized"); // Check if the UUID has already been used bytes32 transactionHash = keccak256(abi.encodePacked(request.to, request.amount, request.uuid, block.chainid)); require(!usedUUIDs[transactionHash], "UUID already used"); // Mark this UUID as used usedUUIDs[transactionHash] = true; _mint(request.to, request.amount); // Mint the full amount to the requester } // Function to burn tokens, reducing the total supply function burn(uint256 amount) public { _burn(msg.sender, amount); // Burn the specified amount of tokens from the caller's balance } // Function to pause the contract, only accessible by admin function pause() public onlyRole(DEFAULT_ADMIN_ROLE) { _pause(); } // Function to unpause the contract, only accessible by admin function unpause() public onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } }
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":[{"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":[],"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":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"uuid","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct WrappedAIPG.MintRequest","name":"request","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"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":[{"internalType":"address","name":"_feeAccount","type":"address"}],"name":"setFeeAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feePercent","type":"uint256"}],"name":"setFeePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101606040526003600a5534801562000016575f80fd5b506040518060400160405280601281526020017f577261707065644149506f7765724772696400000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280601581526020017f5772617070656420414920506f776572204772696400000000000000000000008152506040518060400160405280600581526020017f774149504700000000000000000000000000000000000000000000000000000081525081600390816200010091906200075b565b5080600490816200011291906200075b565b5050505f60065f6101000a81548160ff021916908315150217905550620001446007836200026c60201b90919060201c565b6101208181525050620001626008826200026c60201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a08181525050620001a1620002c160201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050620001f25f801b336200031d60201b60201c565b50620002257f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336200031d60201b60201c565b503360095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062000a52565b5f602083511015620002915762000289836200041960201b60201c565b9050620002bb565b82620002a3836200048360201b60201c565b5f019081620002b391906200075b565b5060ff5f1b90505b92915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e05161010051463060405160200162000302959493929190620008ad565b60405160208183030381529060405280519060200120905090565b5f6200033083836200048c60201b60201c565b6200040f57600160055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550620003ab620004f060201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001905062000413565b5f90505b92915050565b5f80829050601f815111156200046857826040517f305a27a90000000000000000000000000000000000000000000000000000000081526004016200045f919062000992565b60405180910390fd5b8051816200047690620009e3565b5f1c175f1b915050919050565b5f819050919050565b5f60055f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200057357607f821691505b6020821081036200058957620005886200052e565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620005ed7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620005b0565b620005f98683620005b0565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f620006436200063d620006378462000611565b6200061a565b62000611565b9050919050565b5f819050919050565b6200065e8362000623565b620006766200066d826200064a565b848454620005bc565b825550505050565b5f90565b6200068c6200067e565b6200069981848462000653565b505050565b5b81811015620006c057620006b45f8262000682565b6001810190506200069f565b5050565b601f8211156200070f57620006d9816200058f565b620006e484620005a1565b81016020851015620006f4578190505b6200070c6200070385620005a1565b8301826200069e565b50505b505050565b5f82821c905092915050565b5f620007315f198460080262000714565b1980831691505092915050565b5f6200074b838362000720565b9150826002028217905092915050565b6200076682620004f7565b67ffffffffffffffff81111562000782576200078162000501565b5b6200078e82546200055b565b6200079b828285620006c4565b5f60209050601f831160018114620007d1575f8415620007bc578287015190505b620007c885826200073e565b86555062000837565b601f198416620007e1866200058f565b5f5b828110156200080a57848901518255600182019150602085019450602081019050620007e3565b868310156200082a578489015162000826601f89168262000720565b8355505b6001600288020188555050505b505050505050565b5f819050919050565b62000853816200083f565b82525050565b620008648162000611565b82525050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f62000895826200086a565b9050919050565b620008a78162000889565b82525050565b5f60a082019050620008c25f83018862000848565b620008d1602083018762000848565b620008e0604083018662000848565b620008ef606083018562000859565b620008fe60808301846200089c565b9695505050505050565b5f82825260208201905092915050565b5f5b83811015620009375780820151818401526020810190506200091a565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6200095e82620004f7565b6200096a818562000908565b93506200097c81856020860162000918565b620009878162000942565b840191505092915050565b5f6020820190508181035f830152620009ac818462000952565b905092915050565b5f81519050919050565b5f819050602082019050919050565b5f620009da82516200083f565b80915050919050565b5f620009ef82620009b4565b82620009fb84620009be565b905062000a0881620009cd565b9250602082101562000a4b5762000a467fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802620005b0565b831692505b5050919050565b60805160a05160c05160e05161010051610120516101405161296362000aa45f395f6113be01525f61138301525f611bd001525f611baf01525f611a2601525f611a7c01525f611aa501526129635ff3fe608060405234801561000f575f80fd5b50600436106101c2575f3560e01c806370a08231116100f7578063966e2a4611610095578063bc063e1a1161006f578063bc063e1a146104e6578063d539139314610504578063d547741f14610522578063dd62ed3e1461053e576101c2565b8063966e2a461461047c578063a217fddf14610498578063a9059cbb146104b6576101c2565b80638456cb59116100d15780638456cb591461040057806384b0196e1461040a57806391d148541461042e57806395d89b411461045e576101c2565b806370a08231146103965780637ce3489b146103c65780637fd6f15c146103e2576101c2565b8063313ce5671161016457806342966c681161013e57806342966c68146103225780634b023cf81461033e5780635c975abb1461035a57806365e17c9d14610378576101c2565b8063313ce567146102de57806336568abe146102fc5780633f4ba83a14610318576101c2565b806318160ddd116101a057806318160ddd1461024457806323b872dd14610262578063248a9ca3146102925780632f2ff15d146102c2576101c2565b806301ffc9a7146101c657806306fdde03146101f6578063095ea7b314610214575b5f80fd5b6101e060048036038101906101db9190611cc7565b61056e565b6040516101ed9190611d0c565b60405180910390f35b6101fe6105e7565b60405161020b9190611daf565b60405180910390f35b61022e60048036038101906102299190611e5c565b610677565b60405161023b9190611d0c565b60405180910390f35b61024c610699565b6040516102599190611ea9565b60405180910390f35b61027c60048036038101906102779190611ec2565b6106a2565b6040516102899190611d0c565b60405180910390f35b6102ac60048036038101906102a79190611f45565b6106d0565b6040516102b99190611f7f565b60405180910390f35b6102dc60048036038101906102d79190611f98565b6106ed565b005b6102e661070f565b6040516102f39190611ff1565b60405180910390f35b61031660048036038101906103119190611f98565b610717565b005b610320610792565b005b61033c6004803603810190610337919061200a565b6107a9565b005b61035860048036038101906103539190612035565b6107b6565b005b610362610806565b60405161036f9190611d0c565b60405180910390f35b61038061081b565b60405161038d919061206f565b60405180910390f35b6103b060048036038101906103ab9190612035565b610840565b6040516103bd9190611ea9565b60405180910390f35b6103e060048036038101906103db919061200a565b610885565b005b6103ea6108e0565b6040516103f79190611ea9565b60405180910390f35b6104086108e6565b005b6104126108fd565b6040516104259796959493929190612179565b60405180910390f35b61044860048036038101906104439190611f98565b6109a2565b6040516104559190611d0c565b60405180910390f35b610466610a06565b6040516104739190611daf565b60405180910390f35b61049660048036038101906104919190612247565b610a96565b005b6104a0610d09565b6040516104ad9190611f7f565b60405180910390f35b6104d060048036038101906104cb9190611e5c565b610d0f565b6040516104dd9190611d0c565b60405180910390f35b6104ee610d7f565b6040516104fb9190611ea9565b60405180910390f35b61050c610d84565b6040516105199190611f7f565b60405180910390f35b61053c60048036038101906105379190611f98565b610da8565b005b610558600480360381019061055391906122ab565b610dca565b6040516105659190611ea9565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105e057506105df82610e4c565b5b9050919050565b6060600380546105f690612316565b80601f016020809104026020016040519081016040528092919081815260200182805461062290612316565b801561066d5780601f106106445761010080835404028352916020019161066d565b820191905f5260205f20905b81548152906001019060200180831161065057829003601f168201915b5050505050905090565b5f80610681610eb5565b905061068e818585610ebc565b600191505092915050565b5f600254905090565b5f806106ac610eb5565b90506106b9858285610ece565b6106c4858585610f60565b60019150509392505050565b5f60055f8381526020019081526020015f20600101549050919050565b6106f6826106d0565b6106ff81611050565b6107098383611064565b50505050565b5f6012905090565b61071f610eb5565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610783576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61078d828261114e565b505050565b5f801b61079e81611050565b6107a6611238565b50565b6107b33382611299565b50565b5f801b6107c281611050565b8160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f60065f9054906101000a900460ff16905090565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f801b61089181611050565b60058211156108d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cc90612390565b60405180910390fd5b81600a819055505050565b600a5481565b5f801b6108f281611050565b6108fa611318565b50565b5f6060805f805f606061090e61137a565b6109166113b5565b46305f801b5f67ffffffffffffffff811115610935576109346123ae565b5b6040519080825280602002602001820160405280156109635781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60055f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b606060048054610a1590612316565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190612316565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050905090565b8360600135421115610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad490612425565b60405180910390fd5b5f7f05dac90127b5beea9d6bac8bf6962ef964e99f78ca9a5ee126ed3158f14d003c855f016020810190610b119190612035565b866020013587604001358860600135604051602001610b34959493929190612443565b6040516020818303038152906040528051906020012090505f610b56826113f0565b90505f6001828787876040515f8152602001604052604051610b7b9493929190612494565b6020604051602081039080840390855afa158015610b9b573d5f803e3d5ffd5b505050602060405103519050610bd17f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6826109a2565b610c10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0790612547565b60405180910390fd5b5f875f016020810190610c239190612035565b8860200135896040013546604051602001610c4194939291906125ca565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff1615610cb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cae90612661565b60405180910390fd5b6001600b5f8381526020019081526020015f205f6101000a81548160ff021916908315150217905550610cff885f016020810190610cf59190612035565b8960200135611409565b5050505050505050565b5f801b81565b5f806064600a5484610d2191906126ac565b610d2b919061271a565b90505f8184610d3a919061274a565b9050610d6760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611488565b50610d728582611488565b5060019250505092915050565b600581565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610db1826106d0565b610dba81611050565b610dc4838361114e565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b610ec983838360016114aa565b505050565b5f610ed98484610dca565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610f5a5781811015610f4b578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401610f429392919061277d565b60405180910390fd5b610f5984848484035f6114aa565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd0575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610fc7919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611040575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611037919061206f565b60405180910390fd5b61104b838383611679565b505050565b6110618161105c610eb5565b611892565b50565b5f61106f83836109a2565b61114457600160055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506110e1610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611148565b5f90505b92915050565b5f61115983836109a2565b1561122e575f60055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506111cb610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611232565b5f90505b92915050565b6112406118e3565b5f60065f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611282610eb5565b60405161128f919061206f565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611309575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611300919061206f565b60405180910390fd5b611314825f83611679565b5050565b61132061192c565b600160065f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611363610eb5565b604051611370919061206f565b60405180910390a1565b60606113b060077f000000000000000000000000000000000000000000000000000000000000000061197690919063ffffffff16565b905090565b60606113eb60087f000000000000000000000000000000000000000000000000000000000000000061197690919063ffffffff16565b905090565b5f6114026113fc611a23565b83611ad9565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611479575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611470919061206f565b60405180910390fd5b6114845f8383611679565b5050565b5f80611492610eb5565b905061149f818585610f60565b600191505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361151a575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611511919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158a575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401611581919061206f565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015611673578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161166a9190611ea9565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036116c9578060025f8282546116bd91906127b2565b92505081905550611797565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611752578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016117499392919061277d565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117de578060025f8282540392505081905550611828565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516118859190611ea9565b60405180910390a3505050565b61189c82826109a2565b6118df5780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016118d69291906127e5565b60405180910390fd5b5050565b6118eb610806565b61192a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192190612856565b60405180910390fd5b565b611934610806565b15611974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196b906128be565b60405180910390fd5b565b606060ff5f1b83146119925761198b83611b19565b9050611a1d565b81805461199e90612316565b80601f01602080910402602001604051908101604052809291908181526020018280546119ca90612316565b8015611a155780601f106119ec57610100808354040283529160200191611a15565b820191905f5260205f20905b8154815290600101906020018083116119f857829003601f168201915b505050505090505b92915050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611a9e57507f000000000000000000000000000000000000000000000000000000000000000046145b15611acb577f00000000000000000000000000000000000000000000000000000000000000009050611ad6565b611ad3611b8b565b90505b90565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60605f611b2583611c20565b90505f602067ffffffffffffffff811115611b4357611b426123ae565b5b6040519080825280601f01601f191660200182016040528015611b755781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000004630604051602001611c059594939291906128dc565b60405160208183030381529060405280519060200120905090565b5f8060ff835f1c169050601f811115611c65576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611ca681611c72565b8114611cb0575f80fd5b50565b5f81359050611cc181611c9d565b92915050565b5f60208284031215611cdc57611cdb611c6e565b5b5f611ce984828501611cb3565b91505092915050565b5f8115159050919050565b611d0681611cf2565b82525050565b5f602082019050611d1f5f830184611cfd565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611d5c578082015181840152602081019050611d41565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611d8182611d25565b611d8b8185611d2f565b9350611d9b818560208601611d3f565b611da481611d67565b840191505092915050565b5f6020820190508181035f830152611dc78184611d77565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611df882611dcf565b9050919050565b611e0881611dee565b8114611e12575f80fd5b50565b5f81359050611e2381611dff565b92915050565b5f819050919050565b611e3b81611e29565b8114611e45575f80fd5b50565b5f81359050611e5681611e32565b92915050565b5f8060408385031215611e7257611e71611c6e565b5b5f611e7f85828601611e15565b9250506020611e9085828601611e48565b9150509250929050565b611ea381611e29565b82525050565b5f602082019050611ebc5f830184611e9a565b92915050565b5f805f60608486031215611ed957611ed8611c6e565b5b5f611ee686828701611e15565b9350506020611ef786828701611e15565b9250506040611f0886828701611e48565b9150509250925092565b5f819050919050565b611f2481611f12565b8114611f2e575f80fd5b50565b5f81359050611f3f81611f1b565b92915050565b5f60208284031215611f5a57611f59611c6e565b5b5f611f6784828501611f31565b91505092915050565b611f7981611f12565b82525050565b5f602082019050611f925f830184611f70565b92915050565b5f8060408385031215611fae57611fad611c6e565b5b5f611fbb85828601611f31565b9250506020611fcc85828601611e15565b9150509250929050565b5f60ff82169050919050565b611feb81611fd6565b82525050565b5f6020820190506120045f830184611fe2565b92915050565b5f6020828403121561201f5761201e611c6e565b5b5f61202c84828501611e48565b91505092915050565b5f6020828403121561204a57612049611c6e565b5b5f61205784828501611e15565b91505092915050565b61206981611dee565b82525050565b5f6020820190506120825f830184612060565b92915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6120bc81612088565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6120f481611e29565b82525050565b5f61210583836120eb565b60208301905092915050565b5f602082019050919050565b5f612127826120c2565b61213181856120cc565b935061213c836120dc565b805f5b8381101561216c57815161215388826120fa565b975061215e83612111565b92505060018101905061213f565b5085935050505092915050565b5f60e08201905061218c5f83018a6120b3565b818103602083015261219e8189611d77565b905081810360408301526121b28188611d77565b90506121c16060830187611e9a565b6121ce6080830186612060565b6121db60a0830185611f70565b81810360c08301526121ed818461211d565b905098975050505050505050565b5f80fd5b5f60808284031215612214576122136121fb565b5b81905092915050565b61222681611fd6565b8114612230575f80fd5b50565b5f813590506122418161221d565b92915050565b5f805f8060e0858703121561225f5761225e611c6e565b5b5f61226c878288016121ff565b945050608061227d87828801612233565b93505060a061228e87828801611f31565b92505060c061229f87828801611f31565b91505092959194509250565b5f80604083850312156122c1576122c0611c6e565b5b5f6122ce85828601611e15565b92505060206122df85828601611e15565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061232d57607f821691505b6020821081036123405761233f6122e9565b5b50919050565b7f4665652070657263656e7420746f6f20686967680000000000000000000000005f82015250565b5f61237a601483611d2f565b915061238582612346565b602082019050919050565b5f6020820190508181035f8301526123a78161236e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4578706972656420646561646c696e65000000000000000000000000000000005f82015250565b5f61240f601083611d2f565b915061241a826123db565b602082019050919050565b5f6020820190508181035f83015261243c81612403565b9050919050565b5f60a0820190506124565f830188611f70565b6124636020830187612060565b6124706040830186611e9a565b61247d6060830185611e9a565b61248a6080830184611e9a565b9695505050505050565b5f6080820190506124a75f830187611f70565b6124b46020830186611fe2565b6124c16040830185611f70565b6124ce6060830184611f70565b95945050505050565b7f496e76616c6964207369676e6174757265206f7220756e617574686f72697a655f8201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b5f612531602183611d2f565b915061253c826124d7565b604082019050919050565b5f6020820190508181035f83015261255e81612525565b9050919050565b5f8160601b9050919050565b5f61257b82612565565b9050919050565b5f61258c82612571565b9050919050565b6125a461259f82611dee565b612582565b82525050565b5f819050919050565b6125c46125bf82611e29565b6125aa565b82525050565b5f6125d58287612593565b6014820191506125e582866125b3565b6020820191506125f582856125b3565b60208201915061260582846125b3565b60208201915081905095945050505050565b7f5555494420616c726561647920757365640000000000000000000000000000005f82015250565b5f61264b601183611d2f565b915061265682612617565b602082019050919050565b5f6020820190508181035f8301526126788161263f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126b682611e29565b91506126c183611e29565b92508282026126cf81611e29565b915082820484148315176126e6576126e561267f565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61272482611e29565b915061272f83611e29565b92508261273f5761273e6126ed565b5b828204905092915050565b5f61275482611e29565b915061275f83611e29565b92508282039050818111156127775761277661267f565b5b92915050565b5f6060820190506127905f830186612060565b61279d6020830185611e9a565b6127aa6040830184611e9a565b949350505050565b5f6127bc82611e29565b91506127c783611e29565b92508282019050808211156127df576127de61267f565b5b92915050565b5f6040820190506127f85f830185612060565b6128056020830184611f70565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f612840601483611d2f565b915061284b8261280c565b602082019050919050565b5f6020820190508181035f83015261286d81612834565b9050919050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f6128a8601083611d2f565b91506128b382612874565b602082019050919050565b5f6020820190508181035f8301526128d58161289c565b9050919050565b5f60a0820190506128ef5f830188611f70565b6128fc6020830187611f70565b6129096040830186611f70565b6129166060830185611e9a565b6129236080830184612060565b969550505050505056fea2646970667358221220e82b19a89abf63c1048f41713e43e786d4a36f7c3ccef9d5c065216568b2c19b64736f6c63430008140033
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101c2575f3560e01c806370a08231116100f7578063966e2a4611610095578063bc063e1a1161006f578063bc063e1a146104e6578063d539139314610504578063d547741f14610522578063dd62ed3e1461053e576101c2565b8063966e2a461461047c578063a217fddf14610498578063a9059cbb146104b6576101c2565b80638456cb59116100d15780638456cb591461040057806384b0196e1461040a57806391d148541461042e57806395d89b411461045e576101c2565b806370a08231146103965780637ce3489b146103c65780637fd6f15c146103e2576101c2565b8063313ce5671161016457806342966c681161013e57806342966c68146103225780634b023cf81461033e5780635c975abb1461035a57806365e17c9d14610378576101c2565b8063313ce567146102de57806336568abe146102fc5780633f4ba83a14610318576101c2565b806318160ddd116101a057806318160ddd1461024457806323b872dd14610262578063248a9ca3146102925780632f2ff15d146102c2576101c2565b806301ffc9a7146101c657806306fdde03146101f6578063095ea7b314610214575b5f80fd5b6101e060048036038101906101db9190611cc7565b61056e565b6040516101ed9190611d0c565b60405180910390f35b6101fe6105e7565b60405161020b9190611daf565b60405180910390f35b61022e60048036038101906102299190611e5c565b610677565b60405161023b9190611d0c565b60405180910390f35b61024c610699565b6040516102599190611ea9565b60405180910390f35b61027c60048036038101906102779190611ec2565b6106a2565b6040516102899190611d0c565b60405180910390f35b6102ac60048036038101906102a79190611f45565b6106d0565b6040516102b99190611f7f565b60405180910390f35b6102dc60048036038101906102d79190611f98565b6106ed565b005b6102e661070f565b6040516102f39190611ff1565b60405180910390f35b61031660048036038101906103119190611f98565b610717565b005b610320610792565b005b61033c6004803603810190610337919061200a565b6107a9565b005b61035860048036038101906103539190612035565b6107b6565b005b610362610806565b60405161036f9190611d0c565b60405180910390f35b61038061081b565b60405161038d919061206f565b60405180910390f35b6103b060048036038101906103ab9190612035565b610840565b6040516103bd9190611ea9565b60405180910390f35b6103e060048036038101906103db919061200a565b610885565b005b6103ea6108e0565b6040516103f79190611ea9565b60405180910390f35b6104086108e6565b005b6104126108fd565b6040516104259796959493929190612179565b60405180910390f35b61044860048036038101906104439190611f98565b6109a2565b6040516104559190611d0c565b60405180910390f35b610466610a06565b6040516104739190611daf565b60405180910390f35b61049660048036038101906104919190612247565b610a96565b005b6104a0610d09565b6040516104ad9190611f7f565b60405180910390f35b6104d060048036038101906104cb9190611e5c565b610d0f565b6040516104dd9190611d0c565b60405180910390f35b6104ee610d7f565b6040516104fb9190611ea9565b60405180910390f35b61050c610d84565b6040516105199190611f7f565b60405180910390f35b61053c60048036038101906105379190611f98565b610da8565b005b610558600480360381019061055391906122ab565b610dca565b6040516105659190611ea9565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806105e057506105df82610e4c565b5b9050919050565b6060600380546105f690612316565b80601f016020809104026020016040519081016040528092919081815260200182805461062290612316565b801561066d5780601f106106445761010080835404028352916020019161066d565b820191905f5260205f20905b81548152906001019060200180831161065057829003601f168201915b5050505050905090565b5f80610681610eb5565b905061068e818585610ebc565b600191505092915050565b5f600254905090565b5f806106ac610eb5565b90506106b9858285610ece565b6106c4858585610f60565b60019150509392505050565b5f60055f8381526020019081526020015f20600101549050919050565b6106f6826106d0565b6106ff81611050565b6107098383611064565b50505050565b5f6012905090565b61071f610eb5565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610783576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61078d828261114e565b505050565b5f801b61079e81611050565b6107a6611238565b50565b6107b33382611299565b50565b5f801b6107c281611050565b8160095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f60065f9054906101000a900460ff16905090565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f801b61089181611050565b60058211156108d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108cc90612390565b60405180910390fd5b81600a819055505050565b600a5481565b5f801b6108f281611050565b6108fa611318565b50565b5f6060805f805f606061090e61137a565b6109166113b5565b46305f801b5f67ffffffffffffffff811115610935576109346123ae565b5b6040519080825280602002602001820160405280156109635781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b5f60055f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b606060048054610a1590612316565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190612316565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050905090565b8360600135421115610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad490612425565b60405180910390fd5b5f7f05dac90127b5beea9d6bac8bf6962ef964e99f78ca9a5ee126ed3158f14d003c855f016020810190610b119190612035565b866020013587604001358860600135604051602001610b34959493929190612443565b6040516020818303038152906040528051906020012090505f610b56826113f0565b90505f6001828787876040515f8152602001604052604051610b7b9493929190612494565b6020604051602081039080840390855afa158015610b9b573d5f803e3d5ffd5b505050602060405103519050610bd17f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6826109a2565b610c10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0790612547565b60405180910390fd5b5f875f016020810190610c239190612035565b8860200135896040013546604051602001610c4194939291906125ca565b604051602081830303815290604052805190602001209050600b5f8281526020019081526020015f205f9054906101000a900460ff1615610cb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cae90612661565b60405180910390fd5b6001600b5f8381526020019081526020015f205f6101000a81548160ff021916908315150217905550610cff885f016020810190610cf59190612035565b8960200135611409565b5050505050505050565b5f801b81565b5f806064600a5484610d2191906126ac565b610d2b919061271a565b90505f8184610d3a919061274a565b9050610d6760095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683611488565b50610d728582611488565b5060019250505092915050565b600581565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610db1826106d0565b610dba81611050565b610dc4838361114e565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b610ec983838360016114aa565b505050565b5f610ed98484610dca565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610f5a5781811015610f4b578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401610f429392919061277d565b60405180910390fd5b610f5984848484035f6114aa565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fd0575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610fc7919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611040575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611037919061206f565b60405180910390fd5b61104b838383611679565b505050565b6110618161105c610eb5565b611892565b50565b5f61106f83836109a2565b61114457600160055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506110e1610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611148565b5f90505b92915050565b5f61115983836109a2565b1561122e575f60055f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506111cb610eb5565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050611232565b5f90505b92915050565b6112406118e3565b5f60065f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611282610eb5565b60405161128f919061206f565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611309575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611300919061206f565b60405180910390fd5b611314825f83611679565b5050565b61132061192c565b600160065f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611363610eb5565b604051611370919061206f565b60405180910390a1565b60606113b060077f577261707065644149506f77657247726964000000000000000000000000001261197690919063ffffffff16565b905090565b60606113eb60087f310000000000000000000000000000000000000000000000000000000000000161197690919063ffffffff16565b905090565b5f6114026113fc611a23565b83611ad9565b9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611479575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611470919061206f565b60405180910390fd5b6114845f8383611679565b5050565b5f80611492610eb5565b905061149f818585610f60565b600191505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361151a575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401611511919061206f565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361158a575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401611581919061206f565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015611673578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161166a9190611ea9565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036116c9578060025f8282546116bd91906127b2565b92505081905550611797565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611752578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016117499392919061277d565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117de578060025f8282540392505081905550611828565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516118859190611ea9565b60405180910390a3505050565b61189c82826109a2565b6118df5780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016118d69291906127e5565b60405180910390fd5b5050565b6118eb610806565b61192a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192190612856565b60405180910390fd5b565b611934610806565b15611974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196b906128be565b60405180910390fd5b565b606060ff5f1b83146119925761198b83611b19565b9050611a1d565b81805461199e90612316565b80601f01602080910402602001604051908101604052809291908181526020018280546119ca90612316565b8015611a155780601f106119ec57610100808354040283529160200191611a15565b820191905f5260205f20905b8154815290600101906020018083116119f857829003601f168201915b505050505090505b92915050565b5f7f000000000000000000000000a1c0def10828a7343bb75cb5036a58570105b30373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611a9e57507f000000000000000000000000000000000000000000000000000000000000000146145b15611acb577f784e0e8df2a866b93ebb2d1d8fac3915fb8cbc0308bb0c76f7407b9d7bed06649050611ad6565b611ad3611b8b565b90505b90565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60605f611b2583611c20565b90505f602067ffffffffffffffff811115611b4357611b426123ae565b5b6040519080825280601f01601f191660200182016040528015611b755781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7fe7a21fcf0b8af70ba7f6fe639866ffa7065e564f5694d61fd1bfeae2bada280c7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64630604051602001611c059594939291906128dc565b60405160208183030381529060405280519060200120905090565b5f8060ff835f1c169050601f811115611c65576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611ca681611c72565b8114611cb0575f80fd5b50565b5f81359050611cc181611c9d565b92915050565b5f60208284031215611cdc57611cdb611c6e565b5b5f611ce984828501611cb3565b91505092915050565b5f8115159050919050565b611d0681611cf2565b82525050565b5f602082019050611d1f5f830184611cfd565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015611d5c578082015181840152602081019050611d41565b5f8484015250505050565b5f601f19601f8301169050919050565b5f611d8182611d25565b611d8b8185611d2f565b9350611d9b818560208601611d3f565b611da481611d67565b840191505092915050565b5f6020820190508181035f830152611dc78184611d77565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611df882611dcf565b9050919050565b611e0881611dee565b8114611e12575f80fd5b50565b5f81359050611e2381611dff565b92915050565b5f819050919050565b611e3b81611e29565b8114611e45575f80fd5b50565b5f81359050611e5681611e32565b92915050565b5f8060408385031215611e7257611e71611c6e565b5b5f611e7f85828601611e15565b9250506020611e9085828601611e48565b9150509250929050565b611ea381611e29565b82525050565b5f602082019050611ebc5f830184611e9a565b92915050565b5f805f60608486031215611ed957611ed8611c6e565b5b5f611ee686828701611e15565b9350506020611ef786828701611e15565b9250506040611f0886828701611e48565b9150509250925092565b5f819050919050565b611f2481611f12565b8114611f2e575f80fd5b50565b5f81359050611f3f81611f1b565b92915050565b5f60208284031215611f5a57611f59611c6e565b5b5f611f6784828501611f31565b91505092915050565b611f7981611f12565b82525050565b5f602082019050611f925f830184611f70565b92915050565b5f8060408385031215611fae57611fad611c6e565b5b5f611fbb85828601611f31565b9250506020611fcc85828601611e15565b9150509250929050565b5f60ff82169050919050565b611feb81611fd6565b82525050565b5f6020820190506120045f830184611fe2565b92915050565b5f6020828403121561201f5761201e611c6e565b5b5f61202c84828501611e48565b91505092915050565b5f6020828403121561204a57612049611c6e565b5b5f61205784828501611e15565b91505092915050565b61206981611dee565b82525050565b5f6020820190506120825f830184612060565b92915050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6120bc81612088565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6120f481611e29565b82525050565b5f61210583836120eb565b60208301905092915050565b5f602082019050919050565b5f612127826120c2565b61213181856120cc565b935061213c836120dc565b805f5b8381101561216c57815161215388826120fa565b975061215e83612111565b92505060018101905061213f565b5085935050505092915050565b5f60e08201905061218c5f83018a6120b3565b818103602083015261219e8189611d77565b905081810360408301526121b28188611d77565b90506121c16060830187611e9a565b6121ce6080830186612060565b6121db60a0830185611f70565b81810360c08301526121ed818461211d565b905098975050505050505050565b5f80fd5b5f60808284031215612214576122136121fb565b5b81905092915050565b61222681611fd6565b8114612230575f80fd5b50565b5f813590506122418161221d565b92915050565b5f805f8060e0858703121561225f5761225e611c6e565b5b5f61226c878288016121ff565b945050608061227d87828801612233565b93505060a061228e87828801611f31565b92505060c061229f87828801611f31565b91505092959194509250565b5f80604083850312156122c1576122c0611c6e565b5b5f6122ce85828601611e15565b92505060206122df85828601611e15565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061232d57607f821691505b6020821081036123405761233f6122e9565b5b50919050565b7f4665652070657263656e7420746f6f20686967680000000000000000000000005f82015250565b5f61237a601483611d2f565b915061238582612346565b602082019050919050565b5f6020820190508181035f8301526123a78161236e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4578706972656420646561646c696e65000000000000000000000000000000005f82015250565b5f61240f601083611d2f565b915061241a826123db565b602082019050919050565b5f6020820190508181035f83015261243c81612403565b9050919050565b5f60a0820190506124565f830188611f70565b6124636020830187612060565b6124706040830186611e9a565b61247d6060830185611e9a565b61248a6080830184611e9a565b9695505050505050565b5f6080820190506124a75f830187611f70565b6124b46020830186611fe2565b6124c16040830185611f70565b6124ce6060830184611f70565b95945050505050565b7f496e76616c6964207369676e6174757265206f7220756e617574686f72697a655f8201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b5f612531602183611d2f565b915061253c826124d7565b604082019050919050565b5f6020820190508181035f83015261255e81612525565b9050919050565b5f8160601b9050919050565b5f61257b82612565565b9050919050565b5f61258c82612571565b9050919050565b6125a461259f82611dee565b612582565b82525050565b5f819050919050565b6125c46125bf82611e29565b6125aa565b82525050565b5f6125d58287612593565b6014820191506125e582866125b3565b6020820191506125f582856125b3565b60208201915061260582846125b3565b60208201915081905095945050505050565b7f5555494420616c726561647920757365640000000000000000000000000000005f82015250565b5f61264b601183611d2f565b915061265682612617565b602082019050919050565b5f6020820190508181035f8301526126788161263f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126b682611e29565b91506126c183611e29565b92508282026126cf81611e29565b915082820484148315176126e6576126e561267f565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61272482611e29565b915061272f83611e29565b92508261273f5761273e6126ed565b5b828204905092915050565b5f61275482611e29565b915061275f83611e29565b92508282039050818111156127775761277661267f565b5b92915050565b5f6060820190506127905f830186612060565b61279d6020830185611e9a565b6127aa6040830184611e9a565b949350505050565b5f6127bc82611e29565b91506127c783611e29565b92508282019050808211156127df576127de61267f565b5b92915050565b5f6040820190506127f85f830185612060565b6128056020830184611f70565b9392505050565b7f5061757361626c653a206e6f74207061757365640000000000000000000000005f82015250565b5f612840601483611d2f565b915061284b8261280c565b602082019050919050565b5f6020820190508181035f83015261286d81612834565b9050919050565b7f5061757361626c653a20706175736564000000000000000000000000000000005f82015250565b5f6128a8601083611d2f565b91506128b382612874565b602082019050919050565b5f6020820190508181035f8301526128d58161289c565b9050919050565b5f60a0820190506128ef5f830188611f70565b6128fc6020830187611f70565b6129096040830186611f70565b6129166060830185611e9a565b6129236080830184612060565b969550505050505056fea2646970667358221220e82b19a89abf63c1048f41713e43e786d4a36f7c3ccef9d5c065216568b2c19b64736f6c63430008140033
Deployed Bytecode Sourcemap
78072:3906:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30428:204;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13330:91;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;15623:190;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14432:99;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;16391:249;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;31708:122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32140:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;14283:84;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33277:251;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;81891:84;;;:::i;:::-;;81517:146;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;79573:125;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;36727:86;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;78534:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;14594:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;79813:191;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;78607:29;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;81736:80;;;:::i;:::-;;76012:580;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;30724:138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13540:95;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80547:899;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;30036:49;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;80067:355;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;78682:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;78198:62;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32571:140;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;15162:142;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;30428:204;30513:4;30552:32;30537:47;;;:11;:47;;;;:87;;;;30588:36;30612:11;30588:23;:36::i;:::-;30537:87;30530:94;;30428:204;;;:::o;13330:91::-;13375:13;13408:5;13401:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13330:91;:::o;15623:190::-;15696:4;15713:13;15729:12;:10;:12::i;:::-;15713:28;;15752:31;15761:5;15768:7;15777:5;15752:8;:31::i;:::-;15801:4;15794:11;;;15623:190;;;;:::o;14432:99::-;14484:7;14511:12;;14504:19;;14432:99;:::o;16391:249::-;16478:4;16495:15;16513:12;:10;:12::i;:::-;16495:30;;16536:37;16552:4;16558:7;16567:5;16536:15;:37::i;:::-;16584:26;16594:4;16600:2;16604:5;16584:9;:26::i;:::-;16628:4;16621:11;;;16391:249;;;;;:::o;31708:122::-;31773:7;31800:6;:12;31807:4;31800:12;;;;;;;;;;;:22;;;31793:29;;31708:122;;;:::o;32140:138::-;32214:18;32227:4;32214:12;:18::i;:::-;30320:16;30331:4;30320:10;:16::i;:::-;32245:25:::1;32256:4;32262:7;32245:10;:25::i;:::-;;32140:138:::0;;;:::o;14283:84::-;14332:5;14357:2;14350:9;;14283:84;:::o;33277:251::-;33393:12;:10;:12::i;:::-;33371:34;;:18;:34;;;33367:104;;33429:30;;;;;;;;;;;;;;33367:104;33483:37;33495:4;33501:18;33483:11;:37::i;:::-;;33277:251;;:::o;81891:84::-;30081:4;81926:18;;30320:16;30331:4;30320:10;:16::i;:::-;81957:10:::1;:8;:10::i;:::-;81891:84:::0;:::o;81517:146::-;81565:25;81571:10;81583:6;81565:5;:25::i;:::-;81517:146;:::o;79573:125::-;30081:4;79635:18;;30320:16;30331:4;30320:10;:16::i;:::-;79679:11:::1;79666:10;;:24;;;;;;;;;;;;;;;;;;79573:125:::0;;:::o;36727:86::-;36774:4;36798:7;;;;;;;;;;;36791:14;;36727:86;:::o;78534:25::-;;;;;;;;;;;;;:::o;14594:118::-;14659:7;14686:9;:18;14696:7;14686:18;;;;;;;;;;;;;;;;14679:25;;14594:118;;;:::o;79813:191::-;30081:4;79875:18;;30320:16;30331:4;30320:10;:16::i;:::-;78716:1:::1;79914:11;:22;;79906:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;79985:11;79972:10;:24;;;;79813:191:::0;;:::o;78607:29::-;;;;:::o;81736:80::-;30081:4;81769:18;;30320:16;30331:4;30320:10;:16::i;:::-;81800:8:::1;:6;:8::i;:::-;81736:80:::0;:::o;76012:580::-;76115:13;76143:18;76176:21;76212:15;76242:25;76282:12;76309:27;76417:13;:11;:13::i;:::-;76445:16;:14;:16::i;:::-;76476:13;76512:4;76540:1;76532:10;;76571:1;76557:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76364:220;;;;;;;;;;;;;;;;;;;;;76012:580;;;;;;;:::o;30724:138::-;30801:4;30825:6;:12;30832:4;30825:12;;;;;;;;;;;:20;;:29;30846:7;30825:29;;;;;;;;;;;;;;;;;;;;;;;;;30818:36;;30724:138;;;;:::o;13540:95::-;13587:13;13620:7;13613:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13540:95;:::o;80547:899::-;80667:7;:16;;;80648:15;:35;;80640:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;80715:18;78395:81;80772:7;:10;;;;;;;;;;:::i;:::-;80784:7;:14;;;80800:7;:12;;;80814:7;:16;;;80746:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;80736:96;;;;;;80715:117;;80843:14;80860:28;80877:10;80860:16;:28::i;:::-;80843:45;;80899:14;80916:26;80926:6;80934:1;80937;80940;80916:26;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80899:43;;80961:28;78236:24;80982:6;80961:7;:28::i;:::-;80953:74;;;;;;;;;;;;:::i;:::-;;;;;;;;;81092:23;81145:7;:10;;;;;;;;;;:::i;:::-;81157:7;:14;;;81173:7;:12;;;81187:13;81128:73;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;81118:84;;;;;;81092:110;;81222:9;:26;81232:15;81222:26;;;;;;;;;;;;;;;;;;;;;81221:27;81213:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;81347:4;81318:9;:26;81328:15;81318:26;;;;;;;;;;;;:33;;;;;;;;;;;;;;;;;;81364;81370:7;:10;;;;;;;;;;:::i;:::-;81382:7;:14;;;81364:5;:33::i;:::-;80629:817;;;;80547:899;;;;:::o;30036:49::-;30081:4;30036:49;;;:::o;80067:355::-;80145:4;80162:11;80200:3;80186:10;;80177:6;:19;;;;:::i;:::-;80176:27;;;;:::i;:::-;80162:41;;80214:22;80248:3;80239:6;:12;;;;:::i;:::-;80214:37;;80262:31;80277:10;;;;;;;;;;;80289:3;80262:14;:31::i;:::-;;80324:41;80339:9;80350:14;80324;:41::i;:::-;;80410:4;80403:11;;;;80067:355;;;;:::o;78682:35::-;78716:1;78682:35;:::o;78198:62::-;78236:24;78198:62;:::o;32571:140::-;32646:18;32659:4;32646:12;:18::i;:::-;30320:16;30331:4;30320:10;:16::i;:::-;32677:26:::1;32689:4;32695:7;32677:11;:26::i;:::-;;32571:140:::0;;;:::o;15162:142::-;15242:7;15269:11;:18;15281:5;15269:18;;;;;;;;;;;;;;;:27;15288:7;15269:27;;;;;;;;;;;;;;;;15262:34;;15162:142;;;;:::o;27764:148::-;27840:4;27879:25;27864:40;;;:11;:40;;;;27857:47;;27764:148;;;:::o;4335:98::-;4388:7;4415:10;4408:17;;4335:98;:::o;20450:130::-;20535:37;20544:5;20551:7;20560:5;20567:4;20535:8;:37::i;:::-;20450:130;;;:::o;22166:487::-;22266:24;22293:25;22303:5;22310:7;22293:9;:25::i;:::-;22266:52;;22353:17;22333:16;:37;22329:317;;22410:5;22391:16;:24;22387:132;;;22470:7;22479:16;22497:5;22443:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;22387:132;22562:57;22571:5;22578:7;22606:5;22587:16;:24;22613:5;22562:8;:57::i;:::-;22329:317;22255:398;22166:487;;;:::o;17025:308::-;17125:1;17109:18;;:4;:18;;;17105:88;;17178:1;17151:30;;;;;;;;;;;:::i;:::-;;;;;;;;17105:88;17221:1;17207:16;;:2;:16;;;17203:88;;17276:1;17247:32;;;;;;;;;;;:::i;:::-;;;;;;;;17203:88;17301:24;17309:4;17315:2;17319:5;17301:7;:24::i;:::-;17025:308;;;:::o;31077:105::-;31144:30;31155:4;31161:12;:10;:12::i;:::-;31144:10;:30::i;:::-;31077:105;:::o;34154:324::-;34231:4;34253:22;34261:4;34267:7;34253;:22::i;:::-;34248:223;;34324:4;34292:6;:12;34299:4;34292:12;;;;;;;;;;;:20;;:29;34313:7;34292:29;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;34375:12;:10;:12::i;:::-;34348:40;;34366:7;34348:40;;34360:4;34348:40;;;;;;;;;;34410:4;34403:11;;;;34248:223;34454:5;34447:12;;34154:324;;;;;:::o;34722:325::-;34800:4;34821:22;34829:4;34835:7;34821;:22::i;:::-;34817:223;;;34892:5;34860:6;:12;34867:4;34860:12;;;;;;;;;;;:20;;:29;34881:7;34860:29;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;34944:12;:10;:12::i;:::-;34917:40;;34935:7;34917:40;;34929:4;34917:40;;;;;;;;;;34979:4;34972:11;;;;34817:223;35023:5;35016:12;;34722:325;;;;;:::o;37582:120::-;36591:16;:14;:16::i;:::-;37651:5:::1;37641:7;;:15;;;;;;;;;;;;;;;;;;37672:22;37681:12;:10;:12::i;:::-;37672:22;;;;;;:::i;:::-;;;;;;;;37582:120::o:0;19686:211::-;19776:1;19757:21;;:7;:21;;;19753:91;;19829:1;19802:30;;;;;;;;;;;:::i;:::-;;;;;;;;19753:91;19854:35;19862:7;19879:1;19883:5;19854:7;:35::i;:::-;19686:211;;:::o;37323:118::-;36332:19;:17;:19::i;:::-;37393:4:::1;37383:7;;:14;;;;;;;;;;;;;;;;;;37413:20;37420:12;:10;:12::i;:::-;37413:20;;;;;;:::i;:::-;;;;;;;;37323:118::o:0;76921:128::-;76967:13;77000:41;77027:13;77000:5;:26;;:41;;;;:::i;:::-;76993:48;;76921:128;:::o;77384:137::-;77433:13;77466:47;77496:16;77466:8;:29;;:47;;;;:::i;:::-;77459:54;;77384:137;:::o;75778:178::-;75855:7;75882:66;75915:20;:18;:20::i;:::-;75937:10;75882:32;:66::i;:::-;75875:73;;75778:178;;;:::o;19145:213::-;19235:1;19216:21;;:7;:21;;;19212:93;;19290:1;19261:32;;;;;;;;;;;:::i;:::-;;;;;;;;19212:93;19315:35;19331:1;19335:7;19344:5;19315:7;:35::i;:::-;19145:213;;:::o;14917:182::-;14986:4;15003:13;15019:12;:10;:12::i;:::-;15003:28;;15042:27;15052:5;15059:2;15063:5;15042:9;:27::i;:::-;15087:4;15080:11;;;14917:182;;;;:::o;21431:443::-;21561:1;21544:19;;:5;:19;;;21540:91;;21616:1;21587:32;;;;;;;;;;;:::i;:::-;;;;;;;;21540:91;21664:1;21645:21;;:7;:21;;;21641:92;;21718:1;21690:31;;;;;;;;;;;:::i;:::-;;;;;;;;21641:92;21773:5;21743:11;:18;21755:5;21743:18;;;;;;;;;;;;;;;:27;21762:7;21743:27;;;;;;;;;;;;;;;:35;;;;21793:9;21789:78;;;21840:7;21824:31;;21833:5;21824:31;;;21849:5;21824:31;;;;;;:::i;:::-;;;;;;;;21789:78;21431:443;;;;:::o;17657:1135::-;17763:1;17747:18;;:4;:18;;;17743:552;;17901:5;17885:12;;:21;;;;;;;:::i;:::-;;;;;;;;17743:552;;;17939:19;17961:9;:15;17971:4;17961:15;;;;;;;;;;;;;;;;17939:37;;18009:5;17995:11;:19;17991:117;;;18067:4;18073:11;18086:5;18042:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;17991:117;18263:5;18249:11;:19;18231:9;:15;18241:4;18231:15;;;;;;;;;;;;;;;:37;;;;17924:371;17743:552;18325:1;18311:16;;:2;:16;;;18307:435;;18493:5;18477:12;;:21;;;;;;;;;;;18307:435;;;18710:5;18693:9;:13;18703:2;18693:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;18307:435;18774:2;18759:25;;18768:4;18759:25;;;18778:5;18759:25;;;;;;:::i;:::-;;;;;;;;17657:1135;;;:::o;31318:201::-;31407:22;31415:4;31421:7;31407;:22::i;:::-;31402:110;;31486:7;31495:4;31453:47;;;;;;;;;;;;:::i;:::-;;;;;;;;31402:110;31318:201;;:::o;37071:108::-;37138:8;:6;:8::i;:::-;37130:41;;;;;;;;;;;;:::i;:::-;;;;;;;;;37071:108::o;36886:::-;36957:8;:6;:8::i;:::-;36956:9;36948:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;36886:108::o;69148:273::-;69242:13;67094:66;69301:17;;69291:5;69272:46;69268:146;;69342:15;69351:5;69342:8;:15::i;:::-;69335:22;;;;69268:146;69397:5;69390:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69148:273;;;;;:::o;74679:268::-;74732:7;74773:11;74756:28;;74764:4;74756:28;;;:63;;;;;74805:14;74788:13;:31;74756:63;74752:188;;;74843:22;74836:29;;;;74752:188;74905:23;:21;:23::i;:::-;74898:30;;74679:268;;:::o;61171:410::-;61264:14;61376:4;61370:11;61407:10;61402:3;61395:23;61455:15;61448:4;61443:3;61439:14;61432:39;61508:10;61501:4;61496:3;61492:14;61485:34;61558:4;61553:3;61543:20;61533:30;;61344:230;61171:410;;;;:::o;67803:415::-;67862:13;67888:11;67902:16;67913:4;67902:10;:16::i;:::-;67888:30;;68008:17;68039:2;68028:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68008:34;;68133:3;68128;68121:16;68174:4;68167;68162:3;68158:14;68151:28;68207:3;68200:10;;;;67803:415;;;:::o;74955:181::-;75010:7;72871:95;75069:11;75082:14;75098:13;75121:4;75047:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;75037:91;;;;;;75030:98;;74955:181;:::o;68295:251::-;68356:7;68376:14;68429:4;68420;68393:33;;:40;68376:57;;68457:2;68448:6;:11;68444:71;;;68483:20;;;;;;;;;;;;;;68444:71;68532:6;68525:13;;;68295: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:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:126::-;2897:7;2937:42;2930:5;2926:54;2915:65;;2860:126;;;:::o;2992:96::-;3029:7;3058:24;3076:5;3058:24;:::i;:::-;3047:35;;2992:96;;;:::o;3094:122::-;3167:24;3185:5;3167:24;:::i;:::-;3160:5;3157:35;3147:63;;3206:1;3203;3196:12;3147:63;3094:122;:::o;3222:139::-;3268:5;3306:6;3293:20;3284:29;;3322:33;3349:5;3322:33;:::i;:::-;3222:139;;;;:::o;3367:77::-;3404:7;3433:5;3422:16;;3367:77;;;:::o;3450:122::-;3523:24;3541:5;3523:24;:::i;:::-;3516:5;3513:35;3503:63;;3562:1;3559;3552:12;3503:63;3450:122;:::o;3578:139::-;3624:5;3662:6;3649:20;3640:29;;3678:33;3705:5;3678:33;:::i;:::-;3578:139;;;;:::o;3723:474::-;3791:6;3799;3848:2;3836:9;3827:7;3823:23;3819:32;3816:119;;;3854:79;;:::i;:::-;3816:119;3974:1;3999:53;4044:7;4035:6;4024:9;4020:22;3999:53;:::i;:::-;3989:63;;3945:117;4101:2;4127:53;4172:7;4163:6;4152:9;4148:22;4127:53;:::i;:::-;4117:63;;4072:118;3723:474;;;;;:::o;4203:118::-;4290:24;4308:5;4290:24;:::i;:::-;4285:3;4278:37;4203:118;;:::o;4327:222::-;4420:4;4458:2;4447:9;4443:18;4435:26;;4471:71;4539:1;4528:9;4524:17;4515:6;4471:71;:::i;:::-;4327:222;;;;:::o;4555:619::-;4632:6;4640;4648;4697:2;4685:9;4676:7;4672:23;4668:32;4665:119;;;4703:79;;:::i;:::-;4665:119;4823:1;4848:53;4893:7;4884:6;4873:9;4869:22;4848:53;:::i;:::-;4838:63;;4794:117;4950:2;4976:53;5021:7;5012:6;5001:9;4997:22;4976:53;:::i;:::-;4966:63;;4921:118;5078:2;5104:53;5149:7;5140:6;5129:9;5125:22;5104:53;:::i;:::-;5094:63;;5049:118;4555:619;;;;;:::o;5180:77::-;5217:7;5246:5;5235:16;;5180:77;;;:::o;5263:122::-;5336:24;5354:5;5336:24;:::i;:::-;5329:5;5326:35;5316:63;;5375:1;5372;5365:12;5316:63;5263:122;:::o;5391:139::-;5437:5;5475:6;5462:20;5453:29;;5491:33;5518:5;5491:33;:::i;:::-;5391:139;;;;:::o;5536:329::-;5595:6;5644:2;5632:9;5623:7;5619:23;5615:32;5612:119;;;5650:79;;:::i;:::-;5612:119;5770:1;5795:53;5840:7;5831:6;5820:9;5816:22;5795:53;:::i;:::-;5785:63;;5741:117;5536:329;;;;:::o;5871:118::-;5958:24;5976:5;5958:24;:::i;:::-;5953:3;5946:37;5871:118;;:::o;5995:222::-;6088:4;6126:2;6115:9;6111:18;6103:26;;6139:71;6207:1;6196:9;6192:17;6183:6;6139:71;:::i;:::-;5995:222;;;;:::o;6223:474::-;6291:6;6299;6348:2;6336:9;6327:7;6323:23;6319:32;6316:119;;;6354:79;;:::i;:::-;6316:119;6474:1;6499:53;6544:7;6535:6;6524:9;6520:22;6499:53;:::i;:::-;6489:63;;6445:117;6601:2;6627:53;6672:7;6663:6;6652:9;6648:22;6627:53;:::i;:::-;6617:63;;6572:118;6223:474;;;;;:::o;6703:86::-;6738:7;6778:4;6771:5;6767:16;6756:27;;6703:86;;;:::o;6795:112::-;6878:22;6894:5;6878:22;:::i;:::-;6873:3;6866:35;6795:112;;:::o;6913:214::-;7002:4;7040:2;7029:9;7025:18;7017:26;;7053:67;7117:1;7106:9;7102:17;7093:6;7053:67;:::i;:::-;6913:214;;;;:::o;7133:329::-;7192:6;7241:2;7229:9;7220:7;7216:23;7212:32;7209:119;;;7247:79;;:::i;:::-;7209:119;7367:1;7392:53;7437:7;7428:6;7417:9;7413:22;7392:53;:::i;:::-;7382:63;;7338:117;7133:329;;;;:::o;7468:::-;7527:6;7576:2;7564:9;7555:7;7551:23;7547:32;7544:119;;;7582:79;;:::i;:::-;7544:119;7702:1;7727:53;7772:7;7763:6;7752:9;7748:22;7727:53;:::i;:::-;7717:63;;7673:117;7468:329;;;;:::o;7803:118::-;7890:24;7908:5;7890:24;:::i;:::-;7885:3;7878:37;7803:118;;:::o;7927:222::-;8020:4;8058:2;8047:9;8043:18;8035:26;;8071:71;8139:1;8128:9;8124:17;8115:6;8071:71;:::i;:::-;7927:222;;;;:::o;8155:149::-;8191:7;8231:66;8224:5;8220:78;8209:89;;8155:149;;;:::o;8310:115::-;8395:23;8412:5;8395:23;:::i;:::-;8390:3;8383:36;8310:115;;:::o;8431:114::-;8498:6;8532:5;8526:12;8516:22;;8431:114;;;:::o;8551:184::-;8650:11;8684:6;8679:3;8672:19;8724:4;8719:3;8715:14;8700:29;;8551:184;;;;:::o;8741:132::-;8808:4;8831:3;8823:11;;8861:4;8856:3;8852:14;8844:22;;8741:132;;;:::o;8879:108::-;8956:24;8974:5;8956:24;:::i;:::-;8951:3;8944:37;8879:108;;:::o;8993:179::-;9062:10;9083:46;9125:3;9117:6;9083:46;:::i;:::-;9161:4;9156:3;9152:14;9138:28;;8993:179;;;;:::o;9178:113::-;9248:4;9280;9275:3;9271:14;9263:22;;9178:113;;;:::o;9327:732::-;9446:3;9475:54;9523:5;9475:54;:::i;:::-;9545:86;9624:6;9619:3;9545:86;:::i;:::-;9538:93;;9655:56;9705:5;9655:56;:::i;:::-;9734:7;9765:1;9750:284;9775:6;9772:1;9769:13;9750:284;;;9851:6;9845:13;9878:63;9937:3;9922:13;9878:63;:::i;:::-;9871:70;;9964:60;10017:6;9964:60;:::i;:::-;9954:70;;9810:224;9797:1;9794;9790:9;9785:14;;9750:284;;;9754:14;10050:3;10043:10;;9451:608;;;9327:732;;;;:::o;10065:1215::-;10414:4;10452:3;10441:9;10437:19;10429:27;;10466:69;10532:1;10521:9;10517:17;10508:6;10466:69;:::i;:::-;10582:9;10576:4;10572:20;10567:2;10556:9;10552:18;10545:48;10610:78;10683:4;10674:6;10610:78;:::i;:::-;10602:86;;10735:9;10729:4;10725:20;10720:2;10709:9;10705:18;10698:48;10763:78;10836:4;10827:6;10763:78;:::i;:::-;10755:86;;10851:72;10919:2;10908:9;10904:18;10895:6;10851:72;:::i;:::-;10933:73;11001:3;10990:9;10986:19;10977:6;10933:73;:::i;:::-;11016;11084:3;11073:9;11069:19;11060:6;11016:73;:::i;:::-;11137:9;11131:4;11127:20;11121:3;11110:9;11106:19;11099:49;11165:108;11268:4;11259:6;11165:108;:::i;:::-;11157:116;;10065:1215;;;;;;;;;;:::o;11286:117::-;11395:1;11392;11385:12;11447:236;11524:5;11565:3;11556:6;11551:3;11547:16;11543:26;11540:113;;;11572:79;;:::i;:::-;11540:113;11671:6;11662:15;;11447:236;;;;:::o;11689:118::-;11760:22;11776:5;11760:22;:::i;:::-;11753:5;11750:33;11740:61;;11797:1;11794;11787:12;11740:61;11689:118;:::o;11813:135::-;11857:5;11895:6;11882:20;11873:29;;11911:31;11936:5;11911:31;:::i;:::-;11813:135;;;;:::o;11954:826::-;12069:6;12077;12085;12093;12142:3;12130:9;12121:7;12117:23;12113:33;12110:120;;;12149:79;;:::i;:::-;12110:120;12269:1;12294:84;12370:7;12361:6;12350:9;12346:22;12294:84;:::i;:::-;12284:94;;12240:148;12427:3;12454:51;12497:7;12488:6;12477:9;12473:22;12454:51;:::i;:::-;12444:61;;12398:117;12554:3;12581:53;12626:7;12617:6;12606:9;12602:22;12581:53;:::i;:::-;12571:63;;12525:119;12683:3;12710:53;12755:7;12746:6;12735:9;12731:22;12710:53;:::i;:::-;12700:63;;12654:119;11954:826;;;;;;;:::o;12786:474::-;12854:6;12862;12911:2;12899:9;12890:7;12886:23;12882:32;12879:119;;;12917:79;;:::i;:::-;12879:119;13037:1;13062:53;13107:7;13098:6;13087:9;13083:22;13062:53;:::i;:::-;13052:63;;13008:117;13164:2;13190:53;13235:7;13226:6;13215:9;13211:22;13190:53;:::i;:::-;13180:63;;13135:118;12786:474;;;;;:::o;13266:180::-;13314:77;13311:1;13304:88;13411:4;13408:1;13401:15;13435:4;13432:1;13425:15;13452:320;13496:6;13533:1;13527:4;13523:12;13513:22;;13580:1;13574:4;13570:12;13601:18;13591:81;;13657:4;13649:6;13645:17;13635:27;;13591:81;13719:2;13711:6;13708:14;13688:18;13685:38;13682:84;;13738:18;;:::i;:::-;13682:84;13503:269;13452:320;;;:::o;13778:170::-;13918:22;13914:1;13906:6;13902:14;13895:46;13778:170;:::o;13954:366::-;14096:3;14117:67;14181:2;14176:3;14117:67;:::i;:::-;14110:74;;14193:93;14282:3;14193:93;:::i;:::-;14311:2;14306:3;14302:12;14295:19;;13954:366;;;:::o;14326:419::-;14492:4;14530:2;14519:9;14515:18;14507:26;;14579:9;14573:4;14569:20;14565:1;14554:9;14550:17;14543:47;14607:131;14733:4;14607:131;:::i;:::-;14599:139;;14326:419;;;:::o;14751:180::-;14799:77;14796:1;14789:88;14896:4;14893:1;14886:15;14920:4;14917:1;14910:15;14937:166;15077:18;15073:1;15065:6;15061:14;15054:42;14937:166;:::o;15109:366::-;15251:3;15272:67;15336:2;15331:3;15272:67;:::i;:::-;15265:74;;15348:93;15437:3;15348:93;:::i;:::-;15466:2;15461:3;15457:12;15450:19;;15109:366;;;:::o;15481:419::-;15647:4;15685:2;15674:9;15670:18;15662:26;;15734:9;15728:4;15724:20;15720:1;15709:9;15705:17;15698:47;15762:131;15888:4;15762:131;:::i;:::-;15754:139;;15481:419;;;:::o;15906:664::-;16111:4;16149:3;16138:9;16134:19;16126:27;;16163:71;16231:1;16220:9;16216:17;16207:6;16163:71;:::i;:::-;16244:72;16312:2;16301:9;16297:18;16288:6;16244:72;:::i;:::-;16326;16394:2;16383:9;16379:18;16370:6;16326:72;:::i;:::-;16408;16476:2;16465:9;16461:18;16452:6;16408:72;:::i;:::-;16490:73;16558:3;16547:9;16543:19;16534:6;16490:73;:::i;:::-;15906:664;;;;;;;;:::o;16576:545::-;16749:4;16787:3;16776:9;16772:19;16764:27;;16801:71;16869:1;16858:9;16854:17;16845:6;16801:71;:::i;:::-;16882:68;16946:2;16935:9;16931:18;16922:6;16882:68;:::i;:::-;16960:72;17028:2;17017:9;17013:18;17004:6;16960:72;:::i;:::-;17042;17110:2;17099:9;17095:18;17086:6;17042:72;:::i;:::-;16576:545;;;;;;;:::o;17127:220::-;17267:34;17263:1;17255:6;17251:14;17244:58;17336:3;17331:2;17323:6;17319:15;17312:28;17127:220;:::o;17353:366::-;17495:3;17516:67;17580:2;17575:3;17516:67;:::i;:::-;17509:74;;17592:93;17681:3;17592:93;:::i;:::-;17710:2;17705:3;17701:12;17694:19;;17353:366;;;:::o;17725:419::-;17891:4;17929:2;17918:9;17914:18;17906:26;;17978:9;17972:4;17968:20;17964:1;17953:9;17949:17;17942:47;18006:131;18132:4;18006:131;:::i;:::-;17998:139;;17725:419;;;:::o;18150:94::-;18183:8;18231:5;18227:2;18223:14;18202:35;;18150:94;;;:::o;18250:::-;18289:7;18318:20;18332:5;18318:20;:::i;:::-;18307:31;;18250:94;;;:::o;18350:100::-;18389:7;18418:26;18438:5;18418:26;:::i;:::-;18407:37;;18350:100;;;:::o;18456:157::-;18561:45;18581:24;18599:5;18581:24;:::i;:::-;18561:45;:::i;:::-;18556:3;18549:58;18456:157;;:::o;18619:79::-;18658:7;18687:5;18676:16;;18619:79;;;:::o;18704:157::-;18809:45;18829:24;18847:5;18829:24;:::i;:::-;18809:45;:::i;:::-;18804:3;18797:58;18704:157;;:::o;18867:679::-;19063:3;19078:75;19149:3;19140:6;19078:75;:::i;:::-;19178:2;19173:3;19169:12;19162:19;;19191:75;19262:3;19253:6;19191:75;:::i;:::-;19291:2;19286:3;19282:12;19275:19;;19304:75;19375:3;19366:6;19304:75;:::i;:::-;19404:2;19399:3;19395:12;19388:19;;19417:75;19488:3;19479:6;19417:75;:::i;:::-;19517:2;19512:3;19508:12;19501:19;;19537:3;19530:10;;18867:679;;;;;;;:::o;19552:167::-;19692:19;19688:1;19680:6;19676:14;19669:43;19552:167;:::o;19725:366::-;19867:3;19888:67;19952:2;19947:3;19888:67;:::i;:::-;19881:74;;19964:93;20053:3;19964:93;:::i;:::-;20082:2;20077:3;20073:12;20066:19;;19725:366;;;:::o;20097:419::-;20263:4;20301:2;20290:9;20286:18;20278:26;;20350:9;20344:4;20340:20;20336:1;20325:9;20321:17;20314:47;20378:131;20504:4;20378:131;:::i;:::-;20370:139;;20097:419;;;:::o;20522:180::-;20570:77;20567:1;20560:88;20667:4;20664:1;20657:15;20691:4;20688:1;20681:15;20708:410;20748:7;20771:20;20789:1;20771:20;:::i;:::-;20766:25;;20805:20;20823:1;20805:20;:::i;:::-;20800:25;;20860:1;20857;20853:9;20882:30;20900:11;20882:30;:::i;:::-;20871:41;;21061:1;21052:7;21048:15;21045:1;21042:22;21022:1;21015:9;20995:83;20972:139;;21091:18;;:::i;:::-;20972:139;20756:362;20708:410;;;;:::o;21124:180::-;21172:77;21169:1;21162:88;21269:4;21266:1;21259:15;21293:4;21290:1;21283:15;21310:185;21350:1;21367:20;21385:1;21367:20;:::i;:::-;21362:25;;21401:20;21419:1;21401:20;:::i;:::-;21396:25;;21440:1;21430:35;;21445:18;;:::i;:::-;21430:35;21487:1;21484;21480:9;21475:14;;21310:185;;;;:::o;21501:194::-;21541:4;21561:20;21579:1;21561:20;:::i;:::-;21556:25;;21595:20;21613:1;21595:20;:::i;:::-;21590:25;;21639:1;21636;21632:9;21624:17;;21663:1;21657:4;21654:11;21651:37;;;21668:18;;:::i;:::-;21651:37;21501:194;;;;:::o;21701:442::-;21850:4;21888:2;21877:9;21873:18;21865:26;;21901:71;21969:1;21958:9;21954:17;21945:6;21901:71;:::i;:::-;21982:72;22050:2;22039:9;22035:18;22026:6;21982:72;:::i;:::-;22064;22132:2;22121:9;22117:18;22108:6;22064:72;:::i;:::-;21701:442;;;;;;:::o;22149:191::-;22189:3;22208:20;22226:1;22208:20;:::i;:::-;22203:25;;22242:20;22260:1;22242:20;:::i;:::-;22237:25;;22285:1;22282;22278:9;22271:16;;22306:3;22303:1;22300:10;22297:36;;;22313:18;;:::i;:::-;22297:36;22149:191;;;;:::o;22346:332::-;22467:4;22505:2;22494:9;22490:18;22482:26;;22518:71;22586:1;22575:9;22571:17;22562:6;22518:71;:::i;:::-;22599:72;22667:2;22656:9;22652:18;22643:6;22599:72;:::i;:::-;22346:332;;;;;:::o;22684:170::-;22824:22;22820:1;22812:6;22808:14;22801:46;22684:170;:::o;22860:366::-;23002:3;23023:67;23087:2;23082:3;23023:67;:::i;:::-;23016:74;;23099:93;23188:3;23099:93;:::i;:::-;23217:2;23212:3;23208:12;23201:19;;22860:366;;;:::o;23232:419::-;23398:4;23436:2;23425:9;23421:18;23413:26;;23485:9;23479:4;23475:20;23471:1;23460:9;23456:17;23449:47;23513:131;23639:4;23513:131;:::i;:::-;23505:139;;23232:419;;;:::o;23657:166::-;23797:18;23793:1;23785:6;23781:14;23774:42;23657:166;:::o;23829:366::-;23971:3;23992:67;24056:2;24051:3;23992:67;:::i;:::-;23985:74;;24068:93;24157:3;24068:93;:::i;:::-;24186:2;24181:3;24177:12;24170:19;;23829:366;;;:::o;24201:419::-;24367:4;24405:2;24394:9;24390:18;24382:26;;24454:9;24448:4;24444:20;24440:1;24429:9;24425:17;24418:47;24482:131;24608:4;24482:131;:::i;:::-;24474:139;;24201:419;;;:::o;24626:664::-;24831:4;24869:3;24858:9;24854:19;24846:27;;24883:71;24951:1;24940:9;24936:17;24927:6;24883:71;:::i;:::-;24964:72;25032:2;25021:9;25017:18;25008:6;24964:72;:::i;:::-;25046;25114:2;25103:9;25099:18;25090:6;25046:72;:::i;:::-;25128;25196:2;25185:9;25181:18;25172:6;25128:72;:::i;:::-;25210:73;25278:3;25267:9;25263:19;25254:6;25210:73;:::i;:::-;24626:664;;;;;;;;:::o
Swarm Source
ipfs://e82b19a89abf63c1048f41713e43e786d4a36f7c3ccef9d5c065216568b2c19b
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.