Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 441 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Mint | 22792067 | 32 hrs ago | IN | 0 ETH | 0.00021188 | ||||
Mint | 22791948 | 32 hrs ago | IN | 0 ETH | 0.00020414 | ||||
Mint | 22790398 | 37 hrs ago | IN | 0 ETH | 0.00037182 | ||||
Set Token Active | 22790387 | 37 hrs ago | IN | 0 ETH | 0.00010934 | ||||
Mint | 22776584 | 3 days ago | IN | 0 ETH | 0.00036487 | ||||
Mint | 22776426 | 3 days ago | IN | 0 ETH | 0.00049455 | ||||
Mint | 22776371 | 3 days ago | IN | 0 ETH | 0.00053319 | ||||
Mint | 22772832 | 4 days ago | IN | 0 ETH | 0.00024445 | ||||
Mint | 22772813 | 4 days ago | IN | 0 ETH | 0.00023885 | ||||
Mint | 22772636 | 4 days ago | IN | 0 ETH | 0.00023992 | ||||
Mint | 22772628 | 4 days ago | IN | 0 ETH | 0.00023033 | ||||
Mint | 22772580 | 4 days ago | IN | 0 ETH | 0.00018771 | ||||
Mint | 22772519 | 4 days ago | IN | 0 ETH | 0.00017053 | ||||
Mint | 22761017 | 5 days ago | IN | 0 ETH | 0.00027813 | ||||
Mint | 22761012 | 5 days ago | IN | 0 ETH | 0.00027751 | ||||
Mint | 22761006 | 5 days ago | IN | 0 ETH | 0.00038855 | ||||
Set Approval For... | 22743563 | 8 days ago | IN | 0 ETH | 0.00001873 | ||||
Safe Transfer Fr... | 22740648 | 8 days ago | IN | 0 ETH | 0.00006868 | ||||
Mint | 22735757 | 9 days ago | IN | 0 ETH | 0.00002861 | ||||
Mint | 22735748 | 9 days ago | IN | 0 ETH | 0.00003863 | ||||
Set Approval For... | 22731079 | 9 days ago | IN | 0 ETH | 0.00006076 | ||||
Mint | 22727829 | 10 days ago | IN | 0 ETH | 0.00009109 | ||||
Mint | 22721220 | 11 days ago | IN | 0 ETH | 0.00004116 | ||||
Mint | 22720508 | 11 days ago | IN | 0 ETH | 0.00012212 | ||||
Mint | 22720504 | 11 days ago | IN | 0 ETH | 0.00014327 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TralaNFT
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.27; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; /** * @title TralaNFT * @dev Implementation of the Trala Platform NFT system with multiple token grades * and configurable parameters for each grade. */ contract TralaNFT is ERC1155, ERC1155Supply, ERC1155Burnable, AccessControl, Pausable, ReentrancyGuard, EIP712 { // Custom errors error TokenNotActive(uint256 tokenId); error InsufficientPayment(uint256 required, uint256 sent); error ExceedsMaxSupply(uint256 tokenId, uint256 maxSupply, uint256 currentSupply, uint256 requestedAmount); error SignatureRequired(); error InvalidSignature(); error TokenIsSoulbound(uint256 tokenId); error NoFundsToWithdraw(); error WithdrawalFailed(); bytes32 private constant MINT_AUTHORIZATION_TYPEHASH = keccak256("MintAuthorization(address minter,address to,uint256 tokenId,uint256 quantity,bytes32 salt,uint256 nonce,uint256 chainId,address contractAddress)"); // Role definitions bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 public constant SIGNER_ROLE = keccak256("SIGNER_ROLE"); bytes32 public constant TREASURY_ROLE = keccak256("TREASURY_ROLE"); string public name; string public symbol; // Token configuration struct TokenConfig { string name; // Grade name (A, S, SS, SSS, B, C) uint256 maxSupply; // Maximum supply (0 = unlimited) uint256 price; // Price in wei bool allowlistRequired; // Whether allowlist is required for minting bool active; // Whether token is currently mintable bool soulbound; // Whether token is soulbound (non-transferable) } // Mapping from token ID to its configuration mapping(uint256 => TokenConfig) public tokenConfigs; // Array to track all created token IDs uint256[] private _tokenIds; // Mapping to track used signatures mapping(bytes => bool) private _usedSignatures; // Mapping to track nonces per address for signature verification mapping(address => uint256) private _nonces; // Events event TokenConfigured(uint256 indexed tokenId, string name, uint256 maxSupply, uint256 price, bool allowlistRequired, bool active, bool soulbound); event TokenMinted(address indexed to, uint256 indexed tokenId, uint256 amount); event WithdrawFunds(address indexed to, uint256 amount); /** * @dev Constructor * @param _name Collection name * @param _symbol Collection symbol * @param _uri Base URI for token metadata * @param _initialTreasury Address to be granted admin role * @param _initialSigner Address to be granted signer role */ constructor( string memory _name, string memory _symbol, string memory _uri, address _initialTreasury, address _initialSigner ) ERC1155(_uri) EIP712(_name, "1") { name = _name; symbol = _symbol; // Setup roles _grantRole(ADMIN_ROLE, msg.sender); _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(TREASURY_ROLE, _initialTreasury); _grantRole(SIGNER_ROLE, _initialSigner); } /** * @dev Creates a new token type with specified configuration * @param tokenId ID of the token to configure * @param _name Name of the token grade * @param _maxSupply Maximum supply (0 for unlimited) * @param _price Price in wei * @param _allowlistRequired Whether allowlist is required * @param _active Whether the token is active for minting * @param _soulbound Whether the token is non-transferable */ function configureToken( uint256 tokenId, string memory _name, uint256 _maxSupply, uint256 _price, bool _allowlistRequired, bool _active, bool _soulbound ) external onlyRole(ADMIN_ROLE) { // Check if this is a new token ID if (bytes(tokenConfigs[tokenId].name).length == 0) { _tokenIds.push(tokenId); } // Set the token configuration tokenConfigs[tokenId] = TokenConfig({ name: _name, maxSupply: _maxSupply, price: _price, allowlistRequired: _allowlistRequired, active: _active, soulbound: _soulbound }); emit TokenConfigured(tokenId, _name, _maxSupply, _price, _allowlistRequired, _active, _soulbound); } /** * @dev Returns the current nonce for an address * @param owner Address to get nonce for */ function nonces(address owner) public view returns (uint256) { return _nonces[owner]; } /** * @dev Unified mint function that handles both public and allowlist minting * @param to Recipient address * @param tokenId Token ID to mint * @param amount Amount to mint * @param signature Signature for allowlist authorization (can be empty for public minting) */ function mint( address to, uint256 tokenId, uint256 amount, bytes calldata signature ) external payable nonReentrant whenNotPaused { TokenConfig memory config = tokenConfigs[tokenId]; // Validations if (!config.active) { revert TokenNotActive(tokenId); } if (msg.value < config.price * amount) { revert InsufficientPayment(config.price * amount, msg.value); } // Check max supply if (config.maxSupply > 0) { uint256 currentSupply = totalSupply(tokenId); if (currentSupply + amount > config.maxSupply) { revert ExceedsMaxSupply(tokenId, config.maxSupply, currentSupply, amount); } } // If allowlist is required, verify signature if (config.allowlistRequired) { if (signature.length == 0) { revert SignatureRequired(); } // Get the current nonce for the sender uint256 nonce = _nonces[msg.sender]; // Need to match the salt calculation with backend bytes32 salt = keccak256(bytes("BlockusMintAuthorizationSignature")); // Create the struct hash according to EIP-712 encoding bytes32 structHash = keccak256( abi.encode( MINT_AUTHORIZATION_TYPEHASH, msg.sender, // minter to, // to tokenId, // tokenId amount, // quantity salt, // salt nonce, // nonce block.chainid, // chainId address(this) // contractAddress ) ); // Get the EIP-712 typed data hash bytes32 hash = _hashTypedDataV4(structHash); // Recover the signer from the signature address signer = ECDSA.recover(hash, signature); // Verify the signer has the required role if (!hasRole(SIGNER_ROLE, signer)) { revert InvalidSignature(); } // Increment nonce to prevent signature reuse _nonces[msg.sender]++; } // Mint tokens _mint(to, tokenId, amount, ""); emit TokenMinted(to, tokenId, amount); } /** * @dev Override _update to implement ERC1155Supply and soulbound functionality */ function _update( address from, address to, uint256[] memory ids, uint256[] memory values ) internal virtual override(ERC1155, ERC1155Supply) { // Skip checks for minting (from = address(0)) and burning (to = address(0)) if (from != address(0) && to != address(0)) { for (uint256 i = 0; i < ids.length; i++) { // Check if the token is soulbound if (tokenConfigs[ids[i]].soulbound) { revert TokenIsSoulbound(ids[i]); } } } super._update(from, to, ids, values); } /** * @dev Sets the base URI for all token types * @param newuri New base URI */ function setURI(string memory newuri) external onlyRole(ADMIN_ROLE) { _setURI(newuri); } /** * @dev Sets the active status of a token * @param tokenId Token ID * @param active Whether the token is active */ function setTokenActive(uint256 tokenId, bool active) external onlyRole(ADMIN_ROLE) { tokenConfigs[tokenId].active = active; } /** * @dev Sets whether a token requires allowlist * @param tokenId Token ID * @param required Whether allowlist is required */ function setAllowlistRequired(uint256 tokenId, bool required) external onlyRole(ADMIN_ROLE) { tokenConfigs[tokenId].allowlistRequired = required; } /** * @dev Updates the price of a token * @param tokenId Token ID * @param price New price in wei */ function setTokenPrice(uint256 tokenId, uint256 price) external onlyRole(ADMIN_ROLE) { tokenConfigs[tokenId].price = price; } /** * @dev Gets all token IDs * @return Array of token IDs */ function getAllTokenIds() external view returns (uint256[] memory) { return _tokenIds; } /** * @dev Pauses all token minting */ function pause() external onlyRole(ADMIN_ROLE) { _pause(); } /** * @dev Unpauses token minting */ function unpause() external onlyRole(ADMIN_ROLE) { _unpause(); } /** * @dev Withdraws funds to the contract owner */ function withdraw() external onlyRole(TREASURY_ROLE) { uint256 balance = address(this).balance; if (balance == 0) { revert NoFundsToWithdraw(); } (bool success, ) = payable(msg.sender).call{value: balance}(""); if (!success) { revert WithdrawalFailed(); } emit WithdrawFunds(msg.sender, balance); } /** * @dev Required override to support ERC1155Supply */ function supportsInterface(bytes4 interfaceId) public view override(ERC1155, AccessControl) returns (bool) { return super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @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; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // 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 ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.20; import {IERC1155} from "./IERC1155.sol"; import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol"; import {ERC1155Utils} from "./utils/ERC1155Utils.sol"; import {Context} from "../../utils/Context.sol"; import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; import {Arrays} from "../../utils/Arrays.sol"; import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 */ abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors { using Arrays for uint256[]; using Arrays for address[]; mapping(uint256 id => mapping(address account => uint256)) private _balances; mapping(address account => mapping(address operator => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256 /* id */) public view virtual returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. */ function balanceOf(address account, uint256 id) public view virtual returns (uint256) { return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] memory accounts, uint256[] memory ids ) public view virtual returns (uint256[] memory) { if (accounts.length != ids.length) { revert ERC1155InvalidArrayLength(ids.length, accounts.length); } uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i)); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeTransferFrom(from, to, id, value, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeBatchTransferFrom(from, to, ids, values, data); } /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` * (or `to`) is the zero address. * * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. * * Requirements: * * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. * - `ids` and `values` must have the same length. * * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead. */ function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual { if (ids.length != values.length) { revert ERC1155InvalidArrayLength(ids.length, values.length); } address operator = _msgSender(); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids.unsafeMemoryAccess(i); uint256 value = values.unsafeMemoryAccess(i); if (from != address(0)) { uint256 fromBalance = _balances[id][from]; if (fromBalance < value) { revert ERC1155InsufficientBalance(from, fromBalance, value, id); } unchecked { // Overflow not possible: value <= fromBalance _balances[id][from] = fromBalance - value; } } if (to != address(0)) { _balances[id][to] += value; } } if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); emit TransferSingle(operator, from, to, id, value); } else { emit TransferBatch(operator, from, to, ids, values); } } /** * @dev Version of {_update} that performs the token acceptance check by calling * {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it * contains code (eg. is a smart contract at the moment of execution). * * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any * update to the contract state after this function would break the check-effect-interaction pattern. Consider * overriding {_update} instead. */ function _updateWithAcceptanceCheck( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal virtual { _update(from, to, ids, values); if (to != address(0)) { address operator = _msgSender(); if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data); } else { ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data); } } } /** * @dev Transfers a `value` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. * - `ids` and `values` must have the same length. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the ERC]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the values in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `values` must have the same length. * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev Destroys a `value` amount of tokens of type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. */ function _burn(address from, uint256 id, uint256 value) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. * - `ids` and `values` must have the same length. */ function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the zero address. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC1155InvalidOperator(address(0)); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Creates an array in memory with only one value for each of the elements provided. */ function _asSingletonArrays( uint256 element1, uint256 element2 ) private pure returns (uint256[] memory array1, uint256[] memory array2) { assembly ("memory-safe") { // Load the free memory pointer array1 := mload(0x40) // Set array length to 1 mstore(array1, 1) // Store the single element at the next word after the length (where content starts) mstore(add(array1, 0x20), element1) // Repeat for next array locating it right after the first array array2 := add(array1, 0x40) mstore(array2, 1) mstore(add(array2, 0x20), element2) // Update the free memory pointer by pointing after the second array mstore(0x40, add(array2, 0x40)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Burnable.sol) pragma solidity ^0.8.20; import {ERC1155} from "../ERC1155.sol"; /** * @dev Extension of {ERC1155} that allows token holders to destroy both their * own tokens and those that they have been approved to use. */ abstract contract ERC1155Burnable is ERC1155 { function burn(address account, uint256 id, uint256 value) public virtual { if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { revert ERC1155MissingApprovalForAll(_msgSender(), account); } _burn(account, id, value); } function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual { if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { revert ERC1155MissingApprovalForAll(_msgSender(), account); } _burnBatch(account, ids, values); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.20; import {ERC1155} from "../ERC1155.sol"; import {Arrays} from "../../../utils/Arrays.sol"; /** * @dev Extension of ERC-1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. * * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens * that can be minted. * * CAUTION: This extension should not be added in an upgrade to an already deployed contract. */ abstract contract ERC1155Supply is ERC1155 { using Arrays for uint256[]; mapping(uint256 id => uint256) private _totalSupply; uint256 private _totalSupplyAll; /** * @dev Total value of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Total value of tokens. */ function totalSupply() public view virtual returns (uint256) { return _totalSupplyAll; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return totalSupply(id) > 0; } /** * @dev See {ERC1155-_update}. */ function _update( address from, address to, uint256[] memory ids, uint256[] memory values ) internal virtual override { super._update(from, to, ids, values); if (from == address(0)) { uint256 totalMintValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values.unsafeMemoryAccess(i); // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply[ids.unsafeMemoryAccess(i)] += value; totalMintValue += value; } // Overflow check required: The rest of the code assumes that totalSupplyAll never overflows _totalSupplyAll += totalMintValue; } if (to == address(0)) { uint256 totalBurnValue = 0; for (uint256 i = 0; i < ids.length; ++i) { uint256 value = values.unsafeMemoryAccess(i); unchecked { // Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i]) _totalSupply[ids.unsafeMemoryAccess(i)] -= value; // Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll totalBurnValue += value; } } unchecked { // Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll _totalSupplyAll -= totalBurnValue; } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.20; import {IERC1155} from "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC]. */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC-1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[ERC]. */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the value of tokens of token type `id` owned by `account`. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the zero address. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments. * * Requirements: * * - `ids` and `values` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC-1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC-1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Utils.sol) pragma solidity ^0.8.20; import {IERC1155Receiver} from "../IERC1155Receiver.sol"; import {IERC1155Errors} from "../../../interfaces/draft-IERC6093.sol"; /** * @dev Library that provide common ERC-1155 utility functions. * * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155]. * * _Available since v5.1._ */ library ERC1155Utils { /** * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155-onERC1155Received} * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). * * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept * the transfer. */ function checkOnERC1155Received( address operator, address from, address to, uint256 id, uint256 value, bytes memory data ) internal { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { // Tokens rejected revert IERC1155Errors.ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-IERC1155Receiver implementer revert IERC1155Errors.ERC1155InvalidReceiver(to); } else { assembly ("memory-safe") { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155-onERC1155BatchReceived} * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). * * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept * the transfer. */ function checkOnERC1155BatchReceived( address operator, address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { // Tokens rejected revert IERC1155Errors.ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-IERC1155Receiver implementer revert IERC1155Errors.ERC1155InvalidReceiver(to); } else { assembly ("memory-safe") { revert(add(32, reason), mload(reason)) } } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Arrays.sol) // This file was procedurally generated from scripts/generate/templates/Arrays.js. pragma solidity ^0.8.20; import {Comparators} from "./Comparators.sol"; import {SlotDerivation} from "./SlotDerivation.sol"; import {StorageSlot} from "./StorageSlot.sol"; import {Math} from "./math/Math.sol"; /** * @dev Collection of functions related to array types. */ library Arrays { using SlotDerivation for bytes32; using StorageSlot for bytes32; /** * @dev Sort an array of uint256 (in memory) following the provided comparator function. * * This function does the sorting "in place", meaning that it overrides the input. The object is returned for * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. * * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may * consume more gas than is available in a block, leading to potential DoS. * * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. */ function sort( uint256[] memory array, function(uint256, uint256) pure returns (bool) comp ) internal pure returns (uint256[] memory) { _quickSort(_begin(array), _end(array), comp); return array; } /** * @dev Variant of {sort} that sorts an array of uint256 in increasing order. */ function sort(uint256[] memory array) internal pure returns (uint256[] memory) { sort(array, Comparators.lt); return array; } /** * @dev Sort an array of address (in memory) following the provided comparator function. * * This function does the sorting "in place", meaning that it overrides the input. The object is returned for * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. * * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may * consume more gas than is available in a block, leading to potential DoS. * * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. */ function sort( address[] memory array, function(address, address) pure returns (bool) comp ) internal pure returns (address[] memory) { sort(_castToUint256Array(array), _castToUint256Comp(comp)); return array; } /** * @dev Variant of {sort} that sorts an array of address in increasing order. */ function sort(address[] memory array) internal pure returns (address[] memory) { sort(_castToUint256Array(array), Comparators.lt); return array; } /** * @dev Sort an array of bytes32 (in memory) following the provided comparator function. * * This function does the sorting "in place", meaning that it overrides the input. The object is returned for * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. * * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may * consume more gas than is available in a block, leading to potential DoS. * * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way. */ function sort( bytes32[] memory array, function(bytes32, bytes32) pure returns (bool) comp ) internal pure returns (bytes32[] memory) { sort(_castToUint256Array(array), _castToUint256Comp(comp)); return array; } /** * @dev Variant of {sort} that sorts an array of bytes32 in increasing order. */ function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) { sort(_castToUint256Array(array), Comparators.lt); return array; } /** * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops * at end (exclusive). Sorting follows the `comp` comparator. * * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls. * * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should * be used only if the limits are within a memory array. */ function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure { unchecked { if (end - begin < 0x40) return; // Use first element as pivot uint256 pivot = _mload(begin); // Position where the pivot should be at the end of the loop uint256 pos = begin; for (uint256 it = begin + 0x20; it < end; it += 0x20) { if (comp(_mload(it), pivot)) { // If the value stored at the iterator's position comes before the pivot, we increment the // position of the pivot and move the value there. pos += 0x20; _swap(pos, it); } } _swap(begin, pos); // Swap pivot into place _quickSort(begin, pos, comp); // Sort the left side of the pivot _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot } } /** * @dev Pointer to the memory location of the first element of `array`. */ function _begin(uint256[] memory array) private pure returns (uint256 ptr) { assembly ("memory-safe") { ptr := add(array, 0x20) } } /** * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word * that comes just after the last element of the array. */ function _end(uint256[] memory array) private pure returns (uint256 ptr) { unchecked { return _begin(array) + array.length * 0x20; } } /** * @dev Load memory word (as a uint256) at location `ptr`. */ function _mload(uint256 ptr) private pure returns (uint256 value) { assembly { value := mload(ptr) } } /** * @dev Swaps the elements memory location `ptr1` and `ptr2`. */ function _swap(uint256 ptr1, uint256 ptr2) private pure { assembly { let value1 := mload(ptr1) let value2 := mload(ptr2) mstore(ptr1, value2) mstore(ptr2, value1) } } /// @dev Helper: low level cast address memory array to uint256 memory array function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) { assembly { output := input } } /// @dev Helper: low level cast bytes32 memory array to uint256 memory array function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) { assembly { output := input } } /// @dev Helper: low level cast address comp function to uint256 comp function function _castToUint256Comp( function(address, address) pure returns (bool) input ) private pure returns (function(uint256, uint256) pure returns (bool) output) { assembly { output := input } } /// @dev Helper: low level cast bytes32 comp function to uint256 comp function function _castToUint256Comp( function(bytes32, bytes32) pure returns (bool) input ) private pure returns (function(uint256, uint256) pure returns (bool) output) { assembly { output := input } } /** * @dev Searches a sorted `array` and returns the first index that contains * a value greater or equal to `element`. If no such index exists (i.e. all * values in the array are strictly less than `element`), the array length is * returned. Time complexity O(log n). * * NOTE: The `array` is expected to be sorted in ascending order, and to * contain no repeated elements. * * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks * support for repeated elements in the array. The {lowerBound} function should * be used instead. */ function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeAccess(array, mid).value > element) { high = mid; } else { low = mid + 1; } } // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. if (low > 0 && unsafeAccess(array, low - 1).value == element) { return low - 1; } else { return low; } } /** * @dev Searches an `array` sorted in ascending order and returns the first * index that contains a value greater or equal than `element`. If no such index * exists (i.e. all values in the array are strictly less than `element`), the array * length is returned. Time complexity O(log n). * * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound]. */ function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeAccess(array, mid).value < element) { // this cannot overflow because mid < high unchecked { low = mid + 1; } } else { high = mid; } } return low; } /** * @dev Searches an `array` sorted in ascending order and returns the first * index that contains a value strictly greater than `element`. If no such index * exists (i.e. all values in the array are strictly less than `element`), the array * length is returned. Time complexity O(log n). * * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound]. */ function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeAccess(array, mid).value > element) { high = mid; } else { // this cannot overflow because mid < high unchecked { low = mid + 1; } } } return low; } /** * @dev Same as {lowerBound}, but with an array in memory. */ function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeMemoryAccess(array, mid) < element) { // this cannot overflow because mid < high unchecked { low = mid + 1; } } else { high = mid; } } return low; } /** * @dev Same as {upperBound}, but with an array in memory. */ function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeMemoryAccess(array, mid) > element) { high = mid; } else { // this cannot overflow because mid < high unchecked { low = mid + 1; } } } return low; } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) { bytes32 slot; assembly ("memory-safe") { slot := arr.slot } return slot.deriveArray().offset(pos).getAddressSlot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) { bytes32 slot; assembly ("memory-safe") { slot := arr.slot } return slot.deriveArray().offset(pos).getBytes32Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) { bytes32 slot; assembly ("memory-safe") { slot := arr.slot } return slot.deriveArray().offset(pos).getUint256Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } /** * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. * * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. */ function unsafeSetLength(address[] storage array, uint256 len) internal { assembly ("memory-safe") { sstore(array.slot, len) } } /** * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. * * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. */ function unsafeSetLength(bytes32[] storage array, uint256 len) internal { assembly ("memory-safe") { sstore(array.slot, len) } } /** * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. * * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. */ function unsafeSetLength(uint256[] storage array, uint256 len) internal { assembly ("memory-safe") { sstore(array.slot, len) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol) pragma solidity ^0.8.20; /** * @dev Provides a set of functions to compare values. * * _Available since v5.1._ */ library Comparators { function lt(uint256 a, uint256 b) internal pure returns (bool) { return a < b; } function gt(uint256 a, uint256 b) internal pure returns (bool) { return a > b; } }
// SPDX-License-Identifier: MIT // 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover( bytes32 hash, bytes memory signature ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly ("memory-safe") { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures] */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; import {MessageHashUtils} from "./MessageHashUtils.sol"; import {ShortStrings, ShortString} from "../ShortStrings.sol"; import {IERC5267} from "../../interfaces/IERC5267.sol"; /** * @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); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an ERC-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { assembly ("memory-safe") { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an ERC-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an ERC-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { assembly ("memory-safe") { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) pragma solidity ^0.8.20; import {Panic} from "../Panic.sol"; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 1); } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 1); } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { bool private _paused; /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ShortStrings.sol) pragma solidity ^0.8.20; import {StorageSlot} from "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); assembly ("memory-safe") { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using * {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/SlotDerivation.sol) // This file was procedurally generated from scripts/generate/templates/SlotDerivation.js. pragma solidity ^0.8.20; /** * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by * the solidity language / compiler. * * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.]. * * Example usage: * ```solidity * contract Example { * // Add the library methods * using StorageSlot for bytes32; * using SlotDerivation for bytes32; * * // Declare a namespace * string private constant _NAMESPACE = "<namespace>" // eg. OpenZeppelin.Slot * * function setValueInNamespace(uint256 key, address newValue) internal { * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue; * } * * function getValueInNamespace(uint256 key) internal view returns (address) { * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value; * } * } * ``` * * TIP: Consider using this library along with {StorageSlot}. * * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking * upgrade safety will ignore the slots accessed through this library. * * _Available since v5.1._ */ library SlotDerivation { /** * @dev Derive an ERC-7201 slot from a string (namespace). */ function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) { assembly ("memory-safe") { mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1)) slot := and(keccak256(0x00, 0x20), not(0xff)) } } /** * @dev Add an offset to a slot to get the n-th element of a structure or an array. */ function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) { unchecked { return bytes32(uint256(slot) + pos); } } /** * @dev Derive the location of the first element in an array from the slot where the length is stored. */ function deriveArray(bytes32 slot) internal pure returns (bytes32 result) { assembly ("memory-safe") { mstore(0x00, slot) result := keccak256(0x00, 0x20) } } /** * @dev Derive the location of a mapping element from the key. */ function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) { assembly ("memory-safe") { mstore(0x00, and(key, shr(96, not(0)))) mstore(0x20, slot) result := keccak256(0x00, 0x40) } } /** * @dev Derive the location of a mapping element from the key. */ function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) { assembly ("memory-safe") { mstore(0x00, iszero(iszero(key))) mstore(0x20, slot) result := keccak256(0x00, 0x40) } } /** * @dev Derive the location of a mapping element from the key. */ function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) { assembly ("memory-safe") { mstore(0x00, key) mstore(0x20, slot) result := keccak256(0x00, 0x40) } } /** * @dev Derive the location of a mapping element from the key. */ function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) { assembly ("memory-safe") { mstore(0x00, key) mstore(0x20, slot) result := keccak256(0x00, 0x40) } } /** * @dev Derive the location of a mapping element from the key. */ function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) { assembly ("memory-safe") { mstore(0x00, key) mstore(0x20, slot) result := keccak256(0x00, 0x40) } } /** * @dev Derive the location of a mapping element from the key. */ function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) { assembly ("memory-safe") { let length := mload(key) let begin := add(key, 0x20) let end := add(begin, length) let cache := mload(end) mstore(end, slot) result := keccak256(begin, add(length, 0x20)) mstore(end, cache) } } /** * @dev Derive the location of a mapping element from the key. */ function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) { assembly ("memory-safe") { let length := mload(key) let begin := add(key, 0x20) let end := add(begin, length) let cache := mload(end) mstore(end, slot) result := keccak256(begin, add(length, 0x20)) mstore(end, cache) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC-1967 implementation slot: * ```solidity * contract ERC1967 { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct Int256Slot { int256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Int256Slot` with member `value` located at `slot`. */ function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } /** * @dev Returns a `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; assembly ("memory-safe") { ptr := add(buffer, add(32, length)) } while (true) { ptr--; assembly ("memory-safe") { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal * representation, according to EIP-55. */ function toChecksumHexString(address addr) internal pure returns (string memory) { bytes memory buffer = bytes(toHexString(addr)); // hash the hex part of buffer (skip length + 2 bytes, length 40) uint256 hashValue; assembly ("memory-safe") { hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) } for (uint256 i = 41; i > 1; --i) { // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { // case shift by xoring with 0x20 buffer[i] ^= 0x20; } hashValue >>= 4; } return string(buffer); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_initialTreasury","type":"address"},{"internalType":"address","name":"_initialSigner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC1155InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC1155InvalidApprover","type":"error"},{"inputs":[{"internalType":"uint256","name":"idsLength","type":"uint256"},{"internalType":"uint256","name":"valuesLength","type":"uint256"}],"name":"ERC1155InvalidArrayLength","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC1155InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC1155InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC1155InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC1155MissingApprovalForAll","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"currentSupply","type":"uint256"},{"internalType":"uint256","name":"requestedAmount","type":"uint256"}],"name":"ExceedsMaxSupply","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"sent","type":"uint256"}],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NoFundsToWithdraw","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"SignatureRequired","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TokenIsSoulbound","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"TokenNotActive","type":"error"},{"inputs":[],"name":"WithdrawalFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","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":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"maxSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"bool","name":"allowlistRequired","type":"bool"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"},{"indexed":false,"internalType":"bool","name":"soulbound","type":"bool"}],"name":"TokenConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawFunds","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"burnBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"bool","name":"_allowlistRequired","type":"bool"},{"internalType":"bool","name":"_active","type":"bool"},{"internalType":"bool","name":"_soulbound","type":"bool"}],"name":"configureToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllTokenIds","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":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"required","type":"bool"}],"name":"setAllowlistRequired","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setTokenActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"setTokenPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newuri","type":"string"}],"name":"setURI","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":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenConfigs","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"allowlistRequired","type":"bool"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bool","name":"soulbound","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61016060405234801561001157600080fd5b50604051615d71380380615d718339818101604052810190610033919061068d565b846040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152508461007a8161021960201b60201c565b506000600660006101000a81548160ff02191690831515021790555060016007819055506100b260088361022c60201b90919060201c565b61012081815250506100ce60098261022c60201b90919060201c565b6101408181525050818051906020012060e08181525050808051906020012061010081815250504660a0818152505061010b61027c60201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1681525050505084600a9081610157919061097d565b5083600b9081610167919061097d565b506101987fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775336102d760201b60201c565b506101ac6000801b336102d760201b60201c565b506101dd7fe1dcbdb91df27212a29bc27177c840cf2f819ecf2187432e1fac86c2dd5dfca9836102d760201b60201c565b5061020e7fe2f4eaae4a9751e85a3e4a7b9587827a877f29914755229b07a7b2da98285f70826102d760201b60201c565b505050505050610bdc565b8060029081610228919061097d565b5050565b600060208351101561024e57610247836103d560201b60201c565b9050610276565b8261025e8361043d60201b60201c565b600001908161026d919061097d565b5060ff60001b90505b92915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60e0516101005146306040516020016102bc959493929190610a86565b60405160208183030381529060405280519060200120905090565b60006102e9838361044760201b60201c565b6103ca5760016005600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506103676104b260201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506103cf565b600090505b92915050565b600080829050601f8151111561042257826040517f305a27a90000000000000000000000000000000000000000000000000000000081526004016104199190610b23565b60405180910390fd5b80518161042e90610b75565b60001c1760001b915050919050565b6000819050919050565b60006005600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610521826104d8565b810181811067ffffffffffffffff821117156105405761053f6104e9565b5b80604052505050565b60006105536104ba565b905061055f8282610518565b919050565b600067ffffffffffffffff82111561057f5761057e6104e9565b5b610588826104d8565b9050602081019050919050565b60005b838110156105b3578082015181840152602081019050610598565b60008484015250505050565b60006105d26105cd84610564565b610549565b9050828152602081018484840111156105ee576105ed6104d3565b5b6105f9848285610595565b509392505050565b600082601f830112610616576106156104ce565b5b81516106268482602086016105bf565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061065a8261062f565b9050919050565b61066a8161064f565b811461067557600080fd5b50565b60008151905061068781610661565b92915050565b600080600080600060a086880312156106a9576106a86104c4565b5b600086015167ffffffffffffffff8111156106c7576106c66104c9565b5b6106d388828901610601565b955050602086015167ffffffffffffffff8111156106f4576106f36104c9565b5b61070088828901610601565b945050604086015167ffffffffffffffff811115610721576107206104c9565b5b61072d88828901610601565b935050606061073e88828901610678565b925050608061074f88828901610678565b9150509295509295909350565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806107ae57607f821691505b6020821081036107c1576107c0610767565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026108297fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826107ec565b61083386836107ec565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600061087a6108756108708461084b565b610855565b61084b565b9050919050565b6000819050919050565b6108948361085f565b6108a86108a082610881565b8484546107f9565b825550505050565b600090565b6108bd6108b0565b6108c881848461088b565b505050565b5b818110156108ec576108e16000826108b5565b6001810190506108ce565b5050565b601f82111561093157610902816107c7565b61090b846107dc565b8101602085101561091a578190505b61092e610926856107dc565b8301826108cd565b50505b505050565b600082821c905092915050565b600061095460001984600802610936565b1980831691505092915050565b600061096d8383610943565b9150826002028217905092915050565b6109868261075c565b67ffffffffffffffff81111561099f5761099e6104e9565b5b6109a98254610796565b6109b48282856108f0565b600060209050601f8311600181146109e757600084156109d5578287015190505b6109df8582610961565b865550610a47565b601f1984166109f5866107c7565b60005b82811015610a1d578489015182556001820191506020850194506020810190506109f8565b86831015610a3a5784890151610a36601f891682610943565b8355505b6001600288020188555050505b505050505050565b6000819050919050565b610a6281610a4f565b82525050565b610a718161084b565b82525050565b610a808161064f565b82525050565b600060a082019050610a9b6000830188610a59565b610aa86020830187610a59565b610ab56040830186610a59565b610ac26060830185610a68565b610acf6080830184610a77565b9695505050505050565b600082825260208201905092915050565b6000610af58261075c565b610aff8185610ad9565b9350610b0f818560208601610595565b610b18816104d8565b840191505092915050565b60006020820190508181036000830152610b3d8184610aea565b905092915050565b600081519050919050565b6000819050602082019050919050565b6000610b6c8251610a4f565b80915050919050565b6000610b8082610b45565b82610b8a84610b50565b9050610b9581610b60565b92506020821015610bd557610bd07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008026107ec565b831692505b5050919050565b60805160a05160c05160e05161010051610120516101405161513b610c3660003960006123fb015260006123c00152600061325a0152600061323901526000612978015260006129ce015260006129f7015261513b6000f3fe6080604052600436106102245760003560e01c80637ecebe0011610123578063bd85b039116100ab578063e985e9c51161006f578063e985e9c514610816578063eb685c4714610853578063f242432a1461087c578063f5298aca146108a5578063ffc54ea4146108ce57610224565b8063bd85b03914610718578063bdbed72214610755578063c01bd0e914610780578063d11a57ec146107c2578063d547741f146107ed57610224565b806391d14854116100f257806391d148541461063157806395d89b411461066e578063a1ebf35d14610699578063a217fddf146106c4578063a22cb465146106ef57610224565b80637ecebe00146105835780637ed6797c146105c05780638456cb59146105e957806384b0196e1461060057610224565b806336568abe116101b15780634f558e79116101755780634f558e79146104ab5780635c975abb146104e85780636b20c45414610513578063731133e91461053c57806375b238fc1461055857610224565b806336568abe146103ee5780633c9c2084146104175780633ccfd60b146104405780633f4ba83a146104575780634e1273f41461046e57610224565b80630e89341c116101f85780630e89341c146102f757806318160ddd14610334578063248a9ca31461035f5780632eb2c2d61461039c5780632f2ff15d146103c557610224565b8062fdd58e1461022957806301ffc9a71461026657806302fe5305146102a357806306fdde03146102cc575b600080fd5b34801561023557600080fd5b50610250600480360381019061024b9190613a3d565b6108f7565b60405161025d9190613a8c565b60405180910390f35b34801561027257600080fd5b5061028d60048036038101906102889190613aff565b610951565b60405161029a9190613b47565b60405180910390f35b3480156102af57600080fd5b506102ca60048036038101906102c59190613ca8565b610963565b005b3480156102d857600080fd5b506102e161099a565b6040516102ee9190613d70565b60405180910390f35b34801561030357600080fd5b5061031e60048036038101906103199190613d92565b610a28565b60405161032b9190613d70565b60405180910390f35b34801561034057600080fd5b50610349610abc565b6040516103569190613a8c565b60405180910390f35b34801561036b57600080fd5b5061038660048036038101906103819190613df5565b610ac6565b6040516103939190613e31565b60405180910390f35b3480156103a857600080fd5b506103c360048036038101906103be9190613fb5565b610ae6565b005b3480156103d157600080fd5b506103ec60048036038101906103e79190614084565b610b8e565b005b3480156103fa57600080fd5b5061041560048036038101906104109190614084565b610bb0565b005b34801561042357600080fd5b5061043e600480360381019061043991906140f0565b610c2b565b005b34801561044c57600080fd5b50610455610dc7565b005b34801561046357600080fd5b5061046c610f26565b005b34801561047a57600080fd5b5061049560048036038101906104909190614271565b610f5b565b6040516104a291906143a7565b60405180910390f35b3480156104b757600080fd5b506104d260048036038101906104cd9190613d92565b611064565b6040516104df9190613b47565b60405180910390f35b3480156104f457600080fd5b506104fd611078565b60405161050a9190613b47565b60405180910390f35b34801561051f57600080fd5b5061053a600480360381019061053591906143c9565b61108f565b005b610556600480360381019061055191906144af565b61113b565b005b34801561056457600080fd5b5061056d611627565b60405161057a9190613e31565b60405180910390f35b34801561058f57600080fd5b506105aa60048036038101906105a59190614537565b61164b565b6040516105b79190613a8c565b60405180910390f35b3480156105cc57600080fd5b506105e760048036038101906105e29190614564565b611694565b005b3480156105f557600080fd5b506105fe6116f1565b005b34801561060c57600080fd5b50610615611726565b60405161062897969594939291906145ee565b60405180910390f35b34801561063d57600080fd5b5061065860048036038101906106539190614084565b6117d0565b6040516106659190613b47565b60405180910390f35b34801561067a57600080fd5b5061068361183b565b6040516106909190613d70565b60405180910390f35b3480156106a557600080fd5b506106ae6118c9565b6040516106bb9190613e31565b60405180910390f35b3480156106d057600080fd5b506106d96118ed565b6040516106e69190613e31565b60405180910390f35b3480156106fb57600080fd5b5061071660048036038101906107119190614672565b6118f4565b005b34801561072457600080fd5b5061073f600480360381019061073a9190613d92565b61190a565b60405161074c9190613a8c565b60405180910390f35b34801561076157600080fd5b5061076a611927565b60405161077791906143a7565b60405180910390f35b34801561078c57600080fd5b506107a760048036038101906107a29190613d92565b61197f565b6040516107b9969594939291906146b2565b60405180910390f35b3480156107ce57600080fd5b506107d7611a6a565b6040516107e49190613e31565b60405180910390f35b3480156107f957600080fd5b50610814600480360381019061080f9190614084565b611a8e565b005b34801561082257600080fd5b5061083d6004803603810190610838919061471a565b611ab0565b60405161084a9190613b47565b60405180910390f35b34801561085f57600080fd5b5061087a6004803603810190610875919061475a565b611b44565b005b34801561088857600080fd5b506108a3600480360381019061089e919061479a565b611b8e565b005b3480156108b157600080fd5b506108cc60048036038101906108c79190614831565b611c36565b005b3480156108da57600080fd5b506108f560048036038101906108f09190614564565b611ce2565b005b600080600083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600061095c82611d3f565b9050919050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561098d81611db9565b61099682611dcd565b5050565b600a80546109a7906148b3565b80601f01602080910402602001604051908101604052809291908181526020018280546109d3906148b3565b8015610a205780601f106109f557610100808354040283529160200191610a20565b820191906000526020600020905b815481529060010190602001808311610a0357829003601f168201915b505050505081565b606060028054610a37906148b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610a63906148b3565b8015610ab05780601f10610a8557610100808354040283529160200191610ab0565b820191906000526020600020905b815481529060010190602001808311610a9357829003601f168201915b50505050509050919050565b6000600454905090565b600060056000838152602001908152602001600020600101549050919050565b6000610af0611de0565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610b355750610b338682611ab0565b155b15610b795780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610b709291906148e4565b60405180910390fd5b610b868686868686611de8565b505050505050565b610b9782610ac6565b610ba081611db9565b610baa8383611ee0565b50505050565b610bb8611de0565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c1c576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c268282611fd2565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610c5581611db9565b6000600c60008a81526020019081526020016000206000018054610c78906148b3565b905003610ca957600d8890806001815401808255809150506001900390600052602060002001600090919091909150555b6040518060c0016040528088815260200187815260200186815260200185151581526020018415158152602001831515815250600c60008a81526020019081526020016000206000820151816000019081610d049190614ab9565b50602082015181600101556040820151816002015560608201518160030160006101000a81548160ff02191690831515021790555060808201518160030160016101000a81548160ff02191690831515021790555060a08201518160030160026101000a81548160ff021916908315150217905550905050877ec205a6f1b6faa2dd08b5ab78d5327b5149a6ca345161c9ec276f4684b1e070888888888888604051610db5969594939291906146b2565b60405180910390a25050505050505050565b7fe1dcbdb91df27212a29bc27177c840cf2f819ecf2187432e1fac86c2dd5dfca9610df181611db9565b600047905060008103610e30576040517f67e3990d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003373ffffffffffffffffffffffffffffffffffffffff1682604051610e5690614bbc565b60006040518083038185875af1925050503d8060008114610e93576040519150601f19603f3d011682016040523d82523d6000602084013e610e98565b606091505b5050905080610ed3576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f21901fa892c430ea8bd38b9390225ac8e67eac75ee10ffba16feefc539a288f983604051610f199190613a8c565b60405180910390a2505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610f5081611db9565b610f586120c5565b50565b60608151835114610fa757815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610f9e929190614bd1565b60405180910390fd5b6000835167ffffffffffffffff811115610fc457610fc3613b7d565b5b604051908082528060200260200182016040528015610ff25781602001602082028036833780820191505090505b50905060005b84518110156110595761102f611017828761212890919063ffffffff16565b61102a838761213c90919063ffffffff16565b6108f7565b82828151811061104257611041614bfa565b5b602002602001018181525050806001019050610ff8565b508091505092915050565b6000806110708361190a565b119050919050565b6000600660009054906101000a900460ff16905090565b611097611de0565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156110e057506110de836110d9611de0565b611ab0565b155b1561112b576110ed611de0565b836040517fe237d9220000000000000000000000000000000000000000000000000000000081526004016111229291906148e4565b60405180910390fd5b611136838383612150565b505050565b6111436121e4565b61114b61222a565b6000600c60008681526020019081526020016000206040518060c001604052908160008201805461117b906148b3565b80601f01602080910402602001604051908101604052809291908181526020018280546111a7906148b3565b80156111f45780601f106111c9576101008083540402835291602001916111f4565b820191906000526020600020905b8154815290600101906020018083116111d757829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff161515151581526020016003820160019054906101000a900460ff161515151581526020016003820160029054906101000a900460ff161515151581525050905080608001516112aa57846040517ff3f613390000000000000000000000000000000000000000000000000000000081526004016112a19190613a8c565b60405180910390fd5b8381604001516112ba9190614c58565b34101561130f578381604001516112d19190614c58565b346040517fb99e2ab7000000000000000000000000000000000000000000000000000000008152600401611306929190614bd1565b60405180910390fd5b6000816020015111156113895760006113278661190a565b90508160200151858261133a9190614c9a565b11156113875785826020015182876040517f70e5fab800000000000000000000000000000000000000000000000000000000815260040161137e9493929190614cce565b60405180910390fd5b505b8060600151156115ad57600083839050036113d0576040517f229bfb1f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060006040518060600160405280602181526020016150e56021913980519060200120905060007f1e50097d2987432345f4e4ee4a1c02d620bd59b1783afb55d685831b20a238a7338a8a8a8688463060405160200161147b99989796959493929190614d13565b604051602081830303815290604052805190602001209050600061149e8261226b565b905060006114f08289898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612285565b905061151c7fe2f4eaae4a9751e85a3e4a7b9587827a877f29914755229b07a7b2da98285f70826117d0565b611552576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906115a290614da0565b919050555050505050505b6115c8868686604051806020016040528060008152506122b1565b848673ffffffffffffffffffffffffffffffffffffffff167f96234cb3d6c373a1aaa06497a540bc166d4b0359243a088eaf95e21d7253d0be8660405161160f9190613a8c565b60405180910390a35061162061234a565b5050505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b6000600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756116be81611db9565b81600c600085815260200190815260200160002060030160006101000a81548160ff021916908315150217905550505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561171b81611db9565b611723612354565b50565b60006060806000806000606061173a6123b7565b6117426123f2565b46306000801b600067ffffffffffffffff81111561176357611762613b7d565b5b6040519080825280602002602001820160405280156117915781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b60006005600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600b8054611848906148b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611874906148b3565b80156118c15780601f10611896576101008083540402835291602001916118c1565b820191906000526020600020905b8154815290600101906020018083116118a457829003601f168201915b505050505081565b7fe2f4eaae4a9751e85a3e4a7b9587827a877f29914755229b07a7b2da98285f7081565b6000801b81565b6119066118ff611de0565b838361242d565b5050565b600060036000838152602001908152602001600020549050919050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561197557602002820191906000526020600020905b815481526020019060010190808311611961575b5050505050905090565b600c6020528060005260406000206000915090508060000180546119a2906148b3565b80601f01602080910402602001604051908101604052809291908181526020018280546119ce906148b3565b8015611a1b5780601f106119f057610100808354040283529160200191611a1b565b820191906000526020600020905b8154815290600101906020018083116119fe57829003601f168201915b5050505050908060010154908060020154908060030160009054906101000a900460ff16908060030160019054906101000a900460ff16908060030160029054906101000a900460ff16905086565b7fe1dcbdb91df27212a29bc27177c840cf2f819ecf2187432e1fac86c2dd5dfca981565b611a9782610ac6565b611aa081611db9565b611aaa8383611fd2565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775611b6e81611db9565b81600c600085815260200190815260200160002060020181905550505050565b6000611b98611de0565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015611bdd5750611bdb8682611ab0565b155b15611c215780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611c189291906148e4565b60405180910390fd5b611c2e868686868661259d565b505050505050565b611c3e611de0565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015611c875750611c8583611c80611de0565b611ab0565b155b15611cd257611c94611de0565b836040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611cc99291906148e4565b60405180910390fd5b611cdd8383836126a8565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775611d0c81611db9565b81600c600085815260200190815260200160002060030160016101000a81548160ff021916908315150217905550505050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611db25750611db18261274f565b5b9050919050565b611dca81611dc5611de0565b612831565b50565b8060029081611ddc9190614ab9565b5050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611e5a5760006040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611e519190614de8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611ecc5760006040517f01a83514000000000000000000000000000000000000000000000000000000008152600401611ec39190614de8565b60405180910390fd5b611ed98585858585612882565b5050505050565b6000611eec83836117d0565b611fc75760016005600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611f64611de0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611fcc565b600090505b92915050565b6000611fde83836117d0565b156120ba5760006005600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612057611de0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4600190506120bf565b600090505b92915050565b6120cd612934565b6000600660006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612111611de0565b60405161211e9190614de8565b60405180910390a1565b600060208202602084010151905092915050565b600060208202602084010151905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036121c25760006040517f01a835140000000000000000000000000000000000000000000000000000000081526004016121b99190614de8565b60405180910390fd5b6121df836000848460405180602001604052806000815250612882565b505050565b600260075403612220576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600781905550565b612232611078565b15612269576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600061227e612278612974565b83612a2b565b9050919050565b6000806000806122958686612a6c565b9250925092506122a58282612ac8565b82935050505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036123235760006040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161231a9190614de8565b60405180910390fd5b6000806123308585612c2c565b91509150612342600087848487612882565b505050505050565b6001600781905550565b61235c61222a565b6001600660006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586123a0611de0565b6040516123ad9190614de8565b60405180910390a1565b60606123ed60087f0000000000000000000000000000000000000000000000000000000000000000612c5c90919063ffffffff16565b905090565b606061242860097f0000000000000000000000000000000000000000000000000000000000000000612c5c90919063ffffffff16565b905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361249f5760006040517fced3e1000000000000000000000000000000000000000000000000000000000081526004016124969190614de8565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516125909190613b47565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361260f5760006040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016126069190614de8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036126815760006040517f01a835140000000000000000000000000000000000000000000000000000000081526004016126789190614de8565b60405180910390fd5b60008061268e8585612c2c565b9150915061269f8787848487612882565b50505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361271a5760006040517f01a835140000000000000000000000000000000000000000000000000000000081526004016127119190614de8565b60405180910390fd5b6000806127278484612c2c565b91509150612748856000848460405180602001604052806000815250612882565b5050505050565b60007fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061281a57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061282a575061282982612d0c565b5b9050919050565b61283b82826117d0565b61287e5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401612875929190614e03565b60405180910390fd5b5050565b61288e85858585612d76565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461292d5760006128cc611de0565b9050600184510361291c5760006128ed60008661213c90919063ffffffff16565b9050600061290560008661213c90919063ffffffff16565b9050612915838989858589612eac565b505061292b565b61292a818787878787613060565b5b505b5050505050565b61293c611078565b612972576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480156129f057507f000000000000000000000000000000000000000000000000000000000000000046145b15612a1d577f00000000000000000000000000000000000000000000000000000000000000009050612a28565b612a25613214565b90505b90565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060006041845103612ab15760008060006020870151925060408701519150606087015160001a9050612aa3888285856132aa565b955095509550505050612ac1565b60006002855160001b9250925092505b9250925092565b60006003811115612adc57612adb614e2c565b5b826003811115612aef57612aee614e2c565b5b0315612c285760016003811115612b0957612b08614e2c565b5b826003811115612b1c57612b1b614e2c565b5b03612b53576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612b6757612b66614e2c565b5b826003811115612b7a57612b79614e2c565b5b03612bbf578060001c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612bb69190613a8c565b60405180910390fd5b600380811115612bd257612bd1614e2c565b5b826003811115612be557612be4614e2c565b5b03612c2757806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612c1e9190613e31565b60405180910390fd5b5b5050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b606060ff60001b8314612c7957612c728361339e565b9050612d06565b818054612c85906148b3565b80601f0160208091040260200160405190810160405280929190818152602001828054612cb1906148b3565b8015612cfe5780601f10612cd357610100808354040283529160200191612cfe565b820191906000526020600020905b815481529060010190602001808311612ce157829003601f168201915b505050505090505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614158015612de05750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b15612e9a5760005b8251811015612e9857600c6000848381518110612e0857612e07614bfa565b5b6020026020010151815260200190815260200160002060030160029054906101000a900460ff1615612e8b57828181518110612e4757612e46614bfa565b5b60200260200101516040517f8c3baa3e000000000000000000000000000000000000000000000000000000008152600401612e829190613a8c565b60405180910390fd5b8080600101915050612de8565b505b612ea684848484613412565b50505050565b60008473ffffffffffffffffffffffffffffffffffffffff163b1115613058578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401612f0d959493929190614eb0565b6020604051808303816000875af1925050508015612f4957506040513d601f19601f82011682018060405250810190612f469190614f1f565b60015b612fcd573d8060008114612f79576040519150601f19603f3d011682016040523d82523d6000602084013e612f7e565b606091505b506000815103612fc557846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401612fbc9190614de8565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461305657846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161304d9190614de8565b60405180910390fd5b505b505050505050565b60008473ffffffffffffffffffffffffffffffffffffffff163b111561320c578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016130c1959493929190614f4c565b6020604051808303816000875af19250505080156130fd57506040513d601f19601f820116820180604052508101906130fa9190614f1f565b60015b613181573d806000811461312d576040519150601f19603f3d011682016040523d82523d6000602084013e613132565b606091505b50600081510361317957846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016131709190614de8565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461320a57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016132019190614de8565b60405180910390fd5b505b505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000463060405160200161328f959493929190614fb4565b60405160208183030381529060405280519060200120905090565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c11156132ea576000600385925092509250613394565b60006001888888886040516000815260200160405260405161330f9493929190615023565b6020604051602081039080840390855afa158015613331573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361338557600060016000801b93509350935050613394565b8060008060001b935093509350505b9450945094915050565b606060006133ab8361359d565b90506000602067ffffffffffffffff8111156133ca576133c9613b7d565b5b6040519080825280601f01601f1916602001820160405280156133fc5781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b61341e848484846135ed565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036134e8576000805b83518110156134cc576000613474828561213c90919063ffffffff16565b9050806003600061348e858961213c90919063ffffffff16565b815260200190815260200160002060008282546134ab9190614c9a565b9250508190555080836134be9190614c9a565b925050806001019050613456565b5080600460008282546134df9190614c9a565b92505081905550505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613597576000805b835181101561358457600061353e828561213c90919063ffffffff16565b90508060036000613558858961213c90919063ffffffff16565b815260200190815260200160002060008282540392505081905550808301925050806001019050613520565b5080600460008282540392505081905550505b50505050565b60008060ff8360001c169050601f8111156135e4576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b805182511461363757815181516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161362e929190614bd1565b60405180910390fd5b6000613641611de0565b905060005b8351811015613850576000613664828661213c90919063ffffffff16565b9050600061367b838661213c90919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146137a857600080600084815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561375057888183856040517f03dee4c50000000000000000000000000000000000000000000000000000000081526004016137479493929190615068565b60405180910390fd5b81810360008085815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614613843578060008084815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461383b9190614c9a565b925050819055505b5050806001019050613646565b50600183510361390f57600061387060008561213c90919063ffffffff16565b9050600061388860008561213c90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051613900929190614bd1565b60405180910390a4505061398e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516139859291906150ad565b60405180910390a45b5050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006139d4826139a9565b9050919050565b6139e4816139c9565b81146139ef57600080fd5b50565b600081359050613a01816139db565b92915050565b6000819050919050565b613a1a81613a07565b8114613a2557600080fd5b50565b600081359050613a3781613a11565b92915050565b60008060408385031215613a5457613a5361399f565b5b6000613a62858286016139f2565b9250506020613a7385828601613a28565b9150509250929050565b613a8681613a07565b82525050565b6000602082019050613aa16000830184613a7d565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613adc81613aa7565b8114613ae757600080fd5b50565b600081359050613af981613ad3565b92915050565b600060208284031215613b1557613b1461399f565b5b6000613b2384828501613aea565b91505092915050565b60008115159050919050565b613b4181613b2c565b82525050565b6000602082019050613b5c6000830184613b38565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613bb582613b6c565b810181811067ffffffffffffffff82111715613bd457613bd3613b7d565b5b80604052505050565b6000613be7613995565b9050613bf38282613bac565b919050565b600067ffffffffffffffff821115613c1357613c12613b7d565b5b613c1c82613b6c565b9050602081019050919050565b82818337600083830152505050565b6000613c4b613c4684613bf8565b613bdd565b905082815260208101848484011115613c6757613c66613b67565b5b613c72848285613c29565b509392505050565b600082601f830112613c8f57613c8e613b62565b5b8135613c9f848260208601613c38565b91505092915050565b600060208284031215613cbe57613cbd61399f565b5b600082013567ffffffffffffffff811115613cdc57613cdb6139a4565b5b613ce884828501613c7a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613d2b578082015181840152602081019050613d10565b60008484015250505050565b6000613d4282613cf1565b613d4c8185613cfc565b9350613d5c818560208601613d0d565b613d6581613b6c565b840191505092915050565b60006020820190508181036000830152613d8a8184613d37565b905092915050565b600060208284031215613da857613da761399f565b5b6000613db684828501613a28565b91505092915050565b6000819050919050565b613dd281613dbf565b8114613ddd57600080fd5b50565b600081359050613def81613dc9565b92915050565b600060208284031215613e0b57613e0a61399f565b5b6000613e1984828501613de0565b91505092915050565b613e2b81613dbf565b82525050565b6000602082019050613e466000830184613e22565b92915050565b600067ffffffffffffffff821115613e6757613e66613b7d565b5b602082029050602081019050919050565b600080fd5b6000613e90613e8b84613e4c565b613bdd565b90508083825260208201905060208402830185811115613eb357613eb2613e78565b5b835b81811015613edc5780613ec88882613a28565b845260208401935050602081019050613eb5565b5050509392505050565b600082601f830112613efb57613efa613b62565b5b8135613f0b848260208601613e7d565b91505092915050565b600067ffffffffffffffff821115613f2f57613f2e613b7d565b5b613f3882613b6c565b9050602081019050919050565b6000613f58613f5384613f14565b613bdd565b905082815260208101848484011115613f7457613f73613b67565b5b613f7f848285613c29565b509392505050565b600082601f830112613f9c57613f9b613b62565b5b8135613fac848260208601613f45565b91505092915050565b600080600080600060a08688031215613fd157613fd061399f565b5b6000613fdf888289016139f2565b9550506020613ff0888289016139f2565b945050604086013567ffffffffffffffff811115614011576140106139a4565b5b61401d88828901613ee6565b935050606086013567ffffffffffffffff81111561403e5761403d6139a4565b5b61404a88828901613ee6565b925050608086013567ffffffffffffffff81111561406b5761406a6139a4565b5b61407788828901613f87565b9150509295509295909350565b6000806040838503121561409b5761409a61399f565b5b60006140a985828601613de0565b92505060206140ba858286016139f2565b9150509250929050565b6140cd81613b2c565b81146140d857600080fd5b50565b6000813590506140ea816140c4565b92915050565b600080600080600080600060e0888a03121561410f5761410e61399f565b5b600061411d8a828b01613a28565b975050602088013567ffffffffffffffff81111561413e5761413d6139a4565b5b61414a8a828b01613c7a565b965050604061415b8a828b01613a28565b955050606061416c8a828b01613a28565b945050608061417d8a828b016140db565b93505060a061418e8a828b016140db565b92505060c061419f8a828b016140db565b91505092959891949750929550565b600067ffffffffffffffff8211156141c9576141c8613b7d565b5b602082029050602081019050919050565b60006141ed6141e8846141ae565b613bdd565b905080838252602082019050602084028301858111156142105761420f613e78565b5b835b81811015614239578061422588826139f2565b845260208401935050602081019050614212565b5050509392505050565b600082601f83011261425857614257613b62565b5b81356142688482602086016141da565b91505092915050565b600080604083850312156142885761428761399f565b5b600083013567ffffffffffffffff8111156142a6576142a56139a4565b5b6142b285828601614243565b925050602083013567ffffffffffffffff8111156142d3576142d26139a4565b5b6142df85828601613ee6565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61431e81613a07565b82525050565b60006143308383614315565b60208301905092915050565b6000602082019050919050565b6000614354826142e9565b61435e81856142f4565b935061436983614305565b8060005b8381101561439a5781516143818882614324565b975061438c8361433c565b92505060018101905061436d565b5085935050505092915050565b600060208201905081810360008301526143c18184614349565b905092915050565b6000806000606084860312156143e2576143e161399f565b5b60006143f0868287016139f2565b935050602084013567ffffffffffffffff811115614411576144106139a4565b5b61441d86828701613ee6565b925050604084013567ffffffffffffffff81111561443e5761443d6139a4565b5b61444a86828701613ee6565b9150509250925092565b600080fd5b60008083601f84011261446f5761446e613b62565b5b8235905067ffffffffffffffff81111561448c5761448b614454565b5b6020830191508360018202830111156144a8576144a7613e78565b5b9250929050565b6000806000806000608086880312156144cb576144ca61399f565b5b60006144d9888289016139f2565b95505060206144ea88828901613a28565b94505060406144fb88828901613a28565b935050606086013567ffffffffffffffff81111561451c5761451b6139a4565b5b61452888828901614459565b92509250509295509295909350565b60006020828403121561454d5761454c61399f565b5b600061455b848285016139f2565b91505092915050565b6000806040838503121561457b5761457a61399f565b5b600061458985828601613a28565b925050602061459a858286016140db565b9150509250929050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6145d9816145a4565b82525050565b6145e8816139c9565b82525050565b600060e082019050614603600083018a6145d0565b81810360208301526146158189613d37565b905081810360408301526146298188613d37565b90506146386060830187613a7d565b61464560808301866145df565b61465260a0830185613e22565b81810360c08301526146648184614349565b905098975050505050505050565b600080604083850312156146895761468861399f565b5b6000614697858286016139f2565b92505060206146a8858286016140db565b9150509250929050565b600060c08201905081810360008301526146cc8189613d37565b90506146db6020830188613a7d565b6146e86040830187613a7d565b6146f56060830186613b38565b6147026080830185613b38565b61470f60a0830184613b38565b979650505050505050565b600080604083850312156147315761473061399f565b5b600061473f858286016139f2565b9250506020614750858286016139f2565b9150509250929050565b600080604083850312156147715761477061399f565b5b600061477f85828601613a28565b925050602061479085828601613a28565b9150509250929050565b600080600080600060a086880312156147b6576147b561399f565b5b60006147c4888289016139f2565b95505060206147d5888289016139f2565b94505060406147e688828901613a28565b93505060606147f788828901613a28565b925050608086013567ffffffffffffffff811115614818576148176139a4565b5b61482488828901613f87565b9150509295509295909350565b60008060006060848603121561484a5761484961399f565b5b6000614858868287016139f2565b935050602061486986828701613a28565b925050604061487a86828701613a28565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806148cb57607f821691505b6020821081036148de576148dd614884565b5b50919050565b60006040820190506148f960008301856145df565b61490660208301846145df565b9392505050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261496f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614932565b6149798683614932565b95508019841693508086168417925050509392505050565b6000819050919050565b60006149b66149b16149ac84613a07565b614991565b613a07565b9050919050565b6000819050919050565b6149d08361499b565b6149e46149dc826149bd565b84845461493f565b825550505050565b600090565b6149f96149ec565b614a048184846149c7565b505050565b5b81811015614a2857614a1d6000826149f1565b600181019050614a0a565b5050565b601f821115614a6d57614a3e8161490d565b614a4784614922565b81016020851015614a56578190505b614a6a614a6285614922565b830182614a09565b50505b505050565b600082821c905092915050565b6000614a9060001984600802614a72565b1980831691505092915050565b6000614aa98383614a7f565b9150826002028217905092915050565b614ac282613cf1565b67ffffffffffffffff811115614adb57614ada613b7d565b5b614ae582546148b3565b614af0828285614a2c565b600060209050601f831160018114614b235760008415614b11578287015190505b614b1b8582614a9d565b865550614b83565b601f198416614b318661490d565b60005b82811015614b5957848901518255600182019150602085019450602081019050614b34565b86831015614b765784890151614b72601f891682614a7f565b8355505b6001600288020188555050505b505050505050565b600081905092915050565b50565b6000614ba6600083614b8b565b9150614bb182614b96565b600082019050919050565b6000614bc782614b99565b9150819050919050565b6000604082019050614be66000830185613a7d565b614bf36020830184613a7d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614c6382613a07565b9150614c6e83613a07565b9250828202614c7c81613a07565b91508282048414831517614c9357614c92614c29565b5b5092915050565b6000614ca582613a07565b9150614cb083613a07565b9250828201905080821115614cc857614cc7614c29565b5b92915050565b6000608082019050614ce36000830187613a7d565b614cf06020830186613a7d565b614cfd6040830185613a7d565b614d0a6060830184613a7d565b95945050505050565b600061012082019050614d29600083018c613e22565b614d36602083018b6145df565b614d43604083018a6145df565b614d506060830189613a7d565b614d5d6080830188613a7d565b614d6a60a0830187613e22565b614d7760c0830186613a7d565b614d8460e0830185613a7d565b614d926101008301846145df565b9a9950505050505050505050565b6000614dab82613a07565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ddd57614ddc614c29565b5b600182019050919050565b6000602082019050614dfd60008301846145df565b92915050565b6000604082019050614e1860008301856145df565b614e256020830184613e22565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000614e8282614e5b565b614e8c8185614e66565b9350614e9c818560208601613d0d565b614ea581613b6c565b840191505092915050565b600060a082019050614ec560008301886145df565b614ed260208301876145df565b614edf6040830186613a7d565b614eec6060830185613a7d565b8181036080830152614efe8184614e77565b90509695505050505050565b600081519050614f1981613ad3565b92915050565b600060208284031215614f3557614f3461399f565b5b6000614f4384828501614f0a565b91505092915050565b600060a082019050614f6160008301886145df565b614f6e60208301876145df565b8181036040830152614f808186614349565b90508181036060830152614f948185614349565b90508181036080830152614fa88184614e77565b90509695505050505050565b600060a082019050614fc96000830188613e22565b614fd66020830187613e22565b614fe36040830186613e22565b614ff06060830185613a7d565b614ffd60808301846145df565b9695505050505050565b600060ff82169050919050565b61501d81615007565b82525050565b60006080820190506150386000830187613e22565b6150456020830186615014565b6150526040830185613e22565b61505f6060830184613e22565b95945050505050565b600060808201905061507d60008301876145df565b61508a6020830186613a7d565b6150976040830185613a7d565b6150a46060830184613a7d565b95945050505050565b600060408201905081810360008301526150c78185614349565b905081810360208301526150db8184614349565b9050939250505056fe426c6f636b75734d696e74417574686f72697a6174696f6e5369676e6174757265a2646970667358221220d5dd6da946e8951dde2b641453d828c665f579c76832f675c54ab1926632f81064736f6c634300081b003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000bde4d8669c7543acd972da1ad96478e7a5d857c200000000000000000000000071b81e78f08c3f2d799e3c1d5d4ce877ab0c8804000000000000000000000000000000000000000000000000000000000000000c5472616c6120417263616465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055452414c41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b68747470733a2f2f7465616c2d67656e75696e652d63617264696e616c2d3132302e6d7970696e6174612e636c6f75642f697066732f626166796265696861767468616f746d677062336274766d767a7668326e62776575786f77716b71646e6e33677366636e686c346b6737747a37712f7b69647d2e6a736f6e0000000000
Deployed Bytecode
0x6080604052600436106102245760003560e01c80637ecebe0011610123578063bd85b039116100ab578063e985e9c51161006f578063e985e9c514610816578063eb685c4714610853578063f242432a1461087c578063f5298aca146108a5578063ffc54ea4146108ce57610224565b8063bd85b03914610718578063bdbed72214610755578063c01bd0e914610780578063d11a57ec146107c2578063d547741f146107ed57610224565b806391d14854116100f257806391d148541461063157806395d89b411461066e578063a1ebf35d14610699578063a217fddf146106c4578063a22cb465146106ef57610224565b80637ecebe00146105835780637ed6797c146105c05780638456cb59146105e957806384b0196e1461060057610224565b806336568abe116101b15780634f558e79116101755780634f558e79146104ab5780635c975abb146104e85780636b20c45414610513578063731133e91461053c57806375b238fc1461055857610224565b806336568abe146103ee5780633c9c2084146104175780633ccfd60b146104405780633f4ba83a146104575780634e1273f41461046e57610224565b80630e89341c116101f85780630e89341c146102f757806318160ddd14610334578063248a9ca31461035f5780632eb2c2d61461039c5780632f2ff15d146103c557610224565b8062fdd58e1461022957806301ffc9a71461026657806302fe5305146102a357806306fdde03146102cc575b600080fd5b34801561023557600080fd5b50610250600480360381019061024b9190613a3d565b6108f7565b60405161025d9190613a8c565b60405180910390f35b34801561027257600080fd5b5061028d60048036038101906102889190613aff565b610951565b60405161029a9190613b47565b60405180910390f35b3480156102af57600080fd5b506102ca60048036038101906102c59190613ca8565b610963565b005b3480156102d857600080fd5b506102e161099a565b6040516102ee9190613d70565b60405180910390f35b34801561030357600080fd5b5061031e60048036038101906103199190613d92565b610a28565b60405161032b9190613d70565b60405180910390f35b34801561034057600080fd5b50610349610abc565b6040516103569190613a8c565b60405180910390f35b34801561036b57600080fd5b5061038660048036038101906103819190613df5565b610ac6565b6040516103939190613e31565b60405180910390f35b3480156103a857600080fd5b506103c360048036038101906103be9190613fb5565b610ae6565b005b3480156103d157600080fd5b506103ec60048036038101906103e79190614084565b610b8e565b005b3480156103fa57600080fd5b5061041560048036038101906104109190614084565b610bb0565b005b34801561042357600080fd5b5061043e600480360381019061043991906140f0565b610c2b565b005b34801561044c57600080fd5b50610455610dc7565b005b34801561046357600080fd5b5061046c610f26565b005b34801561047a57600080fd5b5061049560048036038101906104909190614271565b610f5b565b6040516104a291906143a7565b60405180910390f35b3480156104b757600080fd5b506104d260048036038101906104cd9190613d92565b611064565b6040516104df9190613b47565b60405180910390f35b3480156104f457600080fd5b506104fd611078565b60405161050a9190613b47565b60405180910390f35b34801561051f57600080fd5b5061053a600480360381019061053591906143c9565b61108f565b005b610556600480360381019061055191906144af565b61113b565b005b34801561056457600080fd5b5061056d611627565b60405161057a9190613e31565b60405180910390f35b34801561058f57600080fd5b506105aa60048036038101906105a59190614537565b61164b565b6040516105b79190613a8c565b60405180910390f35b3480156105cc57600080fd5b506105e760048036038101906105e29190614564565b611694565b005b3480156105f557600080fd5b506105fe6116f1565b005b34801561060c57600080fd5b50610615611726565b60405161062897969594939291906145ee565b60405180910390f35b34801561063d57600080fd5b5061065860048036038101906106539190614084565b6117d0565b6040516106659190613b47565b60405180910390f35b34801561067a57600080fd5b5061068361183b565b6040516106909190613d70565b60405180910390f35b3480156106a557600080fd5b506106ae6118c9565b6040516106bb9190613e31565b60405180910390f35b3480156106d057600080fd5b506106d96118ed565b6040516106e69190613e31565b60405180910390f35b3480156106fb57600080fd5b5061071660048036038101906107119190614672565b6118f4565b005b34801561072457600080fd5b5061073f600480360381019061073a9190613d92565b61190a565b60405161074c9190613a8c565b60405180910390f35b34801561076157600080fd5b5061076a611927565b60405161077791906143a7565b60405180910390f35b34801561078c57600080fd5b506107a760048036038101906107a29190613d92565b61197f565b6040516107b9969594939291906146b2565b60405180910390f35b3480156107ce57600080fd5b506107d7611a6a565b6040516107e49190613e31565b60405180910390f35b3480156107f957600080fd5b50610814600480360381019061080f9190614084565b611a8e565b005b34801561082257600080fd5b5061083d6004803603810190610838919061471a565b611ab0565b60405161084a9190613b47565b60405180910390f35b34801561085f57600080fd5b5061087a6004803603810190610875919061475a565b611b44565b005b34801561088857600080fd5b506108a3600480360381019061089e919061479a565b611b8e565b005b3480156108b157600080fd5b506108cc60048036038101906108c79190614831565b611c36565b005b3480156108da57600080fd5b506108f560048036038101906108f09190614564565b611ce2565b005b600080600083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600061095c82611d3f565b9050919050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561098d81611db9565b61099682611dcd565b5050565b600a80546109a7906148b3565b80601f01602080910402602001604051908101604052809291908181526020018280546109d3906148b3565b8015610a205780601f106109f557610100808354040283529160200191610a20565b820191906000526020600020905b815481529060010190602001808311610a0357829003601f168201915b505050505081565b606060028054610a37906148b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610a63906148b3565b8015610ab05780601f10610a8557610100808354040283529160200191610ab0565b820191906000526020600020905b815481529060010190602001808311610a9357829003601f168201915b50505050509050919050565b6000600454905090565b600060056000838152602001908152602001600020600101549050919050565b6000610af0611de0565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015610b355750610b338682611ab0565b155b15610b795780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401610b709291906148e4565b60405180910390fd5b610b868686868686611de8565b505050505050565b610b9782610ac6565b610ba081611db9565b610baa8383611ee0565b50505050565b610bb8611de0565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c1c576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c268282611fd2565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610c5581611db9565b6000600c60008a81526020019081526020016000206000018054610c78906148b3565b905003610ca957600d8890806001815401808255809150506001900390600052602060002001600090919091909150555b6040518060c0016040528088815260200187815260200186815260200185151581526020018415158152602001831515815250600c60008a81526020019081526020016000206000820151816000019081610d049190614ab9565b50602082015181600101556040820151816002015560608201518160030160006101000a81548160ff02191690831515021790555060808201518160030160016101000a81548160ff02191690831515021790555060a08201518160030160026101000a81548160ff021916908315150217905550905050877ec205a6f1b6faa2dd08b5ab78d5327b5149a6ca345161c9ec276f4684b1e070888888888888604051610db5969594939291906146b2565b60405180910390a25050505050505050565b7fe1dcbdb91df27212a29bc27177c840cf2f819ecf2187432e1fac86c2dd5dfca9610df181611db9565b600047905060008103610e30576040517f67e3990d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003373ffffffffffffffffffffffffffffffffffffffff1682604051610e5690614bbc565b60006040518083038185875af1925050503d8060008114610e93576040519150601f19603f3d011682016040523d82523d6000602084013e610e98565b606091505b5050905080610ed3576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f21901fa892c430ea8bd38b9390225ac8e67eac75ee10ffba16feefc539a288f983604051610f199190613a8c565b60405180910390a2505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610f5081611db9565b610f586120c5565b50565b60608151835114610fa757815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600401610f9e929190614bd1565b60405180910390fd5b6000835167ffffffffffffffff811115610fc457610fc3613b7d565b5b604051908082528060200260200182016040528015610ff25781602001602082028036833780820191505090505b50905060005b84518110156110595761102f611017828761212890919063ffffffff16565b61102a838761213c90919063ffffffff16565b6108f7565b82828151811061104257611041614bfa565b5b602002602001018181525050806001019050610ff8565b508091505092915050565b6000806110708361190a565b119050919050565b6000600660009054906101000a900460ff16905090565b611097611de0565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156110e057506110de836110d9611de0565b611ab0565b155b1561112b576110ed611de0565b836040517fe237d9220000000000000000000000000000000000000000000000000000000081526004016111229291906148e4565b60405180910390fd5b611136838383612150565b505050565b6111436121e4565b61114b61222a565b6000600c60008681526020019081526020016000206040518060c001604052908160008201805461117b906148b3565b80601f01602080910402602001604051908101604052809291908181526020018280546111a7906148b3565b80156111f45780601f106111c9576101008083540402835291602001916111f4565b820191906000526020600020905b8154815290600101906020018083116111d757829003601f168201915b5050505050815260200160018201548152602001600282015481526020016003820160009054906101000a900460ff161515151581526020016003820160019054906101000a900460ff161515151581526020016003820160029054906101000a900460ff161515151581525050905080608001516112aa57846040517ff3f613390000000000000000000000000000000000000000000000000000000081526004016112a19190613a8c565b60405180910390fd5b8381604001516112ba9190614c58565b34101561130f578381604001516112d19190614c58565b346040517fb99e2ab7000000000000000000000000000000000000000000000000000000008152600401611306929190614bd1565b60405180910390fd5b6000816020015111156113895760006113278661190a565b90508160200151858261133a9190614c9a565b11156113875785826020015182876040517f70e5fab800000000000000000000000000000000000000000000000000000000815260040161137e9493929190614cce565b60405180910390fd5b505b8060600151156115ad57600083839050036113d0576040517f229bfb1f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060006040518060600160405280602181526020016150e56021913980519060200120905060007f1e50097d2987432345f4e4ee4a1c02d620bd59b1783afb55d685831b20a238a7338a8a8a8688463060405160200161147b99989796959493929190614d13565b604051602081830303815290604052805190602001209050600061149e8261226b565b905060006114f08289898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612285565b905061151c7fe2f4eaae4a9751e85a3e4a7b9587827a877f29914755229b07a7b2da98285f70826117d0565b611552576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906115a290614da0565b919050555050505050505b6115c8868686604051806020016040528060008152506122b1565b848673ffffffffffffffffffffffffffffffffffffffff167f96234cb3d6c373a1aaa06497a540bc166d4b0359243a088eaf95e21d7253d0be8660405161160f9190613a8c565b60405180910390a35061162061234a565b5050505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b6000600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756116be81611db9565b81600c600085815260200190815260200160002060030160006101000a81548160ff021916908315150217905550505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561171b81611db9565b611723612354565b50565b60006060806000806000606061173a6123b7565b6117426123f2565b46306000801b600067ffffffffffffffff81111561176357611762613b7d565b5b6040519080825280602002602001820160405280156117915781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b60006005600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600b8054611848906148b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611874906148b3565b80156118c15780601f10611896576101008083540402835291602001916118c1565b820191906000526020600020905b8154815290600101906020018083116118a457829003601f168201915b505050505081565b7fe2f4eaae4a9751e85a3e4a7b9587827a877f29914755229b07a7b2da98285f7081565b6000801b81565b6119066118ff611de0565b838361242d565b5050565b600060036000838152602001908152602001600020549050919050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561197557602002820191906000526020600020905b815481526020019060010190808311611961575b5050505050905090565b600c6020528060005260406000206000915090508060000180546119a2906148b3565b80601f01602080910402602001604051908101604052809291908181526020018280546119ce906148b3565b8015611a1b5780601f106119f057610100808354040283529160200191611a1b565b820191906000526020600020905b8154815290600101906020018083116119fe57829003601f168201915b5050505050908060010154908060020154908060030160009054906101000a900460ff16908060030160019054906101000a900460ff16908060030160029054906101000a900460ff16905086565b7fe1dcbdb91df27212a29bc27177c840cf2f819ecf2187432e1fac86c2dd5dfca981565b611a9782610ac6565b611aa081611db9565b611aaa8383611fd2565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775611b6e81611db9565b81600c600085815260200190815260200160002060020181905550505050565b6000611b98611de0565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614158015611bdd5750611bdb8682611ab0565b155b15611c215780866040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611c189291906148e4565b60405180910390fd5b611c2e868686868661259d565b505050505050565b611c3e611de0565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015611c875750611c8583611c80611de0565b611ab0565b155b15611cd257611c94611de0565b836040517fe237d922000000000000000000000000000000000000000000000000000000008152600401611cc99291906148e4565b60405180910390fd5b611cdd8383836126a8565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775611d0c81611db9565b81600c600085815260200190815260200160002060030160016101000a81548160ff021916908315150217905550505050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611db25750611db18261274f565b5b9050919050565b611dca81611dc5611de0565b612831565b50565b8060029081611ddc9190614ab9565b5050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611e5a5760006040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401611e519190614de8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603611ecc5760006040517f01a83514000000000000000000000000000000000000000000000000000000008152600401611ec39190614de8565b60405180910390fd5b611ed98585858585612882565b5050505050565b6000611eec83836117d0565b611fc75760016005600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611f64611de0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611fcc565b600090505b92915050565b6000611fde83836117d0565b156120ba5760006005600085815260200190815260200160002060000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612057611de0565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4600190506120bf565b600090505b92915050565b6120cd612934565b6000600660006101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612111611de0565b60405161211e9190614de8565b60405180910390a1565b600060208202602084010151905092915050565b600060208202602084010151905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036121c25760006040517f01a835140000000000000000000000000000000000000000000000000000000081526004016121b99190614de8565b60405180910390fd5b6121df836000848460405180602001604052806000815250612882565b505050565b600260075403612220576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600781905550565b612232611078565b15612269576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600061227e612278612974565b83612a2b565b9050919050565b6000806000806122958686612a6c565b9250925092506122a58282612ac8565b82935050505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036123235760006040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161231a9190614de8565b60405180910390fd5b6000806123308585612c2c565b91509150612342600087848487612882565b505050505050565b6001600781905550565b61235c61222a565b6001600660006101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586123a0611de0565b6040516123ad9190614de8565b60405180910390a1565b60606123ed60087f5472616c6120417263616465000000000000000000000000000000000000000c612c5c90919063ffffffff16565b905090565b606061242860097f3100000000000000000000000000000000000000000000000000000000000001612c5c90919063ffffffff16565b905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361249f5760006040517fced3e1000000000000000000000000000000000000000000000000000000000081526004016124969190614de8565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516125909190613b47565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361260f5760006040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016126069190614de8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036126815760006040517f01a835140000000000000000000000000000000000000000000000000000000081526004016126789190614de8565b60405180910390fd5b60008061268e8585612c2c565b9150915061269f8787848487612882565b50505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361271a5760006040517f01a835140000000000000000000000000000000000000000000000000000000081526004016127119190614de8565b60405180910390fd5b6000806127278484612c2c565b91509150612748856000848460405180602001604052806000815250612882565b5050505050565b60007fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061281a57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061282a575061282982612d0c565b5b9050919050565b61283b82826117d0565b61287e5780826040517fe2517d3f000000000000000000000000000000000000000000000000000000008152600401612875929190614e03565b60405180910390fd5b5050565b61288e85858585612d76565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461292d5760006128cc611de0565b9050600184510361291c5760006128ed60008661213c90919063ffffffff16565b9050600061290560008661213c90919063ffffffff16565b9050612915838989858589612eac565b505061292b565b61292a818787878787613060565b5b505b5050505050565b61293c611078565b612972576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60007f000000000000000000000000b8d1de4219b750c51c0fcfd02a6d138d0589619b73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480156129f057507f000000000000000000000000000000000000000000000000000000000000000146145b15612a1d577fb744d03c0ed8b5867fb5925637dcf922b3a9d85cd6477c8b2a06977a411536fa9050612a28565b612a25613214565b90505b90565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060006041845103612ab15760008060006020870151925060408701519150606087015160001a9050612aa3888285856132aa565b955095509550505050612ac1565b60006002855160001b9250925092505b9250925092565b60006003811115612adc57612adb614e2c565b5b826003811115612aef57612aee614e2c565b5b0315612c285760016003811115612b0957612b08614e2c565b5b826003811115612b1c57612b1b614e2c565b5b03612b53576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612b6757612b66614e2c565b5b826003811115612b7a57612b79614e2c565b5b03612bbf578060001c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612bb69190613a8c565b60405180910390fd5b600380811115612bd257612bd1614e2c565b5b826003811115612be557612be4614e2c565b5b03612c2757806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612c1e9190613e31565b60405180910390fd5b5b5050565b60608060405191506001825283602083015260408201905060018152826020820152604081016040529250929050565b606060ff60001b8314612c7957612c728361339e565b9050612d06565b818054612c85906148b3565b80601f0160208091040260200160405190810160405280929190818152602001828054612cb1906148b3565b8015612cfe5780601f10612cd357610100808354040283529160200191612cfe565b820191906000526020600020905b815481529060010190602001808311612ce157829003601f168201915b505050505090505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614158015612de05750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b15612e9a5760005b8251811015612e9857600c6000848381518110612e0857612e07614bfa565b5b6020026020010151815260200190815260200160002060030160029054906101000a900460ff1615612e8b57828181518110612e4757612e46614bfa565b5b60200260200101516040517f8c3baa3e000000000000000000000000000000000000000000000000000000008152600401612e829190613a8c565b60405180910390fd5b8080600101915050612de8565b505b612ea684848484613412565b50505050565b60008473ffffffffffffffffffffffffffffffffffffffff163b1115613058578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401612f0d959493929190614eb0565b6020604051808303816000875af1925050508015612f4957506040513d601f19601f82011682018060405250810190612f469190614f1f565b60015b612fcd573d8060008114612f79576040519150601f19603f3d011682016040523d82523d6000602084013e612f7e565b606091505b506000815103612fc557846040517f57f447ce000000000000000000000000000000000000000000000000000000008152600401612fbc9190614de8565b60405180910390fd5b805181602001fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461305657846040517f57f447ce00000000000000000000000000000000000000000000000000000000815260040161304d9190614de8565b60405180910390fd5b505b505050505050565b60008473ffffffffffffffffffffffffffffffffffffffff163b111561320c578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016130c1959493929190614f4c565b6020604051808303816000875af19250505080156130fd57506040513d601f19601f820116820180604052508101906130fa9190614f1f565b60015b613181573d806000811461312d576040519150601f19603f3d011682016040523d82523d6000602084013e613132565b606091505b50600081510361317957846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016131709190614de8565b60405180910390fd5b805181602001fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461320a57846040517f57f447ce0000000000000000000000000000000000000000000000000000000081526004016132019190614de8565b60405180910390fd5b505b505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7fa681a386e5b804005dbf0ded02d4fd34e8766523516ad6483e55ff4f89b797ef7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6463060405160200161328f959493929190614fb4565b60405160208183030381529060405280519060200120905090565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c11156132ea576000600385925092509250613394565b60006001888888886040516000815260200160405260405161330f9493929190615023565b6020604051602081039080840390855afa158015613331573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361338557600060016000801b93509350935050613394565b8060008060001b935093509350505b9450945094915050565b606060006133ab8361359d565b90506000602067ffffffffffffffff8111156133ca576133c9613b7d565b5b6040519080825280601f01601f1916602001820160405280156133fc5781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b61341e848484846135ed565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036134e8576000805b83518110156134cc576000613474828561213c90919063ffffffff16565b9050806003600061348e858961213c90919063ffffffff16565b815260200190815260200160002060008282546134ab9190614c9a565b9250508190555080836134be9190614c9a565b925050806001019050613456565b5080600460008282546134df9190614c9a565b92505081905550505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613597576000805b835181101561358457600061353e828561213c90919063ffffffff16565b90508060036000613558858961213c90919063ffffffff16565b815260200190815260200160002060008282540392505081905550808301925050806001019050613520565b5080600460008282540392505081905550505b50505050565b60008060ff8360001c169050601f8111156135e4576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b805182511461363757815181516040517f5b05999100000000000000000000000000000000000000000000000000000000815260040161362e929190614bd1565b60405180910390fd5b6000613641611de0565b905060005b8351811015613850576000613664828661213c90919063ffffffff16565b9050600061367b838661213c90919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146137a857600080600084815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508181101561375057888183856040517f03dee4c50000000000000000000000000000000000000000000000000000000081526004016137479493929190615068565b60405180910390fd5b81810360008085815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614613843578060008084815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461383b9190614c9a565b925050819055505b5050806001019050613646565b50600183510361390f57600061387060008561213c90919063ffffffff16565b9050600061388860008561213c90919063ffffffff16565b90508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051613900929190614bd1565b60405180910390a4505061398e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516139859291906150ad565b60405180910390a45b5050505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006139d4826139a9565b9050919050565b6139e4816139c9565b81146139ef57600080fd5b50565b600081359050613a01816139db565b92915050565b6000819050919050565b613a1a81613a07565b8114613a2557600080fd5b50565b600081359050613a3781613a11565b92915050565b60008060408385031215613a5457613a5361399f565b5b6000613a62858286016139f2565b9250506020613a7385828601613a28565b9150509250929050565b613a8681613a07565b82525050565b6000602082019050613aa16000830184613a7d565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613adc81613aa7565b8114613ae757600080fd5b50565b600081359050613af981613ad3565b92915050565b600060208284031215613b1557613b1461399f565b5b6000613b2384828501613aea565b91505092915050565b60008115159050919050565b613b4181613b2c565b82525050565b6000602082019050613b5c6000830184613b38565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613bb582613b6c565b810181811067ffffffffffffffff82111715613bd457613bd3613b7d565b5b80604052505050565b6000613be7613995565b9050613bf38282613bac565b919050565b600067ffffffffffffffff821115613c1357613c12613b7d565b5b613c1c82613b6c565b9050602081019050919050565b82818337600083830152505050565b6000613c4b613c4684613bf8565b613bdd565b905082815260208101848484011115613c6757613c66613b67565b5b613c72848285613c29565b509392505050565b600082601f830112613c8f57613c8e613b62565b5b8135613c9f848260208601613c38565b91505092915050565b600060208284031215613cbe57613cbd61399f565b5b600082013567ffffffffffffffff811115613cdc57613cdb6139a4565b5b613ce884828501613c7a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613d2b578082015181840152602081019050613d10565b60008484015250505050565b6000613d4282613cf1565b613d4c8185613cfc565b9350613d5c818560208601613d0d565b613d6581613b6c565b840191505092915050565b60006020820190508181036000830152613d8a8184613d37565b905092915050565b600060208284031215613da857613da761399f565b5b6000613db684828501613a28565b91505092915050565b6000819050919050565b613dd281613dbf565b8114613ddd57600080fd5b50565b600081359050613def81613dc9565b92915050565b600060208284031215613e0b57613e0a61399f565b5b6000613e1984828501613de0565b91505092915050565b613e2b81613dbf565b82525050565b6000602082019050613e466000830184613e22565b92915050565b600067ffffffffffffffff821115613e6757613e66613b7d565b5b602082029050602081019050919050565b600080fd5b6000613e90613e8b84613e4c565b613bdd565b90508083825260208201905060208402830185811115613eb357613eb2613e78565b5b835b81811015613edc5780613ec88882613a28565b845260208401935050602081019050613eb5565b5050509392505050565b600082601f830112613efb57613efa613b62565b5b8135613f0b848260208601613e7d565b91505092915050565b600067ffffffffffffffff821115613f2f57613f2e613b7d565b5b613f3882613b6c565b9050602081019050919050565b6000613f58613f5384613f14565b613bdd565b905082815260208101848484011115613f7457613f73613b67565b5b613f7f848285613c29565b509392505050565b600082601f830112613f9c57613f9b613b62565b5b8135613fac848260208601613f45565b91505092915050565b600080600080600060a08688031215613fd157613fd061399f565b5b6000613fdf888289016139f2565b9550506020613ff0888289016139f2565b945050604086013567ffffffffffffffff811115614011576140106139a4565b5b61401d88828901613ee6565b935050606086013567ffffffffffffffff81111561403e5761403d6139a4565b5b61404a88828901613ee6565b925050608086013567ffffffffffffffff81111561406b5761406a6139a4565b5b61407788828901613f87565b9150509295509295909350565b6000806040838503121561409b5761409a61399f565b5b60006140a985828601613de0565b92505060206140ba858286016139f2565b9150509250929050565b6140cd81613b2c565b81146140d857600080fd5b50565b6000813590506140ea816140c4565b92915050565b600080600080600080600060e0888a03121561410f5761410e61399f565b5b600061411d8a828b01613a28565b975050602088013567ffffffffffffffff81111561413e5761413d6139a4565b5b61414a8a828b01613c7a565b965050604061415b8a828b01613a28565b955050606061416c8a828b01613a28565b945050608061417d8a828b016140db565b93505060a061418e8a828b016140db565b92505060c061419f8a828b016140db565b91505092959891949750929550565b600067ffffffffffffffff8211156141c9576141c8613b7d565b5b602082029050602081019050919050565b60006141ed6141e8846141ae565b613bdd565b905080838252602082019050602084028301858111156142105761420f613e78565b5b835b81811015614239578061422588826139f2565b845260208401935050602081019050614212565b5050509392505050565b600082601f83011261425857614257613b62565b5b81356142688482602086016141da565b91505092915050565b600080604083850312156142885761428761399f565b5b600083013567ffffffffffffffff8111156142a6576142a56139a4565b5b6142b285828601614243565b925050602083013567ffffffffffffffff8111156142d3576142d26139a4565b5b6142df85828601613ee6565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61431e81613a07565b82525050565b60006143308383614315565b60208301905092915050565b6000602082019050919050565b6000614354826142e9565b61435e81856142f4565b935061436983614305565b8060005b8381101561439a5781516143818882614324565b975061438c8361433c565b92505060018101905061436d565b5085935050505092915050565b600060208201905081810360008301526143c18184614349565b905092915050565b6000806000606084860312156143e2576143e161399f565b5b60006143f0868287016139f2565b935050602084013567ffffffffffffffff811115614411576144106139a4565b5b61441d86828701613ee6565b925050604084013567ffffffffffffffff81111561443e5761443d6139a4565b5b61444a86828701613ee6565b9150509250925092565b600080fd5b60008083601f84011261446f5761446e613b62565b5b8235905067ffffffffffffffff81111561448c5761448b614454565b5b6020830191508360018202830111156144a8576144a7613e78565b5b9250929050565b6000806000806000608086880312156144cb576144ca61399f565b5b60006144d9888289016139f2565b95505060206144ea88828901613a28565b94505060406144fb88828901613a28565b935050606086013567ffffffffffffffff81111561451c5761451b6139a4565b5b61452888828901614459565b92509250509295509295909350565b60006020828403121561454d5761454c61399f565b5b600061455b848285016139f2565b91505092915050565b6000806040838503121561457b5761457a61399f565b5b600061458985828601613a28565b925050602061459a858286016140db565b9150509250929050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6145d9816145a4565b82525050565b6145e8816139c9565b82525050565b600060e082019050614603600083018a6145d0565b81810360208301526146158189613d37565b905081810360408301526146298188613d37565b90506146386060830187613a7d565b61464560808301866145df565b61465260a0830185613e22565b81810360c08301526146648184614349565b905098975050505050505050565b600080604083850312156146895761468861399f565b5b6000614697858286016139f2565b92505060206146a8858286016140db565b9150509250929050565b600060c08201905081810360008301526146cc8189613d37565b90506146db6020830188613a7d565b6146e86040830187613a7d565b6146f56060830186613b38565b6147026080830185613b38565b61470f60a0830184613b38565b979650505050505050565b600080604083850312156147315761473061399f565b5b600061473f858286016139f2565b9250506020614750858286016139f2565b9150509250929050565b600080604083850312156147715761477061399f565b5b600061477f85828601613a28565b925050602061479085828601613a28565b9150509250929050565b600080600080600060a086880312156147b6576147b561399f565b5b60006147c4888289016139f2565b95505060206147d5888289016139f2565b94505060406147e688828901613a28565b93505060606147f788828901613a28565b925050608086013567ffffffffffffffff811115614818576148176139a4565b5b61482488828901613f87565b9150509295509295909350565b60008060006060848603121561484a5761484961399f565b5b6000614858868287016139f2565b935050602061486986828701613a28565b925050604061487a86828701613a28565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806148cb57607f821691505b6020821081036148de576148dd614884565b5b50919050565b60006040820190506148f960008301856145df565b61490660208301846145df565b9392505050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261496f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614932565b6149798683614932565b95508019841693508086168417925050509392505050565b6000819050919050565b60006149b66149b16149ac84613a07565b614991565b613a07565b9050919050565b6000819050919050565b6149d08361499b565b6149e46149dc826149bd565b84845461493f565b825550505050565b600090565b6149f96149ec565b614a048184846149c7565b505050565b5b81811015614a2857614a1d6000826149f1565b600181019050614a0a565b5050565b601f821115614a6d57614a3e8161490d565b614a4784614922565b81016020851015614a56578190505b614a6a614a6285614922565b830182614a09565b50505b505050565b600082821c905092915050565b6000614a9060001984600802614a72565b1980831691505092915050565b6000614aa98383614a7f565b9150826002028217905092915050565b614ac282613cf1565b67ffffffffffffffff811115614adb57614ada613b7d565b5b614ae582546148b3565b614af0828285614a2c565b600060209050601f831160018114614b235760008415614b11578287015190505b614b1b8582614a9d565b865550614b83565b601f198416614b318661490d565b60005b82811015614b5957848901518255600182019150602085019450602081019050614b34565b86831015614b765784890151614b72601f891682614a7f565b8355505b6001600288020188555050505b505050505050565b600081905092915050565b50565b6000614ba6600083614b8b565b9150614bb182614b96565b600082019050919050565b6000614bc782614b99565b9150819050919050565b6000604082019050614be66000830185613a7d565b614bf36020830184613a7d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614c6382613a07565b9150614c6e83613a07565b9250828202614c7c81613a07565b91508282048414831517614c9357614c92614c29565b5b5092915050565b6000614ca582613a07565b9150614cb083613a07565b9250828201905080821115614cc857614cc7614c29565b5b92915050565b6000608082019050614ce36000830187613a7d565b614cf06020830186613a7d565b614cfd6040830185613a7d565b614d0a6060830184613a7d565b95945050505050565b600061012082019050614d29600083018c613e22565b614d36602083018b6145df565b614d43604083018a6145df565b614d506060830189613a7d565b614d5d6080830188613a7d565b614d6a60a0830187613e22565b614d7760c0830186613a7d565b614d8460e0830185613a7d565b614d926101008301846145df565b9a9950505050505050505050565b6000614dab82613a07565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ddd57614ddc614c29565b5b600182019050919050565b6000602082019050614dfd60008301846145df565b92915050565b6000604082019050614e1860008301856145df565b614e256020830184613e22565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000614e8282614e5b565b614e8c8185614e66565b9350614e9c818560208601613d0d565b614ea581613b6c565b840191505092915050565b600060a082019050614ec560008301886145df565b614ed260208301876145df565b614edf6040830186613a7d565b614eec6060830185613a7d565b8181036080830152614efe8184614e77565b90509695505050505050565b600081519050614f1981613ad3565b92915050565b600060208284031215614f3557614f3461399f565b5b6000614f4384828501614f0a565b91505092915050565b600060a082019050614f6160008301886145df565b614f6e60208301876145df565b8181036040830152614f808186614349565b90508181036060830152614f948185614349565b90508181036080830152614fa88184614e77565b90509695505050505050565b600060a082019050614fc96000830188613e22565b614fd66020830187613e22565b614fe36040830186613e22565b614ff06060830185613a7d565b614ffd60808301846145df565b9695505050505050565b600060ff82169050919050565b61501d81615007565b82525050565b60006080820190506150386000830187613e22565b6150456020830186615014565b6150526040830185613e22565b61505f6060830184613e22565b95945050505050565b600060808201905061507d60008301876145df565b61508a6020830186613a7d565b6150976040830185613a7d565b6150a46060830184613a7d565b95945050505050565b600060408201905081810360008301526150c78185614349565b905081810360208301526150db8184614349565b9050939250505056fe426c6f636b75734d696e74417574686f72697a6174696f6e5369676e6174757265a2646970667358221220d5dd6da946e8951dde2b641453d828c665f579c76832f675c54ab1926632f81064736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000bde4d8669c7543acd972da1ad96478e7a5d857c200000000000000000000000071b81e78f08c3f2d799e3c1d5d4ce877ab0c8804000000000000000000000000000000000000000000000000000000000000000c5472616c6120417263616465000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055452414c41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b68747470733a2f2f7465616c2d67656e75696e652d63617264696e616c2d3132302e6d7970696e6174612e636c6f75642f697066732f626166796265696861767468616f746d677062336274766d767a7668326e62776575786f77716b71646e6e33677366636e686c346b6737747a37712f7b69647d2e6a736f6e0000000000
-----Decoded View---------------
Arg [0] : _name (string): Trala Arcade
Arg [1] : _symbol (string): TRALA
Arg [2] : _uri (string): https://teal-genuine-cardinal-120.mypinata.cloud/ipfs/bafybeihavthaotmgpb3btvmvzvh2nbweuxowqkqdnn3gsfcnhl4kg7tz7q/{id}.json
Arg [3] : _initialTreasury (address): 0xBDE4d8669C7543acd972DA1Ad96478E7A5D857c2
Arg [4] : _initialSigner (address): 0x71B81e78F08c3f2d799e3C1d5D4cE877ab0c8804
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [3] : 000000000000000000000000bde4d8669c7543acd972da1ad96478e7a5d857c2
Arg [4] : 00000000000000000000000071b81e78f08c3f2d799e3c1d5d4ce877ab0c8804
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [6] : 5472616c61204172636164650000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [8] : 5452414c41000000000000000000000000000000000000000000000000000000
Arg [9] : 000000000000000000000000000000000000000000000000000000000000007b
Arg [10] : 68747470733a2f2f7465616c2d67656e75696e652d63617264696e616c2d3132
Arg [11] : 302e6d7970696e6174612e636c6f75642f697066732f62616679626569686176
Arg [12] : 7468616f746d677062336274766d767a7668326e62776575786f77716b71646e
Arg [13] : 6e33677366636e686c346b6737747a37712f7b69647d2e6a736f6e0000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.