Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Batch Airdrop | 3637506 | 47 hrs ago | IN | 0 ETH | 0.00000764 |
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
3634475 | 2 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
Bitemares
Compiler Version
v0.8.24+commit.e11b9ed9
ZkSolc Version
v1.5.11
Optimization Enabled:
Yes with Mode 3
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; import {ERC721Pausable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {Ownable} from "solady/src/auth/Ownable.sol"; import {LibString} from "solady/src/utils/LibString.sol"; import {MerkleProofLib} from "solady/src/utils/MerkleProofLib.sol"; import {ReentrancyGuard} from "solady/src/utils/ReentrancyGuard.sol"; import { ERC721AQueryable, IERC721AQueryable, ERC721A, IERC721A } from "erc721a/contracts/extensions/ERC721AQueryable.sol"; import {ERC2981} from "solady/src/tokens/ERC2981.sol"; import {ERC721ABurnable} from "erc721a/contracts/extensions/ERC721ABurnable.sol"; contract Bitemares is Ownable,ERC721AQueryable,ERC721ABurnable, ReentrancyGuard, ERC2981 { using LibString for uint256; using Math for uint256; /// @notice Max supply for the collection uint256 public maxSupply; /// @notice BaseURI for metadata string public baseURI; /// @notice metadata url suffix string public _baseTokenSuffix; /// @notice WL merkle bytes32 public wlMerkleRoot; /// @notice WL mint price uint256 public wlPrice; /// @notice Public mint price uint256 public publicPrice; /// @notice Mint start timestamp bool public mintLive; /// @notice nft metadata revealed bool public isRevealed; event MetadataUpdate(uint256 _tokenId); event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); modifier withinThreshold(uint256 _amount) { require(totalSupply() + _amount < maxSupply, "!supply"); _; } modifier isWhitelisted(bytes32 _merkleRoot, bytes32[] calldata _proof) { bytes32 leaf = keccak256(abi.encodePacked(msg.sender)); require( MerkleProofLib.verify(_proof, _merkleRoot, leaf), "!whitelisted" ); _; } constructor( string memory _uri, address _royaltiesReceiver, bytes32 _wlMerkleRoot ) ERC721A("Bitemares", "BITE") ERC2981() { _initializeOwner(msg.sender); baseURI = _uri; _setDefaultRoyalty(_royaltiesReceiver, 500); // 5% wlPrice = 0.0095 ether; publicPrice = 0.015 ether; maxSupply = 1234; isRevealed = true; wlMerkleRoot = _wlMerkleRoot; } /** * @dev Check if user have whitelist * @param _address The user address * @param _proof The proof to verify merkle with root */ function checkWhitelisted(address _address, bytes32[] calldata _proof) public view returns (bool) { bytes32 leaf = keccak256(abi.encodePacked(_address)); return MerkleProofLib.verify(_proof, wlMerkleRoot, leaf); } /** * @dev WL mint function - only whitelisted peoples can mint with wlPrice * @param _amount The amount of nft to mint * @param _proof The merkle proof for whitelist check */ function whitelistMint( uint256 _amount, bytes32[] calldata _proof ) external payable withinThreshold(_amount) isWhitelisted(wlMerkleRoot, _proof) { require(isMintLive(), "!live"); require(msg.value >= _amount * wlPrice, "Not enough ether to mint"); _mint(msg.sender, _amount); } /** * @dev Public mint function - anyone can mint with public price * @param _amount The amount of nft to mint */ function mint( uint256 _amount ) external payable withinThreshold(_amount) { require(isMintLive(), "!live"); require( msg.value >= _amount * publicPrice, "Not enough ether to mint" ); _mint(msg.sender, _amount); } /** * @notice Airdrop NFTs * @param _receiver The receiver of the airdrop * @param _amount The amount of nft to receive */ function airdrop(address _receiver, uint256 _amount) public withinThreshold(_amount) onlyOwner { _mint(_receiver, _amount); } /** * @notice Batch Airdrop NFTs * @param _receivers addresses of receivers */ function batchAirdrop(address[] calldata _receivers) public withinThreshold(_receivers.length) onlyOwner { uint256 _supplyBefore = totalSupply(); for(uint256 i=0;i<_receivers.length;++i) { if (_receivers[i] == address(0)) { _mint(owner(), 1); } else { _mint(_receivers[i], 1); } } emit BatchMetadataUpdate(_supplyBefore, totalSupply()); } /** * @notice Set base uri * @param _uri The base uri */ function setBaseURI(string memory _uri) external onlyOwner { baseURI = _uri; emit BatchMetadataUpdate(_startTokenId(), totalSupply()); } /** * @notice Set base uri suffix * @param _new_suffix New token suffix */ function setBaseTokenSuffix(string memory _new_suffix) external onlyOwner { _baseTokenSuffix = _new_suffix; emit BatchMetadataUpdate(_startTokenId(), totalSupply()); } /** * @notice Sets the collection max supply * @param _maxSupply The max supply of the collection */ function setMaxSupply(uint256 _maxSupply) external onlyOwner { maxSupply = _maxSupply; } /** * @notice Set wl mint price * @param _ethPrice The eth price in wei */ function setWLPrice( uint256 _ethPrice ) external onlyOwner { wlPrice = _ethPrice; } /** * @notice Set public mint price * @param _ethPrice The eth price in wei */ function setPublicPrice( uint256 _ethPrice ) external onlyOwner { publicPrice = _ethPrice; } function _startTokenId() internal view virtual override returns (uint256) { return 1; } function _baseURI() internal view override returns (string memory) { return baseURI; } /// @dev Check if mint is live function isMintLive() public view returns (bool) { return mintLive; } /** * @notice Set isRevealed * @param _reveal bool */ function setIsRevealed( bool _reveal ) external onlyOwner { isRevealed = _reveal; } /** * @notice Set Is Mint Live * @param _live bool */ function setIsMintLive( bool _live ) external onlyOwner { mintLive = _live; } /** * @notice Set the wl merkle root * @param _wlMerkleRoot The wl merkle root to set */ function setWlMerkleRoot(bytes32 _wlMerkleRoot) external onlyOwner { wlMerkleRoot = _wlMerkleRoot; } // function whitelistMint( // uint256 _amount, // bytes32[] calldata _proof // ) external payable withinThreshold(_amount) isWhitelisted(wlMerkleRoot, _proof) { // require(isMintLive(), "!live"); // require(msg.value >= _amount * wlPrice, "Not enough ether to mint"); // _mint(msg.sender, _amount); // } function tokenURI( uint256 tokenId ) public view virtual override(IERC721A, ERC721A) returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory uri = _baseURI(); if(!isRevealed) { return uri; } return bytes(uri).length > 0 ? string(abi.encodePacked(uri, tokenId.toString(), _baseTokenSuffix)) : ""; } function supportsInterface( bytes4 interfaceId ) public view virtual override(IERC721A, ERC721A, ERC2981) returns (bool) { return ERC721A.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId) || interfaceId == 0x49064906; // IERC4906 } /** * @notice Set Default Royalty * @param _receiver The receiver of the royalty * @param _amount The numerator of the royalty (1000 = 10%) */ function setDefaultRoyalty( address payable _receiver, uint96 _amount ) public onlyOwner { _setDefaultRoyalty(_receiver, _amount); } // /** // * @notice Withdraw funds // * @param _to The receiver of the funds // */ // function withdraw(address payable _to) external onlyOwner { // _to.transfer(address(this).balance); // } /** * @notice Withdraw funds * @param _to The receiver of the funds */ function withdraw(address payable _to) external onlyOwner { (bool success, ) = _to.call{value: address(this).balance}(""); require(success, "Withdraw failed"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) library MerkleProofLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MERKLE PROOF VERIFICATION OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if mload(proof) { // Initialize `offset` to the offset of `proof` elements in memory. let offset := add(proof, 0x20) // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(offset, shl(5, mload(proof))) // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, mload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), mload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if proof.length { // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(proof.offset, shl(5, proof.length)) // Initialize `offset` to the offset of `proof` in the calldata. let offset := proof.offset // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, calldataload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), calldataload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - The sum of the lengths of `proof` and `leaves` must never overflow. /// - Any non-zero word in the `flags` array is treated as true. /// - The memory offset of `proof` must be non-zero /// (i.e. `proof` is not pointing to the scratch space). function verifyMultiProof( bytes32[] memory proof, bytes32 root, bytes32[] memory leaves, bool[] memory flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // Cache the lengths of the arrays. let leavesLength := mload(leaves) let proofLength := mload(proof) let flagsLength := mload(flags) // Advance the pointers of the arrays to point to the data. leaves := add(0x20, leaves) proof := add(0x20, proof) flags := add(0x20, flags) // If the number of flags is correct. for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flagsLength) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof, shl(5, proofLength)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. leavesLength := shl(5, leavesLength) for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } { mstore(add(hashesFront, i), mload(add(leaves, i))) } // Compute the back of the hashes. let hashesBack := add(hashesFront, leavesLength) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flagsLength := add(hashesBack, shl(5, flagsLength)) for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(mload(flags)) { // Loads the next proof. b := mload(proof) proof := add(proof, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag. flags := add(flags, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flagsLength)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof) ) break } } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - Any non-zero word in the `flags` array is treated as true. /// - The calldata offset of `proof` must be non-zero /// (i.e. `proof` is from a regular Solidity function with a 4-byte selector). function verifyMultiProofCalldata( bytes32[] calldata proof, bytes32 root, bytes32[] calldata leaves, bool[] calldata flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // If the number of flags is correct. for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flags.length) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. // forgefmt: disable-next-item isValid := eq( calldataload( xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length)) ), root ) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof.offset, shl(5, proof.length)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length)) // Compute the back of the hashes. let hashesBack := add(hashesFront, shl(5, leaves.length)) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flags.length := add(hashesBack, shl(5, flags.length)) // We don't need to make a copy of `proof.offset` or `flags.offset`, // as they are pass-by-value (this trick may not always save gas). for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(calldataload(flags.offset)) { // Loads the next proof. b := calldataload(proof.offset) proof.offset := add(proof.offset, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag offset. flags.offset := add(flags.offset, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flags.length)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof.offset) ) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes32 array. function emptyProof() internal pure returns (bytes32[] calldata proof) { /// @solidity memory-safe-assembly assembly { proof.length := 0 } } /// @dev Returns an empty calldata bytes32 array. function emptyLeaves() internal pure returns (bytes32[] calldata leaves) { /// @solidity memory-safe-assembly assembly { leaves.length := 0 } } /// @dev Returns an empty calldata bool array. function emptyFlags() internal pure returns (bool[] calldata flags) { /// @solidity memory-safe-assembly assembly { flags.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Reentrancy guard mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuard.sol) abstract contract ReentrancyGuard { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unauthorized reentrant call. error Reentrancy(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to: `uint72(bytes9(keccak256("_REENTRANCY_GUARD_SLOT")))`. /// 9 bytes is large enough to avoid collisions with lower slots, /// but not too large to result in excessive bytecode bloat. uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* REENTRANCY GUARD */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Guards a function from reentrancy. modifier nonReentrant() virtual { /// @solidity memory-safe-assembly assembly { if eq(sload(_REENTRANCY_GUARD_SLOT), address()) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } sstore(_REENTRANCY_GUARD_SLOT, address()) } _; /// @solidity memory-safe-assembly assembly { sstore(_REENTRANCY_GUARD_SLOT, codesize()) } } /// @dev Guards a view function from read-only reentrancy. modifier nonReadReentrant() virtual { /// @solidity memory-safe-assembly assembly { if eq(sload(_REENTRANCY_GUARD_SLOT), address()) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } } _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721ABurnable.sol'; import '../ERC721A.sol'; /** * @title ERC721ABurnable. * * @dev ERC721A token that can be irreversibly burned (destroyed). */ abstract contract ERC721ABurnable is ERC721A, IERC721ABurnable { /** * @dev Burns `tokenId`. See {ERC721A-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) public virtual override { _burn(tokenId, true); } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721AQueryable.sol'; import '../ERC721A.sol'; /** * @title ERC721AQueryable. * * @dev ERC721A subclass with convenience query functions. */ abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable { /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory ownership) { unchecked { if (tokenId >= _startTokenId()) { if (tokenId > _sequentialUpTo()) return _ownershipAt(tokenId); if (tokenId < _nextTokenId()) { // If the `tokenId` is within bounds, // scan backwards for the initialized ownership slot. while (!_ownershipIsInitialized(tokenId)) --tokenId; return _ownershipAt(tokenId); } } } } /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] calldata tokenIds) external view virtual override returns (TokenOwnership[] memory) { TokenOwnership[] memory ownerships; uint256 i = tokenIds.length; assembly { // Grab the free memory pointer. ownerships := mload(0x40) // Store the length. mstore(ownerships, i) // Allocate one word for the length, // `tokenIds.length` words for the pointers. i := shl(5, i) // Multiply `i` by 32. mstore(0x40, add(add(ownerships, 0x20), i)) } while (i != 0) { uint256 tokenId; assembly { i := sub(i, 0x20) tokenId := calldataload(add(tokenIds.offset, i)) } TokenOwnership memory ownership = explicitOwnershipOf(tokenId); assembly { // Store the pointer of `ownership` in the `ownerships` array. mstore(add(add(ownerships, 0x20), i), ownership) } } return ownerships; } /** * @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 {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view virtual override returns (uint256[] memory) { return _tokensOfOwnerIn(owner, start, stop); } /** * @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 {ERC721AQueryable-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) external view virtual override returns (uint256[] memory) { // If spot mints are enabled, full-range scan is disabled. if (_sequentialUpTo() != type(uint256).max) _revert(NotCompatibleWithSpotMints.selector); uint256 start = _startTokenId(); uint256 stop = _nextTokenId(); uint256[] memory tokenIds; if (start != stop) tokenIds = _tokensOfOwnerIn(owner, start, stop); return tokenIds; } /** * @dev Helper function for returning an array of token IDs owned by `owner`. * * Note that this function is optimized for smaller bytecode size over runtime gas, * since it is meant to be called off-chain. */ function _tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) private view returns (uint256[] memory tokenIds) { unchecked { if (start >= stop) _revert(InvalidQueryRange.selector); // Set `start = max(start, _startTokenId())`. if (start < _startTokenId()) start = _startTokenId(); uint256 nextTokenId = _nextTokenId(); // If spot mints are enabled, scan all the way until the specified `stop`. uint256 stopLimit = _sequentialUpTo() != type(uint256).max ? stop : nextTokenId; // Set `stop = min(stop, stopLimit)`. if (stop >= stopLimit) stop = stopLimit; // Number of tokens to scan. uint256 tokenIdsMaxLength = balanceOf(owner); // Set `tokenIdsMaxLength` to zero if the range contains no tokens. if (start >= stop) tokenIdsMaxLength = 0; // If there are one or more tokens to scan. if (tokenIdsMaxLength != 0) { // Set `tokenIdsMaxLength = min(balanceOf(owner), tokenIdsMaxLength)`. if (stop - start <= tokenIdsMaxLength) tokenIdsMaxLength = stop - start; uint256 m; // Start of available memory. assembly { // Grab the free memory pointer. tokenIds := mload(0x40) // Allocate one word for the length, and `tokenIdsMaxLength` words // for the data. `shl(5, x)` is equivalent to `mul(32, x)`. m := add(tokenIds, shl(5, add(tokenIdsMaxLength, 1))) mstore(0x40, m) } // We need to call `explicitOwnershipOf(start)`, // because the slot at `start` may not be initialized. TokenOwnership memory ownership = explicitOwnershipOf(start); address currOwnershipAddr; // If the starting slot exists (i.e. not burned), // initialize `currOwnershipAddr`. // `ownership.address` will not be zero, // as `start` is clamped to the valid token ID range. if (!ownership.burned) currOwnershipAddr = ownership.addr; uint256 tokenIdsIdx; // Use a do-while, which is slightly more efficient for this case, // as the array will at least contain one element. do { if (_sequentialUpTo() != type(uint256).max) { // Skip the remaining unused sequential slots. if (start == nextTokenId) start = _sequentialUpTo() + 1; // Reset `currOwnershipAddr`, as each spot-minted token is a batch of one. if (start > _sequentialUpTo()) currOwnershipAddr = address(0); } ownership = _ownershipAt(start); // This implicitly allocates memory. assembly { switch mload(add(ownership, 0x40)) // if `ownership.burned == false`. case 0 { // if `ownership.addr != address(0)`. // The `addr` already has it's upper 96 bits clearned, // since it is written to memory with regular Solidity. if mload(ownership) { currOwnershipAddr := mload(ownership) } // if `currOwnershipAddr == owner`. // The `shl(96, x)` is to make the comparison agnostic to any // dirty upper 96 bits in `owner`. if iszero(shl(96, xor(currOwnershipAddr, owner))) { tokenIdsIdx := add(tokenIdsIdx, 1) mstore(add(tokenIds, shl(5, tokenIdsIdx)), start) } } // Otherwise, reset `currOwnershipAddr`. // This handles the case of batch burned tokens // (burned bit of first slot set, remaining slots left uninitialized). default { currOwnershipAddr := 0 } start := add(start, 1) // Free temporary memory implicitly allocated for ownership // to avoid quadratic memory expansion costs. mstore(0x40, m) } } while (!(start == stop || tokenIdsIdx == tokenIdsMaxLength)); // Store the length of the array. assembly { mstore(tokenIds, tokenIdsIdx) } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {LibBytes} from "./LibBytes.sol"; /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) /// /// @dev Note: /// For performance and bytecode compactness, most of the string operations are restricted to /// byte strings (7-bit ASCII), except where otherwise specified. /// Usage of byte string operations on charsets with runes spanning two or more bytes /// can lead to undefined behavior. library LibString { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Goated string storage struct that totally MOGs, no cap, fr. /// Uses less gas and bytecode than Solidity's native string storage. It's meta af. /// Packs length with the first 31 bytes if <255 bytes, so it’s mad tight. struct StringStorage { bytes32 _spacer; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The length of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /// @dev The length of the string is more than 32 bytes. error TooBigForSmallString(); /// @dev The input string must be a 7-bit ASCII. error StringNot7BitASCII(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant ALPHANUMERIC_7_BIT_ASCII = 0x7fffffe07fffffe03ff000000000000; /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant LETTERS_7_BIT_ASCII = 0x7fffffe07fffffe0000000000000000; /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyz'. uint128 internal constant LOWERCASE_7_BIT_ASCII = 0x7fffffe000000000000000000000000; /// @dev Lookup for 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant UPPERCASE_7_BIT_ASCII = 0x7fffffe0000000000000000; /// @dev Lookup for '0123456789'. uint128 internal constant DIGITS_7_BIT_ASCII = 0x3ff000000000000; /// @dev Lookup for '0123456789abcdefABCDEF'. uint128 internal constant HEXDIGITS_7_BIT_ASCII = 0x7e0000007e03ff000000000000; /// @dev Lookup for '01234567'. uint128 internal constant OCTDIGITS_7_BIT_ASCII = 0xff000000000000; /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'. uint128 internal constant PRINTABLE_7_BIT_ASCII = 0x7fffffffffffffffffffffff00003e00; /// @dev Lookup for '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'. uint128 internal constant PUNCTUATION_7_BIT_ASCII = 0x78000001f8000001fc00fffe00000000; /// @dev Lookup for ' \t\n\r\x0b\x0c'. uint128 internal constant WHITESPACE_7_BIT_ASCII = 0x100003e00; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRING STORAGE OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sets the value of the string storage `$` to `s`. function set(StringStorage storage $, string memory s) internal { LibBytes.set(bytesStorage($), bytes(s)); } /// @dev Sets the value of the string storage `$` to `s`. function setCalldata(StringStorage storage $, string calldata s) internal { LibBytes.setCalldata(bytesStorage($), bytes(s)); } /// @dev Sets the value of the string storage `$` to the empty string. function clear(StringStorage storage $) internal { delete $._spacer; } /// @dev Returns whether the value stored is `$` is the empty string "". function isEmpty(StringStorage storage $) internal view returns (bool) { return uint256($._spacer) & 0xff == uint256(0); } /// @dev Returns the length of the value stored in `$`. function length(StringStorage storage $) internal view returns (uint256) { return LibBytes.length(bytesStorage($)); } /// @dev Returns the value stored in `$`. function get(StringStorage storage $) internal view returns (string memory) { return string(LibBytes.get(bytesStorage($))); } /// @dev Helper to cast `$` to a `BytesStorage`. function bytesStorage(StringStorage storage $) internal pure returns (LibBytes.BytesStorage storage casted) { /// @solidity memory-safe-assembly assembly { casted.slot := $.slot } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. result := add(mload(0x40), 0x80) mstore(0x40, add(result, 0x20)) // Allocate memory. mstore(result, 0) // Zeroize the slot after the string. let end := result // Cache the end of the memory to calculate the length later. let w := not(0) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { result := add(result, w) // `sub(result, 1)`. // Store the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(result, add(48, mod(temp, 10))) temp := div(temp, 10) // Keep dividing `temp` until zero. if iszero(temp) { break } } let n := sub(end, result) result := sub(result, 0x20) // Move the pointer 32 bytes back to make room for the length. mstore(result, n) // Store the length. } } /// @dev Returns the base 10 decimal representation of `value`. function toString(int256 value) internal pure returns (string memory result) { if (value >= 0) return toString(uint256(value)); unchecked { result = toString(~uint256(value) + 1); } /// @solidity memory-safe-assembly assembly { // We still have some spare memory space on the left, // as we have allocated 3 words (96 bytes) for up to 78 digits. let n := mload(result) // Load the string length. mstore(result, 0x2d) // Store the '-' character. result := sub(result, 1) // Move back the string pointer by a byte. mstore(result, add(n, 1)) // Update the string length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `byteCount` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `byteCount * 2 + 2` bytes. /// Reverts if `byteCount` is too small for the output to contain all the digits. function toHexString(uint256 value, uint256 byteCount) internal pure returns (string memory result) { result = toHexStringNoPrefix(value, byteCount); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `byteCount` bytes. /// The output is not prefixed with "0x" and is encoded using 2 hexadecimal digits per byte, /// giving a total length of `byteCount * 2` bytes. /// Reverts if `byteCount` is too small for the output to contain all the digits. function toHexStringNoPrefix(uint256 value, uint256 byteCount) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, `byteCount * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. result := add(mload(0x40), and(add(shl(1, byteCount), 0x42), not(0x1f))) mstore(0x40, add(result, 0x20)) // Allocate memory. mstore(result, 0) // Zeroize the slot after the string. let end := result // Cache the end to calculate the length later. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let start := sub(result, add(byteCount, byteCount)) let w := not(1) // Tsk. let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { result := add(result, w) // `sub(result, 2)`. mstore8(add(result, 1), mload(and(temp, 15))) mstore8(result, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(xor(result, start)) { break } } if temp { mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`. revert(0x1c, 0x04) } let n := sub(end, result) result := sub(result, 0x20) mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2 + 2` bytes. function toHexString(uint256 value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x". /// The output excludes leading "0" from the `toHexString` output. /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`. function toMinimalHexString(uint256 value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(result, 0x20))), 0x30) // Whether leading zero is present. let n := add(mload(result), 2) // Compute the length. mstore(add(result, o), 0x3078) // Store the "0x" prefix, accounting for leading zero. result := sub(add(result, o), 2) // Move the pointer, accounting for leading zero. mstore(result, sub(n, o)) // Store the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output excludes leading "0" from the `toHexStringNoPrefix` output. /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`. function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(result, 0x20))), 0x30) // Whether leading zero is present. let n := mload(result) // Get the length. result := add(result, o) // Move the pointer, accounting for leading zero. mstore(result, sub(n, o)) // Store the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2` bytes. function toHexStringNoPrefix(uint256 value) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. result := add(mload(0x40), 0x80) mstore(0x40, add(result, 0x20)) // Allocate memory. mstore(result, 0) // Zeroize the slot after the string. let end := result // Cache the end to calculate the length later. mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. let w := not(1) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { result := add(result, w) // `sub(result, 2)`. mstore8(add(result, 1), mload(and(temp, 15))) mstore8(result, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(temp) { break } } let n := sub(end, result) result := sub(result, 0x20) mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, /// and the alphabets are capitalized conditionally according to /// https://eips.ethereum.org/EIPS/eip-55 function toHexStringChecksummed(address value) internal pure returns (string memory result) { result = toHexString(value); /// @solidity memory-safe-assembly assembly { let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...` let o := add(result, 0x22) let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... ` let t := shl(240, 136) // `0b10001000 << 240` for { let i := 0 } 1 {} { mstore(add(i, i), mul(t, byte(i, hashed))) i := add(i, 1) if eq(i, 20) { break } } mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask))))) o := add(o, 0x20) mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask))))) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. function toHexString(address value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(address value) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Allocate memory. // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80. mstore(0x40, add(result, 0x80)) mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. result := add(result, 2) mstore(result, 40) // Store the length. let o := add(result, 0x20) mstore(add(o, 40), 0) // Zeroize the slot after the string. value := shl(96, value) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let i := 0 } 1 {} { let p := add(o, add(i, i)) let temp := byte(i, value) mstore8(add(p, 1), mload(and(temp, 15))) mstore8(p, mload(shr(4, temp))) i := add(i, 1) if eq(i, 20) { break } } } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexString(bytes memory raw) internal pure returns (string memory result) { result = toHexStringNoPrefix(raw); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let n := mload(raw) result := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix. mstore(result, add(n, n)) // Store the length of the output. mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. let o := add(result, 0x20) let end := add(raw, n) for {} iszero(eq(raw, end)) {} { raw := add(raw, 1) mstore8(add(o, 1), mload(and(mload(raw), 15))) mstore8(o, mload(and(shr(4, mload(raw)), 15))) o := add(o, 2) } mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RUNE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of UTF characters in the string. function runeCount(string memory s) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { mstore(0x00, div(not(0), 255)) mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506) let o := add(s, 0x20) let end := add(o, mload(s)) for { result := 1 } 1 { result := add(result, 1) } { o := add(o, byte(0, mload(shr(250, mload(o))))) if iszero(lt(o, end)) { break } } } } } /// @dev Returns if this string is a 7-bit ASCII string. /// (i.e. all characters codes are in [0..127]) function is7BitASCII(string memory s) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := 1 let mask := shl(7, div(not(0), 255)) let n := mload(s) if n { let o := add(s, 0x20) let end := add(o, n) let last := mload(end) mstore(end, 0) for {} 1 {} { if and(mask, mload(o)) { result := 0 break } o := add(o, 0x20) if iszero(lt(o, end)) { break } } mstore(end, last) } } } /// @dev Returns if this string is a 7-bit ASCII string, /// AND all characters are in the `allowed` lookup. /// Note: If `s` is empty, returns true regardless of `allowed`. function is7BitASCII(string memory s, uint128 allowed) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := 1 if mload(s) { let allowed_ := shr(128, shl(128, allowed)) let o := add(s, 0x20) for { let end := add(o, mload(s)) } 1 {} { result := and(result, shr(byte(0, mload(o)), allowed_)) o := add(o, 1) if iszero(and(result, lt(o, end))) { break } } } } } /// @dev Converts the bytes in the 7-bit ASCII string `s` to /// an allowed lookup for use in `is7BitASCII(s, allowed)`. /// To save runtime gas, you can cache the result in an immutable variable. function to7BitASCIIAllowedLookup(string memory s) internal pure returns (uint128 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { let o := add(s, 0x20) for { let end := add(o, mload(s)) } 1 {} { result := or(result, shl(byte(0, mload(o)), 1)) o := add(o, 1) if iszero(lt(o, end)) { break } } if shr(128, result) { mstore(0x00, 0xc9807e0d) // `StringNot7BitASCII()`. revert(0x1c, 0x04) } } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // For performance and bytecode compactness, byte string operations are restricted // to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets. // Usage of byte string operations on charsets with runes spanning two or more bytes // can lead to undefined behavior. /// @dev Returns `subject` all occurrences of `needle` replaced with `replacement`. function replace(string memory subject, string memory needle, string memory replacement) internal pure returns (string memory) { return string(LibBytes.replace(bytes(subject), bytes(needle), bytes(replacement))); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(string memory subject, string memory needle, uint256 from) internal pure returns (uint256) { return LibBytes.indexOf(bytes(subject), bytes(needle), from); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(string memory subject, string memory needle) internal pure returns (uint256) { return LibBytes.indexOf(bytes(subject), bytes(needle), 0); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(string memory subject, string memory needle, uint256 from) internal pure returns (uint256) { return LibBytes.lastIndexOf(bytes(subject), bytes(needle), from); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(string memory subject, string memory needle) internal pure returns (uint256) { return LibBytes.lastIndexOf(bytes(subject), bytes(needle), type(uint256).max); } /// @dev Returns true if `needle` is found in `subject`, false otherwise. function contains(string memory subject, string memory needle) internal pure returns (bool) { return LibBytes.contains(bytes(subject), bytes(needle)); } /// @dev Returns whether `subject` starts with `needle`. function startsWith(string memory subject, string memory needle) internal pure returns (bool) { return LibBytes.startsWith(bytes(subject), bytes(needle)); } /// @dev Returns whether `subject` ends with `needle`. function endsWith(string memory subject, string memory needle) internal pure returns (bool) { return LibBytes.endsWith(bytes(subject), bytes(needle)); } /// @dev Returns `subject` repeated `times`. function repeat(string memory subject, uint256 times) internal pure returns (string memory) { return string(LibBytes.repeat(bytes(subject), times)); } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(string memory subject, uint256 start, uint256 end) internal pure returns (string memory) { return string(LibBytes.slice(bytes(subject), start, end)); } /// @dev Returns a copy of `subject` sliced from `start` to the end of the string. /// `start` is a byte offset. function slice(string memory subject, uint256 start) internal pure returns (string memory) { return string(LibBytes.slice(bytes(subject), start, type(uint256).max)); } /// @dev Returns all the indices of `needle` in `subject`. /// The indices are byte offsets. function indicesOf(string memory subject, string memory needle) internal pure returns (uint256[] memory) { return LibBytes.indicesOf(bytes(subject), bytes(needle)); } /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string. function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) { bytes[] memory a = LibBytes.split(bytes(subject), bytes(delimiter)); /// @solidity memory-safe-assembly assembly { result := a } } /// @dev Returns a concatenated string of `a` and `b`. /// Cheaper than `string.concat()` and does not de-align the free memory pointer. function concat(string memory a, string memory b) internal pure returns (string memory) { return string(LibBytes.concat(bytes(a), bytes(b))); } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. /// WARNING! This function is only compatible with 7-bit ASCII strings. function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let n := mload(subject) if n { result := mload(0x40) let o := add(result, 0x20) let d := sub(subject, result) let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff) for { let end := add(o, n) } 1 {} { let b := byte(0, mload(add(d, o))) mstore8(o, xor(and(shr(b, flags), 0x20), b)) o := add(o, 1) if eq(o, end) { break } } mstore(result, n) // Store the length. mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate memory. } } } /// @dev Returns a string from a small bytes32 string. /// `s` must be null-terminated, or behavior will be undefined. function fromSmallString(bytes32 s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let n := 0 for {} byte(n, s) { n := add(n, 1) } {} // Scan for '\0'. mstore(result, n) // Store the length. let o := add(result, 0x20) mstore(o, s) // Store the bytes of the string. mstore(add(o, n), 0) // Zeroize the slot after the string. mstore(0x40, add(result, 0x40)) // Allocate memory. } } /// @dev Returns the small string, with all bytes after the first null byte zeroized. function normalizeSmallString(bytes32 s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { for {} byte(result, s) { result := add(result, 1) } {} // Scan for '\0'. mstore(0x00, s) mstore(result, 0x00) result := mload(0x00) } } /// @dev Returns the string as a normalized null-terminated small string. function toSmallString(string memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := mload(s) if iszero(lt(result, 33)) { mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`. revert(0x1c, 0x04) } result := shl(shl(3, sub(32, result)), mload(add(s, result))) } } /// @dev Returns a lowercased copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function upper(string memory subject) internal pure returns (string memory result) { result = toCase(subject, true); } /// @dev Escapes the string to be used within HTML tags. function escapeHTML(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let end := add(s, mload(s)) let o := add(result, 0x20) // Store the bytes of the packed offsets and strides into the scratch space. // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6. mstore(0x1f, 0x900094) mstore(0x08, 0xc0000000a6ab) // Store ""&'<>" into the scratch space. mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // Not in `["\"","'","&","<",">"]`. if iszero(and(shl(c, 1), 0x500000c400000000)) { mstore8(o, c) o := add(o, 1) continue } let t := shr(248, mload(c)) mstore(o, mload(and(t, 0x1f))) o := add(o, shr(5, t)) } mstore(o, 0) // Zeroize the slot after the string. mstore(result, sub(o, add(result, 0x20))) // Store the length. mstore(0x40, add(o, 0x20)) // Allocate memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes. function escapeJSON(string memory s, bool addDoubleQuotes) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let o := add(result, 0x20) if addDoubleQuotes { mstore8(o, 34) o := add(1, o) } // Store "\\u0000" in scratch space. // Store "0123456789abcdef" in scratch space. // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`. // into the scratch space. mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672) // Bitmask for detecting `["\"","\\"]`. let e := or(shl(0x22, 1), shl(0x5c, 1)) for { let end := add(s, mload(s)) } iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) if iszero(lt(c, 0x20)) { if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`. mstore8(o, c) o := add(o, 1) continue } mstore8(o, 0x5c) // "\\". mstore8(add(o, 1), c) o := add(o, 2) continue } if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`. mstore8(0x1d, mload(shr(4, c))) // Hex value. mstore8(0x1e, mload(and(c, 15))) // Hex value. mstore(o, mload(0x19)) // "\\u00XX". o := add(o, 6) continue } mstore8(o, 0x5c) // "\\". mstore8(add(o, 1), mload(add(c, 8))) o := add(o, 2) } if addDoubleQuotes { mstore8(o, 34) o := add(1, o) } mstore(o, 0) // Zeroize the slot after the string. mstore(result, sub(o, add(result, 0x20))) // Store the length. mstore(0x40, add(o, 0x20)) // Allocate memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { result = escapeJSON(s, false); } /// @dev Encodes `s` so that it can be safely used in a URI, /// just like `encodeURIComponent` in JavaScript. /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent /// See: https://datatracker.ietf.org/doc/html/rfc2396 /// See: https://datatracker.ietf.org/doc/html/rfc3986 function encodeURIComponent(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Store "0123456789ABCDEF" in scratch space. // Uppercased to be consistent with JavaScript's implementation. mstore(0x0f, 0x30313233343536373839414243444546) let o := add(result, 0x20) for { let end := add(s, mload(s)) } iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // If not in `[0-9A-Z-a-z-_.!~*'()]`. if iszero(and(1, shr(c, 0x47fffffe87fffffe03ff678200000000))) { mstore8(o, 0x25) // '%'. mstore8(add(o, 1), mload(and(shr(4, c), 15))) mstore8(add(o, 2), mload(and(c, 15))) o := add(o, 3) continue } mstore8(o, c) o := add(o, 1) } mstore(result, sub(o, add(result, 0x20))) // Store the length. mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate memory. } } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small string. function eqs(string memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`. let x := not(or(m, or(b, add(m, and(b, m))))) let r := shl(7, iszero(iszero(shr(128, x)))) r := or(r, shl(6, iszero(iszero(shr(64, 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 result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))), xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20))))) } } /// @dev Returns 0 if `a == b`, -1 if `a < b`, +1 if `a > b`. /// If `a` == b[:a.length]`, and `a.length < b.length`, returns -1. function cmp(string memory a, string memory b) internal pure returns (int256) { return LibBytes.cmp(bytes(a), bytes(b)); } /// @dev Packs a single string with its length into a single word. /// Returns `bytes32(0)` if the length is zero or greater than 31. function packOne(string memory a) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { // We don't need to zero right pad the string, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes. mload(add(a, 0x1f)), // `length != 0 && length < 32`. Abuses underflow. // Assumes that the length is valid and within the block gas limit. lt(sub(mload(a), 1), 0x1f) ) } } /// @dev Unpacks a string packed using {packOne}. /// Returns the empty string if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packOne}, the output behavior is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Grab the free memory pointer. mstore(0x40, add(result, 0x40)) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(result, 0) // Zeroize the length slot. mstore(add(result, 0x1f), packed) // Store the length and bytes. mstore(add(add(result, 0x20), mload(result)), 0) // Right pad with zeroes. } } /// @dev Packs two strings with their lengths into a single word. /// Returns `bytes32(0)` if combined length is zero or greater than 30. function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let aLen := mload(a) // We don't need to zero right pad the strings, // since this is our own custom non-standard packing scheme. result := mul( or( // Load the length and the bytes of `a` and `b`. shl(shl(3, sub(0x1f, aLen)), mload(add(a, aLen))), mload(sub(add(b, 0x1e), aLen))), // `totalLen != 0 && totalLen < 31`. Abuses underflow. // Assumes that the lengths are valid and within the block gas limit. lt(sub(add(aLen, mload(b)), 1), 0x1e) ) } } /// @dev Unpacks strings packed using {packTwo}. /// Returns the empty strings if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packTwo}, the output behavior is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { resultA := mload(0x40) // Grab the free memory pointer. resultB := add(resultA, 0x40) // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words. mstore(0x40, add(resultB, 0x40)) // Zeroize the length slots. mstore(resultA, 0) mstore(resultB, 0) // Store the lengths and bytes. mstore(add(resultA, 0x1f), packed) mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA)))) // Right pad with zeroes. mstore(add(add(resultA, 0x20), mload(resultA)), 0) mstore(add(add(resultB, 0x20), mload(resultB)), 0) } } /// @dev Directly returns `a` without copying. function directReturn(string memory a) internal pure { /// @solidity memory-safe-assembly assembly { // Assumes that the string does not start from the scratch space. let retStart := sub(a, 0x20) let retUnpaddedSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the string is produced // by a method that doesn't zero right pad. mstore(add(retStart, retUnpaddedSize), 0) mstore(retStart, 0x20) // Store the return offset. // End the transaction, returning the string. return(retStart, and(not(0x1f), add(0x1f, retUnpaddedSize))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple ERC2981 NFT Royalty Standard implementation. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC2981.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/common/ERC2981.sol) abstract contract ERC2981 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The royalty fee numerator exceeds the fee denominator. error RoyaltyOverflow(); /// @dev The royalty receiver cannot be the zero address. error RoyaltyReceiverIsZeroAddress(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The default royalty info is given by: /// ``` /// let packed := sload(_ERC2981_MASTER_SLOT_SEED) /// let receiver := shr(96, packed) /// let royaltyFraction := xor(packed, shl(96, receiver)) /// ``` /// /// The per token royalty info is given by. /// ``` /// mstore(0x00, tokenId) /// mstore(0x20, _ERC2981_MASTER_SLOT_SEED) /// let packed := sload(keccak256(0x00, 0x40)) /// let receiver := shr(96, packed) /// let royaltyFraction := xor(packed, shl(96, receiver)) /// ``` uint256 private constant _ERC2981_MASTER_SLOT_SEED = 0xaa4ec00224afccfdb7; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC2981 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Checks that `_feeDenominator` is non-zero. constructor() { require(_feeDenominator() != 0, "Fee denominator cannot be zero."); } /// @dev Returns the denominator for the royalty amount. /// Defaults to 10000, which represents fees in basis points. /// Override this function to return a custom amount if needed. function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /// @dev Returns true if this contract implements the interface defined by `interfaceId`. /// See: https://eips.ethereum.org/EIPS/eip-165 /// This function call must use less than 30000 gas. function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { let s := shr(224, interfaceId) // ERC165: 0x01ffc9a7, ERC2981: 0x2a55205a. result := or(eq(s, 0x01ffc9a7), eq(s, 0x2a55205a)) } } /// @dev Returns the `receiver` and `royaltyAmount` for `tokenId` sold at `salePrice`. function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address receiver, uint256 royaltyAmount) { uint256 feeDenominator = _feeDenominator(); /// @solidity memory-safe-assembly assembly { mstore(0x00, tokenId) mstore(0x20, _ERC2981_MASTER_SLOT_SEED) let packed := sload(keccak256(0x00, 0x40)) receiver := shr(96, packed) if iszero(receiver) { packed := sload(mload(0x20)) receiver := shr(96, packed) } let x := salePrice let y := xor(packed, shl(96, receiver)) // `feeNumerator`. // Overflow check, equivalent to `require(y == 0 || x <= type(uint256).max / y)`. // Out-of-gas revert. Should not be triggered in practice, but included for safety. returndatacopy(returndatasize(), returndatasize(), mul(y, gt(x, div(not(0), y)))) royaltyAmount := div(mul(x, y), feeDenominator) } } /// @dev Sets the default royalty `receiver` and `feeNumerator`. /// /// Requirements: /// - `receiver` must not be the zero address. /// - `feeNumerator` must not be greater than the fee denominator. function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { uint256 feeDenominator = _feeDenominator(); /// @solidity memory-safe-assembly assembly { feeNumerator := shr(160, shl(160, feeNumerator)) if gt(feeNumerator, feeDenominator) { mstore(0x00, 0x350a88b3) // `RoyaltyOverflow()`. revert(0x1c, 0x04) } let packed := shl(96, receiver) if iszero(packed) { mstore(0x00, 0xb4457eaa) // `RoyaltyReceiverIsZeroAddress()`. revert(0x1c, 0x04) } sstore(_ERC2981_MASTER_SLOT_SEED, or(packed, feeNumerator)) } } /// @dev Sets the default royalty `receiver` and `feeNumerator` to zero. function _deleteDefaultRoyalty() internal virtual { /// @solidity memory-safe-assembly assembly { sstore(_ERC2981_MASTER_SLOT_SEED, 0) } } /// @dev Sets the royalty `receiver` and `feeNumerator` for `tokenId`. /// /// Requirements: /// - `receiver` must not be the zero address. /// - `feeNumerator` must not be greater than the fee denominator. function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual { uint256 feeDenominator = _feeDenominator(); /// @solidity memory-safe-assembly assembly { feeNumerator := shr(160, shl(160, feeNumerator)) if gt(feeNumerator, feeDenominator) { mstore(0x00, 0x350a88b3) // `RoyaltyOverflow()`. revert(0x1c, 0x04) } let packed := shl(96, receiver) if iszero(packed) { mstore(0x00, 0xb4457eaa) // `RoyaltyReceiverIsZeroAddress()`. revert(0x1c, 0x04) } mstore(0x00, tokenId) mstore(0x20, _ERC2981_MASTER_SLOT_SEED) sstore(keccak256(0x00, 0x40), or(packed, feeNumerator)) } } /// @dev Sets the royalty `receiver` and `feeNumerator` for `tokenId` to zero. function _resetTokenRoyalty(uint256 tokenId) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x00, tokenId) mstore(0x20, _ERC2981_MASTER_SLOT_SEED) sstore(keccak256(0x00, 0x40), 0) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @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 up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (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; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) 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. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); 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 (rounding == Rounding.Up && 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 down. * * 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 + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @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, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such * that `ownerOf(tokenId)` is `a`. */ // solhint-disable-next-line func-name-mixedcase function __unsafe_increaseBalance(address account, uint256 amount) internal { _balances[account] += amount; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Burnable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../../utils/Context.sol"; /** * @title ERC721 Burnable Token * @dev ERC721 Token that can be burned (destroyed). */ abstract contract ERC721Burnable is Context, ERC721 { /** * @dev Burns `tokenId`. See {ERC721-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) public virtual { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _burn(tokenId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.2) (token/ERC721/extensions/ERC721Pausable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../../security/Pausable.sol"; /** * @dev ERC721 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. * * IMPORTANT: This contract does not include public pause and unpause functions. In * addition to inheriting this contract, you must define both functions, invoking the * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will * make the contract unpausable. */ abstract contract ERC721Pausable is ERC721, Pausable { /** * @dev See {ERC721-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual override { super._beforeTokenTransfer(from, to, firstTokenId, batchSize); require(!paused(), "ERC721Pausable: token transfer while paused"); } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * The `_sequentialUpTo()` function can be overriden to enable spot mints * (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is IERC721A { // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364). struct TokenApprovalRef { address value; } // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) private _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) private _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => TokenApprovalRef) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // The amount of tokens minted above `_sequentialUpTo()`. // We call these spot mints (i.e. non-sequential mints). uint256 private _spotMinted; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID for sequential mints. * * Override this function to change the starting token ID for sequential mints. * * Note: The value returned must never change after any tokens have been minted. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the maximum token ID (inclusive) for sequential mints. * * Override this function to return a value less than 2**256 - 1, * but greater than `_startTokenId()`, to enable spot (non-sequential) mints. * * Note: The value returned must never change after any tokens have been minted. */ function _sequentialUpTo() internal view virtual returns (uint256) { return type(uint256).max; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return _currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view virtual override returns (uint256 result) { // Counter underflow is impossible as `_burnCounter` cannot be incremented // more than `_currentIndex + _spotMinted - _startTokenId()` times. unchecked { // With spot minting, the intermediate `result` can be temporarily negative, // and the computation must be unchecked. result = _currentIndex - _burnCounter - _startTokenId(); if (_sequentialUpTo() != type(uint256).max) result += _spotMinted; } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256 result) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { result = _currentIndex - _startTokenId(); if (_sequentialUpTo() != type(uint256).max) result += _spotMinted; } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return _burnCounter; } /** * @dev Returns the total number of tokens that are spot-minted. */ function _totalSpotMinted() internal view virtual returns (uint256) { return _spotMinted; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector); return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(_packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); _packedAddressData[owner] = packed; } // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : ''; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Returns whether the ownership slot at `index` is initialized. * An uninitialized slot does not necessarily mean that the slot has no owner. */ function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) { return _packedOwnerships[index] != 0; } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * @dev Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) { if (_startTokenId() <= tokenId) { packed = _packedOwnerships[tokenId]; if (tokenId > _sequentialUpTo()) { if (_packedOwnershipExists(packed)) return packed; _revert(OwnerQueryForNonexistentToken.selector); } // If the data at the starting slot does not exist, start the scan. if (packed == 0) { if (tokenId >= _currentIndex) _revert(OwnerQueryForNonexistentToken.selector); // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `tokenId` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. for (;;) { unchecked { packed = _packedOwnerships[--tokenId]; } if (packed == 0) continue; if (packed & _BITMASK_BURNED == 0) return packed; // Otherwise, the token is burned, and we must revert. // This handles the case of batch burned tokens, where only the burned bit // of the starting slot is set, and remaining slots are left uninitialized. _revert(OwnerQueryForNonexistentToken.selector); } } // Otherwise, the data exists and we can skip the scan. // This is possible because we have already achieved the target condition. // This saves 2143 gas on transfers of initialized tokens. // If the token is not burned, return `packed`. Otherwise, revert. if (packed & _BITMASK_BURNED == 0) return packed; } _revert(OwnerQueryForNonexistentToken.selector); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}. * * Requirements: * * - The caller must own the token or be an approved operator. */ function approve(address to, uint256 tokenId) public payable virtual override { _approve(to, tokenId, true); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector); return _tokenApprovals[tokenId].value; } /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) public virtual override { _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool result) { if (_startTokenId() <= tokenId) { if (tokenId > _sequentialUpTo()) return _packedOwnershipExists(_packedOwnerships[tokenId]); if (tokenId < _currentIndex) { uint256 packed; while ((packed = _packedOwnerships[tokenId]) == 0) --tokenId; result = packed & _BITMASK_BURNED == 0; } } } /** * @dev Returns whether `packed` represents a token that exists. */ function _packedOwnershipExists(uint256 packed) private pure returns (bool result) { assembly { // The following is equivalent to `owner != address(0) && burned == false`. // Symbolically tested. result := gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_BURNED)) } } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress(uint256 tokenId) private view returns (uint256 approvedAddressSlot, address approvedAddress) { TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) public payable virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); // Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean. from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS)); if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --_packedAddressData[from]; // Updates: `balance -= 1`. ++_packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. from, // `from`. toMasked, // `to`. tokenId // `tokenId`. ) } if (toMasked == 0) _revert(TransferToZeroAddress.selector); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public payable virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } /** * @dev Hook that is called before a set of serially-ordered token IDs * are about to be transferred. This includes minting. * And also called before burning one token. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns ( bytes4 retval ) { return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { _revert(TransferToNonERC721ReceiverImplementer.selector); } assembly { revert(add(32, reason), mload(reason)) } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (quantity == 0) _revert(MintZeroQuantity.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); uint256 end = startTokenId + quantity; uint256 tokenId = startTokenId; if (end - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector); do { assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } // The `!=` check ensures that large values of `quantity` // that overflows uint256 will make the loop run out of gas. } while (++tokenId != end); _currentIndex = end; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * This function is intended for efficient minting only during contract creation. * * It emits only one {ConsecutiveTransfer} as defined in * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), * instead of a sequence of {Transfer} event(s). * * Calling this function outside of contract creation WILL make your contract * non-compliant with the ERC721 standard. * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309 * {ConsecutiveTransfer} event is only permissible during contract creation. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {ConsecutiveTransfer} event. */ function _mintERC2309(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (to == address(0)) _revert(MintToZeroAddress.selector); if (quantity == 0) _revert(MintZeroQuantity.selector); if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are unrealistic due to the above check for `quantity` to be below the limit. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); if (startTokenId + quantity - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector); emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to); _currentIndex = startTokenId + quantity; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = _currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } while (index < end); // This prevents reentrancy to `_safeMint`. // It does not prevent reentrancy to `_safeMintSpot`. if (_currentIndex != end) revert(); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ''); } /** * @dev Mints a single token at `tokenId`. * * Note: A spot-minted `tokenId` that has been burned can be re-minted again. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` must be greater than `_sequentialUpTo()`. * - `tokenId` must not exist. * * Emits a {Transfer} event for each mint. */ function _mintSpot(address to, uint256 tokenId) internal virtual { if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector); uint256 prevOwnershipPacked = _packedOwnerships[tokenId]; if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector); _beforeTokenTransfers(address(0), to, tokenId, 1); // Overflows are incredibly unrealistic. // The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1. // `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `true` (as `quantity == 1`). _packedOwnerships[tokenId] = _packOwnershipData( to, _nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked) ); // Updates: // - `balance += 1`. // - `numberMinted += 1`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += (1 << _BITPOS_NUMBER_MINTED) | 1; // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } ++_spotMinted; } _afterTokenTransfers(address(0), to, tokenId, 1); } /** * @dev Safely mints a single token at `tokenId`. * * Note: A spot-minted `tokenId` that has been burned can be re-minted again. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}. * - `tokenId` must be greater than `_sequentialUpTo()`. * - `tokenId` must not exist. * * See {_mintSpot}. * * Emits a {Transfer} event. */ function _safeMintSpot( address to, uint256 tokenId, bytes memory _data ) internal virtual { _mintSpot(to, tokenId); unchecked { if (to.code.length != 0) { uint256 currentSpotMinted = _spotMinted; if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } // This prevents reentrancy to `_safeMintSpot`. // It does not prevent reentrancy to `_safeMint`. if (_spotMinted != currentSpotMinted) revert(); } } } /** * @dev Equivalent to `_safeMintSpot(to, tokenId, '')`. */ function _safeMintSpot(address to, uint256 tokenId) internal virtual { _safeMintSpot(to, tokenId, ''); } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Equivalent to `_approve(to, tokenId, false)`. */ function _approve(address to, uint256 tokenId) internal virtual { _approve(to, tokenId, false); } /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - `tokenId` must exist. * * Emits an {Approval} event. */ function _approve( address to, uint256 tokenId, bool approvalCheck ) internal virtual { address owner = ownerOf(tokenId); if (approvalCheck && _msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { _revert(ApprovalCallerNotOwnerNorApproved.selector); } _tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as `_burnCounter` cannot be exceed `_currentIndex + _spotMinted` times. unchecked { _burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = _packedOwnerships[index]; if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); _packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData( address from, address to, uint24 previousExtraData ) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData( address from, address to, uint256 prevOwnershipPacked ) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @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), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(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) { 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] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); 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 keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @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 v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./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); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721A.sol'; /** * @dev Interface of ERC721ABurnable. */ interface IERC721ABurnable is IERC721A { /** * @dev Burns `tokenId`. See {ERC721A-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) external; }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721A.sol'; /** * @dev Interface of ERC721AQueryable. */ interface IERC721AQueryable is IERC721A { /** * Invalid query range (`start` >= `stop`). */ error InvalidQueryRange(); /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory); /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory); /** * @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 {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view returns (uint256[] memory); /** * @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 {ERC721AQueryable-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) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for byte related operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBytes.sol) library LibBytes { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Goated bytes storage struct that totally MOGs, no cap, fr. /// Uses less gas and bytecode than Solidity's native bytes storage. It's meta af. /// Packs length with the first 31 bytes if <255 bytes, so it’s mad tight. struct BytesStorage { bytes32 _spacer; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the bytes. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STORAGE OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sets the value of the bytes storage `$` to `s`. function set(BytesStorage storage $, bytes memory s) internal { /// @solidity memory-safe-assembly assembly { let n := mload(s) let packed := or(0xff, shl(8, n)) for { let i := 0 } 1 {} { if iszero(gt(n, 0xfe)) { i := 0x1f packed := or(n, shl(8, mload(add(s, i)))) if iszero(gt(n, i)) { break } } let o := add(s, 0x20) mstore(0x00, $.slot) for { let p := keccak256(0x00, 0x20) } 1 {} { sstore(add(p, shr(5, i)), mload(add(o, i))) i := add(i, 0x20) if iszero(lt(i, n)) { break } } break } sstore($.slot, packed) } } /// @dev Sets the value of the bytes storage `$` to `s`. function setCalldata(BytesStorage storage $, bytes calldata s) internal { /// @solidity memory-safe-assembly assembly { let packed := or(0xff, shl(8, s.length)) for { let i := 0 } 1 {} { if iszero(gt(s.length, 0xfe)) { i := 0x1f packed := or(s.length, shl(8, shr(8, calldataload(s.offset)))) if iszero(gt(s.length, i)) { break } } mstore(0x00, $.slot) for { let p := keccak256(0x00, 0x20) } 1 {} { sstore(add(p, shr(5, i)), calldataload(add(s.offset, i))) i := add(i, 0x20) if iszero(lt(i, s.length)) { break } } break } sstore($.slot, packed) } } /// @dev Sets the value of the bytes storage `$` to the empty bytes. function clear(BytesStorage storage $) internal { delete $._spacer; } /// @dev Returns whether the value stored is `$` is the empty bytes "". function isEmpty(BytesStorage storage $) internal view returns (bool) { return uint256($._spacer) & 0xff == uint256(0); } /// @dev Returns the length of the value stored in `$`. function length(BytesStorage storage $) internal view returns (uint256 result) { result = uint256($._spacer); /// @solidity memory-safe-assembly assembly { let n := and(0xff, result) result := or(mul(shr(8, result), eq(0xff, n)), mul(n, iszero(eq(0xff, n)))) } } /// @dev Returns the value stored in `$`. function get(BytesStorage storage $) internal view returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let o := add(result, 0x20) let packed := sload($.slot) let n := shr(8, packed) for { let i := 0 } 1 {} { if iszero(eq(or(packed, 0xff), packed)) { mstore(o, packed) n := and(0xff, packed) i := 0x1f if iszero(gt(n, i)) { break } } mstore(0x00, $.slot) for { let p := keccak256(0x00, 0x20) } 1 {} { mstore(add(o, i), sload(add(p, shr(5, i)))) i := add(i, 0x20) if iszero(lt(i, n)) { break } } break } mstore(result, n) // Store the length of the memory. mstore(add(o, n), 0) // Zeroize the slot after the bytes. mstore(0x40, add(add(o, n), 0x20)) // Allocate memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTES OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `subject` all occurrences of `needle` replaced with `replacement`. function replace(bytes memory subject, bytes memory needle, bytes memory replacement) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let needleLen := mload(needle) let replacementLen := mload(replacement) let d := sub(result, subject) // Memory difference. let i := add(subject, 0x20) // Subject bytes pointer. mstore(0x00, add(i, mload(subject))) // End of subject. if iszero(gt(needleLen, mload(subject))) { let subjectSearchEnd := add(sub(mload(0x00), needleLen), 1) let h := 0 // The hash of `needle`. if iszero(lt(needleLen, 0x20)) { h := keccak256(add(needle, 0x20), needleLen) } let s := mload(add(needle, 0x20)) for { let m := shl(3, sub(0x20, and(needleLen, 0x1f))) } 1 {} { let t := mload(i) // Whether the first `needleLen % 32` bytes of `subject` and `needle` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(i, needleLen), h)) { mstore(add(i, d), t) i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. for { let j := 0 } 1 {} { mstore(add(add(i, d), j), mload(add(add(replacement, 0x20), j))) j := add(j, 0x20) if iszero(lt(j, replacementLen)) { break } } d := sub(add(d, replacementLen), needleLen) if needleLen { i := add(i, needleLen) if iszero(lt(i, subjectSearchEnd)) { break } continue } } mstore(add(i, d), t) i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } } } let end := mload(0x00) let n := add(sub(d, add(result, 0x20)), end) // Copy the rest of the bytes one word at a time. for {} lt(i, end) { i := add(i, 0x20) } { mstore(add(i, d), mload(i)) } let o := add(i, d) mstore(o, 0) // Zeroize the slot after the bytes. mstore(0x40, add(o, 0x20)) // Allocate memory. mstore(result, n) // Store the length. } } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(bytes memory subject, bytes memory needle, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { result := not(0) // Initialize to `NOT_FOUND`. for { let subjectLen := mload(subject) } 1 {} { if iszero(mload(needle)) { result := from if iszero(gt(from, subjectLen)) { break } result := subjectLen break } let needleLen := mload(needle) let subjectStart := add(subject, 0x20) subject := add(subjectStart, from) let end := add(sub(add(subjectStart, subjectLen), needleLen), 1) let m := shl(3, sub(0x20, and(needleLen, 0x1f))) let s := mload(add(needle, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLen))) { break } if iszero(lt(needleLen, 0x20)) { for { let h := keccak256(add(needle, 0x20), needleLen) } 1 {} { if iszero(shr(m, xor(mload(subject), s))) { if eq(keccak256(subject, needleLen), h) { result := sub(subject, subjectStart) break } } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } for {} 1 {} { if iszero(shr(m, xor(mload(subject), s))) { result := sub(subject, subjectStart) break } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(bytes memory subject, bytes memory needle) internal pure returns (uint256) { return indexOf(subject, needle, 0); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(bytes memory subject, bytes memory needle, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := not(0) // Initialize to `NOT_FOUND`. let needleLen := mload(needle) if gt(needleLen, mload(subject)) { break } let w := result let fromMax := sub(mload(subject), needleLen) if iszero(gt(fromMax, from)) { from := fromMax } let end := add(add(subject, 0x20), w) subject := add(add(subject, 0x20), from) if iszero(gt(subject, end)) { break } // As this function is not too often used, // we shall simply use keccak256 for smaller bytecode size. for { let h := keccak256(add(needle, 0x20), needleLen) } 1 {} { if eq(keccak256(subject, needleLen), h) { result := sub(subject, add(end, 1)) break } subject := add(subject, w) // `sub(subject, 1)`. if iszero(gt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(bytes memory subject, bytes memory needle) internal pure returns (uint256) { return lastIndexOf(subject, needle, type(uint256).max); } /// @dev Returns true if `needle` is found in `subject`, false otherwise. function contains(bytes memory subject, bytes memory needle) internal pure returns (bool) { return indexOf(subject, needle) != NOT_FOUND; } /// @dev Returns whether `subject` starts with `needle`. function startsWith(bytes memory subject, bytes memory needle) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let n := mload(needle) // Just using keccak256 directly is actually cheaper. let t := eq(keccak256(add(subject, 0x20), n), keccak256(add(needle, 0x20), n)) result := lt(gt(n, mload(subject)), t) } } /// @dev Returns whether `subject` ends with `needle`. function endsWith(bytes memory subject, bytes memory needle) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let n := mload(needle) let notInRange := gt(n, mload(subject)) // `subject + 0x20 + max(subject.length - needle.length, 0)`. let t := add(add(subject, 0x20), mul(iszero(notInRange), sub(mload(subject), n))) // Just using keccak256 directly is actually cheaper. result := gt(eq(keccak256(t, n), keccak256(add(needle, 0x20), n)), notInRange) } } /// @dev Returns `subject` repeated `times`. function repeat(bytes memory subject, uint256 times) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let l := mload(subject) // Subject length. if iszero(or(iszero(times), iszero(l))) { result := mload(0x40) subject := add(subject, 0x20) let o := add(result, 0x20) for {} 1 {} { // Copy the `subject` one word at a time. for { let j := 0 } 1 {} { mstore(add(o, j), mload(add(subject, j))) j := add(j, 0x20) if iszero(lt(j, l)) { break } } o := add(o, l) times := sub(times, 1) if iszero(times) { break } } mstore(o, 0) // Zeroize the slot after the bytes. mstore(0x40, add(o, 0x20)) // Allocate memory. mstore(result, sub(o, add(result, 0x20))) // Store the length. } } } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(bytes memory subject, uint256 start, uint256 end) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let l := mload(subject) // Subject length. if iszero(gt(l, end)) { end := l } if iszero(gt(l, start)) { start := l } if lt(start, end) { result := mload(0x40) let n := sub(end, start) let i := add(subject, start) let w := not(0x1f) // Copy the `subject` one word at a time, backwards. for { let j := and(add(n, 0x1f), w) } 1 {} { mstore(add(result, j), mload(add(i, j))) j := add(j, w) // `sub(j, 0x20)`. if iszero(j) { break } } let o := add(add(result, 0x20), n) mstore(o, 0) // Zeroize the slot after the bytes. mstore(0x40, add(o, 0x20)) // Allocate memory. mstore(result, n) // Store the length. } } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the bytes. /// `start` is a byte offset. function slice(bytes memory subject, uint256 start) internal pure returns (bytes memory result) { result = slice(subject, start, type(uint256).max); } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. Faster than Solidity's native slicing. function sliceCalldata(bytes calldata subject, uint256 start, uint256 end) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { end := xor(end, mul(xor(end, subject.length), lt(subject.length, end))) start := xor(start, mul(xor(start, subject.length), lt(subject.length, start))) result.offset := add(subject.offset, start) result.length := mul(lt(start, end), sub(end, start)) } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the bytes. /// `start` is a byte offset. Faster than Solidity's native slicing. function sliceCalldata(bytes calldata subject, uint256 start) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { start := xor(start, mul(xor(start, subject.length), lt(subject.length, start))) result.offset := add(subject.offset, start) result.length := mul(lt(start, subject.length), sub(subject.length, start)) } } /// @dev Reduces the size of `subject` to `n`. /// If `n` is greater than the size of `subject`, this will be a no-op. function truncate(bytes memory subject, uint256 n) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := subject mstore(mul(lt(n, mload(result)), result), n) } } /// @dev Returns a copy of `subject`, with the length reduced to `n`. /// If `n` is greater than the size of `subject`, this will be a no-op. function truncatedCalldata(bytes calldata subject, uint256 n) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { result.offset := subject.offset result.length := xor(n, mul(xor(n, subject.length), lt(subject.length, n))) } } /// @dev Returns all the indices of `needle` in `subject`. /// The indices are byte offsets. function indicesOf(bytes memory subject, bytes memory needle) internal pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { let searchLen := mload(needle) if iszero(gt(searchLen, mload(subject))) { result := mload(0x40) let i := add(subject, 0x20) let o := add(result, 0x20) let subjectSearchEnd := add(sub(add(i, mload(subject)), searchLen), 1) let h := 0 // The hash of `needle`. if iszero(lt(searchLen, 0x20)) { h := keccak256(add(needle, 0x20), searchLen) } let s := mload(add(needle, 0x20)) for { let m := shl(3, sub(0x20, and(searchLen, 0x1f))) } 1 {} { let t := mload(i) // Whether the first `searchLen % 32` bytes of `subject` and `needle` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(i, searchLen), h)) { i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } continue } } mstore(o, sub(i, add(subject, 0x20))) // Append to `result`. o := add(o, 0x20) i := add(i, searchLen) // Advance `i` by `searchLen`. if searchLen { if iszero(lt(i, subjectSearchEnd)) { break } continue } } i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } } mstore(result, shr(5, sub(o, add(result, 0x20)))) // Store the length of `result`. // Allocate memory for result. // We allocate one more word, so this array can be recycled for {split}. mstore(0x40, add(o, 0x20)) } } } /// @dev Returns a arrays of bytess based on the `delimiter` inside of the `subject` bytes. function split(bytes memory subject, bytes memory delimiter) internal pure returns (bytes[] memory result) { uint256[] memory indices = indicesOf(subject, delimiter); /// @solidity memory-safe-assembly assembly { let w := not(0x1f) let indexPtr := add(indices, 0x20) let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1))) mstore(add(indicesEnd, w), mload(subject)) mstore(indices, add(mload(indices), 1)) for { let prevIndex := 0 } 1 {} { let index := mload(indexPtr) mstore(indexPtr, 0x60) if iszero(eq(index, prevIndex)) { let element := mload(0x40) let l := sub(index, prevIndex) mstore(element, l) // Store the length of the element. // Copy the `subject` one word at a time, backwards. for { let o := and(add(l, 0x1f), w) } 1 {} { mstore(add(element, o), mload(add(add(subject, prevIndex), o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } mstore(add(add(element, 0x20), l), 0) // Zeroize the slot after the bytes. // Allocate memory for the length and the bytes, rounded up to a multiple of 32. mstore(0x40, add(element, and(add(l, 0x3f), w))) mstore(indexPtr, element) // Store the `element` into the array. } prevIndex := add(index, mload(delimiter)) indexPtr := add(indexPtr, 0x20) if iszero(lt(indexPtr, indicesEnd)) { break } } result := indices if iszero(mload(delimiter)) { result := add(indices, 0x20) mstore(result, sub(mload(indices), 2)) } } } /// @dev Returns a concatenated bytes of `a` and `b`. /// Cheaper than `bytes.concat()` and does not de-align the free memory pointer. function concat(bytes memory a, bytes memory b) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let w := not(0x1f) let aLen := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(aLen, 0x20), w) } 1 {} { mstore(add(result, o), mload(add(a, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let bLen := mload(b) let output := add(result, aLen) // Copy `b` one word at a time, backwards. for { let o := and(add(bLen, 0x20), w) } 1 {} { mstore(add(output, o), mload(add(b, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let totalLen := add(aLen, bLen) let last := add(add(result, 0x20), totalLen) mstore(last, 0) // Zeroize the slot after the bytes. mstore(result, totalLen) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate memory. } } /// @dev Returns whether `a` equals `b`. function eq(bytes memory a, bytes memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small bytes. function eqs(bytes memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`. let x := not(or(m, or(b, add(m, and(b, m))))) let r := shl(7, iszero(iszero(shr(128, x)))) r := or(r, shl(6, iszero(iszero(shr(64, 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 result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))), xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20))))) } } /// @dev Returns 0 if `a == b`, -1 if `a < b`, +1 if `a > b`. /// If `a` == b[:a.length]`, and `a.length < b.length`, returns -1. function cmp(bytes memory a, bytes memory b) internal pure returns (int256 result) { /// @solidity memory-safe-assembly assembly { let aLen := mload(a) let bLen := mload(b) let n := and(xor(aLen, mul(xor(aLen, bLen), lt(bLen, aLen))), not(0x1f)) if n { for { let i := 0x20 } 1 {} { let x := mload(add(a, i)) let y := mload(add(b, i)) if iszero(or(xor(x, y), eq(i, n))) { i := add(i, 0x20) continue } result := sub(gt(x, y), lt(x, y)) break } } // forgefmt: disable-next-item if iszero(result) { let l := 0x201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201 let x := and(mload(add(add(a, 0x20), n)), shl(shl(3, byte(sub(aLen, n), l)), not(0))) let y := and(mload(add(add(b, 0x20), n)), shl(shl(3, byte(sub(bLen, n), l)), not(0))) result := sub(gt(x, y), lt(x, y)) if iszero(result) { result := sub(gt(aLen, bLen), lt(aLen, bLen)) } } } } /// @dev Directly returns `a` without copying. function directReturn(bytes memory a) internal pure { /// @solidity memory-safe-assembly assembly { // Assumes that the bytes does not start from the scratch space. let retStart := sub(a, 0x20) let retUnpaddedSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the bytes is produced // by a method that doesn't zero right pad. mstore(add(retStart, retUnpaddedSize), 0) mstore(retStart, 0x20) // Store the return offset. // End the transaction, returning the bytes. return(retStart, and(not(0x1f), add(0x1f, retUnpaddedSize))) } } /// @dev Directly returns `a` with minimal copying. function directReturn(bytes[] memory a) internal pure { /// @solidity memory-safe-assembly assembly { let n := mload(a) // `a.length`. let o := add(a, 0x20) // Start of elements in `a`. let u := a // Highest memory slot. let w := not(0x1f) for { let i := 0 } iszero(eq(i, n)) { i := add(i, 1) } { let c := add(o, shl(5, i)) // Location of pointer to `a[i]`. let s := mload(c) // `a[i]`. let l := mload(s) // `a[i].length`. let r := and(l, 0x1f) // `a[i].length % 32`. let z := add(0x20, and(l, w)) // Offset of last word in `a[i]` from `s`. // If `s` comes before `o`, or `s` is not zero right padded. if iszero(lt(lt(s, o), or(iszero(r), iszero(shl(shl(3, r), mload(add(s, z))))))) { let m := mload(0x40) mstore(m, l) // Copy `a[i].length`. for {} 1 {} { mstore(add(m, z), mload(add(s, z))) // Copy `a[i]`, backwards. z := add(z, w) // `sub(z, 0x20)`. if iszero(z) { break } } let e := add(add(m, 0x20), l) mstore(e, 0) // Zeroize the slot after the copied bytes. mstore(0x40, add(e, 0x20)) // Allocate memory. s := m } mstore(c, sub(s, o)) // Convert to calldata offset. let t := add(l, add(s, 0x20)) if iszero(lt(t, u)) { u := t } } let retStart := add(a, w) // Assumes `a` doesn't start from scratch space. mstore(retStart, 0x20) // Store the return offset. return(retStart, add(0x40, sub(u, retStart))) // End the transaction. } } /// @dev Returns the word at `offset`, without any bounds checks. function load(bytes memory a, uint256 offset) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := mload(add(add(a, 0x20), offset)) } } /// @dev Returns the word at `offset`, without any bounds checks. function loadCalldata(bytes calldata a, uint256 offset) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := calldataload(add(a.offset, offset)) } } /// @dev Returns a slice representing a static struct in the calldata. Performs bounds checks. function staticStructInCalldata(bytes calldata a, uint256 offset) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { let l := sub(a.length, 0x20) result.offset := add(a.offset, offset) result.length := sub(a.length, offset) if or(shr(64, or(l, a.offset)), gt(offset, l)) { revert(l, 0x00) } } } /// @dev Returns a slice representing a dynamic struct in the calldata. Performs bounds checks. function dynamicStructInCalldata(bytes calldata a, uint256 offset) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { let l := sub(a.length, 0x20) let s := calldataload(add(a.offset, offset)) // Relative offset of `result` from `a.offset`. result.offset := add(a.offset, s) result.length := sub(a.length, s) if or(shr(64, or(s, or(l, a.offset))), gt(offset, l)) { revert(l, 0x00) } } } /// @dev Returns bytes in calldata. Performs bounds checks. function bytesInCalldata(bytes calldata a, uint256 offset) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { let l := sub(a.length, 0x20) let s := calldataload(add(a.offset, offset)) // Relative offset of `result` from `a.offset`. result.offset := add(add(a.offset, s), 0x20) result.length := calldataload(add(a.offset, s)) // forgefmt: disable-next-item if or(shr(64, or(result.length, or(s, or(l, a.offset)))), or(gt(add(s, result.length), l), gt(offset, l))) { revert(l, 0x00) } } } /// @dev Returns empty calldata bytes. For silencing the compiler. function emptyCalldata() internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { result.length := 0 } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * 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(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); /** * `_sequentialUpTo()` must be greater than `_startTokenId()`. */ error SequentialUpToTooSmall(); /** * The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`. */ error SequentialMintExceedsLimit(); /** * Spot minting requires a `tokenId` greater than `_sequentialUpTo()`. */ error SpotMintTokenIdTooSmall(); /** * Cannot mint over a token that already exists. */ error TokenAlreadyExists(); /** * The feature is not compatible with spot mints. */ error NotCompatibleWithSpotMints(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @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 v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @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); }
{ "evmVersion": "paris", "optimizer": { "enabled": true, "mode": "3" }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_royaltiesReceiver","type":"address"},{"internalType":"bytes32","name":"_wlMerkleRoot","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotCompatibleWithSpotMints","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"RoyaltyOverflow","type":"error"},{"inputs":[],"name":"RoyaltyReceiverIsZeroAddress","type":"error"},{"inputs":[],"name":"SequentialMintExceedsLimit","type":"error"},{"inputs":[],"name":"SequentialUpToTooSmall","type":"error"},{"inputs":[],"name":"SpotMintTokenIdTooSmall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","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":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","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":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_baseTokenSuffix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_receivers","type":"address[]"}],"name":"batchAirdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"checkWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership","name":"ownership","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRevealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_new_suffix","type":"string"}],"name":"setBaseTokenSuffix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_receiver","type":"address"},{"internalType":"uint96","name":"_amount","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_live","type":"bool"}],"name":"setIsMintLive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_reveal","type":"bool"}],"name":"setIsRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethPrice","type":"uint256"}],"name":"setPublicPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethPrice","type":"uint256"}],"name":"setWLPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_wlMerkleRoot","type":"bytes32"}],"name":"setWlMerkleRoot","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":"tokenId","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":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_to","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wlMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wlPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
860961640000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e689b4f46eeac87784c68dfd48115f5d8011dcf51c7d7b717edd99fc832d153120da7d4ed0c1bdcaaaffaa3283154a12e338534e000000000000000000000000000000000000000000000000000000000000002568747470733a2f2f7777772e63686f6d706965736e66742e636f6d2f6170692f697066732f000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x000400000000000200080000000000020000006004100270000004df0340019700030000003103550002000000010355000004df0040019d0000008004000039000000400040043f00000001002001900000002e0000c13d000000040030008c0000004d0000413d000000000201043b000000e002200270000004f80020009c000000680000a13d000004f90020009c0000007f0000213d0000050b0020009c000001420000a13d0000050c0020009c000002240000a13d0000050d0020009c000003b00000213d000005100020009c000003f00000613d000005110020009c0000004d0000c13d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000101043b137611ef0000040f000000400200043d000800000002001d13760e9b0000040f0000000801000029000004df0010009c000004df01008041000000400110021000000557011001c7000013770001042e0000000002000416000000000002004b0000004d0000c13d0000001f02300039000004e0022001970000008002200039000000400020043f0000001f0530018f000004e10630019800000080026000390000003e0000613d000000000701034f000000007807043c0000000004840436000000000024004b0000003a0000c13d000000000005004b0000004b0000613d000000000161034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000600030008c0000004f0000813d00000000010000190000137800010430000000800200043d000004e20020009c0000004d0000213d0000001f01200039000000000031004b0000000004000019000004e304008041000004e301100197000000000001004b0000000005000019000004e305004041000004e30010009c000000000504c019000000000005004b0000004d0000c13d00000080012000390000000001010433000004e20010009c000000e10000a13d0000056701000041000000000010043f0000004101000039000000040010043f000005680100004100001378000104300000051c0020009c000000b80000a13d0000051d0020009c000001530000a13d0000051e0020009c0000022f0000a13d0000051f0020009c000003b90000213d000005220020009c000004110000613d000005230020009c0000004d0000c13d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000101043b000004e40010009c0000004d0000213d13760fd00000040f000006820000013d000004fa0020009c000001620000a13d000004fb0020009c0000023f0000a13d000004fc0020009c000003d10000213d000004ff0020009c0000041e0000613d000005000020009c0000004d0000c13d000000440030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000800000002001d000004e40020009c0000004d0000213d0000002401100370000000000101043b000004e20010009c0000004d0000213d0000000401100039000000000203001913760e800000040f0000001403000039000000400500043d000500000005001d0000000004350436000600000004001d000000080300002900000060033002100000000000340435000800000001001d000700000002001d0000003402000039000000000105001913760ddf0000040f000000050100002900000000020104330000000601000029137613570000040f0000000c02000039000000000202041a000600000002001d000500000001001d0000000003000031000000080100002900000007020000291376124d0000040f00000006020000290000000503000029137613320000040f000000000001004b000003340000013d0000052e0020009c000001f50000213d000005360020009c000002550000213d0000053a0020009c0000042b0000613d0000053b0020009c0000044c0000613d0000053c0020009c0000004d0000c13d0000000001000416000000000001004b0000004d0000c13d0000000203000039000000000203041a000000010420019000000001012002700000007f0110618f0000001f0010008c00000000050000390000000105002039000000000552013f00000001005001900000070e0000c13d000000800010043f000000000004004b0000082c0000613d000000000030043f000000000001004b0000000002000019000008310000613d000004e9030000410000000002000019000000000403041a000000a005200039000000000045043500000001033000390000002002200039000000000012004b000000d90000413d000008310000013d0000001f041000390000057f044001970000003f044000390000057f04400197000000400600043d0000000004460019000000000064004b00000000050000390000000105004039000004e20040009c000000620000213d0000000100500190000000620000c13d0000008003300039000000400040043f000800000006001d0000000004160436000700000004001d000000a0022000390000000004210019000000000034004b0000004d0000213d000000000001004b0000000706000029000001020000613d000000000300001900000000043600190000000005230019000000000505043300000000005404350000002003300039000000000013004b000000fb0000413d000000080110002900000020011000390000000000010435000000a00100043d000600000001001d000004e40010009c0000004d0000213d000000400300043d000004e50030009c000000620000213d000000c00b00043d0000004001300039000000400010043f00000009010000390000000006130436000004e6010000410000000000160435000000400100043d000004e50010009c000000620000213d0000004002100039000000400020043f00000004020000390000000002210436000004e70400004100000000004204350000000005030433000004e20050009c000000620000213d0000000204000039000000000704041a000000010870019000000001077002700000007f0770618f0000001f0070008c00000000090000390000000109002039000000000098004b0000070e0000c13d000000200070008c0000013a0000413d000000000040043f0000001f085000390000000508800270000004e80880009a000000200050008c000004e9080040410000001f077000390000000507700270000004e80770009a000000000078004b0000013a0000813d000000000008041b0000000108800039000000000078004b000001360000413d0000001f0050008c000009380000a13d000000000040043f0000057f085001980000094f0000c13d0000002007000039000004e9060000410000095b0000013d000005150020009c000002660000213d000005190020009c000004650000613d0000051a0020009c000004720000613d0000051b0020009c0000004d0000c13d0000000001000416000000000001004b0000004d0000c13d000004ee01000041000000000101041a000004e401100197000000800010043f0000053e01000041000013770001042e000005270020009c000002ab0000213d0000052b0020009c000004930000613d0000052c0020009c000004a30000613d0000052d0020009c0000004d0000c13d0000000001000416000000000001004b0000004d0000c13d0000000f01000039000000000101041a0000ff0000100190000003eb0000013d000005040020009c000003160000213d000005080020009c000004c80000613d000005090020009c000004ec0000613d0000050a0020009c0000004d0000c13d000000440030008c0000004d0000413d0000000402100370000000000202043b000600000002001d0000002402100370000000000202043b000004e20020009c0000004d0000213d0000002304200039000000000034004b0000004d0000813d000700040020003d0000000701100360000000000101043b000800000001001d000004e20010009c0000004d0000213d000000240120003900000008020000290000000502200210000300000001001d000500000002001d000400000012001d000000040030006b0000004d0000213d0000000101000039000000000101041a0000058001100167000000000200041a00000000011200190000000602000029000000000021001a000006eb0000413d00000000012100190000000902000039000000000202041a000000000021004b0000089d0000813d0000000c01000039000000000101041a000200000001001d00000000010004110000006001100210000000a00010043f0000001401000039000000800010043f000000c001000039000000400010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000546011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b00000005020000290000003f022000390000054702200197000000400300043d0000000002230019000000000032004b00000000040000390000000104004039000004e20020009c000000620000213d0000000100400190000000620000c13d000000400020043f000000080200002900000000022304360000000405000029000000000050007c0000004d0000213d000000080000006b000001e10000613d0000000704000029000000200440003900000002044003670000000005030019000000030700002900000004080000290000002005500039000000004604043c00000000006504350000002007700039000000000087004b000001bf0000413d0000000003030433000000000003004b000001e10000613d0000000503300210000700000023001d0000000043020434000800000004001d000000000031004b000000000300003900000020030020390000000000130435000000200130015f000000000202043300000000002104350000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b0000000803000029000000070030006c0000000002030019000001ca0000413d000000020010006c00000c850000c13d0000000f01000039000000000101041a000000ff0110018f13760ffc0000040f0000000d01000039000000000201041a0000000601000029137610100000040f0000000002000416000000000012004b000000000100003900000001010080391376101e0000040f00000000010004110000000602000029137612c90000040f0000000001000019000013770001042e0000052f0020009c000003370000213d000005330020009c000005510000613d000005340020009c000005700000613d000005350020009c0000004d0000c13d0000053d010000410000000c0010043f0000000001000411000000000010043f000005430100004100000000001004430000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f000000010020019000000b040000613d000000000101043b000800000001001d0000000001000414000004df0010009c000004df01008041000000c00110021000000542011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b00000008020000290000056f0220009a000000000021041b0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d02000039000000020300003900000570040000410000078d0000013d000005120020009c000005750000613d000005130020009c0000059a0000613d000005140020009c0000004d0000c13d0000000001000416000000000001004b0000004d0000c13d0000000e01000039000007970000013d000005240020009c000005dd0000613d000005250020009c000006790000613d000005260020009c0000004d0000c13d0000000001000416000000000001004b0000004d0000c13d13760df10000040f0000002002000039000000400300043d000800000003001d000000000223043613760dad0000040f000008380000013d000005010020009c000006890000613d000005020020009c000006b80000613d000005030020009c0000004d0000c13d000000240030008c0000004d0000413d0000000001000416000000000001004b0000004d0000c13d13760e3d0000040f000800000001001d137612750000040f0000000f01000039000000000201041a0000058102200197000000080000006b000000010220c1bf000000000021041b0000000001000019000013770001042e000005370020009c000006c90000613d000005380020009c000006f10000613d000005390020009c0000004d0000c13d0000000001000416000000000001004b0000004d0000c13d0000000101000039000000000101041a0000058001100167000000000200041a0000000001120019000000800010043f0000053e01000041000013770001042e000005160020009c000007000000613d000005170020009c000007140000613d000005180020009c0000004d0000c13d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000004e20020009c0000004d0000213d0000002304200039000000000034004b0000004d0000813d0000000404200039000000000141034f000000000101043b000400000001001d000004e20010009c0000004d0000213d000300240020003d000000040100002900000005011002100000000301100029000000000031004b0000004d0000213d0000000101000039000000000101041a0000058002100167000000000100041a00000000042100190000000405000029000000000054001a000006eb0000413d00000000025400190000000903000039000000000303041a000000000032004b0000089d0000813d000004ee02000041000000000202041a0000000003000411000000000023004b000008170000c13d000200000004001d000000000005004b00000a540000c13d000000800100003900000002020000290000002003100039000000000023043500000002020000290000000000210435000004df0010009c000004df0100804100000040011002100000000002000414000004df0020009c000004df02008041000000c002200210000000000112019f00000548011001c70000800d02000039000000010300003900000d5c0000013d000005280020009c000007710000613d000005290020009c000007760000613d0000052a0020009c0000004d0000c13d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000502043b000004e20050009c0000004d0000213d0000002302500039000000000032004b0000004d0000813d0000000406500039000000000261034f000000000202043b000004e20020009c000000620000213d0000001f072000390000057f077001970000003f077000390000057f077001970000054c0070009c000000620000213d00000024055000390000008007700039000000400070043f000000800020043f0000000005520019000000000035004b0000004d0000213d0000002003600039000000000331034f0000057f052001980000001f0620018f000000a001500039000002db0000613d000000a007000039000000000803034f000000008908043c0000000007970436000000000017004b000002d70000c13d000000000006004b000002e80000613d000000000353034f0000000305600210000000000601043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f0000000000310435000000a0012000390000000000010435000004ee01000041000000000101041a0000000002000411000000000012004b000008170000c13d000000800200043d000004e20020009c000000620000213d0000000a01000039000000000501041a000000010050019000000001035002700000007f0330618f0000001f0030008c00000000060000390000000106002039000000000565013f00000001005001900000070e0000c13d000000200030008c0000030e0000413d000000000010043f0000001f052000390000000505500270000004f10550009a000000200020008c000004f2050040410000001f033000390000000503300270000004f10330009a000000000035004b0000030e0000813d000000000005041b0000000105500039000000000035004b0000030a0000413d0000001f0020008c00000c3e0000a13d000000000010043f0000057f0420019800000d070000c13d000000a005000039000004f20300004100000d150000013d000005050020009c000007930000613d000005060020009c000003e50000613d000005070020009c0000004d0000c13d000000440030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000004e40020009c0000004d0000213d0000002401100370000000000101043b000800000001001d000004e40010009c0000004d0000213d000000000020043f0000000701000039000000200010043f00000040020000390000000001000019137613570000040f000000080200002913760ebd0000040f000000000101041a000000ff001001900000000001000039000000010100c039000006820000013d000005300020009c0000079b0000613d000005310020009c000007e50000613d000005320020009c0000004d0000c13d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000101043b000000000001004b000006fc0000613d000700000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000201041a000000000002004b0000036f0000c13d000000000100041a0000000702000029000000000021004b000006fc0000a13d0000000001020019000000010110008a000800000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000201041a000000000002004b00000008010000290000035c0000613d00000551002001980000000701000029000006fc0000c13d000800000002001d000000000010043f0000000601000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d0000000802000029000004e402200197000000000101043b000500000001001d000000000301041a0000000001000411000004e401100197000600000002001d000000000021004b000009900000613d000000000031004b000009900000613d000400000001001d000300000003001d0000000601000029000000000010043f0000000701000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b0000000402000029000000000020043f000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000ff001001900000000303000029000009900000c13d0000056a01000041000000000010043f000005560100004100001378000104300000050e0020009c000007f50000613d0000050f0020009c0000004d0000c13d0000000001000416000000000001004b0000004d0000c13d0000000d01000039000007970000013d000005200020009c000008020000613d000005210020009c0000004d0000c13d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000101043b000004e40010009c0000004d0000213d000000000200041a000000000002004b000008420000613d0003000100200094000008970000c13d000000800300003900000060020000390000000001030019000800000003001d13760eae0000040f000008380000013d000004fd0020009c000003e50000613d000004fe0020009c0000004d0000c13d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000101043b000004e40010009c0000004d0000213d0000053d020000410000000c0020043f000000000010043f0000000c010000390000002002000039137613570000040f000007970000013d0000000001000416000000000001004b0000004d0000c13d0000000f01000039000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f0000053e01000041000013770001042e000000840030008c0000004d0000413d0000000402100370000000000202043b000800000002001d000004e40020009c0000004d0000213d0000002402100370000000000202043b000700000002001d000004e40020009c0000004d0000213d0000006402100370000000000402043b000004e20040009c0000004d0000213d0000002302400039000000000032004b0000004d0000813d0000000402400039000000000121034f000000000201043b000000240140003913760e480000040f00000044020000390000000202200367000000000302043b000000000401001900000008010000290000000702000029137610320000040f0000000001000019000013770001042e000000240030008c0000004d0000413d0000000001000416000000000001004b0000004d0000c13d137612750000040f00000004010000390000000201100367000000000101043b0000000902000039000000000012041b0000000001000019000013770001042e000000240030008c0000004d0000413d0000000001000416000000000001004b0000004d0000c13d137612750000040f00000004010000390000000201100367000000000101043b0000000d02000039000000000012041b0000000001000019000013770001042e000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000301043b00000579003001980000004d0000c13d00000001010000390000057a023001970000057b0020009c000004480000613d0000057c0020009c000004480000613d0000057d0020009c000004480000613d000000e003300270000005300030009c000000000100003900000001010060390000053a0030009c00000001011061bf000004480000613d000005300030009c000004480000613d0000057e0020009c00000000010000390000000101006039000000010110018f000000800010043f0000053e01000041000013770001042e000000440030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000004e40020009c0000004d0000213d0000002401100370000000000101043b0000056d0010009c0000004d0000213d000004ee03000041000000000303041a0000000004000411000000000034004b000008170000c13d0000056d01100197000027110010008c000008f00000413d0000057801000041000000000010043f00000541010000410000137800010430000000240030008c0000004d0000413d0000000001000416000000000001004b0000004d0000c13d137612750000040f00000004010000390000000201100367000000000101043b0000000c02000039000000000012041b0000000001000019000013770001042e000000440030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000800000002001d000004e40020009c0000004d0000213d0000000102000039000000000202041a0000058002200167000000000300041a00000000022300190000002401100370000000000101043b000000000012001a000006eb0000413d000700000001001d00000000011200190000000902000039000000000202041a000000000021004b0000000001000039000000010100403913760fe80000040f137612750000040f00000008010000290000000702000029137612c90000040f0000000001000019000013770001042e000000240030008c0000004d0000413d0000000001000416000000000001004b0000004d0000c13d13760e3d0000040f000800000001001d137612750000040f0000000f01000039000000000201041a0000058202200197000000080000006b000001000220c1bf000000000021041b0000000001000019000013770001042e000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000101043b000800000001001d000004e40010009c0000004d0000213d000004ee01000041000000000101041a0000000002000411000000000012004b000008170000c13d00000564010000410000000000100443000000000100041000000004001004430000000001000414000004df0010009c000004df01008041000000c00110021000000565011001c70000800a02000039137613710000040f000000010020019000000b040000613d000000000301043b0000000001000414000004df0010009c000004df01008041000000c001100210000000000003004b000008f60000c13d0000000802000029000008fa0000013d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d00000080030000390000000401100370000000000201043b000000000002004b000008c60000613d000000000100041a000000000021004b000008c60000a13d000700000002001d000800000002001d000000000020043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b000008a70000c13d0000000802000029000000000002004b000000010220008a000004d60000c13d000006eb0000013d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000502043b000004e20050009c0000004d0000213d0000002302500039000000000032004b0000004d0000813d0000000406500039000000000261034f000000000202043b000004e20020009c000000620000213d0000001f072000390000057f077001970000003f077000390000057f077001970000054c0070009c000000620000213d00000024055000390000008007700039000000400070043f000000800020043f0000000005520019000000000035004b0000004d0000213d0000002003600039000000000331034f0000057f052001980000001f0620018f000000a001500039000005160000613d000000a007000039000000000803034f000000008908043c0000000007970436000000000017004b000005120000c13d000000000006004b000005230000613d000000000353034f0000000305600210000000000601043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f0000000000310435000000a0012000390000000000010435000004ee01000041000000000101041a0000000002000411000000000012004b000008170000c13d000000800200043d000004e20020009c000000620000213d0000000b01000039000000000501041a000000010050019000000001035002700000007f0330618f0000001f0030008c00000000060000390000000106002039000000000565013f00000001005001900000070e0000c13d000000200030008c000005490000413d000000000010043f0000001f0520003900000005055002700000054d0550009a000000200020008c0000054e050040410000001f0330003900000005033002700000054d0330009a000000000035004b000005490000813d000000000005041b0000000105500039000000000035004b000005450000413d0000001f0020008c00000c490000a13d000000000010043f0000057f0420019800000d2f0000c13d000000a0050000390000054e0300004100000d3d0000013d0000000001000416000000000001004b0000004d0000c13d0000000b03000039000000000203041a000000010420019000000001012002700000007f0110618f0000001f0010008c00000000050000390000000105002039000000000552013f00000001005001900000070e0000c13d000000800010043f000000000004004b0000082c0000613d000000000030043f000000000001004b0000000002000019000008310000613d0000054e030000410000000002000019000000000403041a000000a005200039000000000045043500000001033000390000002002200039000000000012004b000005680000413d000008310000013d000000000103001913760e2b0000040f13760ecd0000040f0000000001000019000013770001042e000000240030008c0000004d0000413d0000000102000039000000000202041a0000058002200167000000000300041a00000000022300190000000401100370000000000101043b000000000012001a000006eb0000413d000800000001001d00000000011200190000000902000039000000000202041a000000000021004b0000000001000039000000010100403913760fe80000040f0000000f01000039000000000101041a000000ff0110018f13760ffc0000040f0000000e01000039000000000201041a0000000801000029137610100000040f0000000002000416000000000012004b000000000100003900000001010080391376101e0000040f00000000010004110000000802000029137612c90000040f0000000001000019000013770001042e000000440030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000800000002001d000004e40020009c0000004d0000213d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039000700000002001d000000000012004b0000004d0000c13d0000000001000411000000000010043f0000000701000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000201041a00000581022001970000000703000029000000000232019f000000000021041b000000400100043d0000000000310435000004df0010009c000004df0100804100000040011002100000000002000414000004df0020009c000004df02008041000000c002200210000000000112019f00000558011001c70000800d0200003900000003030000390000055904000041000000000500041100000008060000290000078e0000013d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000004e20020009c0000004d0000213d0000002304200039000000000034004b0000004d0000813d000700040020003d0000000704100360000000000504043b000004e20050009c0000004d0000213d000000050450021000000000024200190000002402200039000000000032004b0000004d0000213d000000800050043f000000a002400039000000400020043f000000000005004b0000061f0000c13d00000020010000390000000001120436000000800300043d00000000003104350000004001200039000000000003004b000008390000613d00000080040000390000000005000019000000200440003900000000060404330000000087060434000004e40770019700000000077104360000000008080433000004e208800197000000000087043500000040076000390000000007070433000000000007004b0000000007000039000000010700c039000000400810003900000000007804350000006006600039000000000606043300000562066001970000006007100039000000000067043500000080011000390000000105500039000000000035004b000006010000413d000008390000013d000000200460008c00000080036000390000000000230435000000400200043d000005f80000613d00000000060400190000000703400029000000000331034f000000000403043b0000054c0020009c000000620000213d0000008003200039000000400030043f0000006003200039000000000003043500000040032000390000000000030435000000200320003900000000000304350000000000020435000000000004004b0000061a0000613d000000000300041a000000000043004b0000061a0000a13d000600000006001d000800000004001d000000000040043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b000006480000c13d0000000804000029000000010440008a000006340000013d000000400100043d0000054c0010009c0000000803000029000000620000213d0000008002100039000000400020043f0000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000000030043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000400200043d0000054c0020009c0000000606000029000000620000213d000000000301034f0000000201000367000000000303043b000000000303041a0000008004200039000000400040043f0000006004200039000000e805300270000000000054043500000551003001980000000004000039000000010400c03900000040052000390000000000450435000004e4043001970000000004420436000000a003300270000004e20330019700000000003404350000061a0000013d000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000101043b1376127f0000040f000004e401100197000000400200043d0000000000120435000004df0020009c000004df0200804100000040012002100000053f011001c7000013770001042e000000240030008c0000004d0000413d0000000401100370000000000101043b000800000001001d000004e40010009c0000004d0000213d000004ee01000041000000000101041a0000000002000411000000000012004b000008170000c13d0000053d010000410000000c0010043f0000000801000029000000000010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000542011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000600000001001d000000000101041a000700000001001d000005430100004100000000001004430000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f000000010020019000000b040000613d000000000101043b000000070010006c000009430000a13d0000054501000041000000000010043f00000541010000410000137800010430000000240030008c0000004d0000413d0000000401100370000000000101043b000004e40010009c0000004d0000213d000004ee02000041000000000202041a0000000003000411000000000023004b000008170000c13d000000000001004b000009460000c13d0000054001000041000000000010043f00000541010000410000137800010430000000240030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000401100370000000000201043b000000000002004b000008d80000613d000000000100041a000000000021004b000008d80000a13d000700000002001d000800000002001d000000000020043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b000008cd0000c13d0000000802000029000000000002004b000000010220008a000006d60000c13d0000056701000041000000000010043f0000001101000039000000040010043f00000568010000410000137800010430000000440030008c0000004d0000413d0000000402100370000000000202043b000700000002001d000004e40020009c0000004d0000213d0000002401100370000000000101043b000000000001004b000008460000c13d0000057401000041000000000010043f000005560100004100001378000104300000000001000416000000000001004b0000004d0000c13d0000000303000039000000000203041a000000010420019000000001012002700000007f0110618f0000001f0010008c00000000050000390000000105002039000000000552013f00000001005001900000081b0000613d0000056701000041000000000010043f0000002201000039000000040010043f00000568010000410000137800010430000000640030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000000402100370000000000202043b000400000002001d000004e40020009c0000004d0000213d0000004402100370000000000202043b0000002401100370000000000301043b000000000023004b000008420000813d000000000100041a000000000012004b0000000002018019000300000002001d000000010030008c000000010300a0390000000401000029000000000001004b000008990000613d000700000003001d000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000100600000003d000000000101043b0000000703000029000000030230006b00000d880000a13d000000000101041a000004e20110019800000d880000613d000000000012004b0000000002018019000200000002001d0000000501200210000000400200043d000100000002001d00000000012100190000002001100039000000400010043f000600000001001d0000054c0010009c000000620000213d00000006020000290000008001200039000000400010043f0000006001200039000000000001043500000040012000390000000000010435000000200120003900000000000104350000000000020435000000000100041a000000000031004b000000000100001900000b2a0000a13d0000000701000029000800000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b00000c540000c13d0000000801000029000000010110008a0000075d0000013d0000000001000416000000000001004b0000004d0000c13d0000000c01000039000007970000013d0000053d010000410000000c0010043f0000000001000411000000000010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000542011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000001041b0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d020000390000000203000039000005630400004100000000050004111376136c0000040f00000001002001900000004d0000613d0000000001000019000013770001042e0000000001000416000000000001004b0000004d0000c13d0000000901000039000000000101041a000000800010043f0000053e01000041000013770001042e000000440030008c0000004d0000413d0000000002000416000000000002004b0000004d0000c13d0000002402100370000000000202043b000800000002001d0000000401100370000000000101043b000000000010043f000004f401000041000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000201041a0000056d0020009c000007b70000213d000004f401000041000000000201041a0000056d012001980000000003000019000000010300c08a000000000313c0d9000000080030006b0000000003000019000000000301201900000001040000310000000005430019000000000045004b0000004d0000213d0000057f053001980000001f0630018f00000003074003670000000003540019000007cc0000613d000000000807034f000000008908043c0000000004940436000000000034004b000007c80000c13d0000006002200270000000000006004b000007da0000613d000000000457034f0000000305600210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f000000000043043500000008011000b9000027100110011a000000400300043d000000200430003900000000001404350000000000230435000004df0030009c000004df0300804100000040013002100000056e011001c7000013770001042e000000000103001913760e2b0000040f000800000001001d000700000002001d000600000003001d000000400100043d000500000001001d13760dd40000040f00000005040000290000000000040435000000080100002900000007020000290000000603000029137610320000040f0000000001000019000013770001042e000000240030008c0000004d0000413d0000000001000416000000000001004b0000004d0000c13d137612750000040f00000004010000390000000201100367000000000101043b0000000e02000039000000000012041b0000000001000019000013770001042e000004ee01000041000000000101041a0000000005000411000000000015004b000008170000c13d0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d020000390000000303000039000004f00400004100000000060000191376136c0000040f00000001002001900000004d0000613d000004ee01000041000000000001041b0000000001000019000013770001042e0000057601000041000000000010043f00000541010000410000137800010430000000800010043f000000000004004b0000082c0000613d000000000030043f000000000001004b0000000002000019000008310000613d000004ec030000410000000002000019000000000403041a000000a005200039000000000045043500000001033000390000002002200039000000000012004b000008240000413d000008310000013d0000058102200197000000a00020043f000000000001004b000000200200003900000000020060390000002002200039000000800100003913760ddf0000040f000000400100043d000800000001001d000000800200003913760dbf0000040f00000008020000290000000001210049000004df0010009c000004df010080410000006001100210000004df0020009c000004df020080410000004002200210000000000121019f000013770001042e0000056001000041000000000010043f00000556010000410000137800010430000600000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b0000086f0000c13d000000000100041a0000000602000029000000000021004b000006fc0000a13d000800000002001d0000000801000029000000010110008a000800000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b0000085c0000613d0000055100100198000006fc0000c13d000804e40010019b0000000002000411000000080020006c00000a310000c13d0000000601000029000000000010043f0000000601000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d0000000702000029000004e406200197000000000101043b000000000201041a0000057202200197000000000262019f000000000021041b0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d0200003900000004030000390000057304000041000000080500002900000006070000291376136c0000040f0000000100200190000007910000c13d0000004d0000013d000000000001004b000008dc0000c13d0000056101000041000000000010043f000005560100004100001378000104300000054a01000041000000800010043f0000002001000039000000840010043f0000000701000039000000a40010043f0000055a01000041000000c40010043f0000055b010000410000137800010430000000400300043d0000055100100198000008c60000c13d0000000a05000039000000000205041a000000010620019000000001012002700000007f0110618f0000001f0010008c00000000040000390000000104002039000000000442013f00000001004001900000070e0000c13d0000000004130436000000000006004b00000b100000613d000000000050043f000000000001004b000000000200001900000b150000613d000004f20500004100000000020000190000000006240019000000000705041a000000000076043500000001055000390000002002200039000000000012004b000008be0000413d00000b150000013d00000555010000410000000000130435000004df0030009c000004df03008041000000400130021000000556011001c7000013780001043000000551001001980000000701000029000008d80000c13d000000000010043f0000000601000039000000200010043f00000040020000390000000001000019137613570000040f000000000101041a000006810000013d0000057501000041000000000010043f00000556010000410000137800010430000600000002001d000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000400300043d000000000101043b000000000101041a000004e20110019800000a020000c13d0000006002000039000003cd0000013d000000000002004b000009490000c13d0000057701000041000000000010043f00000541010000410000137800010430000004ef011001c70000800902000039000000080400002900000000050000191376136c0000040f00030000000103550000006003100270000104df0030019d000004df03300198000009250000613d0000001f04300039000004e0044001970000003f044000390000056604400197000000400500043d0000000004450019000000000054004b00000000060000390000000106004039000004e20040009c000000620000213d0000000100600190000000620000c13d000000400040043f0000001f0430018f0000000006350436000004e1053001980000000003560019000009180000613d000000000701034f000000007807043c0000000006860436000000000036004b000009140000c13d000000000004004b000009250000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000000100200190000007910000c13d000000400100043d00000044021000390000056903000041000000000032043500000024021000390000000f0300003900000000003204350000054a020000410000000000210435000000040210003900000020030000390000000000320435000004df0010009c000004df0100804100000040011002100000054b011001c70000137800010430000000000005004b0000000003000019000009670000613d0000000303500210000005800330027f00000580033001670000000006060433000000000336016f0000000105500210000000000353019f000009670000013d0000000601000029000000000001041b0000000801000029137612b30000040f0000000001000019000013770001042e0000006002200210000000000121019f000004f402000041000000000012041b0000000001000019000013770001042e000004e9060000410000002007000039000000010980008a0000000509900270000004ea0990009a000000000a370019000000000a0a04330000000000a6041b00000020077000390000000106600039000000000096004b000009540000c13d000000000058004b000009650000813d0000000308500210000000f80880018f000005800880027f000005800880016700000000033700190000000003030433000000000383016f000000000036041b000000010350021000000001033001bf000000000034041b0000000004010433000004e20040009c000000620000213d0000000303000039000000000603041a000000010060019000000001056002700000007f0550618f0000001f0050008c00000000070000390000000107002039000000000676013f00000001006001900000070e0000c13d00050000000b001d000000200050008c000009880000413d000000000030043f0000001f064000390000000506600270000004eb0660009a000000200040008c000004ec060040410000001f055000390000000505500270000004eb0550009a000000000056004b000009880000813d000000000006041b0000000106600039000000000056004b000009840000413d000000200040008c00000b050000413d000000000030043f0000057f0640019800000b770000c13d0000002005000039000004ec0200004100000b830000013d000000000003004b000009940000613d0000000501000029000000000001041b0000000601000029000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000201041a0000056b0220009a000000000021041b000005430100004100000000001004430000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f000000010020019000000b040000613d000000000101043b000500000001001d0000000701000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d0000000502000029000000a00220021000000006022001af0000056c022001c7000000000101043b000000000021041b00000008010000290000055c00100198000009ee0000c13d00000007010000290000000101100039000500000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b000009ee0000c13d000000000100041a000000050010006b000009ee0000613d0000000501000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b0000000802000029000000000021041b0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d0200003900000004030000390000055e040000410000000605000029000000000600001900000007070000291376136c0000040f00000001002001900000004d0000613d0000000101000039000000000201041a0000000102200039000000000021041b0000000001000019000013770001042e000000030010006b00000000020100190000000302004029000300000002001d0000000501200210000200000003001d00000000011300190000002001100039000000400010043f000500000001001d0000054c0010009c000000620000213d00000005020000290000008001200039000000400010043f0000006001200039000000000001043500000040012000390000000000010435000000200120003900000000000104350000000000020435000000000100041a000000020010008c000000000100001900000be20000413d0000000101000039000800000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000000001004b00000c8c0000c13d0000000801000029000000010110008a00000a1d0000013d0000000801000029000000000010043f0000000701000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b0000000002000411000004e402200197000000000020043f000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000101041a000000ff00100190000008750000c13d0000057101000041000000000010043f00000556010000410000137800010430000000000400001900000a5c0000013d0000000101300039000000000010041b00000005040000290000000104400039000000040040006c00000da40000813d000600000001001d000500000004001d000000050140021000000003011000290000000201100367000000000101043b000700000001001d000004e40010009c0000004d0000213d00000543010000410000000000100443000000070000006b00000ab30000613d0000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f000000010020019000000b040000613d000000000101043b000800000001001d0000000601000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d0000000802000029000000a0022002100000000703000029000000000223019f0000055c022001c7000000000101043b000000000021041b000000000030043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000201041a0000055d0220009a000000000021041b000800060000002d000000000100001900000aab0000013d00000008070000290000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d0200003900000004030000390000055e0400004100000000050000190000000706000029000800000007001d1376136c0000040f000000010020019000000001010000390000004d0000613d000000010010019000000a9b0000613d00000006030000290000000807000029000000000037004b00000a560000613d000000010770003900000a9c0000013d000004ee01000041000000000101041a000800000001001d0000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f000000010020019000000b040000613d000000000101043b000700000001001d0000000601000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d0000000802000029000004e4032001970000000702000029000000a002200210000000000232019f0000055c022001c7000000000101043b000000000021041b000700000003001d000000000030043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000000101043b000000000201041a0000055d0220009a000000000021041b000000070000006b00000da90000613d000800060000002d000000000100001900000afc0000013d00000008070000290000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d0200003900000004030000390000055e0400004100000000050000190000000706000029000800000007001d1376136c0000040f000000010020019000000001010000390000004d0000613d000000010010019000000aec0000613d00000006030000290000000807000029000000000037004b00000a560000613d000000010770003900000aed0000013d000000000001042f000000000004004b000000000100001900000b8f0000613d0000000301400210000005800110027f00000580011001670000000002020433000000000112016f0000000102400210000000000121019f00000b8f0000013d00000581022001970000000000240435000000000001004b000000200200003900000000020060390000003f012000390000057f051001970000000001350019000000000051004b00000000050000390000000105004039000004e20010009c000000620000213d0000000100500190000000620000c13d000000400010043f0000000f05000039000000000505041a0000ff000050019000000c340000c13d000000000401001900000000010300190000002002000039000800000004001d00000000022404360000023d0000013d000800000001001d0000000001000019000500000000001d000000070500002900000b340000013d000800000000001d0000000601000029000000400010043f00000001055000390000000101000039000000010010019000000b3b0000613d000000030050006c00000d850000613d0000000502000029000000020020006c00000d850000613d000000400100043d0000054c0010009c000000620000213d0000008002100039000000400020043f0000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000700000005001d000000000050043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000400200043d0000054c0020009c0000000705000029000000620000213d000000000101043b000000000101041a0000006003200039000000e8041002700000000000430435000000400320003900000551001001980000000004000039000000010400c0390000000000430435000000a003100270000004e20330019700000020042000390000000000340435000004e401100197000000000012043500000b2f0000c13d000000000001004b00000000020100190000000802006029000800000002001d000000040120014f000004e40010019800000b300000c13d00000005010000290000000101100039000500000001001d00000005011002100000000101100029000000000051043500000b300000013d000004ec020000410000002005000039000000010760008a0000000507700270000004ed0770009a00000000081500190000000008080433000000000082041b00000020055000390000000102200039000000000072004b00000b7c0000c13d000000000046004b00000b8d0000813d0000000306400210000000f80660018f000005800660027f000005800660016700000000011500190000000001010433000000000161016f000000000012041b000000010140021000000001011001bf000000000013041b0000000101000039000000000010041b0000000001000411000004e406100197000004ee01000041000000000061041b0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d02000039000004f00400004100000000050000191376136c0000040f00000001002001900000004d0000613d00000008010000290000000002010433000004e20020009c000000620000213d0000000a01000039000000000401041a000000010040019000000001034002700000007f0330618f0000001f0030008c00000000050000390000000105002039000000000454013f00000001004001900000070e0000c13d000000200030008c00000bc10000413d000000000010043f0000001f042000390000000504400270000004f10440009a000000200020008c000004f2040040410000001f033000390000000503300270000004f10330009a000000000034004b00000bc10000813d000000000004041b0000000104400039000000000034004b00000bbd0000413d000000200020008c000000200300003900000d5e0000413d000000000010043f0000057f06200198000004f2040000410000000005030019000000080900002900000bd50000613d0000002005000039000000010760008a0000000507700270000004f30770009a00000000089500190000000008080433000000000084041b00000020055000390000000104400039000000000074004b00000bce0000c13d000000000026004b00000bdf0000813d0000000306200210000000f80660018f000005800660027f000005800660016700000008055000290000000005050433000000000565016f000000000054041b000000010220021000000001042001bf00000d690000013d000700000001001d0000000105000039000400000000001d0000000001000019000000060200002900000bee0000013d000700000000001d00000006020000290000000501000029000000400010043f00000001055000390000000101000039000000010010019000000bf50000613d000000000025004b00000d8c0000613d0000000402000029000000030020006c00000d8c0000613d000000400100043d0000054c0010009c000000620000213d0000008002100039000000400020043f0000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000800000005001d000000000050043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000400200043d0000054c0020009c0000000805000029000000620000213d000000000101043b000000000101041a0000006003200039000000e8041002700000000000430435000000400320003900000551001001980000000004000039000000010400c0390000000000430435000000a003100270000004e20330019700000020042000390000000000340435000004e401100197000000000012043500000be80000c13d000000000001004b0000000002010019000000070200602900000004010000390000000201100367000000000101043b000700000002001d000000000121013f000004e40010019800000be90000c13d00000004010000290000000101100039000400000001001d00000005011002100000000201100029000000000051043500000be90000013d0000000005030433000000000005004b00000cbd0000c13d000005540010009c000000620000213d0000002002100039000000400020043f0000000000010435000000400400043d00000b260000013d000000000002004b000000000300001900000c420000613d000000a00300043d0000000304200210000005800440027f0000058004400167000000000343016f0000000102200210000000000223019f00000d200000013d000000000002004b000000000300001900000c4d0000613d000000a00300043d0000000304200210000005800440027f0000058004400167000000000343016f0000000102200210000000000223019f00000d480000013d000000400100043d0000054c0010009c000000620000213d0000008002100039000000400020043f00000060021000390000000000020435000000400210003900000000000204350000002002100039000000000002043500000000000104350000000801000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000400200043d0000054c0020009c000000620000213d000000000101043b000000000101041a0000008003200039000000400030043f0000006003200039000000e8041002700000000000430435000000400320003900000551001001980000000004000039000000010400c0390000000000430435000000a003100270000004e20330019700000020042000390000000000340435000004e4011001970000000000120435000800000000001d000800000001601d00000b2b0000013d000000400100043d00000044021000390000054903000041000000000032043500000024021000390000000c030000390000092d0000013d000000400100043d0000054c0010009c000000620000213d0000008002100039000000400020043f00000060021000390000000000020435000000400210003900000000000204350000002002100039000000000002043500000000000104350000000801000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000004d0000613d000000400200043d0000054c0020009c000000620000213d000000000101043b000000000101041a0000008003200039000000400030043f0000006003200039000000e8041002700000000000430435000000400320003900000551001001980000000004000039000000010400c0390000000000430435000000a003100270000004e20330019700000020042000390000000000340435000004e4011001970000000000120435000700000000001d000700000001601d00000be30000013d000000a005100039000000400050043f0000008005100039000000000005043500000007090000290000000006050019000000090090008c0000000a5990011a000000f807500210000000010560008a00000000080504330000055208800197000000000787019f00000553077001c7000000000075043500000cc20000213d00000000016100490000008101100039000000210660008a0000000000160435000000400100043d00000020071000390000000003030433000000000003004b00000cde0000613d00000000080000190000000009780019000000000a840019000000000a0a04330000000000a904350000002008800039000000000038004b00000cd70000413d000000000373001900000000000304350000000004060433000000000004004b00000ceb0000613d000000000600001900000000073600190000000008560019000000000808043300000000008704350000002006600039000000000046004b00000ce40000413d000000000334001900000000000304350000000b06000039000000000506041a000000010750019000000001045002700000007f0440618f0000001f0040008c00000000080000390000000108002039000000000885013f00000001008001900000070e0000c13d000000000007004b00000d910000613d000000000060043f000000000004004b00000d930000613d0000054e0500004100000000060000190000000007360019000000000805041a000000000087043500000001055000390000002006600039000000000046004b00000cff0000413d00000d930000013d000004f2030000410000002006000039000000010540008a0000000505500270000004f30550009a000000000706001900000080066000390000000006060433000000000063041b00000020067000390000000103300039000000000053004b00000d0c0000c13d000000a005700039000000000024004b00000d1e0000813d0000000304200210000000f80440018f000005800440027f00000580044001670000000005050433000000000445016f000000000043041b000000010220021000000001022001bf000000000021041b0000000103000039000000000103041a0000058001100167000000000200041a0000000001120019000000400200043d000000200420003900000000001404350000000000320435000004df0020009c000004df020080410000004001200210000000000200041400000d560000013d0000054e030000410000002006000039000000010540008a00000005055002700000054f0550009a000000000706001900000080066000390000000006060433000000000063041b00000020067000390000000103300039000000000053004b00000d340000c13d000000a005700039000000000024004b00000d460000813d0000000304200210000000f80440018f000005800440027f00000580044001670000000005050433000000000445016f000000000043041b000000010220021000000001022001bf000000000021041b0000000103000039000000000103041a0000058001100167000000000200041a0000000001120019000000400200043d000000200420003900000000001404350000000000320435000004df0020009c000004df0200804100000040012002100000000002000414000004df0020009c000004df02008041000000c002200210000000000112019f00000548011001c70000800d0200003900000550040000410000078e0000013d000000000002004b000000000400001900000d690000613d0000000304200210000005800440027f000005800440016700000007050000290000000005050433000000000445016f0000000102200210000000000424019f000000000041041b00000006010000290000006001100212000008f20000613d000001f4011001bf000004f402000041000000000012041b000004f5010000410000000d02000039000000000012041b000004f6010000410000000e02000039000000000012041b000004d2010000390000000902000039000000000012041b0000000f01000039000000000201041a000005820220019700000100022001bf000000000021041b0000000c010000390000000502000029000000000021041b00000100003004430000012000000443000004f701000041000013770001042e000000010100002900000005020000290000000000210435000000400100043d000800000001001d0000000102000029000003cf0000013d000000020200002900000004010000290000000000120435000000400300043d000003cd0000013d0000058105500197000000000053043500000000031300490000000003340019000000200430008a00000000004104350000001f033000390000057f023001970000000003120019000000000023004b00000000020000390000000102004039000004e20030009c000000620000213d0000000100200190000000620000c13d0000000004030019000000400030043f00000b260000013d0000000101000039000000000101041a0000000002130049000000400100043d0000029b0000013d0000055f01000041000000000010043f0000055601000041000013780001043000000000430104340000000001320436000000000003004b00000db90000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b00000db20000413d000000000213001900000000000204350000001f023000390000057f022001970000000001210019000000000001042d00000020030000390000000004310436000000003202043400000000002404350000004001100039000000000002004b00000dce0000613d000000000400001900000000051400190000000006430019000000000606043300000000006504350000002004400039000000000024004b00000dc70000413d000000000312001900000000000304350000001f022000390000057f022001970000000001120019000000000001042d000005830010009c00000dd90000813d0000002001100039000000400010043f000000000001042d0000056701000041000000000010043f0000004101000039000000040010043f000005680100004100001378000104300000001f022000390000057f022001970000000001120019000000000021004b00000000020000390000000102004039000004e20010009c00000deb0000213d000000010020019000000deb0000c13d000000400010043f000000000001042d0000056701000041000000000010043f0000004101000039000000040010043f000005680100004100001378000104300000000a05000039000000000405041a000000010640019000000001024002700000007f0220618f0000001f0020008c00000000010000390000000101002039000000000016004b00000e1f0000c13d000000400100043d0000000003210436000000000006004b00000e0c0000613d000000000050043f000000000002004b00000e120000613d000004f20500004100000000040000190000000006430019000000000705041a000000000076043500000001055000390000002004400039000000000024004b00000e040000413d00000e130000013d00000581044001970000000000430435000000000002004b0000002004000039000000000400603900000e130000013d00000000040000190000003f024000390000057f032001970000000002130019000000000032004b00000000030000390000000103004039000004e20020009c00000e250000213d000000010030019000000e250000c13d000000400020043f000000000001042d0000056701000041000000000010043f0000002201000039000000040010043f000005680100004100001378000104300000056701000041000000000010043f0000004101000039000000040010043f00000568010000410000137800010430000005840010009c00000e3b0000213d000000630010008c00000e3b0000a13d00000002030003670000000401300370000000000101043b000004e40010009c00000e3b0000213d0000002402300370000000000202043b000004e40020009c00000e3b0000213d0000004403300370000000000303043b000000000001042d0000000001000019000013780001043000000004010000390000000201100367000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b00000e460000c13d000000000001042d00000000010000190000137800010430000005850020009c00000e780000813d00000000040100190000001f012000390000057f011001970000003f011000390000057f05100197000000400100043d0000000005510019000000000015004b00000000070000390000000107004039000004e20050009c00000e780000213d000000010070019000000e780000c13d000000400050043f00000000052104360000000007420019000000000037004b00000e7e0000213d0000057f062001980000001f0720018f0000000204400367000000000365001900000e680000613d000000000804034f0000000009050019000000008a08043c0000000009a90436000000000039004b00000e640000c13d000000000007004b00000e750000613d000000000464034f0000000306700210000000000703043300000000076701cf000000000767022f000000000404043b0000010006600089000000000464022f00000000046401cf000000000474019f000000000043043500000000022500190000000000020435000000000001042d0000056701000041000000000010043f0000004101000039000000040010043f00000568010000410000137800010430000000000100001900001378000104300000001f03100039000000000023004b0000000004000019000004e304004041000004e305200197000004e303300197000000000653013f000000000053004b0000000003000019000004e303002041000004e30060009c000000000304c019000000000003004b00000e990000613d0000000203100367000000000303043b000004e20030009c00000e990000213d000000050430021000000020011000390000000004410019000000000024004b00000e990000213d0000000002030019000000000001042d000000000100001900001378000104300000000043010434000004e40330019700000000033204360000000004040433000004e204400197000000000043043500000040031000390000000003030433000000000003004b0000000003000039000000010300c0390000004004200039000000000034043500000060022000390000006001100039000000000101043300000562011001970000000000120435000000000001042d00000020030000390000000004310436000000000302043300000000003404350000004001100039000000000003004b00000ebc0000613d00000000040000190000002002200039000000000502043300000000015104360000000104400039000000000034004b00000eb60000413d000000000001042d000004e402200197000000000020043f000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000ecb0000613d000000000101043b000000000001042d000000000100001900001378000104300007000000000002000300000002001d000500000001001d000600000003001d000000000003004b00000fbf0000613d0000000601000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b000000000101041a000000000001004b00000efb0000c13d000000000100041a000000060010006c00000fbf0000a13d0000000602000029000000010220008a000700000002001d000000000020043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b000000000101041a000000000001004b000000070200002900000ee80000613d000005510010019800000fbf0000c13d0000000502000029000004e402200197000400000001001d000004e401100197000700000002001d000000000021004b00000fc30000c13d0000000601000029000000000010043f0000000601000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000201043b000000000302041a0000000001000411000004e404100197000000070040006c00000f3c0000613d000000000034004b00000f3c0000613d000500000004001d000100000003001d000200000002001d0000000701000029000000000010043f0000000701000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b0000000502000029000000000020043f000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b000000000101041a000000ff001001900000000202000029000000010300002900000fcc0000613d000000000003004b00000f3f0000613d000000000002041b0000000701000029000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b000000000201041a000000010220008a000000000021041b0000000301000029000004e401100197000500000001001d000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b000000000201041a0000000102200039000000000021041b000005430100004100000000001004430000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f000000010020019000000fc70000613d000000000101043b000300000001001d0000000601000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d0000000302000029000000a00220021000000005022001af0000055c022001c7000000000101043b000000000021041b00000004010000290000055c0010019800000fac0000c13d00000006010000290000000101100039000300000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b000000000101041a000000000001004b00000fac0000c13d000000000100041a000000030010006b00000fac0000613d0000000301000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fbd0000613d000000000101043b0000000402000029000000000021041b0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d0200003900000004030000390000055e040000410000000705000029000000050600002900000006070000291376136c0000040f000000010020019000000fbd0000613d000000050000006b00000fc80000613d000000000001042d000000000100001900001378000104300000057401000041000000000010043f000005560100004100001378000104300000058601000041000000000010043f00000556010000410000137800010430000000000001042f0000058701000041000000000010043f000005560100004100001378000104300000056a01000041000000000010043f00000556010000410000137800010430000004e40110019800000fe20000613d000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f000000010020019000000fe60000613d000000000101043b000000000101041a000004e201100197000000000001042d0000056101000041000000000010043f0000055601000041000013780001043000000000010000190000137800010430000000000001004b00000feb0000613d000000000001042d000000400100043d00000044021000390000055a0300004100000000003204350000002402100039000000070300003900000000003204350000054a020000410000000000210435000000040210003900000020030000390000000000320435000004df0010009c000004df0100804100000040011002100000054b011001c70000137800010430000000000001004b00000fff0000613d000000000001042d000000400100043d0000004402100039000005880300004100000000003204350000002402100039000000050300003900000000003204350000054a020000410000000000210435000000040210003900000020030000390000000000320435000004df0010009c000004df0100804100000040011002100000054b011001c70000137800010430000000000301001900000000011200a9000000000003004b000010170000613d00000000033100d9000000000023004b000010180000c13d000000000001042d0000056701000041000000000010043f0000001101000039000000040010043f00000568010000410000137800010430000000000001004b000010210000613d000000000001042d000000400100043d0000004402100039000005890300004100000000003204350000002402100039000000180300003900000000003204350000054a020000410000000000210435000000040210003900000020030000390000000000320435000004df0010009c000004df0100804100000040011002100000054b011001c700001378000104300008000000000002000200000004001d000500000002001d000600000001001d000700000003001d000000000003004b0000119d0000613d0000000701000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b000000000101041a000000000001004b000010610000c13d000000000100041a000000070010006c0000119d0000a13d0000000702000029000000010220008a000800000002001d000000000020043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b000000000101041a000000000001004b00000008020000290000104e0000613d00000551001001980000119d0000c13d0000000602000029000004e402200197000400000001001d000004e401100197000800000002001d000000000021004b000011a20000c13d0000000701000029000000000010043f0000000601000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000201043b000000000302041a0000000001000411000004e404100197000000080040006c000010a20000613d000000000034004b000010a20000613d000600000004001d000100000003001d000300000002001d0000000801000029000000000010043f0000000701000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b0000000602000029000000000020043f000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b000000000101041a000000ff0010019000000003020000290000000103000029000011ae0000613d000000000003004b000010a50000613d000000000002041b0000000801000029000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b000000000201041a000000010220008a000000000021041b0000000501000029000004e401100197000600000001001d000000000010043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b000000000201041a0000000102200039000000000021041b000005430100004100000000001004430000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f0000000100200190000011a10000613d000000000101043b000300000001001d0000000701000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d0000000302000029000000a00220021000000006022001af0000055c022001c7000000000101043b000000000021041b00000004010000290000055c00100198000011120000c13d00000007010000290000000101100039000300000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b000000000101041a000000000001004b000011120000c13d000000000100041a000000030010006b000011120000613d0000000301000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000119b0000613d000000000101043b0000000402000029000000000021041b0000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d0200003900000004030000390000055e040000410000000805000029000000060600002900000007070000291376136c0000040f00000001002001900000119b0000613d000000060000006b000011a60000613d0000058a010000410000000000100443000000050100002900000004001004430000000001000414000004df0010009c000004df01008041000000c00110021000000565011001c70000800202000039137613710000040f0000000100200190000011a10000613d000000000101043b000000000001004b0000119a0000613d000000400700043d00000064017000390000008002000039000500000002001d00000000002104350000004401700039000000070200002900000000002104350000002401700039000000080200002900000000002104350000058b0100004100000000001704350000000401700039000000000200041100000000002104350000008402700039000000020100002900000000310104340000000000120435000000a402700039000000000001004b000011510000613d000000000400001900000000052400190000000006430019000000000606043300000000006504350000002004400039000000000014004b0000114a0000413d0000001f031000390000057f0330019700000000012100190000000000010435000000a401300039000004df0010009c000004df010080410000006001100210000004df0070009c000004df0200004100000000020740190000004002200210000000000121019f0000000002000414000004df0020009c000004df02008041000000c002200210000000000112019f0000000602000029000800000007001d1376136c0000040f000000080b0000290000006003100270000004df03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000011760000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000011720000c13d000000000006004b000011830000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000011aa0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000004e20010009c000011e00000213d0000000100200190000011e00000c13d000000400010043f000000200030008c0000119b0000413d00000000010b043300000579001001980000119b0000c13d0000057a011001970000058b0010009c000011dc0000c13d000000000001042d000000000100001900001378000104300000057401000041000000000010043f00000556010000410000137800010430000000000001042f0000058601000041000000000010043f000005560100004100001378000104300000058701000041000000000010043f00000556010000410000137800010430000000000003004b000011b20000c13d0000006002000039000011d90000013d0000056a01000041000000000010043f000005560100004100001378000104300000001f02300039000004e0022001970000003f022000390000056604200197000000400200043d0000000004420019000000000024004b00000000050000390000000105004039000004e20040009c000011e00000213d0000000100500190000011e00000c13d000000400040043f0000001f0430018f0000000006320436000004e105300198000500000006001d0000000003560019000011cc0000613d000000000601034f0000000507000029000000006806043c0000000007870436000000000037004b000011c80000c13d000000000004004b000011d90000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000000001020433000000000001004b000011e60000c13d0000058c01000041000000000010043f000005560100004100001378000104300000056701000041000000000010043f0000004101000039000000040010043f000005680100004100001378000104300000000502000029000004df0020009c000004df020080410000004002200210000004df0010009c000004df010080410000006001100210000000000121019f000013780001043000010000000000020000000003010019000000400100043d0000058d0010009c000012470000813d0000008002100039000000400020043f0000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000000003004b000012440000613d000000000200041a000000000032004b000012440000a13d000100000003001d000000000030043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f0000000100200190000012450000613d000000000101043b000000000101041a000000000001004b000012160000c13d0000000103000029000000010330008a000012020000013d000000400100043d0000054c0010009c0000000103000029000012470000213d0000008002100039000000400020043f0000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000000030043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f0000000100200190000012450000613d000000000301034f000000400100043d0000054c0010009c000012470000213d000000000203043b000000000202041a0000008003100039000000400030043f0000006003100039000000e804200270000000000043043500000551002001980000000003000039000000010300c03900000040041000390000000000340435000004e4032001970000000003310436000000a002200270000004e2022001970000000000230435000000000001042d000000000100001900001378000104300000056701000041000000000010043f0000004101000039000000040010043f00000568010000410000137800010430000005850020009c0000126d0000813d00000005052002100000003f045000390000054706400197000000400400043d0000000006640019000000000046004b00000000070000390000000107004039000004e20060009c0000126d0000213d00000001007001900000126d0000c13d000000400060043f00000000002404350000000002150019000000000032004b000012730000213d000000000012004b0000126b0000a13d00000002030003670000000005040019000000000613034f000000000606043b000000200550003900000000006504350000002001100039000000000021004b000012640000413d0000000001040019000000000001042d0000056701000041000000000010043f0000004101000039000000040010043f0000056801000041000013780001043000000000010000190000137800010430000004ee01000041000000000101041a0000000002000411000000000012004b0000127b0000c13d000000000001042d0000057601000041000000000010043f000005410100004100001378000104300001000000000002000000000001004b000012af0000613d000100000001001d000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f0000000100200190000012ad0000613d000000000101043b000000000101041a000000000001004b000012aa0000c13d000000000100041a0000000102000029000000000021004b000012af0000a13d000000010220008a000100000002001d000000000020043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f0000000100200190000012ad0000613d000000000101043b000000000101041a000000000001004b0000000102000029000012970000613d0000055100100198000012af0000c13d000000000001042d000000000100001900001378000104300000057401000041000000000010043f000005560100004100001378000104300001000000000002000004ee02000041000000000502041a0000000002000414000004e406100197000004df0020009c000004df02008041000000c001200210000004ef011001c70000800d020000390000000303000039000004f004000041000100000006001d1376136c0000040f0000000100200190000012c70000613d000004ee010000410000000102000029000000000021041b000000000001042d000000000100001900001378000104300004000000000002000300000001001d000200000002001d000000000002004b000013290000613d000000000100041a000400000001001d000005430100004100000000001004430000000001000414000004df0010009c000004df01008041000000c00110021000000544011001c70000800b02000039137613710000040f00000001002001900000132d0000613d000000000101043b000100000001001d0000000401000029000000000010043f0000000401000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000001002001900000000205000029000013270000613d0000000302000029000004e4042001970000000102000029000000a002200210000000010050008c00000000030000190000055c03006041000000000223019f000000000242019f000000000101043b000000000021041b000300000004001d000000000040043f0000000501000039000000200010043f0000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f00000002040000290000000100200190000013270000613d0000058e024000d1000000000101043b000000000301041a0000000002230019000000000021041b000000030000006b0000132e0000613d000200040040002d00000000010000190000131e0000013d00000004070000290000000001000414000004df0010009c000004df01008041000000c001100210000004ef011001c70000800d0200003900000004030000390000055e0400004100000000050000190000000306000029000400000007001d1376136c0000040f00000001002001900000000101000039000013270000613d00000001001001900000130e0000613d00000004070000290000000107700039000000020070006c0000130f0000c13d0000000201000029000000000010041b000000000001042d000000000100001900001378000104300000058f01000041000000000010043f00000556010000410000137800010430000000000001042f0000055f01000041000000000010043f000005560100004100001378000104300003000000000002000100000002001d0000000012010434000000000002004b000013500000613d0000000502200210000200000021001d0000000042010434000300000004001d000000000023004b000000000200003900000020020020390000000000320435000000200220015f000000000101043300000000001204350000000001000414000004df0010009c000004df01008041000000c00110021000000548011001c70000801002000039137613710000040f0000000100200190000013540000613d000000000301043b0000000302000029000000020020006c0000000001020019000013390000413d000000010030006c00000000010000390000000101006039000000000001042d00000000010000190000137800010430000000000001042f000004df0010009c000004df010080410000004001100210000004df0020009c000004df020080410000006002200210000000000112019f0000000002000414000004df0020009c000004df02008041000000c002200210000000000112019f000004ef011001c70000801002000039137613710000040f00000001002001900000136a0000613d000000000101043b000000000001042d000000000100001900001378000104300000136f002104210000000102000039000000000001042d0000000002000019000000000001042d00001374002104230000000102000039000000000001042d0000000002000019000000000001042d0000137600000432000013770001042e000013780001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffbf426974656d6172657300000000000000000000000000000000000000000000004249544500000000000000000000000000000000000000000000000000000000bfa87805ed57dc1f0d489ce33be4c4577d74ccde357eeeee058a32c55c44a532405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acebfa87805ed57dc1f0d489ce33be4c4577d74ccde357eeeee058a32c55c44a5313da8a5f161a6c3ff06a60736d0ed24d7963cc6a5c4fafd2fa1dae9bb908e07a5c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b3da8a5f161a6c3ff06a60736d0ed24d7963cc6a5c4fafd2fa1dae9bb908e07a4ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e039a5844729cae3e308f36a5ce933956d7c6367997d26743ca06a70b77c062d58c65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a839a5844729cae3e308f36a5ce933956d7c6367997d26743ca06a70b77c062d570000000000000000000000000000000000000000000000aa4ec00224afccfdb70000000000000000000000000000000000000000000000000021c0331d5dc00000000000000000000000000000000000000000000000000000354a6ba7a180000000000200000000000000000000000000000040000001000000000000000000000000000000000000000000000000000000000000000000000000008ac1e16000000000000000000000000000000000000000000000000000000000c87b56dc00000000000000000000000000000000000000000000000000000000f04e283d00000000000000000000000000000000000000000000000000000000f6a5b8e500000000000000000000000000000000000000000000000000000000fdfc7aad00000000000000000000000000000000000000000000000000000000fdfc7aae00000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000f6a5b8e600000000000000000000000000000000000000000000000000000000f8e6b54d00000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000f62625a100000000000000000000000000000000000000000000000000000000d5abeb0000000000000000000000000000000000000000000000000000000000d5abeb0100000000000000000000000000000000000000000000000000000000e8656fcc00000000000000000000000000000000000000000000000000000000e985e9c500000000000000000000000000000000000000000000000000000000c87b56dd00000000000000000000000000000000000000000000000000000000cb173dd900000000000000000000000000000000000000000000000000000000d2cab05600000000000000000000000000000000000000000000000000000000a0712d6700000000000000000000000000000000000000000000000000000000b88d4fdd00000000000000000000000000000000000000000000000000000000c627525400000000000000000000000000000000000000000000000000000000c627525500000000000000000000000000000000000000000000000000000000c7f8d01a00000000000000000000000000000000000000000000000000000000b88d4fde00000000000000000000000000000000000000000000000000000000c23dc68f00000000000000000000000000000000000000000000000000000000a0712d6800000000000000000000000000000000000000000000000000000000a22cb46500000000000000000000000000000000000000000000000000000000a945bf800000000000000000000000000000000000000000000000000000000095d89b400000000000000000000000000000000000000000000000000000000095d89b410000000000000000000000000000000000000000000000000000000099a2557a000000000000000000000000000000000000000000000000000000009edfbec9000000000000000000000000000000000000000000000000000000008ac1e161000000000000000000000000000000000000000000000000000000008ba4cc3c000000000000000000000000000000000000000000000000000000008da5cb5b0000000000000000000000000000000000000000000000000000000049a59809000000000000000000000000000000000000000000000000000000005bbb2176000000000000000000000000000000000000000000000000000000006f8b44af00000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000008462151c000000000000000000000000000000000000000000000000000000006f8b44b00000000000000000000000000000000000000000000000000000000070a08231000000000000000000000000000000000000000000000000000000005bbb2177000000000000000000000000000000000000000000000000000000006352211e000000000000000000000000000000000000000000000000000000006c0360eb0000000000000000000000000000000000000000000000000000000054c06aed0000000000000000000000000000000000000000000000000000000054c06aee0000000000000000000000000000000000000000000000000000000054d1f13d0000000000000000000000000000000000000000000000000000000055f804b30000000000000000000000000000000000000000000000000000000049a5980a0000000000000000000000000000000000000000000000000000000051cff8d90000000000000000000000000000000000000000000000000000000054214f6900000000000000000000000000000000000000000000000000000000197c9d7b000000000000000000000000000000000000000000000000000000002a552059000000000000000000000000000000000000000000000000000000002a55205a0000000000000000000000000000000000000000000000000000000042842e0e0000000000000000000000000000000000000000000000000000000042966c6800000000000000000000000000000000000000000000000000000000197c9d7c0000000000000000000000000000000000000000000000000000000023b872dd000000000000000000000000000000000000000000000000000000002569296200000000000000000000000000000000000000000000000000000000081812fb00000000000000000000000000000000000000000000000000000000081812fc00000000000000000000000000000000000000000000000000000000095ea7b30000000000000000000000000000000000000000000000000000000018160ddd0000000000000000000000000000000000000000000000000000000001ffc9a70000000000000000000000000000000000000000000000000000000004634d8d0000000000000000000000000000000000000000000000000000000006fdde0300000000000000000000000000000000000000000000000000000000389a75e100000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000006f5e88180200000000000000000000000000000000000014000000a000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe002000000000000000000000000000000000000400000000000000000000000002177686974656c6973746564000000000000000000000000000000000000000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7ffe8a4859c7bd88fc0f24184464406785daae8e84cb1860cc4a4eff72e05fe2470175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9fe8a4859c7bd88fc0f24184464406785daae8e84cb1860cc4a4eff72e05fe2466bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c000000010000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdfa14c4b500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000020000000000000000000000000000000000002000000000000000000000000017307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3121737570706c790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000008000000000000000000000000200000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef2e0763000000000000000000000000000000000000000000000000000000000032c1995a000000000000000000000000000000000000000000000000000000008f4eb604000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c929cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f39020000020000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffe04e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000005769746864726177206661696c6564000000000000000000000000000000000059c896be00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000100000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000040000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1dcfb3b94200000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000008c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925df2d9b4200000000000000000000000000000000000000000000000000000000cf4700e4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082b4290000000000000000000000000000000000000000000000000000000000b4457eaa00000000000000000000000000000000000000000000000000000000350a88b300000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000005b5e139f0000000000000000000000000000000000000000000000000000000080ac58cd000000000000000000000000000000000000000000000000000000004906490600000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff000000000000000000000000000000000000000000000000ffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000010000000000000000a114810000000000000000000000000000000000000000000000000000000000ea553b3400000000000000000000000000000000000000000000000000000000216c6976650000000000000000000000000000000000000000000000000000004e6f7420656e6f75676820657468657220746f206d696e7400000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83150b7a0200000000000000000000000000000000000000000000000000000000d1a57ed600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff800000000000000000000000000000000000000000000000010000000000000001b562e8dd0000000000000000000000000000000000000000000000000000000074c4544668617e798e7a8cb327546298d18ddfc467257c90020a07b554d6a887
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e689b4f46eeac87784c68dfd48115f5d8011dcf51c7d7b717edd99fc832d153120da7d4ed0c1bdcaaaffaa3283154a12e338534e000000000000000000000000000000000000000000000000000000000000002568747470733a2f2f7777772e63686f6d706965736e66742e636f6d2f6170692f697066732f000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _uri (string): https://www.chompiesnft.com/api/ipfs/
Arg [1] : _royaltiesReceiver (address): 0xE689B4F46eeaC87784c68dFd48115f5D8011Dcf5
Arg [2] : _wlMerkleRoot (bytes32): 0x1c7d7b717edd99fc832d153120da7d4ed0c1bdcaaaffaa3283154a12e338534e
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 000000000000000000000000e689b4f46eeac87784c68dfd48115f5d8011dcf5
Arg [2] : 1c7d7b717edd99fc832d153120da7d4ed0c1bdcaaaffaa3283154a12e338534e
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000025
Arg [4] : 68747470733a2f2f7777772e63686f6d706965736e66742e636f6d2f6170692f
Arg [5] : 697066732f000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.