Overview
TokenID
59130
Total Transfers
-
Market
Onchain Market Cap
$46,900.00
Circulating Supply Market Cap
$0.00
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
PARADOX
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {ERC425} from "../ERC425.sol"; contract PARADOX is ERC425 { string public dataURI; string public baseTokenURI; mapping(address => bool) private blacklist; uint256 public maxWallet; uint256 private deploymentBlock; constructor( string memory name_, string memory symbol_, uint8 decimals_, uint256 _erc20TokensSupply, string memory uri_ ) ERC425(name_, symbol_, decimals_, _erc20TokensSupply, uri_) { maxWallet = ((_erc20TokensSupply * 10 ** decimals_) * 2) / 100; deploymentBlock = block.number; dataURI = uri_; } function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids ) internal override { require(!blacklist[from], "Sender is blacklisted."); require(!blacklist[to], "Recipient is blacklisted."); require( block.number > deploymentBlock + 50, "Transfers are blocked for the first 50 blocks after deployment." ); super._beforeTokenTransfer(operator, from, to, ids); } function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids ) internal override { if (!nftsTransferExempt[to]) { require( balanceOf(to) <= maxWallet, "Transfer exceeds allowed holding per wallet" ); } super._afterTokenTransfer(operator, from, to, ids); } function setDataURI(string memory _dataURI) public onlyOwner { dataURI = _dataURI; } function setTokenURI(string memory _tokenURI) public onlyOwner { baseTokenURI = _tokenURI; } function setURI(string memory _uri) external onlyOwner { _setURI(_uri); } function tokenURI(uint256 id) public view override returns (string memory) { if (id >= _nextTokenId()) revert InvalidNFTId(); if (bytes(baseTokenURI).length > 0) { return string.concat(baseTokenURI, Strings.toString(id)); } else { uint8 seed = uint8(bytes1(keccak256(abi.encodePacked(id)))); string memory image; string memory color; if (seed <= 100) { image = "1.gif"; color = "Blue"; } else if (seed <= 160) { image = "2.gif"; color = "Red"; } else if (seed <= 210) { image = "3.gif"; color = "Grey"; } else if (seed <= 240) { image = "4.gif"; color = "Green"; } else if (seed <= 255) { image = "5.gif"; color = "Black"; } string memory jsonPreImage = string.concat( string.concat( string.concat('{"name": "Paradox #', Strings.toString(id)), '","description":"A collection of 10,000 NFTs enabled by ERC425, a gas optimized experimental token standard. Earn yield on your semi-fungible tokens by transforming existing illiquid NFTS into liquid assets.","external_url":"https://pdx.build","image":"' ), string.concat(dataURI, image) ); string memory jsonPostImage = string.concat( '","attributes":[{"trait_type":"Color","value":"', color ); string memory jsonPostTraits = '"}]}'; return string.concat( "data:application/json;utf8,", string.concat( string.concat(jsonPreImage, jsonPostImage), jsonPostTraits ) ); } } function uri(uint256 id) public view override returns (string memory) { return tokenURI(id); } function setBlacklist(address target, bool state) public virtual onlyOwner { blacklist[target] = state; } function setMaxWallet(uint256 percentage) external onlyOwner { maxWallet = (totalSupply() * percentage) / 100; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "solady/src/utils/LibBitmap.sol"; import "./interfaces/IERC425.sol"; import "./lib/Address.sol"; abstract contract ERC425 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC425, IERC20, IERC20Metadata, IERC20Errors, Ownable { using Address for address; using LibBitmap for LibBitmap.Bitmap; // Mapping from accout to owned tokens mapping(address => LibBitmap.Bitmap) internal _owned; // Mapping from account to operator approvals mapping(address => mapping(address => 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; // The next token ID to be minted. uint256 private _currentIndex; // NFT Whitelist mapping(address => bool) public nftsTransferExempt; // NFT Approvals mapping(uint256 => address) public getApproved; mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /// @dev Decimals for ERC-20 representation uint8 public immutable decimals; /// @dev Units for ERC-20 representation uint256 public immutable units; constructor( string memory name_, string memory symbol_, uint8 decimals_, uint256 _erc20TokensSupply, string memory uri_ ) Ownable(_msgSender()) { _name = name_; _symbol = symbol_; decimals = decimals_; units = 10 ** decimals; _totalSupply = _erc20TokensSupply * units; _setURI(uri_); _currentIndex = _startTokenId(); nftsTransferExempt[_msgSender()] = true; _balances[msg.sender] = _totalSupply; emit Transfer(address(0), msg.sender, _totalSupply); } function setNFTsTransferExempt( address target, bool state ) public virtual onlyOwner { if (balanceOf(target) >= units && !state) { revert CannotRemoveFromNFTsTransferExempt(); } nftsTransferExempt[target] = state; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value, true); return true; } /** * @dev See {IERC20-allowance}. */ function allowance( address owner, address spender ) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve( address spender, uint256 value ) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom( address from, address to, uint256 value ) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value, true); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer( address from, address to, uint256 value, bool isNFTTransfer ) internal virtual { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } if (from == to) { revert ERC425InvalidSelfTransfer(from, to); } _update(from, to, value, isNFTTransfer); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update( address from, address to, uint256 value, bool isNFTTransfer ) internal virtual { uint256 fromBalance = _balances[from]; uint256 toBalance = _balances[to]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } emit Transfer(from, to, value); if (isNFTTransfer) { // Preload for gas savings bool isFromNFTTransferExempt = nftsTransferExempt[from]; bool isToNFTTransferExempt = nftsTransferExempt[to]; uint256 wholeTokens = value / units; // Skip burning and/or minting of NFTs wherever needed/possible // to save gas, and // NFT transfer exempt addresses won't always have/need NFTs corresponding to their ERC20s. if (isFromNFTTransferExempt && isToNFTTransferExempt) { // Case 1. Both sender and recipient are NFT transfer exempt. So, no NFTs need to be transferred. // NOOP. } else if (isFromNFTTransferExempt) { // Case 2. The sender is NFT transfer exempt, but the recipient is not. Contract should not attempt // to transfer NFTs from the sender, but the recipient should receive NFTs // (by minting) for any whole number increase in their balance. // Only cares about whole number increments. if (wholeTokens > 0) { _mintWithoutCheck(to, wholeTokens); } } else if (isToNFTTransferExempt) { // Case 3. The sender is not NFT transfer exempt, but the recipient is. Contract should attempt // to burn NFTs from the sender, but the recipient should not // receive NFTs(no minting). // Only cares about whole number increments. if (wholeTokens > 0) { _burnBatch(from, wholeTokens); } } else { // Case 4. Neither the sender nor the recipient are NFT transfer exempt. // Strategy: // a. First deal with the whole tokens: Burn from sender and mint at receiver. // b. Look at the fractional part of the value: // (i) If it causes the sender to lose a whole token that was represented by an NFT due to a // fractional part being transferred, burn an additional NFT from the sender. // (ii)) If it causes the receiver to gain a whole new token that should be represented by an NFT // due to receiving a fractional part that completes a whole token, mint an NFT to the recevier. if (wholeTokens > 0) { _burnBatch(from, wholeTokens); _mintWithoutCheck(to, wholeTokens); } // 4(b)(i)look if subtracting the fractional amount from the balance causes the balance to // drop below the original balance % units, which represents the number of whole tokens they started with. uint256 fractionalAmount = value % units; if ((fromBalance - fractionalAmount) / units < (fromBalance / units)) { _burnBatch(from, 1); } // 4(b)(ii) Check if the receive causes the receiver to gain a whole new token that should be represented // by an NFT due to receiving a fractional part that completes a whole token. if ((toBalance + fractionalAmount) / units > (toBalance / units)) { _mintWithoutCheck(to, 1); } } } } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve( address owner, address spender, uint256 value, bool emitEvent ) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 value ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal pure virtual returns (uint256) { return 1; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view returns (uint256) { return _currentIndex; } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view returns (uint256) { return _nextTokenId() - _startTokenId(); } /// @notice tokenURI must be implemented by child contract function tokenURI(uint256 id_) public view virtual returns (string memory); /** * @dev Returns true if the account owns the `id` token. */ function isOwnerOf( address account, uint256 id ) public view virtual override returns (bool) { return _owned[account].get(id); } /** * @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 || interfaceId == type(IERC425).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 EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf( address account, uint256 id ) public view virtual override returns (uint256) { if (account == address(0)) { revert BalanceQueryForZeroAddress(); } if (_owned[account].get(id)) { return 1; } else { return 0; } } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] memory accounts, uint256[] memory ids ) public view virtual override returns (uint256[] memory) { if (accounts.length != ids.length) { revert InputLengthMistmatch(); } uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll( address operator, bool approved ) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll( address account, address operator ) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { if (nftsTransferExempt[to]) { revert NFTTransferToNFTExemptAddress(to); } else if (from == _msgSender() || isApprovedForAll(from, _msgSender())) { _safeTransferFrom(from, to, id, amount, data, true); } else { revert TransferCallerNotOwnerNorApproved(); } } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { if (!(from == _msgSender() || isApprovedForAll(from, _msgSender()))) { revert TransferCallerNotOwnerNorApproved(); } _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `amount` cannot be zero. * - `from` must have a balance of tokens of type `id` of at least `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 amount, bytes memory data, bool approvalCheck ) internal virtual { if (to == address(0)) { revert TransferToZeroAddress(); } address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); _beforeTokenTransfer(operator, from, to, ids); if (amount == 1 && _owned[from].get(id)) { _owned[from].unset(id); _owned[to].set(id); _transfer(from, to, 1 * units, false); } else { revert TransferFromIncorrectOwnerOrInvalidAmount(); } emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids); if (approvalCheck) { _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, 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. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { if (ids.length != amounts.length) { revert InputLengthMistmatch(); } if (to == address(0)) { revert TransferToZeroAddress(); } address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; if (amount == 1 && _owned[from].get(id)) { _owned[from].unset(id); _owned[to].set(id); } else { revert TransferFromIncorrectOwnerOrInvalidAmount(); } } _transfer(from, to, 1 * units * ids.length, false); emit Transfer(from, to, 1 * units * ids.length); emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, 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 EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts 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; } function _mint(address to, uint256 amount) internal virtual { _mint(to, amount, ""); } /** * @dev Creates `amount` tokens, and assigns them to `to`. * * Emits a {TransferBatch} event. * * Requirements: * * - `to` cannot be the zero address. * - `amount` cannot be zero. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 amount, bytes memory data ) internal virtual { (uint256[] memory ids, uint256[] memory amounts) = _mintWithoutCheck( to, amount ); uint256 end = _currentIndex; _doSafeBatchTransferAcceptanceCheck( _msgSender(), address(0), to, ids, amounts, data ); if (_currentIndex != end) revert(); } function _mintWithoutCheck( address to, uint256 amount ) internal virtual returns (uint256[] memory ids, uint256[] memory amounts) { if (to == address(0)) { revert MintToZeroAddress(); } if (amount == 0) { revert MintZeroQuantity(); } address operator = _msgSender(); ids = new uint256[](amount); amounts = new uint256[](amount); uint256 startTokenId = _nextTokenId(); unchecked { require(type(uint256).max - amount >= startTokenId); for (uint256 i = 0; i < amount; i++) { ids[i] = startTokenId + i; amounts[i] = 1; } } _beforeTokenTransfer(operator, address(0), to, ids); _owned[to].setBatch(startTokenId, amount); _currentIndex += amount; emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids); } /** * @dev Destroys token of token type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have the token of token type `id`. */ function _burn(address from, uint256 id) internal virtual { if (from == address(0)) { revert BurnFromZeroAddress(); } address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); _beforeTokenTransfer(operator, from, address(0), ids); if (!_owned[from].get(id)) { revert BurnFromNonOnwerAddress(); } _owned[from].unset(id); emit TransferSingle(operator, from, address(0), id, 1); _afterTokenTransfer(operator, from, address(0), ids); } /** * @dev Destroys tokens of token types in `ids` from `from` * * Emits a {TransferBatch} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have the token of token types in `ids`. */ function _burnBatch(address from, uint256[] memory ids) internal virtual { if (from == address(0)) { revert BurnFromZeroAddress(); } address operator = _msgSender(); uint256[] memory amounts = new uint256[](ids.length); _beforeTokenTransfer(operator, from, address(0), ids); unchecked { for (uint256 i = 0; i < ids.length; i++) { amounts[i] = 1; uint256 id = ids[i]; if (!_owned[from].get(id)) { revert BurnFromNonOnwerAddress(); } _owned[from].unset(id); } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids); } function _burnBatch(address from, uint256 amount) internal virtual { if (from == address(0)) { revert BurnFromZeroAddress(); } address operator = _msgSender(); uint256 searchFrom = _nextTokenId(); uint256[] memory amounts = new uint256[](amount); uint256[] memory ids = new uint256[](amount); unchecked { for (uint256 i = 0; i < amount; i++) { amounts[i] = 1; uint256 id = _owned[from].findLastSet(searchFrom); ids[i] = id; _owned[from].unset(id); searchFrom = id; } } _beforeTokenTransfer(operator, from, address(0), ids); if (amount == 1) emit TransferSingle(operator, from, address(0), ids[0], 1); else emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `ids` and `amounts` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert TransferToNonERC1155ReceiverImplementer(); } } catch Error(string memory reason) { revert(reason); } catch { revert TransferToNonERC1155ReceiverImplementer(); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived( operator, from, ids, amounts, data ) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert TransferToNonERC1155ReceiverImplementer(); } } catch Error(string memory reason) { revert(reason); } catch { revert TransferToNonERC1155ReceiverImplementer(); } } } function _asSingletonArray( uint256 element ) private pure returns (uint256[] memory array) { array = new uint256[](1); array[0] = element; } /** * @dev Returns the number of ERC20 tokens owned by `owner`. */ function balanceOf(address owner) public view virtual returns (uint256) { return _balances[owner]; } /** * @dev Returns the number of tokens owned by `owner`. */ function totalNFTsOwned(address owner) public view virtual returns (uint256) { return balanceOf(owner, _startTokenId(), _nextTokenId()); } /** * @dev Returns the number of tokens owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * Requirements: * * - `start < stop` */ function balanceOf( address owner, uint256 start, uint256 stop ) public view virtual override returns (uint256) { return _owned[owner].popCount(start, stop - start); } /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC1155DelataQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) public view virtual override returns (uint256[] memory) { unchecked { if (start >= stop) revert InvalidQueryRange(); // Set `start = max(start, _startTokenId())`. if (start < _startTokenId()) { start = _startTokenId(); } // Set `stop = min(stop, stopLimit)`. uint256 stopLimit = _nextTokenId(); if (stop > stopLimit) { stop = stopLimit; } uint256 tokenIdsLength; if (start < stop) { tokenIdsLength = balanceOf(owner, start, stop); } else { tokenIdsLength = 0; } uint256[] memory tokenIds = new uint256[](tokenIdsLength); LibBitmap.Bitmap storage bmap = _owned[owner]; for ( (uint256 i, uint256 tokenIdsIdx) = (start, 0); tokenIdsIdx != tokenIdsLength; ++i ) { if (bmap.get(i)) { tokenIds[tokenIdsIdx++] = i; } } return tokenIds; } } /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * See {ERC425Queryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K collections should be fine). */ function tokensOfOwner( address owner ) public view virtual override returns (uint256[] memory) { if (_totalMinted() == 0) { return new uint256[](0); } return tokensOfOwnerIn(owner, _startTokenId(), _nextTokenId()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.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; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require( success, "Address: unable to send value, recipient may have reverted" ); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data ) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require( address(this).balance >= value, "Address: insufficient balance for call" ); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data ) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data ) internal returns (bytes memory) { return functionDelegateCall( target, data, "Address: low-level delegate call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC425 { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * Cannot burn from the zero address. */ error BurnFromZeroAddress(); /** * Cannot burn from the address that doesn't owne the token. */ error BurnFromNonOnwerAddress(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from` or the `amount` is not 1. */ error TransferFromIncorrectOwnerOrInvalidAmount(); /** * Cannot safely transfer to a contract that does not implement the * ERC1155Receiver interface. */ error TransferToNonERC1155ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The length of input arraies is not matching. */ error InputLengthMistmatch(); error InvalidQueryRange(); error DecimalsTooLow(); error ERC425InvalidSelfTransfer(address from, address to); error NFTTransferToNFTExemptAddress(address to); error CannotRemoveFromNFTsTransferExempt(); error InvalidNFTId(); function isOwnerOf(address account, uint256 id) external view returns (bool); function balanceOf( address owner, uint256 start, uint256 stop ) external view returns (uint256); function totalNFTsOwned(address owner) external view returns (uint256); function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view returns (uint256[] memory); function tokensOfOwner( address owner ) external view returns (uint256[] memory); function tokenURI(uint256 id_) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {LibBit} from "./LibBit.sol"; /// @notice Library for storage of packed unsigned booleans. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBitmap.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibBitmap.sol) /// @author Modified from Solidity-Bits (https://github.com/estarriolvetch/solidity-bits/blob/main/contracts/BitMaps.sol) library LibBitmap { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when a bitmap scan does not find a result. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev A bitmap in storage. struct Bitmap { mapping(uint256 => uint256) map; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the boolean value of the bit at `index` in `bitmap`. function get(Bitmap storage bitmap, uint256 index) internal view returns (bool isSet) { // It is better to set `isSet` to either 0 or 1, than zero vs non-zero. // Both cost the same amount of gas, but the former allows the returned value // to be reused without cleaning the upper bits. uint256 b = (bitmap.map[index >> 8] >> (index & 0xff)) & 1; /// @solidity memory-safe-assembly assembly { isSet := b } } /// @dev Updates the bit at `index` in `bitmap` to true. function set(Bitmap storage bitmap, uint256 index) internal { bitmap.map[index >> 8] |= (1 << (index & 0xff)); } /// @dev Updates the bit at `index` in `bitmap` to false. function unset(Bitmap storage bitmap, uint256 index) internal { bitmap.map[index >> 8] &= ~(1 << (index & 0xff)); } /// @dev Flips the bit at `index` in `bitmap`. /// Returns the boolean result of the flipped bit. function toggle(Bitmap storage bitmap, uint256 index) internal returns (bool newIsSet) { /// @solidity memory-safe-assembly assembly { mstore(0x20, bitmap.slot) mstore(0x00, shr(8, index)) let storageSlot := keccak256(0x00, 0x40) let shift := and(index, 0xff) let storageValue := xor(sload(storageSlot), shl(shift, 1)) // It makes sense to return the `newIsSet`, // as it allow us to skip an additional warm `sload`, // and it costs minimal gas (about 15), // which may be optimized away if the returned value is unused. newIsSet := and(1, shr(shift, storageValue)) sstore(storageSlot, storageValue) } } /// @dev Updates the bit at `index` in `bitmap` to `shouldSet`. function setTo(Bitmap storage bitmap, uint256 index, bool shouldSet) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, bitmap.slot) mstore(0x00, shr(8, index)) let storageSlot := keccak256(0x00, 0x40) let storageValue := sload(storageSlot) let shift := and(index, 0xff) sstore( storageSlot, // Unsets the bit at `shift` via `and`, then sets its new value via `or`. or(and(storageValue, not(shl(shift, 1))), shl(shift, iszero(iszero(shouldSet)))) ) } } /// @dev Consecutively sets `amount` of bits starting from the bit at `start`. function setBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let max := not(0) let shift := and(start, 0xff) mstore(0x20, bitmap.slot) mstore(0x00, shr(8, start)) if iszero(lt(add(shift, amount), 257)) { let storageSlot := keccak256(0x00, 0x40) sstore(storageSlot, or(sload(storageSlot), shl(shift, max))) let bucket := add(mload(0x00), 1) let bucketEnd := add(mload(0x00), shr(8, add(amount, shift))) amount := and(add(amount, shift), 0xff) shift := 0 for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } { mstore(0x00, bucket) sstore(keccak256(0x00, 0x40), max) } mstore(0x00, bucket) } let storageSlot := keccak256(0x00, 0x40) sstore(storageSlot, or(sload(storageSlot), shl(shift, shr(sub(256, amount), max)))) } } /// @dev Consecutively unsets `amount` of bits starting from the bit at `start`. function unsetBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let shift := and(start, 0xff) mstore(0x20, bitmap.slot) mstore(0x00, shr(8, start)) if iszero(lt(add(shift, amount), 257)) { let storageSlot := keccak256(0x00, 0x40) sstore(storageSlot, and(sload(storageSlot), not(shl(shift, not(0))))) let bucket := add(mload(0x00), 1) let bucketEnd := add(mload(0x00), shr(8, add(amount, shift))) amount := and(add(amount, shift), 0xff) shift := 0 for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } { mstore(0x00, bucket) sstore(keccak256(0x00, 0x40), 0) } mstore(0x00, bucket) } let storageSlot := keccak256(0x00, 0x40) sstore( storageSlot, and(sload(storageSlot), not(shl(shift, shr(sub(256, amount), not(0))))) ) } } /// @dev Returns number of set bits within a range by /// scanning `amount` of bits starting from the bit at `start`. function popCount(Bitmap storage bitmap, uint256 start, uint256 amount) internal view returns (uint256 count) { unchecked { uint256 bucket = start >> 8; uint256 shift = start & 0xff; if (!(amount + shift < 257)) { count = LibBit.popCount(bitmap.map[bucket] >> shift); uint256 bucketEnd = bucket + ((amount + shift) >> 8); amount = (amount + shift) & 0xff; shift = 0; for (++bucket; bucket != bucketEnd; ++bucket) { count += LibBit.popCount(bitmap.map[bucket]); } } count += LibBit.popCount((bitmap.map[bucket] >> shift) << (256 - amount)); } } /// @dev Returns the index of the most significant set bit before the bit at `before`. /// If no set bit is found, returns `NOT_FOUND`. function findLastSet(Bitmap storage bitmap, uint256 before) internal view returns (uint256 setBitIndex) { uint256 bucket; uint256 bucketBits; /// @solidity memory-safe-assembly assembly { setBitIndex := not(0) bucket := shr(8, before) mstore(0x00, bucket) mstore(0x20, bitmap.slot) let offset := and(0xff, not(before)) // `256 - (255 & before) - 1`. bucketBits := shr(offset, shl(offset, sload(keccak256(0x00, 0x40)))) if iszero(or(bucketBits, iszero(bucket))) { for {} 1 {} { bucket := add(bucket, setBitIndex) // `sub(bucket, 1)`. mstore(0x00, bucket) bucketBits := sload(keccak256(0x00, 0x40)) if or(bucketBits, iszero(bucket)) { break } } } } if (bucketBits != 0) { setBitIndex = (bucket << 8) | LibBit.fls(bucketBits); /// @solidity memory-safe-assembly assembly { setBitIndex := or(setBitIndex, sub(0, gt(setBitIndex, before))) } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// 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.0.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 ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. */ 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`. * * Requirements: * * - `account` cannot be the zero address. */ 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 caller. */ 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.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.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[EIP]. */ 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.0.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 ERC1155 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 ERC1155 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.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for bit twiddling and boolean operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBit.sol) /// @author Inspired by (https://graphics.stanford.edu/~seander/bithacks.html) library LibBit { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BIT TWIDDLING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Find last set. /// Returns the index of the most significant bit of `x`, /// counting from the least significant bit position. /// If `x` is zero, returns 256. function fls(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x))) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020504060203020504030106050205030304010505030400000000)) } } /// @dev Count leading zeros. /// Returns the number of zeros preceding the most significant one bit. /// If `x` is zero, returns 256. function clz(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := add(xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)), iszero(x)) } } /// @dev Find first set. /// Returns the index of the least significant bit of `x`, /// counting from the least significant bit position. /// If `x` is zero, returns 256. /// Equivalent to `ctz` (count trailing zeros), which gives /// the number of zeros following the least significant one bit. function ffs(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Isolate the least significant bit. let b := and(x, add(not(x), 1)) r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, b))) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, b)))) r := or(r, shl(5, lt(0xffffffff, shr(r, b)))) // For the remaining 32 bits, use a De Bruijn lookup. // forgefmt: disable-next-item r := or(r, byte(and(div(0xd76453e0, shr(r, b)), 0x1f), 0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405)) } } /// @dev Returns the number of set bits in `x`. function popCount(uint256 x) internal pure returns (uint256 c) { /// @solidity memory-safe-assembly assembly { let max := not(0) let isMax := eq(x, max) x := sub(x, and(shr(1, x), div(max, 3))) x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5))) x := and(add(x, shr(4, x)), div(max, 17)) c := or(shl(8, isMax), shr(248, mul(x, div(max, 255)))) } } /// @dev Returns whether `x` is a power of 2. function isPo2(uint256 x) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // Equivalent to `x && !(x & (x - 1))`. result := iszero(add(and(x, sub(x, 1)), iszero(x))) } } /// @dev Returns `x` reversed at the bit level. function reverseBits(uint256 x) internal pure returns (uint256 r) { uint256 m0 = 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f; uint256 m1 = m0 ^ (m0 << 2); uint256 m2 = m1 ^ (m1 << 1); r = reverseBytes(x); r = (m2 & (r >> 1)) | ((m2 & r) << 1); r = (m1 & (r >> 2)) | ((m1 & r) << 2); r = (m0 & (r >> 4)) | ((m0 & r) << 4); } /// @dev Returns `x` reversed at the byte level. function reverseBytes(uint256 x) internal pure returns (uint256 r) { unchecked { // Computing masks on-the-fly reduces bytecode size by about 200 bytes. uint256 m0 = 0x100000000000000000000000000000001 * (~toUint(x == 0) >> 192); uint256 m1 = m0 ^ (m0 << 32); uint256 m2 = m1 ^ (m1 << 16); uint256 m3 = m2 ^ (m2 << 8); r = (m3 & (x >> 8)) | ((m3 & x) << 8); r = (m2 & (r >> 16)) | ((m2 & r) << 16); r = (m1 & (r >> 32)) | ((m1 & r) << 32); r = (m0 & (r >> 64)) | ((m0 & r) << 64); r = (r >> 128) | (r << 128); } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BOOLEAN OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // A Solidity bool on the stack or memory is represented as a 256-bit word. // Non-zero values are true, zero is false. // A clean bool is either 0 (false) or 1 (true) under the hood. // Usually, if not always, the bool result of a regular Solidity expression, // or the argument of a public/external function will be a clean bool. // You can usually use the raw variants for more performance. // If uncertain, test (best with exact compiler settings). // Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s). /// @dev Returns `x & y`. Inputs must be clean. function rawAnd(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := and(x, y) } } /// @dev Returns `x & y`. function and(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := and(iszero(iszero(x)), iszero(iszero(y))) } } /// @dev Returns `x | y`. Inputs must be clean. function rawOr(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := or(x, y) } } /// @dev Returns `x | y`. function or(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := or(iszero(iszero(x)), iszero(iszero(y))) } } /// @dev Returns 1 if `b` is true, else 0. Input must be clean. function rawToUint(bool b) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := b } } /// @dev Returns 1 if `b` is true, else 0. function toUint(bool b) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "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
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"uint256","name":"_erc20TokensSupply","type":"uint256"},{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"BurnFromNonOnwerAddress","type":"error"},{"inputs":[],"name":"BurnFromZeroAddress","type":"error"},{"inputs":[],"name":"CannotRemoveFromNFTsTransferExempt","type":"error"},{"inputs":[],"name":"DecimalsTooLow","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"ERC425InvalidSelfTransfer","type":"error"},{"inputs":[],"name":"InputLengthMistmatch","type":"error"},{"inputs":[],"name":"InvalidNFTId","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"NFTTransferToNFTExemptAddress","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwnerOrInvalidAmount","type":"error"},{"inputs":[],"name":"TransferToNonERC1155ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"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"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"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":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"isOwnerOf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nftsTransferExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"amounts","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":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","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":"address","name":"target","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"setBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_dataURI","type":"string"}],"name":"setDataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"setMaxWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"setNFTsTransferExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","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":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"totalNFTsOwned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"units","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c060405234801562000010575f80fd5b5060405162006462380380620064628339818101604052810190620000369190620005ac565b84848484846200004b620002cf60201b60201c565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000be575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000b59190620006d0565b60405180910390fd5b620000cf81620002d660201b60201c565b5084600a9081620000e1919062000919565b5083600b9081620000f3919062000919565b508260ff1660808160ff1681525050608051600a62000113919062000b7a565b60a0818152505060a051826200012a919062000bca565b60098190555062000141816200039760201b60201c565b62000151620003ac60201b60201c565b600481905550600160055f6200016c620002cf60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555060095460075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60095460405162000260919062000c25565b60405180910390a350505050506064600284600a62000280919062000b7a565b846200028d919062000bca565b62000299919062000bca565b620002a5919062000c6d565b600f819055504360108190555080600c9081620002c3919062000919565b50505050505062000ca4565b5f33905090565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8060039081620003a8919062000919565b5050565b5f6001905090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200041582620003cd565b810181811067ffffffffffffffff82111715620004375762000436620003dd565b5b80604052505050565b5f6200044b620003b4565b90506200045982826200040a565b919050565b5f67ffffffffffffffff8211156200047b576200047a620003dd565b5b6200048682620003cd565b9050602081019050919050565b5f5b83811015620004b257808201518184015260208101905062000495565b5f8484015250505050565b5f620004d3620004cd846200045e565b62000440565b905082815260208101848484011115620004f257620004f1620003c9565b5b620004ff84828562000493565b509392505050565b5f82601f8301126200051e576200051d620003c5565b5b815162000530848260208601620004bd565b91505092915050565b5f60ff82169050919050565b620005508162000539565b81146200055b575f80fd5b50565b5f815190506200056e8162000545565b92915050565b5f819050919050565b620005888162000574565b811462000593575f80fd5b50565b5f81519050620005a6816200057d565b92915050565b5f805f805f60a08688031215620005c857620005c7620003bd565b5b5f86015167ffffffffffffffff811115620005e857620005e7620003c1565b5b620005f68882890162000507565b955050602086015167ffffffffffffffff8111156200061a5762000619620003c1565b5b620006288882890162000507565b94505060406200063b888289016200055e565b93505060606200064e8882890162000596565b925050608086015167ffffffffffffffff811115620006725762000671620003c1565b5b620006808882890162000507565b9150509295509295909350565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620006b8826200068d565b9050919050565b620006ca81620006ac565b82525050565b5f602082019050620006e55f830184620006bf565b92915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200073a57607f821691505b60208210810362000750576200074f620006f5565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620007b47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000777565b620007c0868362000777565b95508019841693508086168417925050509392505050565b5f819050919050565b5f62000801620007fb620007f58462000574565b620007d8565b62000574565b9050919050565b5f819050919050565b6200081c83620007e1565b620008346200082b8262000808565b84845462000783565b825550505050565b5f90565b6200084a6200083c565b6200085781848462000811565b505050565b5b818110156200087e57620008725f8262000840565b6001810190506200085d565b5050565b601f821115620008cd57620008978162000756565b620008a28462000768565b81016020851015620008b2578190505b620008ca620008c18562000768565b8301826200085c565b50505b505050565b5f82821c905092915050565b5f620008ef5f1984600802620008d2565b1980831691505092915050565b5f620009098383620008de565b9150826002028217905092915050565b6200092482620006eb565b67ffffffffffffffff81111562000940576200093f620003dd565b5b6200094c825462000722565b6200095982828562000882565b5f60209050601f8311600181146200098f575f84156200097a578287015190505b620009868582620008fc565b865550620009f5565b601f1984166200099f8662000756565b5f5b82811015620009c857848901518255600182019150602085019450602081019050620009a1565b86831015620009e85784890151620009e4601f891682620008de565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f808291508390505b600185111562000a875780860481111562000a5f5762000a5e620009fd565b5b600185161562000a6f5780820291505b808102905062000a7f8562000a2a565b945062000a3f565b94509492505050565b5f8262000aa1576001905062000b73565b8162000ab0575f905062000b73565b816001811462000ac9576002811462000ad45762000b0a565b600191505062000b73565b60ff84111562000ae95762000ae8620009fd565b5b8360020a91508482111562000b035762000b02620009fd565b5b5062000b73565b5060208310610133831016604e8410600b841016171562000b445782820a90508381111562000b3e5762000b3d620009fd565b5b62000b73565b62000b53848484600162000a36565b9250905081840481111562000b6d5762000b6c620009fd565b5b81810290505b9392505050565b5f62000b868262000574565b915062000b938362000539565b925062000bc27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848462000a90565b905092915050565b5f62000bd68262000574565b915062000be38362000574565b925082820262000bf38162000574565b9150828204841483151762000c0d5762000c0c620009fd565b5b5092915050565b62000c1f8162000574565b82525050565b5f60208201905062000c3a5f83018462000c14565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f62000c798262000574565b915062000c868362000574565b92508262000c995762000c9862000c40565b5b828204905092915050565b60805160a05161575662000d0c5f395f8181610f9f015281816111860152818161219601528181612224015281816127be01528181612cff01528181612d9901528181612dc701528181612df301528181612e3c0152612e6801525f610c9501526157565ff3fe608060405234801561000f575f80fd5b506004361061022f575f3560e01c80638462151c1161012e578063c87b56dd116100b6578063e985e9c51161007a578063e985e9c51461071f578063f242432a1461074f578063f28ca1dd1461076b578063f2fde38b14610789578063f8b45b05146107a55761022f565b8063c87b56dd14610655578063d547cfb714610685578063d9adc191146106a3578063dd62ed3e146106d3578063e0df5b6f146107035761022f565b806399a2557a116100fd57806399a2557a1461058d578063a22cb465146105bd578063a9059cbb146105d9578063adcfa01114610609578063c5b8f772146106255761022f565b80638462151c146105035780638da5cb5b1461053357806395d89b4114610551578063976a84351461056f5761022f565b806318d217c3116101bc578063377880ea11610180578063377880ea1461044d5780634e1273f41461047d5780635d0044ca146104ad57806370a08231146104c9578063715018a6146104f95761022f565b806318d217c31461039757806323b872dd146103b35780632d760d57146103e35780632eb2c2d614610413578063313ce5671461042f5761022f565b8063081812fc11610203578063081812fc146102cd578063095ea7b3146102fd5780630e89341c1461032d578063153b0d1e1461035d57806318160ddd146103795761022f565b8062fdd58e1461023357806301ffc9a71461026357806302fe53051461029357806306fdde03146102af575b5f80fd5b61024d60048036038101906102489190613f5d565b6107c3565b60405161025a9190613faa565b60405180910390f35b61027d60048036038101906102789190614018565b610890565b60405161028a919061405d565b60405180910390f35b6102ad60048036038101906102a891906141b2565b6109d9565b005b6102b76109ed565b6040516102c49190614273565b60405180910390f35b6102e760048036038101906102e29190614293565b610a7d565b6040516102f491906142cd565b60405180910390f35b61031760048036038101906103129190613f5d565b610aad565b604051610324919061405d565b60405180910390f35b61034760048036038101906103429190614293565b610acf565b6040516103549190614273565b60405180910390f35b61037760048036038101906103729190614310565b610ae1565b005b610381610b41565b60405161038e9190613faa565b60405180910390f35b6103b160048036038101906103ac91906141b2565b610b4a565b005b6103cd60048036038101906103c8919061434e565b610b65565b6040516103da919061405d565b60405180910390f35b6103fd60048036038101906103f8919061439e565b610b95565b60405161040a9190613faa565b60405180910390f35b61042d60048036038101906104289190614550565b610bfb565b005b610437610c93565b6040516104449190614636565b60405180910390f35b6104676004803603810190610462919061464f565b610cb7565b604051610474919061405d565b60405180910390f35b6104976004803603810190610492919061473a565b610cd4565b6040516104a49190614867565b60405180910390f35b6104c760048036038101906104c29190614293565b610ddc565b005b6104e360048036038101906104de919061464f565b610e0c565b6040516104f09190613faa565b60405180910390f35b610501610e52565b005b61051d6004803603810190610518919061464f565b610e65565b60405161052a9190614867565b60405180910390f35b61053b610ee6565b60405161054891906142cd565b60405180910390f35b610559610f0d565b6040516105669190614273565b60405180910390f35b610577610f9d565b6040516105849190613faa565b60405180910390f35b6105a760048036038101906105a2919061439e565b610fc1565b6040516105b49190614867565b60405180910390f35b6105d760048036038101906105d29190614310565b611142565b005b6105f360048036038101906105ee9190613f5d565b611158565b604051610600919061405d565b60405180910390f35b610623600480360381019061061e9190614310565b61117c565b005b61063f600480360381019061063a9190613f5d565b611249565b60405161064c919061405d565b60405180910390f35b61066f600480360381019061066a9190614293565b6112a1565b60405161067c9190614273565b60405180910390f35b61068d611734565b60405161069a9190614273565b60405180910390f35b6106bd60048036038101906106b8919061464f565b6117c0565b6040516106ca9190613faa565b60405180910390f35b6106ed60048036038101906106e89190614887565b6117e1565b6040516106fa9190613faa565b60405180910390f35b61071d600480360381019061071891906141b2565b611863565b005b61073960048036038101906107349190614887565b61187e565b604051610746919061405d565b60405180910390f35b610769600480360381019061076491906148c5565b61190c565b005b610773611a38565b6040516107809190614273565b60405180910390f35b6107a3600480360381019061079e919061464f565b611ac4565b005b6107ad611b48565b6040516107ba9190613faa565b60405180910390f35b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610829576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108788260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b15610886576001905061088a565b5f90505b92915050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061095a57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806109c257507fe4d82d0f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806109d257506109d182611b7c565b5b9050919050565b6109e1611be5565b6109ea81611c6c565b50565b6060600a80546109fc90614985565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2890614985565b8015610a735780601f10610a4a57610100808354040283529160200191610a73565b820191905f5260205f20905b815481529060010190602001808311610a5657829003601f168201915b5050505050905090565b6006602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f80610ab7611c7f565b9050610ac4818585611c86565b600191505092915050565b6060610ada826112a1565b9050919050565b610ae9611be5565b80600e5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505050565b5f600954905090565b610b52611be5565b80600c9081610b619190614b52565b5050565b5f80610b6f611c7f565b9050610b7c858285611c98565b610b898585856001611d2a565b60019150509392505050565b5f610bf2838484610ba69190614c4e565b60015f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611e8e9092919063ffffffff16565b90509392505050565b610c03611c7f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480610c495750610c4885610c43611c7f565b61187e565b5b610c7f576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c8585858585611f4c565b5050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6005602052805f5260405f205f915054906101000a900460ff1681565b60608151835114610d11576040517f7801f4e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f835167ffffffffffffffff811115610d2d57610d2c61408e565b5b604051908082528060200260200182016040528015610d5b5781602001602082028036833780820191505090505b5090505f5b8451811015610dd157610da7858281518110610d7f57610d7e614c81565b5b6020026020010151858381518110610d9a57610d99614c81565b5b60200260200101516107c3565b828281518110610dba57610db9614c81565b5b602002602001018181525050806001019050610d60565b508091505092915050565b610de4611be5565b606481610def610b41565b610df99190614cae565b610e039190614d1c565b600f8190555050565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b610e5a611be5565b610e635f61230e565b565b60605f610e706123cf565b03610ec5575f67ffffffffffffffff811115610e8f57610e8e61408e565b5b604051908082528060200260200182016040528015610ebd5781602001602082028036833780820191505090505b509050610ee1565b610ede82610ed16123ef565b610ed96123f7565b610fc1565b90505b919050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600b8054610f1c90614985565b80601f0160208091040260200160405190810160405280929190818152602001828054610f4890614985565b8015610f935780601f10610f6a57610100808354040283529160200191610f93565b820191905f5260205f20905b815481529060010190602001808311610f7657829003601f168201915b5050505050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060818310610ffc576040517f32c1995a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110046123ef565b831015611016576110136123ef565b92505b5f61101f6123f7565b90508083111561102d578092505b5f8385101561104857611041868686610b95565b905061104c565b5f90505b5f8167ffffffffffffffff8111156110675761106661408e565b5b6040519080825280602002602001820160405280156110955781602001602082028036833780820191505090505b5090505f60015f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f80885f915091505b848114611132576110fb8284611b4e90919063ffffffff16565b15611127578184828060010193508151811061111a57611119614c81565b5b6020026020010181815250505b8160010191506110e1565b5050819450505050509392505050565b61115461114d611c7f565b8383612400565b5050565b5f80611162611c7f565b90506111718185856001611d2a565b600191505092915050565b611184611be5565b7f00000000000000000000000000000000000000000000000000000000000000006111ae83610e0c565b101580156111ba575080155b156111f1576040517ff543eef600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505050565b5f6112998260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b905092915050565b60606112ab6123f7565b82106112e3576040517f5f6f1f0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600d80546112f190614985565b9050111561132b57600d61130483612567565b604051602001611315929190614e06565b604051602081830303815290604052905061172f565b5f8260405160200161133d9190614e49565b6040516020818303038152906040528051906020012060f81c905060608060648360ff16116113db576040518060400160405280600581526020017f312e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600481526020017f426c75650000000000000000000000000000000000000000000000000000000081525090506115db565b60a08360ff161161145b576040518060400160405280600581526020017f322e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600381526020017f526564000000000000000000000000000000000000000000000000000000000081525090506115da565b60d28360ff16116114db576040518060400160405280600581526020017f332e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600481526020017f477265790000000000000000000000000000000000000000000000000000000081525090506115d9565b60f08360ff161161155b576040518060400160405280600581526020017f342e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600581526020017f477265656e00000000000000000000000000000000000000000000000000000081525090506115d8565b60ff8360ff16116115d7576040518060400160405280600581526020017f352e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600581526020017f426c61636b00000000000000000000000000000000000000000000000000000081525090505b5b5b5b5b5f6115e586612567565b6040516020016115f59190614e89565b6040516020818303038152906040526040516020016116149190615002565b604051602081830303815290604052600c84604051602001611637929190614e06565b604051602081830303815290604052604051602001611657929190615023565b60405160208183030381529060405290505f8260405160200161167a91906150b6565b60405160208183030381529060405290505f6040518060400160405280600481526020017f227d5d7d00000000000000000000000000000000000000000000000000000000815250905082826040516020016116d7929190615023565b604051602081830303815290604052816040516020016116f8929190615023565b60405160208183030381529060405260405160200161171791906150fd565b60405160208183030381529060405296505050505050505b919050565b600d805461174190614985565b80601f016020809104026020016040519081016040528092919081815260200182805461176d90614985565b80156117b85780601f1061178f576101008083540402835291602001916117b8565b820191905f5260205f20905b81548152906001019060200180831161179b57829003601f168201915b505050505081565b5f6117da826117cd6123ef565b6117d56123f7565b610b95565b9050919050565b5f60085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b61186b611be5565b80600d908161187a9190614b52565b5050565b5f60025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff161561199857836040517fbe0c433b00000000000000000000000000000000000000000000000000000000815260040161198f91906142cd565b60405180910390fd5b6119a0611c7f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614806119e657506119e5856119e0611c7f565b61187e565b5b156119ff576119fa85858585856001612631565b611a31565b6040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600c8054611a4590614985565b80601f0160208091040260200160405190810160405280929190818152602001828054611a7190614985565b8015611abc5780601f10611a9357610100808354040283529160200191611abc565b820191905f5260205f20905b815481529060010190602001808311611a9f57829003601f168201915b505050505081565b611acc611be5565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b3c575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611b3391906142cd565b60405180910390fd5b611b458161230e565b50565b600f5481565b5f80600160ff8416855f015f600887901c81526020019081526020015f2054901c1690508091505092915050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b611bed611c7f565b73ffffffffffffffffffffffffffffffffffffffff16611c0b610ee6565b73ffffffffffffffffffffffffffffffffffffffff1614611c6a57611c2e611c7f565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c6191906142cd565b60405180910390fd5b565b8060039081611c7b9190614b52565b5050565b5f33905090565b611c9383838360016128cf565b505050565b5f611ca384846117e1565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611d245781811015611d15578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611d0c93929190615122565b60405180910390fd5b611d2384848484035f6128cf565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611d9a575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611d9191906142cd565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611e0a575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611e0191906142cd565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611e7c5783836040517f2fd6adab000000000000000000000000000000000000000000000000000000008152600401611e73929190615157565b60405180910390fd5b611e8884848484612a9e565b50505050565b5f80600884901c90505f60ff8516905061010181850110611f1a57611ec781875f015f8581526020019081526020015f2054901c612ec1565b92505f6008828601901c8301905060ff8286011694505f91508260010192505b808314611f1857611f09875f015f8581526020019081526020015f2054612ec1565b84019350826001019250611ee7565b505b611f3f846101000382885f015f8681526020019081526020015f2054901c901b612ec1565b8301925050509392505050565b8151835114611f87576040517f7801f4e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611fec576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611ff5611c7f565b905061200381878787612f0a565b5f5b845181101561218c575f85828151811061202257612021614c81565b5b602002602001015190505f8583815181106120405761203f614c81565b5b602002602001015190506001811480156120a557506120a48260015f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b5b1561214d576120f98260015f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2061308090919063ffffffff16565b6121488260015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206130af90919063ffffffff16565b61217f565b6040517f37dbad3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050806001019050612005565b506121d1868686517f000000000000000000000000000000000000000000000000000000000000000060016121c19190614cae565b6121cb9190614cae565b5f611d2a565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86517f0000000000000000000000000000000000000000000000000000000000000000600161224f9190614cae565b6122599190614cae565b6040516122669190613faa565b60405180910390a38473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516122e492919061517e565b60405180910390a46122f8818787876130dd565b61230681878787878761318b565b505050505050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6123d86123ef565b6123e06123f7565b6123ea9190614c4e565b905090565b5f6001905090565b5f600454905090565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361246e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246590615223565b60405180910390fd5b8060025f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161255a919061405d565b60405180910390a3505050565b60605f60016125758461334f565b0190505f8167ffffffffffffffff8111156125935761259261408e565b5b6040519080825280601f01601f1916602001820160405280156125c55781602001600182028036833780820191505090505b5090505f82602001820190505b600115612626578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161261b5761261a614cef565b5b0494505f85036125d2575b819350505050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612696576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61269f611c7f565b90505f6126ab866134a0565b90506126b982898984612f0a565b60018514801561271457506127138660015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b5b156127f4576127688660015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2061308090919063ffffffff16565b6127b78660015f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206130af90919063ffffffff16565b6127ef88887f000000000000000000000000000000000000000000000000000000000000000060016127e99190614cae565b5f611d2a565b612826565b6040517f37dbad3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62898960405161289c929190615241565b60405180910390a46128b0828989846130dd565b82156128c5576128c4828989898989613513565b5b5050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361293f575f6040517fe602df0500000000000000000000000000000000000000000000000000000000815260040161293691906142cd565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129af575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016129a691906142cd565b60405180910390fd5b8160085f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612a98578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a8f9190613faa565b60405180910390a35b50505050565b5f60075f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60075f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905083821015612b69578582856040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612b6093929190615122565b60405180910390fd5b83820360075f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508360075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86604051612c549190613faa565b60405180910390a38215612eb9575f60055f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f60055f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f7f000000000000000000000000000000000000000000000000000000000000000087612d299190614d1c565b9050828015612d355750815b612eb5578215612d59575f811115612d5457612d5188826136d7565b50505b612eb4565b8115612d77575f811115612d7257612d7189826139b5565b5b612eb3565b5f811115612d9657612d8989826139b5565b612d9388826136d7565b50505b5f7f000000000000000000000000000000000000000000000000000000000000000088612dc39190615268565b90507f000000000000000000000000000000000000000000000000000000000000000086612df19190614d1c565b7f00000000000000000000000000000000000000000000000000000000000000008288612e1e9190614c4e565b612e289190614d1c565b1015612e3a57612e398a60016139b5565b5b7f000000000000000000000000000000000000000000000000000000000000000085612e669190614d1c565b7f00000000000000000000000000000000000000000000000000000000000000008287612e939190615298565b612e9d9190614d1c565b1115612eb157612eae8960016136d7565b50505b505b5b5b5050505b505050505050565b5f8019808314600382048460011c1684039350600582048460021c16600583048516019350601182048460041c850116935060ff8204840260f81c8160081b1792505050919050565b600e5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615612f94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f8b90615315565b60405180910390fd5b600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff161561301e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130159061537d565b60405180910390fd5b603260105461302d9190615298565b431161306e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130659061540b565b60405180910390fd5b61307a84848484613d0b565b50505050565b60ff81166001901b19825f015f600884901c81526020019081526020015f205f82825416925050819055505050565b60ff81166001901b825f015f600884901c81526020019081526020015f205f82825417925050819055505050565b60055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661317957600f5461313783610e0c565b1115613178576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161316f90615499565b60405180910390fd5b5b61318584848484613d11565b50505050565b6131aa8473ffffffffffffffffffffffffffffffffffffffff16613d17565b15613347578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016131f0959493929190615509565b6020604051808303815f875af192505050801561322b57506040513d601f19601f820116820180604052508101906132289190615583565b60015b6132c7576132376155ba565b806308c379a003613293575061324b6155d9565b806132565750613295565b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161328a9190614273565b60405180910390fd5b505b6040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614613345576040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b505050505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106133ab577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816133a1576133a0614cef565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106133e8576d04ee2d6d415b85acef810000000083816133de576133dd614cef565b5b0492506020810190505b662386f26fc10000831061341757662386f26fc10000838161340d5761340c614cef565b5b0492506010810190505b6305f5e1008310613440576305f5e100838161343657613435614cef565b5b0492506008810190505b612710831061346557612710838161345b5761345a614cef565b5b0492506004810190505b60648310613488576064838161347e5761347d614cef565b5b0492506002810190505b600a8310613497576001810190505b80915050919050565b6060600167ffffffffffffffff8111156134bd576134bc61408e565b5b6040519080825280602002602001820160405280156134eb5781602001602082028036833780820191505090505b50905081815f8151811061350257613501614c81565b5b602002602001018181525050919050565b6135328473ffffffffffffffffffffffffffffffffffffffff16613d17565b156136cf578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401613578959493929190615668565b6020604051808303815f875af19250505080156135b357506040513d601f19601f820116820180604052508101906135b09190615583565b60015b61364f576135bf6155ba565b806308c379a00361361b57506135d36155d9565b806135de575061361d565b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136129190614273565b60405180910390fd5b505b6040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146136cd576040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b505050505050565b6060805f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361373f576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8303613778576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613781611c7f565b90508367ffffffffffffffff81111561379d5761379c61408e565b5b6040519080825280602002602001820160405280156137cb5781602001602082028036833780820191505090505b5092508367ffffffffffffffff8111156137e8576137e761408e565b5b6040519080825280602002602001820160405280156138165781602001602082028036833780820191505090505b5091505f6138226123f7565b905080857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff031015613852575f80fd5b5f5b858110156138ac5780820185828151811061387257613871614c81565b5b602002602001018181525050600184828151811061389357613892614c81565b5b6020026020010181815250508080600101915050613854565b506138b9825f8887612f0a565b61390a818660015f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20613d289092919063ffffffff16565b8460045f82825461391b9190615298565b925050819055508573ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161399892919061517e565b60405180910390a46139ac825f88876130dd565b50509250929050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613a1a576040517fb817eee700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613a23611c7f565b90505f613a2e6123f7565b90505f8367ffffffffffffffff811115613a4b57613a4a61408e565b5b604051908082528060200260200182016040528015613a795781602001602082028036833780820191505090505b5090505f8467ffffffffffffffff811115613a9757613a9661408e565b5b604051908082528060200260200182016040528015613ac55781602001602082028036833780820191505090505b5090505f5b85811015613bc5576001838281518110613ae757613ae6614c81565b5b6020026020010181815250505f613b438560015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20613da590919063ffffffff16565b905080838381518110613b5957613b58614c81565b5b602002602001018181525050613bb48160015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2061308090919063ffffffff16565b809450508080600101915050613aca565b50613bd284875f84612f0a565b60018503613c78575f73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62845f81518110613c5357613c52614c81565b5b60200260200101516001604051613c6b9291906156f9565b60405180910390a4613cf7565b5f73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8486604051613cee92919061517e565b60405180910390a45b613d0384875f846130dd565b505050505050565b50505050565b50505050565b5f80823b90505f8111915050919050565b5f1960ff8316846020528360081c5f5261010183820110613d8b5760405f2082821b815417815560015f510182850160081c5f510160ff8487011695505f93505b808214613d8457815f528460405f2055600182019150613d69565b815f525050505b60405f208284610100031c821b8154178155505050505050565b5f805f801992508360081c9150815f5284602052831960ff1660405f2054811b811c915082158217613df3575b600115613df2578383019250825f5260405f205491508215821715613dd2575b5b505f8114613e1657613e0481613e1e565b600883901b1792508383115f03831792505b505092915050565b5f816fffffffffffffffffffffffffffffffff1060071b821560081b17905081811c67ffffffffffffffff1060061b8117905081811c63ffffffff1060051b8117905081811c61ffff1060041b8117905081811c60ff1060031b811790507f07060605060205040602030205040301060502050303040105050304000000006f8421084210842108cc6318c6db6d54be83831c1c601f161a81179050919050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ef982613ed0565b9050919050565b613f0981613eef565b8114613f13575f80fd5b50565b5f81359050613f2481613f00565b92915050565b5f819050919050565b613f3c81613f2a565b8114613f46575f80fd5b50565b5f81359050613f5781613f33565b92915050565b5f8060408385031215613f7357613f72613ec8565b5b5f613f8085828601613f16565b9250506020613f9185828601613f49565b9150509250929050565b613fa481613f2a565b82525050565b5f602082019050613fbd5f830184613f9b565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ff781613fc3565b8114614001575f80fd5b50565b5f8135905061401281613fee565b92915050565b5f6020828403121561402d5761402c613ec8565b5b5f61403a84828501614004565b91505092915050565b5f8115159050919050565b61405781614043565b82525050565b5f6020820190506140705f83018461404e565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6140c48261407e565b810181811067ffffffffffffffff821117156140e3576140e261408e565b5b80604052505050565b5f6140f5613ebf565b905061410182826140bb565b919050565b5f67ffffffffffffffff8211156141205761411f61408e565b5b6141298261407e565b9050602081019050919050565b828183375f83830152505050565b5f61415661415184614106565b6140ec565b9050828152602081018484840111156141725761417161407a565b5b61417d848285614136565b509392505050565b5f82601f83011261419957614198614076565b5b81356141a9848260208601614144565b91505092915050565b5f602082840312156141c7576141c6613ec8565b5b5f82013567ffffffffffffffff8111156141e4576141e3613ecc565b5b6141f084828501614185565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015614230578082015181840152602081019050614215565b5f8484015250505050565b5f614245826141f9565b61424f8185614203565b935061425f818560208601614213565b6142688161407e565b840191505092915050565b5f6020820190508181035f83015261428b818461423b565b905092915050565b5f602082840312156142a8576142a7613ec8565b5b5f6142b584828501613f49565b91505092915050565b6142c781613eef565b82525050565b5f6020820190506142e05f8301846142be565b92915050565b6142ef81614043565b81146142f9575f80fd5b50565b5f8135905061430a816142e6565b92915050565b5f806040838503121561432657614325613ec8565b5b5f61433385828601613f16565b9250506020614344858286016142fc565b9150509250929050565b5f805f6060848603121561436557614364613ec8565b5b5f61437286828701613f16565b935050602061438386828701613f16565b925050604061439486828701613f49565b9150509250925092565b5f805f606084860312156143b5576143b4613ec8565b5b5f6143c286828701613f16565b93505060206143d386828701613f49565b92505060406143e486828701613f49565b9150509250925092565b5f67ffffffffffffffff8211156144085761440761408e565b5b602082029050602081019050919050565b5f80fd5b5f61442f61442a846143ee565b6140ec565b9050808382526020820190506020840283018581111561445257614451614419565b5b835b8181101561447b57806144678882613f49565b845260208401935050602081019050614454565b5050509392505050565b5f82601f83011261449957614498614076565b5b81356144a984826020860161441d565b91505092915050565b5f67ffffffffffffffff8211156144cc576144cb61408e565b5b6144d58261407e565b9050602081019050919050565b5f6144f46144ef846144b2565b6140ec565b9050828152602081018484840111156145105761450f61407a565b5b61451b848285614136565b509392505050565b5f82601f83011261453757614536614076565b5b81356145478482602086016144e2565b91505092915050565b5f805f805f60a0868803121561456957614568613ec8565b5b5f61457688828901613f16565b955050602061458788828901613f16565b945050604086013567ffffffffffffffff8111156145a8576145a7613ecc565b5b6145b488828901614485565b935050606086013567ffffffffffffffff8111156145d5576145d4613ecc565b5b6145e188828901614485565b925050608086013567ffffffffffffffff81111561460257614601613ecc565b5b61460e88828901614523565b9150509295509295909350565b5f60ff82169050919050565b6146308161461b565b82525050565b5f6020820190506146495f830184614627565b92915050565b5f6020828403121561466457614663613ec8565b5b5f61467184828501613f16565b91505092915050565b5f67ffffffffffffffff8211156146945761469361408e565b5b602082029050602081019050919050565b5f6146b76146b28461467a565b6140ec565b905080838252602082019050602084028301858111156146da576146d9614419565b5b835b8181101561470357806146ef8882613f16565b8452602084019350506020810190506146dc565b5050509392505050565b5f82601f83011261472157614720614076565b5b81356147318482602086016146a5565b91505092915050565b5f80604083850312156147505761474f613ec8565b5b5f83013567ffffffffffffffff81111561476d5761476c613ecc565b5b6147798582860161470d565b925050602083013567ffffffffffffffff81111561479a57614799613ecc565b5b6147a685828601614485565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6147e281613f2a565b82525050565b5f6147f383836147d9565b60208301905092915050565b5f602082019050919050565b5f614815826147b0565b61481f81856147ba565b935061482a836147ca565b805f5b8381101561485a57815161484188826147e8565b975061484c836147ff565b92505060018101905061482d565b5085935050505092915050565b5f6020820190508181035f83015261487f818461480b565b905092915050565b5f806040838503121561489d5761489c613ec8565b5b5f6148aa85828601613f16565b92505060206148bb85828601613f16565b9150509250929050565b5f805f805f60a086880312156148de576148dd613ec8565b5b5f6148eb88828901613f16565b95505060206148fc88828901613f16565b945050604061490d88828901613f49565b935050606061491e88828901613f49565b925050608086013567ffffffffffffffff81111561493f5761493e613ecc565b5b61494b88828901614523565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061499c57607f821691505b6020821081036149af576149ae614958565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302614a117fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826149d6565b614a1b86836149d6565b95508019841693508086168417925050509392505050565b5f819050919050565b5f614a56614a51614a4c84613f2a565b614a33565b613f2a565b9050919050565b5f819050919050565b614a6f83614a3c565b614a83614a7b82614a5d565b8484546149e2565b825550505050565b5f90565b614a97614a8b565b614aa2818484614a66565b505050565b5b81811015614ac557614aba5f82614a8f565b600181019050614aa8565b5050565b601f821115614b0a57614adb816149b5565b614ae4846149c7565b81016020851015614af3578190505b614b07614aff856149c7565b830182614aa7565b50505b505050565b5f82821c905092915050565b5f614b2a5f1984600802614b0f565b1980831691505092915050565b5f614b428383614b1b565b9150826002028217905092915050565b614b5b826141f9565b67ffffffffffffffff811115614b7457614b7361408e565b5b614b7e8254614985565b614b89828285614ac9565b5f60209050601f831160018114614bba575f8415614ba8578287015190505b614bb28582614b37565b865550614c19565b601f198416614bc8866149b5565b5f5b82811015614bef57848901518255600182019150602085019450602081019050614bca565b86831015614c0c5784890151614c08601f891682614b1b565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614c5882613f2a565b9150614c6383613f2a565b9250828203905081811115614c7b57614c7a614c21565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f614cb882613f2a565b9150614cc383613f2a565b9250828202614cd181613f2a565b91508282048414831517614ce857614ce7614c21565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614d2682613f2a565b9150614d3183613f2a565b925082614d4157614d40614cef565b5b828204905092915050565b5f81905092915050565b5f8154614d6281614985565b614d6c8186614d4c565b9450600182165f8114614d865760018114614d9b57614dcd565b60ff1983168652811515820286019350614dcd565b614da4856149b5565b5f5b83811015614dc557815481890152600182019150602081019050614da6565b838801955050505b50505092915050565b5f614de0826141f9565b614dea8185614d4c565b9350614dfa818560208601614213565b80840191505092915050565b5f614e118285614d56565b9150614e1d8284614dd6565b91508190509392505050565b5f819050919050565b614e43614e3e82613f2a565b614e29565b82525050565b5f614e548284614e32565b60208201915081905092915050565b7f7b226e616d65223a202250617261646f78202300000000000000000000000000815250565b5f614e9382614e63565b601382019150614ea38284614dd6565b915081905092915050565b7f222c226465736372697074696f6e223a224120636f6c6c656374696f6e206f665f8201527f2031302c303030204e46547320656e61626c6564206279204552433432352c2060208201527f6120676173206f7074696d697a6564206578706572696d656e74616c20746f6b60408201527f656e207374616e646172642e204561726e207969656c64206f6e20796f75722060608201527f73656d692d66756e6769626c6520746f6b656e73206279207472616e73666f7260808201527f6d696e67206578697374696e6720696c6c6971756964204e46545320696e746f60a08201527f206c6971756964206173736574732e222c2265787465726e616c5f75726c223a60c08201527f2268747470733a2f2f7064782e6275696c64222c22696d616765223a2200000060e082015250565b5f614fec60fd83614d4c565b9150614ff782614eae565b60fd82019050919050565b5f61500d8284614dd6565b915061501882614fe0565b915081905092915050565b5f61502e8285614dd6565b915061503a8284614dd6565b91508190509392505050565b7f222c2261747472696275746573223a5b7b2274726169745f74797065223a22435f8201527f6f6c6f72222c2276616c7565223a220000000000000000000000000000000000602082015250565b5f6150a0602f83614d4c565b91506150ab82615046565b602f82019050919050565b5f6150c082615094565b91506150cc8284614dd6565b915081905092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b757466382c0000000000815250565b5f615107826150d7565b601b820191506151178284614dd6565b915081905092915050565b5f6060820190506151355f8301866142be565b6151426020830185613f9b565b61514f6040830184613f9b565b949350505050565b5f60408201905061516a5f8301856142be565b61517760208301846142be565b9392505050565b5f6040820190508181035f830152615196818561480b565b905081810360208301526151aa818461480b565b90509392505050565b7f455243313135353a2073657474696e6720617070726f76616c207374617475735f8201527f20666f722073656c660000000000000000000000000000000000000000000000602082015250565b5f61520d602983614203565b9150615218826151b3565b604082019050919050565b5f6020820190508181035f83015261523a81615201565b9050919050565b5f6040820190506152545f830185613f9b565b6152616020830184613f9b565b9392505050565b5f61527282613f2a565b915061527d83613f2a565b92508261528d5761528c614cef565b5b828206905092915050565b5f6152a282613f2a565b91506152ad83613f2a565b92508282019050808211156152c5576152c4614c21565b5b92915050565b7f53656e64657220697320626c61636b6c69737465642e000000000000000000005f82015250565b5f6152ff601683614203565b915061530a826152cb565b602082019050919050565b5f6020820190508181035f83015261532c816152f3565b9050919050565b7f526563697069656e7420697320626c61636b6c69737465642e000000000000005f82015250565b5f615367601983614203565b915061537282615333565b602082019050919050565b5f6020820190508181035f8301526153948161535b565b9050919050565b7f5472616e73666572732061726520626c6f636b656420666f72207468652066695f8201527f72737420353020626c6f636b73206166746572206465706c6f796d656e742e00602082015250565b5f6153f5603f83614203565b91506154008261539b565b604082019050919050565b5f6020820190508181035f830152615422816153e9565b9050919050565b7f5472616e73666572206578636565647320616c6c6f77656420686f6c64696e675f8201527f207065722077616c6c6574000000000000000000000000000000000000000000602082015250565b5f615483602b83614203565b915061548e82615429565b604082019050919050565b5f6020820190508181035f8301526154b081615477565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6154db826154b7565b6154e581856154c1565b93506154f5818560208601614213565b6154fe8161407e565b840191505092915050565b5f60a08201905061551c5f8301886142be565b61552960208301876142be565b818103604083015261553b818661480b565b9050818103606083015261554f818561480b565b9050818103608083015261556381846154d1565b90509695505050505050565b5f8151905061557d81613fee565b92915050565b5f6020828403121561559857615597613ec8565b5b5f6155a58482850161556f565b91505092915050565b5f8160e01c9050919050565b5f60033d11156155d65760045f803e6155d35f516155ae565b90505b90565b5f60443d10615665576155ea613ebf565b60043d036004823e80513d602482011167ffffffffffffffff82111715615612575050615665565b808201805167ffffffffffffffff8111156156305750505050615665565b80602083010160043d03850181111561564d575050505050615665565b61565c826020018501866140bb565b82955050505050505b90565b5f60a08201905061567b5f8301886142be565b61568860208301876142be565b6156956040830186613f9b565b6156a26060830185613f9b565b81810360808301526156b481846154d1565b90509695505050505050565b5f819050919050565b5f6156e36156de6156d9846156c0565b614a33565b613f2a565b9050919050565b6156f3816156c9565b82525050565b5f60408201905061570c5f830185613f9b565b61571960208301846156ea565b939250505056fea2646970667358221220a97ff514bb66e2d3032e04848a0e3b2f317a8dc8bac93d607eb19479c0da03a264736f6c6343000818003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000750617261646f780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035044580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f70617261646f783432352f7064782f6d61696e2f50415241444f582f0000
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061022f575f3560e01c80638462151c1161012e578063c87b56dd116100b6578063e985e9c51161007a578063e985e9c51461071f578063f242432a1461074f578063f28ca1dd1461076b578063f2fde38b14610789578063f8b45b05146107a55761022f565b8063c87b56dd14610655578063d547cfb714610685578063d9adc191146106a3578063dd62ed3e146106d3578063e0df5b6f146107035761022f565b806399a2557a116100fd57806399a2557a1461058d578063a22cb465146105bd578063a9059cbb146105d9578063adcfa01114610609578063c5b8f772146106255761022f565b80638462151c146105035780638da5cb5b1461053357806395d89b4114610551578063976a84351461056f5761022f565b806318d217c3116101bc578063377880ea11610180578063377880ea1461044d5780634e1273f41461047d5780635d0044ca146104ad57806370a08231146104c9578063715018a6146104f95761022f565b806318d217c31461039757806323b872dd146103b35780632d760d57146103e35780632eb2c2d614610413578063313ce5671461042f5761022f565b8063081812fc11610203578063081812fc146102cd578063095ea7b3146102fd5780630e89341c1461032d578063153b0d1e1461035d57806318160ddd146103795761022f565b8062fdd58e1461023357806301ffc9a71461026357806302fe53051461029357806306fdde03146102af575b5f80fd5b61024d60048036038101906102489190613f5d565b6107c3565b60405161025a9190613faa565b60405180910390f35b61027d60048036038101906102789190614018565b610890565b60405161028a919061405d565b60405180910390f35b6102ad60048036038101906102a891906141b2565b6109d9565b005b6102b76109ed565b6040516102c49190614273565b60405180910390f35b6102e760048036038101906102e29190614293565b610a7d565b6040516102f491906142cd565b60405180910390f35b61031760048036038101906103129190613f5d565b610aad565b604051610324919061405d565b60405180910390f35b61034760048036038101906103429190614293565b610acf565b6040516103549190614273565b60405180910390f35b61037760048036038101906103729190614310565b610ae1565b005b610381610b41565b60405161038e9190613faa565b60405180910390f35b6103b160048036038101906103ac91906141b2565b610b4a565b005b6103cd60048036038101906103c8919061434e565b610b65565b6040516103da919061405d565b60405180910390f35b6103fd60048036038101906103f8919061439e565b610b95565b60405161040a9190613faa565b60405180910390f35b61042d60048036038101906104289190614550565b610bfb565b005b610437610c93565b6040516104449190614636565b60405180910390f35b6104676004803603810190610462919061464f565b610cb7565b604051610474919061405d565b60405180910390f35b6104976004803603810190610492919061473a565b610cd4565b6040516104a49190614867565b60405180910390f35b6104c760048036038101906104c29190614293565b610ddc565b005b6104e360048036038101906104de919061464f565b610e0c565b6040516104f09190613faa565b60405180910390f35b610501610e52565b005b61051d6004803603810190610518919061464f565b610e65565b60405161052a9190614867565b60405180910390f35b61053b610ee6565b60405161054891906142cd565b60405180910390f35b610559610f0d565b6040516105669190614273565b60405180910390f35b610577610f9d565b6040516105849190613faa565b60405180910390f35b6105a760048036038101906105a2919061439e565b610fc1565b6040516105b49190614867565b60405180910390f35b6105d760048036038101906105d29190614310565b611142565b005b6105f360048036038101906105ee9190613f5d565b611158565b604051610600919061405d565b60405180910390f35b610623600480360381019061061e9190614310565b61117c565b005b61063f600480360381019061063a9190613f5d565b611249565b60405161064c919061405d565b60405180910390f35b61066f600480360381019061066a9190614293565b6112a1565b60405161067c9190614273565b60405180910390f35b61068d611734565b60405161069a9190614273565b60405180910390f35b6106bd60048036038101906106b8919061464f565b6117c0565b6040516106ca9190613faa565b60405180910390f35b6106ed60048036038101906106e89190614887565b6117e1565b6040516106fa9190613faa565b60405180910390f35b61071d600480360381019061071891906141b2565b611863565b005b61073960048036038101906107349190614887565b61187e565b604051610746919061405d565b60405180910390f35b610769600480360381019061076491906148c5565b61190c565b005b610773611a38565b6040516107809190614273565b60405180910390f35b6107a3600480360381019061079e919061464f565b611ac4565b005b6107ad611b48565b6040516107ba9190613faa565b60405180910390f35b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610829576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108788260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b15610886576001905061088a565b5f90505b92915050565b5f7fd9b67a26000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061095a57507f0e89341c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806109c257507fe4d82d0f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806109d257506109d182611b7c565b5b9050919050565b6109e1611be5565b6109ea81611c6c565b50565b6060600a80546109fc90614985565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2890614985565b8015610a735780601f10610a4a57610100808354040283529160200191610a73565b820191905f5260205f20905b815481529060010190602001808311610a5657829003601f168201915b5050505050905090565b6006602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f80610ab7611c7f565b9050610ac4818585611c86565b600191505092915050565b6060610ada826112a1565b9050919050565b610ae9611be5565b80600e5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505050565b5f600954905090565b610b52611be5565b80600c9081610b619190614b52565b5050565b5f80610b6f611c7f565b9050610b7c858285611c98565b610b898585856001611d2a565b60019150509392505050565b5f610bf2838484610ba69190614c4e565b60015f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611e8e9092919063ffffffff16565b90509392505050565b610c03611c7f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480610c495750610c4885610c43611c7f565b61187e565b5b610c7f576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c8585858585611f4c565b5050505050565b7f000000000000000000000000000000000000000000000000000000000000001281565b6005602052805f5260405f205f915054906101000a900460ff1681565b60608151835114610d11576040517f7801f4e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f835167ffffffffffffffff811115610d2d57610d2c61408e565b5b604051908082528060200260200182016040528015610d5b5781602001602082028036833780820191505090505b5090505f5b8451811015610dd157610da7858281518110610d7f57610d7e614c81565b5b6020026020010151858381518110610d9a57610d99614c81565b5b60200260200101516107c3565b828281518110610dba57610db9614c81565b5b602002602001018181525050806001019050610d60565b508091505092915050565b610de4611be5565b606481610def610b41565b610df99190614cae565b610e039190614d1c565b600f8190555050565b5f60075f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b610e5a611be5565b610e635f61230e565b565b60605f610e706123cf565b03610ec5575f67ffffffffffffffff811115610e8f57610e8e61408e565b5b604051908082528060200260200182016040528015610ebd5781602001602082028036833780820191505090505b509050610ee1565b610ede82610ed16123ef565b610ed96123f7565b610fc1565b90505b919050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6060600b8054610f1c90614985565b80601f0160208091040260200160405190810160405280929190818152602001828054610f4890614985565b8015610f935780601f10610f6a57610100808354040283529160200191610f93565b820191905f5260205f20905b815481529060010190602001808311610f7657829003601f168201915b5050505050905090565b7f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b6060818310610ffc576040517f32c1995a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110046123ef565b831015611016576110136123ef565b92505b5f61101f6123f7565b90508083111561102d578092505b5f8385101561104857611041868686610b95565b905061104c565b5f90505b5f8167ffffffffffffffff8111156110675761106661408e565b5b6040519080825280602002602001820160405280156110955781602001602082028036833780820191505090505b5090505f60015f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f80885f915091505b848114611132576110fb8284611b4e90919063ffffffff16565b15611127578184828060010193508151811061111a57611119614c81565b5b6020026020010181815250505b8160010191506110e1565b5050819450505050509392505050565b61115461114d611c7f565b8383612400565b5050565b5f80611162611c7f565b90506111718185856001611d2a565b600191505092915050565b611184611be5565b7f0000000000000000000000000000000000000000000000000de0b6b3a76400006111ae83610e0c565b101580156111ba575080155b156111f1576040517ff543eef600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505050565b5f6112998260015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b905092915050565b60606112ab6123f7565b82106112e3576040517f5f6f1f0b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600d80546112f190614985565b9050111561132b57600d61130483612567565b604051602001611315929190614e06565b604051602081830303815290604052905061172f565b5f8260405160200161133d9190614e49565b6040516020818303038152906040528051906020012060f81c905060608060648360ff16116113db576040518060400160405280600581526020017f312e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600481526020017f426c75650000000000000000000000000000000000000000000000000000000081525090506115db565b60a08360ff161161145b576040518060400160405280600581526020017f322e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600381526020017f526564000000000000000000000000000000000000000000000000000000000081525090506115da565b60d28360ff16116114db576040518060400160405280600581526020017f332e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600481526020017f477265790000000000000000000000000000000000000000000000000000000081525090506115d9565b60f08360ff161161155b576040518060400160405280600581526020017f342e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600581526020017f477265656e00000000000000000000000000000000000000000000000000000081525090506115d8565b60ff8360ff16116115d7576040518060400160405280600581526020017f352e67696600000000000000000000000000000000000000000000000000000081525091506040518060400160405280600581526020017f426c61636b00000000000000000000000000000000000000000000000000000081525090505b5b5b5b5b5f6115e586612567565b6040516020016115f59190614e89565b6040516020818303038152906040526040516020016116149190615002565b604051602081830303815290604052600c84604051602001611637929190614e06565b604051602081830303815290604052604051602001611657929190615023565b60405160208183030381529060405290505f8260405160200161167a91906150b6565b60405160208183030381529060405290505f6040518060400160405280600481526020017f227d5d7d00000000000000000000000000000000000000000000000000000000815250905082826040516020016116d7929190615023565b604051602081830303815290604052816040516020016116f8929190615023565b60405160208183030381529060405260405160200161171791906150fd565b60405160208183030381529060405296505050505050505b919050565b600d805461174190614985565b80601f016020809104026020016040519081016040528092919081815260200182805461176d90614985565b80156117b85780601f1061178f576101008083540402835291602001916117b8565b820191905f5260205f20905b81548152906001019060200180831161179b57829003601f168201915b505050505081565b5f6117da826117cd6123ef565b6117d56123f7565b610b95565b9050919050565b5f60085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b61186b611be5565b80600d908161187a9190614b52565b5050565b5f60025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff161561199857836040517fbe0c433b00000000000000000000000000000000000000000000000000000000815260040161198f91906142cd565b60405180910390fd5b6119a0611c7f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614806119e657506119e5856119e0611c7f565b61187e565b5b156119ff576119fa85858585856001612631565b611a31565b6040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b600c8054611a4590614985565b80601f0160208091040260200160405190810160405280929190818152602001828054611a7190614985565b8015611abc5780601f10611a9357610100808354040283529160200191611abc565b820191905f5260205f20905b815481529060010190602001808311611a9f57829003601f168201915b505050505081565b611acc611be5565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611b3c575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611b3391906142cd565b60405180910390fd5b611b458161230e565b50565b600f5481565b5f80600160ff8416855f015f600887901c81526020019081526020015f2054901c1690508091505092915050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b611bed611c7f565b73ffffffffffffffffffffffffffffffffffffffff16611c0b610ee6565b73ffffffffffffffffffffffffffffffffffffffff1614611c6a57611c2e611c7f565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611c6191906142cd565b60405180910390fd5b565b8060039081611c7b9190614b52565b5050565b5f33905090565b611c9383838360016128cf565b505050565b5f611ca384846117e1565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611d245781811015611d15578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611d0c93929190615122565b60405180910390fd5b611d2384848484035f6128cf565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611d9a575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611d9191906142cd565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611e0a575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611e0191906142cd565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611e7c5783836040517f2fd6adab000000000000000000000000000000000000000000000000000000008152600401611e73929190615157565b60405180910390fd5b611e8884848484612a9e565b50505050565b5f80600884901c90505f60ff8516905061010181850110611f1a57611ec781875f015f8581526020019081526020015f2054901c612ec1565b92505f6008828601901c8301905060ff8286011694505f91508260010192505b808314611f1857611f09875f015f8581526020019081526020015f2054612ec1565b84019350826001019250611ee7565b505b611f3f846101000382885f015f8681526020019081526020015f2054901c901b612ec1565b8301925050509392505050565b8151835114611f87576040517f7801f4e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611fec576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611ff5611c7f565b905061200381878787612f0a565b5f5b845181101561218c575f85828151811061202257612021614c81565b5b602002602001015190505f8583815181106120405761203f614c81565b5b602002602001015190506001811480156120a557506120a48260015f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b5b1561214d576120f98260015f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2061308090919063ffffffff16565b6121488260015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206130af90919063ffffffff16565b61217f565b6040517f37dbad3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050806001019050612005565b506121d1868686517f0000000000000000000000000000000000000000000000000de0b6b3a764000060016121c19190614cae565b6121cb9190614cae565b5f611d2a565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86517f0000000000000000000000000000000000000000000000000de0b6b3a7640000600161224f9190614cae565b6122599190614cae565b6040516122669190613faa565b60405180910390a38473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516122e492919061517e565b60405180910390a46122f8818787876130dd565b61230681878787878761318b565b505050505050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6123d86123ef565b6123e06123f7565b6123ea9190614c4e565b905090565b5f6001905090565b5f600454905090565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361246e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246590615223565b60405180910390fd5b8060025f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161255a919061405d565b60405180910390a3505050565b60605f60016125758461334f565b0190505f8167ffffffffffffffff8111156125935761259261408e565b5b6040519080825280601f01601f1916602001820160405280156125c55781602001600182028036833780820191505090505b5090505f82602001820190505b600115612626578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161261b5761261a614cef565b5b0494505f85036125d2575b819350505050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612696576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61269f611c7f565b90505f6126ab866134a0565b90506126b982898984612f0a565b60018514801561271457506127138660015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20611b4e90919063ffffffff16565b5b156127f4576127688660015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2061308090919063ffffffff16565b6127b78660015f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206130af90919063ffffffff16565b6127ef88887f0000000000000000000000000000000000000000000000000de0b6b3a764000060016127e99190614cae565b5f611d2a565b612826565b6040517f37dbad3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62898960405161289c929190615241565b60405180910390a46128b0828989846130dd565b82156128c5576128c4828989898989613513565b5b5050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361293f575f6040517fe602df0500000000000000000000000000000000000000000000000000000000815260040161293691906142cd565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129af575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016129a691906142cd565b60405180910390fd5b8160085f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612a98578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051612a8f9190613faa565b60405180910390a35b50505050565b5f60075f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60075f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905083821015612b69578582856040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401612b6093929190615122565b60405180910390fd5b83820360075f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508360075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef86604051612c549190613faa565b60405180910390a38215612eb9575f60055f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f60055f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1690505f7f0000000000000000000000000000000000000000000000000de0b6b3a764000087612d299190614d1c565b9050828015612d355750815b612eb5578215612d59575f811115612d5457612d5188826136d7565b50505b612eb4565b8115612d77575f811115612d7257612d7189826139b5565b5b612eb3565b5f811115612d9657612d8989826139b5565b612d9388826136d7565b50505b5f7f0000000000000000000000000000000000000000000000000de0b6b3a764000088612dc39190615268565b90507f0000000000000000000000000000000000000000000000000de0b6b3a764000086612df19190614d1c565b7f0000000000000000000000000000000000000000000000000de0b6b3a76400008288612e1e9190614c4e565b612e289190614d1c565b1015612e3a57612e398a60016139b5565b5b7f0000000000000000000000000000000000000000000000000de0b6b3a764000085612e669190614d1c565b7f0000000000000000000000000000000000000000000000000de0b6b3a76400008287612e939190615298565b612e9d9190614d1c565b1115612eb157612eae8960016136d7565b50505b505b5b5b5050505b505050505050565b5f8019808314600382048460011c1684039350600582048460021c16600583048516019350601182048460041c850116935060ff8204840260f81c8160081b1792505050919050565b600e5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1615612f94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f8b90615315565b60405180910390fd5b600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff161561301e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130159061537d565b60405180910390fd5b603260105461302d9190615298565b431161306e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130659061540b565b60405180910390fd5b61307a84848484613d0b565b50505050565b60ff81166001901b19825f015f600884901c81526020019081526020015f205f82825416925050819055505050565b60ff81166001901b825f015f600884901c81526020019081526020015f205f82825417925050819055505050565b60055f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661317957600f5461313783610e0c565b1115613178576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161316f90615499565b60405180910390fd5b5b61318584848484613d11565b50505050565b6131aa8473ffffffffffffffffffffffffffffffffffffffff16613d17565b15613347578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016131f0959493929190615509565b6020604051808303815f875af192505050801561322b57506040513d601f19601f820116820180604052508101906132289190615583565b60015b6132c7576132376155ba565b806308c379a003613293575061324b6155d9565b806132565750613295565b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161328a9190614273565b60405180910390fd5b505b6040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614613345576040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b505050505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106133ab577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816133a1576133a0614cef565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106133e8576d04ee2d6d415b85acef810000000083816133de576133dd614cef565b5b0492506020810190505b662386f26fc10000831061341757662386f26fc10000838161340d5761340c614cef565b5b0492506010810190505b6305f5e1008310613440576305f5e100838161343657613435614cef565b5b0492506008810190505b612710831061346557612710838161345b5761345a614cef565b5b0492506004810190505b60648310613488576064838161347e5761347d614cef565b5b0492506002810190505b600a8310613497576001810190505b80915050919050565b6060600167ffffffffffffffff8111156134bd576134bc61408e565b5b6040519080825280602002602001820160405280156134eb5781602001602082028036833780820191505090505b50905081815f8151811061350257613501614c81565b5b602002602001018181525050919050565b6135328473ffffffffffffffffffffffffffffffffffffffff16613d17565b156136cf578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b8152600401613578959493929190615668565b6020604051808303815f875af19250505080156135b357506040513d601f19601f820116820180604052508101906135b09190615583565b60015b61364f576135bf6155ba565b806308c379a00361361b57506135d36155d9565b806135de575061361d565b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136129190614273565b60405180910390fd5b505b6040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146136cd576040517f9c05499b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b505050505050565b6060805f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361373f576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8303613778576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613781611c7f565b90508367ffffffffffffffff81111561379d5761379c61408e565b5b6040519080825280602002602001820160405280156137cb5781602001602082028036833780820191505090505b5092508367ffffffffffffffff8111156137e8576137e761408e565b5b6040519080825280602002602001820160405280156138165781602001602082028036833780820191505090505b5091505f6138226123f7565b905080857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff031015613852575f80fd5b5f5b858110156138ac5780820185828151811061387257613871614c81565b5b602002602001018181525050600184828151811061389357613892614c81565b5b6020026020010181815250508080600101915050613854565b506138b9825f8887612f0a565b61390a818660015f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20613d289092919063ffffffff16565b8460045f82825461391b9190615298565b925050819055508573ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161399892919061517e565b60405180910390a46139ac825f88876130dd565b50509250929050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603613a1a576040517fb817eee700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613a23611c7f565b90505f613a2e6123f7565b90505f8367ffffffffffffffff811115613a4b57613a4a61408e565b5b604051908082528060200260200182016040528015613a795781602001602082028036833780820191505090505b5090505f8467ffffffffffffffff811115613a9757613a9661408e565b5b604051908082528060200260200182016040528015613ac55781602001602082028036833780820191505090505b5090505f5b85811015613bc5576001838281518110613ae757613ae6614c81565b5b6020026020010181815250505f613b438560015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20613da590919063ffffffff16565b905080838381518110613b5957613b58614c81565b5b602002602001018181525050613bb48160015f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2061308090919063ffffffff16565b809450508080600101915050613aca565b50613bd284875f84612f0a565b60018503613c78575f73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62845f81518110613c5357613c52614c81565b5b60200260200101516001604051613c6b9291906156f9565b60405180910390a4613cf7565b5f73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8486604051613cee92919061517e565b60405180910390a45b613d0384875f846130dd565b505050505050565b50505050565b50505050565b5f80823b90505f8111915050919050565b5f1960ff8316846020528360081c5f5261010183820110613d8b5760405f2082821b815417815560015f510182850160081c5f510160ff8487011695505f93505b808214613d8457815f528460405f2055600182019150613d69565b815f525050505b60405f208284610100031c821b8154178155505050505050565b5f805f801992508360081c9150815f5284602052831960ff1660405f2054811b811c915082158217613df3575b600115613df2578383019250825f5260405f205491508215821715613dd2575b5b505f8114613e1657613e0481613e1e565b600883901b1792508383115f03831792505b505092915050565b5f816fffffffffffffffffffffffffffffffff1060071b821560081b17905081811c67ffffffffffffffff1060061b8117905081811c63ffffffff1060051b8117905081811c61ffff1060041b8117905081811c60ff1060031b811790507f07060605060205040602030205040301060502050303040105050304000000006f8421084210842108cc6318c6db6d54be83831c1c601f161a81179050919050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613ef982613ed0565b9050919050565b613f0981613eef565b8114613f13575f80fd5b50565b5f81359050613f2481613f00565b92915050565b5f819050919050565b613f3c81613f2a565b8114613f46575f80fd5b50565b5f81359050613f5781613f33565b92915050565b5f8060408385031215613f7357613f72613ec8565b5b5f613f8085828601613f16565b9250506020613f9185828601613f49565b9150509250929050565b613fa481613f2a565b82525050565b5f602082019050613fbd5f830184613f9b565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613ff781613fc3565b8114614001575f80fd5b50565b5f8135905061401281613fee565b92915050565b5f6020828403121561402d5761402c613ec8565b5b5f61403a84828501614004565b91505092915050565b5f8115159050919050565b61405781614043565b82525050565b5f6020820190506140705f83018461404e565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6140c48261407e565b810181811067ffffffffffffffff821117156140e3576140e261408e565b5b80604052505050565b5f6140f5613ebf565b905061410182826140bb565b919050565b5f67ffffffffffffffff8211156141205761411f61408e565b5b6141298261407e565b9050602081019050919050565b828183375f83830152505050565b5f61415661415184614106565b6140ec565b9050828152602081018484840111156141725761417161407a565b5b61417d848285614136565b509392505050565b5f82601f83011261419957614198614076565b5b81356141a9848260208601614144565b91505092915050565b5f602082840312156141c7576141c6613ec8565b5b5f82013567ffffffffffffffff8111156141e4576141e3613ecc565b5b6141f084828501614185565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015614230578082015181840152602081019050614215565b5f8484015250505050565b5f614245826141f9565b61424f8185614203565b935061425f818560208601614213565b6142688161407e565b840191505092915050565b5f6020820190508181035f83015261428b818461423b565b905092915050565b5f602082840312156142a8576142a7613ec8565b5b5f6142b584828501613f49565b91505092915050565b6142c781613eef565b82525050565b5f6020820190506142e05f8301846142be565b92915050565b6142ef81614043565b81146142f9575f80fd5b50565b5f8135905061430a816142e6565b92915050565b5f806040838503121561432657614325613ec8565b5b5f61433385828601613f16565b9250506020614344858286016142fc565b9150509250929050565b5f805f6060848603121561436557614364613ec8565b5b5f61437286828701613f16565b935050602061438386828701613f16565b925050604061439486828701613f49565b9150509250925092565b5f805f606084860312156143b5576143b4613ec8565b5b5f6143c286828701613f16565b93505060206143d386828701613f49565b92505060406143e486828701613f49565b9150509250925092565b5f67ffffffffffffffff8211156144085761440761408e565b5b602082029050602081019050919050565b5f80fd5b5f61442f61442a846143ee565b6140ec565b9050808382526020820190506020840283018581111561445257614451614419565b5b835b8181101561447b57806144678882613f49565b845260208401935050602081019050614454565b5050509392505050565b5f82601f83011261449957614498614076565b5b81356144a984826020860161441d565b91505092915050565b5f67ffffffffffffffff8211156144cc576144cb61408e565b5b6144d58261407e565b9050602081019050919050565b5f6144f46144ef846144b2565b6140ec565b9050828152602081018484840111156145105761450f61407a565b5b61451b848285614136565b509392505050565b5f82601f83011261453757614536614076565b5b81356145478482602086016144e2565b91505092915050565b5f805f805f60a0868803121561456957614568613ec8565b5b5f61457688828901613f16565b955050602061458788828901613f16565b945050604086013567ffffffffffffffff8111156145a8576145a7613ecc565b5b6145b488828901614485565b935050606086013567ffffffffffffffff8111156145d5576145d4613ecc565b5b6145e188828901614485565b925050608086013567ffffffffffffffff81111561460257614601613ecc565b5b61460e88828901614523565b9150509295509295909350565b5f60ff82169050919050565b6146308161461b565b82525050565b5f6020820190506146495f830184614627565b92915050565b5f6020828403121561466457614663613ec8565b5b5f61467184828501613f16565b91505092915050565b5f67ffffffffffffffff8211156146945761469361408e565b5b602082029050602081019050919050565b5f6146b76146b28461467a565b6140ec565b905080838252602082019050602084028301858111156146da576146d9614419565b5b835b8181101561470357806146ef8882613f16565b8452602084019350506020810190506146dc565b5050509392505050565b5f82601f83011261472157614720614076565b5b81356147318482602086016146a5565b91505092915050565b5f80604083850312156147505761474f613ec8565b5b5f83013567ffffffffffffffff81111561476d5761476c613ecc565b5b6147798582860161470d565b925050602083013567ffffffffffffffff81111561479a57614799613ecc565b5b6147a685828601614485565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6147e281613f2a565b82525050565b5f6147f383836147d9565b60208301905092915050565b5f602082019050919050565b5f614815826147b0565b61481f81856147ba565b935061482a836147ca565b805f5b8381101561485a57815161484188826147e8565b975061484c836147ff565b92505060018101905061482d565b5085935050505092915050565b5f6020820190508181035f83015261487f818461480b565b905092915050565b5f806040838503121561489d5761489c613ec8565b5b5f6148aa85828601613f16565b92505060206148bb85828601613f16565b9150509250929050565b5f805f805f60a086880312156148de576148dd613ec8565b5b5f6148eb88828901613f16565b95505060206148fc88828901613f16565b945050604061490d88828901613f49565b935050606061491e88828901613f49565b925050608086013567ffffffffffffffff81111561493f5761493e613ecc565b5b61494b88828901614523565b9150509295509295909350565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061499c57607f821691505b6020821081036149af576149ae614958565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302614a117fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826149d6565b614a1b86836149d6565b95508019841693508086168417925050509392505050565b5f819050919050565b5f614a56614a51614a4c84613f2a565b614a33565b613f2a565b9050919050565b5f819050919050565b614a6f83614a3c565b614a83614a7b82614a5d565b8484546149e2565b825550505050565b5f90565b614a97614a8b565b614aa2818484614a66565b505050565b5b81811015614ac557614aba5f82614a8f565b600181019050614aa8565b5050565b601f821115614b0a57614adb816149b5565b614ae4846149c7565b81016020851015614af3578190505b614b07614aff856149c7565b830182614aa7565b50505b505050565b5f82821c905092915050565b5f614b2a5f1984600802614b0f565b1980831691505092915050565b5f614b428383614b1b565b9150826002028217905092915050565b614b5b826141f9565b67ffffffffffffffff811115614b7457614b7361408e565b5b614b7e8254614985565b614b89828285614ac9565b5f60209050601f831160018114614bba575f8415614ba8578287015190505b614bb28582614b37565b865550614c19565b601f198416614bc8866149b5565b5f5b82811015614bef57848901518255600182019150602085019450602081019050614bca565b86831015614c0c5784890151614c08601f891682614b1b565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614c5882613f2a565b9150614c6383613f2a565b9250828203905081811115614c7b57614c7a614c21565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f614cb882613f2a565b9150614cc383613f2a565b9250828202614cd181613f2a565b91508282048414831517614ce857614ce7614c21565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614d2682613f2a565b9150614d3183613f2a565b925082614d4157614d40614cef565b5b828204905092915050565b5f81905092915050565b5f8154614d6281614985565b614d6c8186614d4c565b9450600182165f8114614d865760018114614d9b57614dcd565b60ff1983168652811515820286019350614dcd565b614da4856149b5565b5f5b83811015614dc557815481890152600182019150602081019050614da6565b838801955050505b50505092915050565b5f614de0826141f9565b614dea8185614d4c565b9350614dfa818560208601614213565b80840191505092915050565b5f614e118285614d56565b9150614e1d8284614dd6565b91508190509392505050565b5f819050919050565b614e43614e3e82613f2a565b614e29565b82525050565b5f614e548284614e32565b60208201915081905092915050565b7f7b226e616d65223a202250617261646f78202300000000000000000000000000815250565b5f614e9382614e63565b601382019150614ea38284614dd6565b915081905092915050565b7f222c226465736372697074696f6e223a224120636f6c6c656374696f6e206f665f8201527f2031302c303030204e46547320656e61626c6564206279204552433432352c2060208201527f6120676173206f7074696d697a6564206578706572696d656e74616c20746f6b60408201527f656e207374616e646172642e204561726e207969656c64206f6e20796f75722060608201527f73656d692d66756e6769626c6520746f6b656e73206279207472616e73666f7260808201527f6d696e67206578697374696e6720696c6c6971756964204e46545320696e746f60a08201527f206c6971756964206173736574732e222c2265787465726e616c5f75726c223a60c08201527f2268747470733a2f2f7064782e6275696c64222c22696d616765223a2200000060e082015250565b5f614fec60fd83614d4c565b9150614ff782614eae565b60fd82019050919050565b5f61500d8284614dd6565b915061501882614fe0565b915081905092915050565b5f61502e8285614dd6565b915061503a8284614dd6565b91508190509392505050565b7f222c2261747472696275746573223a5b7b2274726169745f74797065223a22435f8201527f6f6c6f72222c2276616c7565223a220000000000000000000000000000000000602082015250565b5f6150a0602f83614d4c565b91506150ab82615046565b602f82019050919050565b5f6150c082615094565b91506150cc8284614dd6565b915081905092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b757466382c0000000000815250565b5f615107826150d7565b601b820191506151178284614dd6565b915081905092915050565b5f6060820190506151355f8301866142be565b6151426020830185613f9b565b61514f6040830184613f9b565b949350505050565b5f60408201905061516a5f8301856142be565b61517760208301846142be565b9392505050565b5f6040820190508181035f830152615196818561480b565b905081810360208301526151aa818461480b565b90509392505050565b7f455243313135353a2073657474696e6720617070726f76616c207374617475735f8201527f20666f722073656c660000000000000000000000000000000000000000000000602082015250565b5f61520d602983614203565b9150615218826151b3565b604082019050919050565b5f6020820190508181035f83015261523a81615201565b9050919050565b5f6040820190506152545f830185613f9b565b6152616020830184613f9b565b9392505050565b5f61527282613f2a565b915061527d83613f2a565b92508261528d5761528c614cef565b5b828206905092915050565b5f6152a282613f2a565b91506152ad83613f2a565b92508282019050808211156152c5576152c4614c21565b5b92915050565b7f53656e64657220697320626c61636b6c69737465642e000000000000000000005f82015250565b5f6152ff601683614203565b915061530a826152cb565b602082019050919050565b5f6020820190508181035f83015261532c816152f3565b9050919050565b7f526563697069656e7420697320626c61636b6c69737465642e000000000000005f82015250565b5f615367601983614203565b915061537282615333565b602082019050919050565b5f6020820190508181035f8301526153948161535b565b9050919050565b7f5472616e73666572732061726520626c6f636b656420666f72207468652066695f8201527f72737420353020626c6f636b73206166746572206465706c6f796d656e742e00602082015250565b5f6153f5603f83614203565b91506154008261539b565b604082019050919050565b5f6020820190508181035f830152615422816153e9565b9050919050565b7f5472616e73666572206578636565647320616c6c6f77656420686f6c64696e675f8201527f207065722077616c6c6574000000000000000000000000000000000000000000602082015250565b5f615483602b83614203565b915061548e82615429565b604082019050919050565b5f6020820190508181035f8301526154b081615477565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f6154db826154b7565b6154e581856154c1565b93506154f5818560208601614213565b6154fe8161407e565b840191505092915050565b5f60a08201905061551c5f8301886142be565b61552960208301876142be565b818103604083015261553b818661480b565b9050818103606083015261554f818561480b565b9050818103608083015261556381846154d1565b90509695505050505050565b5f8151905061557d81613fee565b92915050565b5f6020828403121561559857615597613ec8565b5b5f6155a58482850161556f565b91505092915050565b5f8160e01c9050919050565b5f60033d11156155d65760045f803e6155d35f516155ae565b90505b90565b5f60443d10615665576155ea613ebf565b60043d036004823e80513d602482011167ffffffffffffffff82111715615612575050615665565b808201805167ffffffffffffffff8111156156305750505050615665565b80602083010160043d03850181111561564d575050505050615665565b61565c826020018501866140bb565b82955050505050505b90565b5f60a08201905061567b5f8301886142be565b61568860208301876142be565b6156956040830186613f9b565b6156a26060830185613f9b565b81810360808301526156b481846154d1565b90509695505050505050565b5f819050919050565b5f6156e36156de6156d9846156c0565b614a33565b613f2a565b9050919050565b6156f3816156c9565b82525050565b5f60408201905061570c5f830185613f9b565b61571960208301846156ea565b939250505056fea2646970667358221220a97ff514bb66e2d3032e04848a0e3b2f317a8dc8bac93d607eb19479c0da03a264736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000750617261646f780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035044580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f70617261646f783432352f7064782f6d61696e2f50415241444f582f0000
-----Decoded View---------------
Arg [0] : name_ (string): Paradox
Arg [1] : symbol_ (string): PDX
Arg [2] : decimals_ (uint8): 18
Arg [3] : _erc20TokensSupply (uint256): 10000
Arg [4] : uri_ (string): https://raw.githubusercontent.com/paradox425/pdx/main/PARADOX/
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [3] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [6] : 50617261646f7800000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [8] : 5044580000000000000000000000000000000000000000000000000000000000
Arg [9] : 000000000000000000000000000000000000000000000000000000000000003e
Arg [10] : 68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f
Arg [11] : 6d2f70617261646f783432352f7064782f6d61696e2f50415241444f582f0000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.