Transaction Hash:
Block:
16326016 at Jan-03-2023 11:39:47 AM +UTC
Transaction Fee:
0.00090307 ETH
$2.16
Gas Used:
64,505 Gas / 14 Gwei
Emitted Events:
169 |
FluffyNextGen.Transfer( from=[Sender] 0xd05043232f674d020dc136bcd7cc9339ac3eb8a4, to=0x3a377A50...3887bb320, tokenId=765 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x4675C7e5...ef3b0a263
Miner
| (Coinbase: MEV Builder) | 0.041547387619113995 Eth | 0.041602979102509275 Eth | 0.00005559148339528 | |
0x7Ce58271...f4Ab32b05 | |||||
0xd0504323...9ac3EB8a4 | (Fluffy Fucks: Deployer) |
0.217698702500996033 Eth
Nonce: 210
|
0.216795632500996033 Eth
Nonce: 211
| 0.00090307 |
Execution Trace
FluffyNextGen.safeTransferFrom( from=0xd05043232f674D020DC136BcD7cC9339ac3EB8a4, to=0x3a377A50C556644DAD487Bb00C0505B3887bb320, tokenId=765 )
safeTransferFrom[ERC721A (ln:984)]
safeTransferFrom[ERC721A (ln:989)]
safeTransferFrom[ERC721A (ln:989)]
// File: @openzeppelin/contracts/utils/cryptography/MerkleProof.sol // OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Trees proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = _efficientHash(computedHash, proofElement); } else { // Hash(current element of the proof + current computed hash) computedHash = _efficientHash(proofElement, computedHash); } } return computedHash; } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } } // File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol // 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); } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts v4.4.1 (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; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @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] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } } // File: erc721a/contracts/IERC721A.sol // ERC721A Contracts v4.0.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of an ERC721A compliant contract. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * The caller cannot approve to their own address. */ error ApproveToCaller(); /** * The caller cannot approve to the current owner. */ error ApprovalToCurrentOwner(); /** * 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(); struct TokenOwnership { // The address of the owner. address addr; // Keeps track of the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; } /** * @dev Returns the total amount of tokens stored by the contract. * * Burned tokens are calculated here, use `_totalMinted()` if you want to count just minted tokens. */ function totalSupply() external view returns (uint256); // ============================== // 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); // ============================== // 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`. * * 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 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 ) external; /** * @dev Transfers `tokenId` token 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; /** * @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); // ============================== // 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); } // File: erc721a/contracts/ERC721A.sol // ERC721A Contracts v4.0.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev ERC721 token receiver interface. */ interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension. Built to optimize for lower gas during batch mints. * * Assumes serials are sequentially minted starting at _startTokenId() (defaults to 0, e.g. 0, 1, 2, 3..). * * Assumes that an owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * * Assumes that the maximum token id cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is IERC721A { // 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 tokenId of the next token 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` 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 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); } /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view 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 override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than `_currentIndex - _startTokenId()` times. unchecked { return _currentIndex - _burnCounter - _startTokenId(); } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view returns (uint256) { // Counter underflow is impossible as _currentIndex does not decrement, // and it is initialized to `_startTokenId()` unchecked { return _currentIndex - _startTokenId(); } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view returns (uint256) { return _burnCounter; } /** * @dev See {IERC165-supportsInterface}. */ 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: 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. } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view override returns (uint256) { if (owner == address(0)) revert BalanceQueryForZeroAddress(); 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 auxillary 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 auxillary 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 { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; assembly { // Cast aux without masking. auxCasted := aux } packed = (packed & BITMASK_AUX_COMPLEMENT) | (auxCasted << BITPOS_AUX); _packedAddressData[owner] = packed; } /** * Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) { uint256 curr = tokenId; unchecked { if (_startTokenId() <= curr) if (curr < _currentIndex) { uint256 packed = _packedOwnerships[curr]; // If not burned. if (packed & BITMASK_BURNED == 0) { // Invariant: // There will always be an ownership that has an address and is not burned // before an ownership that does not have an address and is not burned. // Hence, curr will not underflow. // // We can directly compare the packed value. // If the address is zero, packed is zero. while (packed == 0) { packed = _packedOwnerships[--curr]; } return packed; } } } revert OwnerQueryForNonexistentToken(); } /** * 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; } /** * Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around in the collection over time. */ function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @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) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); 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, can be overriden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } /** * @dev Casts the address to uint256 without masking. */ function _addressToUint256(address value) private pure returns (uint256 result) { assembly { result := value } } /** * @dev Casts the boolean to uint256 without branching. */ function _boolToUint256(bool value) private pure returns (uint256 result) { assembly { result := value } } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public override { address owner = address(uint160(_packedOwnershipOf(tokenId))); if (to == owner) revert ApprovalToCurrentOwner(); if (_msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { revert ApprovalCallerNotOwnerNorApproved(); } _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view override returns (address) { if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken(); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { if (operator == _msgSenderERC721A()) revert ApproveToCaller(); _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), 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 { _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 { _transfer(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } /** * @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`), */ function _exists(uint256 tokenId) internal view returns (bool) { return _startTokenId() <= tokenId && tokenId < _currentIndex && // If within bounds, _packedOwnerships[tokenId] & BITMASK_BURNED == 0; // and not burned. } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal { _safeMint(to, 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. * * Emits a {Transfer} event. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1 // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1 unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the balance and number minted. _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] = _addressToUint256(to) | (block.timestamp << BITPOS_START_TIMESTAMP) | (_boolToUint256(quantity == 1) << BITPOS_NEXT_INITIALIZED); uint256 updatedIndex = startTokenId; uint256 end = updatedIndex + quantity; if (to.code.length != 0) { do { emit Transfer(address(0), to, updatedIndex); if (!_checkContractOnERC721Received(address(0), to, updatedIndex++, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } while (updatedIndex < end); // Reentrancy protection if (_currentIndex != startTokenId) revert(); } else { do { emit Transfer(address(0), to, updatedIndex++); } while (updatedIndex < end); } _currentIndex = updatedIndex; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @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. */ function _mint(address to, uint256 quantity) internal { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1 // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1 unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the balance and number minted. _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] = _addressToUint256(to) | (block.timestamp << BITPOS_START_TIMESTAMP) | (_boolToUint256(quantity == 1) << BITPOS_NEXT_INITIALIZED); uint256 updatedIndex = startTokenId; uint256 end = updatedIndex + quantity; do { emit Transfer(address(0), to, updatedIndex++); } while (updatedIndex < end); _currentIndex = updatedIndex; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Transfers `tokenId` from `from` to `to`. * * 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 ) private { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner(); bool isApprovedOrOwner = (_msgSenderERC721A() == from || isApprovedForAll(from, _msgSenderERC721A()) || getApproved(tokenId) == _msgSenderERC721A()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); if (to == address(0)) revert TransferToZeroAddress(); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. delete _tokenApprovals[tokenId]; // 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] = _addressToUint256(to) | (block.timestamp << BITPOS_START_TIMESTAMP) | BITMASK_NEXT_INITIALIZED; // 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, to, tokenId); _afterTokenTransfers(from, to, tokenId, 1); } /** * @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)); if (approvalCheck) { bool isApprovedOrOwner = (_msgSenderERC721A() == from || isApprovedForAll(from, _msgSenderERC721A()) || getApproved(tokenId) == _msgSenderERC721A()); if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved(); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. delete _tokenApprovals[tokenId]; // 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] = _addressToUint256(from) | (block.timestamp << BITPOS_START_TIMESTAMP) | BITMASK_BURNED | BITMASK_NEXT_INITIALIZED; // 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 times. unchecked { _burnCounter++; } } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target 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 _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(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } /** * @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 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 returns (string memory ptr) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), // but we allocate 128 bytes to keep the free memory pointer 32-byte word aliged. // We will need 1 32-byte word to store the length, // and 3 32-byte words to store a maximum of 78 digits. Total: 32 + 3 * 32 = 128. ptr := add(mload(0x40), 128) // Update the free memory pointer to allocate. mstore(0x40, ptr) // Cache the end of the memory to calculate the length later. let end := ptr // We write the string from the rightmost digit to the leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // Costs a bit more than early returning for the zero case, // but cheaper in terms of deployment and overall runtime costs. for { // Initialize and perform the first pass without check. let temp := value // Move the pointer 1 byte leftwards to point to an empty character slot. ptr := sub(ptr, 1) // Write the character to the pointer. 48 is the ASCII index of '0'. mstore8(ptr, add(48, mod(temp, 10))) temp := div(temp, 10) } temp { // Keep dividing `temp` until zero. temp := div(temp, 10) } { // Body of the for loop. ptr := sub(ptr, 1) mstore8(ptr, add(48, mod(temp, 10))) } let length := sub(end, ptr) // Move the pointer 32 bytes leftwards to make room for the length. ptr := sub(ptr, 32) // Store the length. mstore(ptr, length) } } } // File: erc721a/contracts/extensions/IERC721AQueryable.sol // ERC721A Contracts v4.0.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of an ERC721AQueryable compliant contract. */ 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` * * If the `tokenId` is burned: * - `addr` = `<Address of owner before token was burned>` * - `startTimestamp` = `<Timestamp when token was burned>` * - `burned = `true` * * Otherwise: * - `addr` = `<Address of owner>` * - `startTimestamp` = `<Timestamp of start of ownership>` * - `burned = `false` */ 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 pfp collections should be fine). */ function tokensOfOwner(address owner) external view returns (uint256[] memory); } // File: erc721a/contracts/extensions/ERC721AQueryable.sol // ERC721A Contracts v4.0.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @title ERC721A Queryable * @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` * * If the `tokenId` is burned: * - `addr` = `<Address of owner before token was burned>` * - `startTimestamp` = `<Timestamp when token was burned>` * - `burned = `true` * * Otherwise: * - `addr` = `<Address of owner>` * - `startTimestamp` = `<Timestamp of start of ownership>` * - `burned = `false` */ function explicitOwnershipOf(uint256 tokenId) public view override returns (TokenOwnership memory) { TokenOwnership memory ownership; if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) { return ownership; } ownership = _ownershipAt(tokenId); if (ownership.burned) { return ownership; } return _ownershipOf(tokenId); } /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] memory tokenIds) external view override returns (TokenOwnership[] memory) { unchecked { uint256 tokenIdsLength = tokenIds.length; TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength); for (uint256 i; i != tokenIdsLength; ++i) { ownerships[i] = explicitOwnershipOf(tokenIds[i]); } 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 override returns (uint256[] memory) { unchecked { if (start >= stop) revert InvalidQueryRange(); uint256 tokenIdsIdx; uint256 stopLimit = _nextTokenId(); // Set `start = max(start, _startTokenId())`. if (start < _startTokenId()) { start = _startTokenId(); } // Set `stop = min(stop, stopLimit)`. if (stop > stopLimit) { stop = stopLimit; } uint256 tokenIdsMaxLength = balanceOf(owner); // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`, // to cater for cases where `balanceOf(owner)` is too big. if (start < stop) { uint256 rangeLength = stop - start; if (rangeLength < tokenIdsMaxLength) { tokenIdsMaxLength = rangeLength; } } else { tokenIdsMaxLength = 0; } uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength); if (tokenIdsMaxLength == 0) { return tokenIds; } // 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; } for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) { ownership = _ownershipAt(i); if (ownership.burned) { continue; } if (ownership.addr != address(0)) { currOwnershipAddr = ownership.addr; } if (currOwnershipAddr == owner) { tokenIds[tokenIdsIdx++] = i; } } // Downsize the array to fit. assembly { mstore(tokenIds, tokenIdsIdx) } return tokenIds; } } /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(totalSupply) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K pfp collections should be fine). */ function tokensOfOwner(address owner) external view override returns (uint256[] memory) { unchecked { uint256 tokenIdsIdx; address currOwnershipAddr; uint256 tokenIdsLength = balanceOf(owner); uint256[] memory tokenIds = new uint256[](tokenIdsLength); TokenOwnership memory ownership; for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) { ownership = _ownershipAt(i); if (ownership.burned) { continue; } if (ownership.addr != address(0)) { currOwnershipAddr = ownership.addr; } if (currOwnershipAddr == owner) { tokenIds[tokenIdsIdx++] = i; } } return tokenIds; } } } // File: contracts/FluffyFucksReborn.sol pragma solidity >=0.7.0 <0.9.0; contract FluffyFucksReborn is ERC721AQueryable, Ownable { using Strings for uint256; string public uriPrefix = ""; //http://www.site.com/data/ string public uriSuffix = ".json"; string public _contractURI = ""; uint256 public maxSupply = 6061; bool public paused = false; constructor() ERC721A("Fluffy Fucks", "FFXv2") { } function _startTokenId() internal pure override returns(uint256) { return 1; } function mintForAddress(uint256 _mintAmount, address _receiver) public onlyOwner { require(!paused, "The contract is paused!"); require(totalSupply() + _mintAmount < maxSupply, "Max supply exceeded!"); _safeMint(_receiver, _mintAmount); } function mintForAddressMultiple(address[] calldata addresses, uint256[] calldata amount) public onlyOwner { require(!paused, "The contract is paused!"); require(addresses.length == amount.length, "Address and amount length mismatch"); for (uint256 i; i < addresses.length; ++i) { _safeMint(addresses[i], amount[i]); } require(totalSupply() < maxSupply, "Max supply exceeded!"); } function tokenURI(uint256 _tokenId) public view virtual override (ERC721A, IERC721A) returns (string memory) { require( _exists(_tokenId), "ERC721Metadata: URI query for nonexistent token" ); string memory currentBaseURI = _baseURI(); return bytes(currentBaseURI).length > 0 ? string(abi.encodePacked(currentBaseURI, _tokenId.toString(), uriSuffix)) : ""; } function contractURI() public view returns (string memory) { return bytes(_contractURI).length > 0 ? string(abi.encodePacked(_contractURI)) : ""; } function setUriPrefix(string memory _uriPrefix) public onlyOwner { uriPrefix = _uriPrefix; } function setUriSuffix(string memory _uriSuffix) public onlyOwner { uriSuffix = _uriSuffix; } function setContractURI(string memory newContractURI) public onlyOwner { _contractURI = newContractURI; } function setPaused(bool _state) public onlyOwner { paused = _state; } function withdraw() public onlyOwner { (bool os, ) = payable(owner()).call{value: address(this).balance}(""); require(os); } function _baseURI() internal view virtual override returns (string memory) { return uriPrefix; } } // File: contracts/FluffyStaker.sol pragma solidity >=0.8.0 <0.9.0; contract FluffyStaker is IERC721Receiver, ReentrancyGuard { address public ownerAddress; bool public active = true; mapping(uint256 => address) staked; FluffyFucksReborn public ffxr; constructor() { ownerAddress = msg.sender; } fallback() external payable nonReentrant { revert(); } receive() external payable nonReentrant { revert(); } /** * on token received */ function onERC721Received ( address /*operator*/, address from, uint256 tokenId, bytes calldata /*data*/ ) public override onlyFromFluffyContract(msg.sender) returns(bytes4) { staked[tokenId] = from; return IERC721Receiver.onERC721Received.selector; } /** * ADMIN ONLY */ function setFluffyAddress(address contractAddress) public onlyOwner { ffxr = FluffyFucksReborn(contractAddress); } function restoreOddball(uint256 tokenId, address restoreTo) public onlyOwner { require(staked[tokenId] == address(0x0), "Token has a known owner."); ffxr.safeTransferFrom(address(this), restoreTo, tokenId); } function forceUnstake(uint256 tokenId) public onlyOwner { _forceUnstake(tokenId); } function forceUnstakeBatch(uint256[] calldata tokenIds) public onlyOwner { for(uint256 i = 0; i < tokenIds.length; ++i) { _forceUnstake(tokenIds[i]); } } function forceUnstakeAll() public onlyOwner { uint256[] memory tokens = ffxr.tokensOfOwner(address(this)); for(uint256 i = 0; i < tokens.length; ++i) { _forceUnstake(tokens[i]); } } function _forceUnstake(uint256 tokenId) private onlyOwner { if(staked[tokenId] != address(0x0)) { ffxr.safeTransferFrom(address(this), staked[tokenId], tokenId); staked[tokenId] = address(0x0); } } function toggleActive(bool setTo) public onlyOwner { active = setTo; } /** * LOOKUPS */ function tokenStaker(uint256 tokenId) public view returns(address) { return staked[tokenId]; } function tokenStakers(uint256[] calldata tokenIds) public view returns(address[] memory) { address[] memory stakers = new address[](tokenIds.length); for(uint256 i = 0; i < tokenIds.length; ++i) { stakers[i] = staked[tokenIds[i]]; } return stakers; } function allTokenStakers() isFluffyContractSet public view returns (uint256[] memory, address[] memory) { uint256[] memory tokens = ffxr.tokensOfOwner(address(this)); uint256[] memory stakedTokens; address[] memory stakers; uint256 count = 0; for(uint256 i = 0; i < tokens.length; ++i) { if (staked[tokens[i]] != address(0x0)) { ++count; } } stakedTokens = new uint256[](count); stakers = new address[](count); count = 0; for(uint256 i = 0; i < tokens.length; ++i) { stakedTokens[count] = tokens[i]; stakers[count] = staked[tokens[i]]; count++; } return (stakedTokens, stakers); } function totalStaked() isFluffyContractSet public view returns (uint256 count) { uint256[] memory tokens = ffxr.tokensOfOwner(address(this)); count = 0; for (uint256 i = 0; i < tokens.length; i++) { if (staked[tokens[i]] != address(0x0)) { ++count; } } } function tokensStakedByAddress(address ogOwner) public view returns(uint256[] memory tokenIds) { uint256[] memory tokens = ffxr.tokensOfOwner(address(this)); uint256 owned = 0; for (uint256 i = 0; i < tokens.length; ++i) { if (ogOwner == staked[tokens[i]]) { ++owned; } } tokenIds = new uint256[](owned); owned = 0; for (uint256 i = 0; i < tokens.length; ++i) { if (ogOwner == staked[tokens[i]]) { tokenIds[owned] = tokens[i]; ++owned; } } } function isStakingEnabled() public view returns (bool) { return this.isStakingEnabled(msg.sender); } function isStakingEnabled(address send) public view returns (bool) { return ffxr.isApprovedForAll(send, address(this)); } function oddballTokensThatShouldNotBeHere() public view returns (uint256[] memory tokenIds) { uint256 count = 0; uint256[] memory tokens = ffxr.tokensOfOwner(address(this)); for(uint256 i = 0; i < tokens.length; ++i) { if (staked[tokens[i]] == address(0x0)) { ++count; } } tokenIds = new uint256[](count); count = 0; for(uint256 i = 0; i < tokens.length; ++i) { if (staked[tokens[i]] == address(0x0)) { tokenIds[count] = tokens[i]; ++count; } } } /** * STAKING */ function stakeBatch(uint256[] calldata tokenIds) isStakingActive isApproved(msg.sender) external { for (uint256 i = 0; i < tokenIds.length; ++i) { _stake(tokenIds[i]); } } function stake(uint256 tokenId) isStakingActive isApproved(msg.sender) external { _stake(tokenId); } function _stake(uint256 tokenId) isFluffyContractSet private { ffxr.safeTransferFrom(msg.sender, address(this), tokenId); } /** * UNSTAKING */ function unstakeBatch(uint256[] calldata tokenIds) external { for (uint256 i = 0; i < tokenIds.length; ++i) { _unstake(tokenIds[i]); } } function unstake(uint256 tokenId) external { _unstake(tokenId); } function _unstake(uint256 tokenId) isFluffyContractSet onlyOriginalTokenOwner(tokenId) private { ffxr.safeTransferFrom(address(this), staked[tokenId], tokenId); staked[tokenId] = address(0x0); } /** * MODIFIERS */ modifier onlyOriginalTokenOwner(uint256 tokenId) { require(msg.sender == staked[tokenId], "You are not tokens original owner"); _; } modifier onlyOwner() { require(msg.sender == ownerAddress, "You are not owner."); _; } modifier onlyFromFluffyContract(address sentFromAddress) { require(sentFromAddress == address(ffxr), "Not sent from Fluffy contract."); _; } modifier isFluffyContractSet() { require(address(ffxr) != address(0x0), "Fluffy address is not set"); _; } modifier isApproved(address send) { require(this.isStakingEnabled(send), "You have not approved FluffyStaker."); _; } modifier isStakingActive() { require(active, "Staking is not active."); _; } } // File: contracts/FluffyNextGen.sol /** * SPDX-License-Identifier: UNLICENSED */ pragma solidity >=0.8.0 <0.9.0; contract FluffyNextGen is ERC721AQueryable, Ownable, ReentrancyGuard { FluffyFucksReborn public ffxr; bool public paused = true; bool public holderWlMintOpen = false; bool public publicMintOpen = false; uint256 public supply = 1212; uint256 public teamSupply = 30; uint256 public defaultMaxPerWallet = 5; uint256 public price = 0.0069 ether; bytes32 public merkleRoot; string private contractMetadataUrl; string private tokenMetadataUrlRoot; mapping(address => uint256) private addressHasMinted; mapping(address => uint256) private stakerHasMintedFree; mapping(address => uint256) private stakerSnapshot; /** * CONSTRUCTOR */ constructor () ERC721A("FluffyFucks Koalas", "FFXg2.0") { deploySnapshot(); } /** * MINTING */ // team mint function teamMint(uint256 _quantity) public onlyOwner nonReentrant supplyExists(_quantity) { require(addressHasMinted[msg.sender] + _quantity <= teamSupply); _safeMint(msg.sender, _quantity); addressHasMinted[msg.sender] += _quantity; } // mint function mint( uint256 _quantity, uint256 _freeMints, bytes32[] calldata _proof ) public payable isMintingOpen nonReentrant supplyExists(_quantity + _freeMints) { require(_quantity + _freeMints > 0, "No point minting nothing."); // checking if person is an active staker if(stakerSnapshot[msg.sender] > 0) { return stakerMint(stakerSnapshot[msg.sender], msg.sender, _quantity, _freeMints, msg.value); } require(_quantity > 0, "No point minting no fluffs."); // checking if person is an active holder uint256 balance = ffxr.balanceOf(msg.sender); if (balance > 0) { return holderMint(msg.sender, _quantity, msg.value); } // checking if person is whitelisted if (isAddressWhitelisted(msg.sender, _proof)) { return whitelistMint(msg.sender, _quantity, msg.value); } // defaulting to public mint return publicMint(msg.sender, _quantity, msg.value); } // staker mint function stakerMint(uint256 _numberStaked, address _minter, uint256 _quantity, uint256 _freeMints, uint256 _payment) private hasFunds(_quantity, _payment) { (uint256 maxFreeMints, uint256 maxMinted) = howManyCanStakerMint(_numberStaked); require(_freeMints + stakerHasMintedFree[_minter] <= maxFreeMints, "You cannot mint this many free mints."); require(_quantity + _freeMints + addressHasMinted[_minter] <= maxMinted, "You cannot mint this many fluffs."); _safeMint(_minter, _quantity + _freeMints); addressHasMinted[_minter] += _quantity + _freeMints; stakerHasMintedFree[_minter] += _freeMints; } // whitelist mint function whitelistMint(address _minter, uint256 _quantity, uint256 _payment) private isHolderWlMintOpen hasFunds(_quantity, _payment) canMintAmount(_minter, _quantity) { _safeMint(_minter, _quantity); addressHasMinted[_minter] += _quantity; } // holder mint function holderMint(address _minter, uint256 _quantity, uint256 _payment) private isHolderWlMintOpen hasFunds(_quantity, _payment) canMintAmount(_minter, _quantity) { _safeMint(_minter, _quantity); addressHasMinted[_minter] += _quantity; } // public mint function publicMint(address _minter, uint256 _quantity, uint256 _payment) private isPublicMintOpen hasFunds(_quantity, _payment) canMintAmount(_minter, _quantity) { _safeMint(_minter, _quantity); addressHasMinted[_minter] += _quantity; } /** * GETTERS AND SETTERS */ function setPaused(bool _paused) public onlyOwner { paused = _paused; } function setPublicMintOpen(bool _publicOpen) public onlyOwner { publicMintOpen = _publicOpen; } function setHolderWlMintOpen(bool _holdWlOpen) public onlyOwner { holderWlMintOpen = _holdWlOpen; } function setFluffyContract(address _contract) public onlyOwner { ffxr = FluffyFucksReborn(_contract); } function setMerkleRoot(bytes32 _merkle) public onlyOwner { merkleRoot = _merkle; } function setContractMetadataUrl(string calldata _metadataUrl) public onlyOwner { contractMetadataUrl = _metadataUrl; } function setTokenMetadataUrlRoot(string calldata _tokenMetadataRoot) public onlyOwner { tokenMetadataUrlRoot = _tokenMetadataRoot; } /** * VIEWS */ function howManyCanSomeoneMint(address _minter) public view returns(uint256 freeMints, uint256 maxMints) { if(stakerSnapshot[_minter] > 1) { (freeMints, maxMints) = howManyCanStakerMint(stakerSnapshot[_minter]); return ( freeMints - stakerHasMintedFree[_minter], maxMints - addressHasMinted[_minter] ); } else { return (0, defaultMaxPerWallet - addressHasMinted[_minter]); } } function howManyCanStakerMint(uint256 _staked) public pure returns(uint256 freeMints, uint256 maxMints) { if (_staked == 0) { // 0 staked return (0, 0); } else if (_staked == 1) { // 1 staked return (0, 5); } else if (_staked < 10) { // less than 10 return (_staked / 2, 5); } else if (_staked < 20) { // less than 20 return (_staked / 2, 10); } else if (_staked < 40) { // less than 40 return (10, 20); } else if (_staked < 69) { // less than 69 return (20, 40); } else { // 69 or more return (35, 69); } } function isAddressWhitelisted(address _minter, bytes32[] calldata _proof) private view returns(bool) { return MerkleProof.verify(_proof, merkleRoot, keccak256(abi.encodePacked(_minter))); } /** * MODIFIERS */ modifier isMintingOpen() { require(paused == false, "Minting is not active."); _; } modifier isPublicMintOpen() { require(publicMintOpen, "Public mint is not open."); _; } modifier isHolderWlMintOpen() { require(holderWlMintOpen, "Holder and Whitelist mint is not open."); _; } modifier supplyExists(uint256 _quantity) { require(_totalMinted() + _quantity <= supply, "This would exceed minting supply."); _; } modifier hasFunds(uint256 _quantity, uint256 _payment) { require(_quantity * price <= _payment, "You do not have enough money to mint."); _; } modifier canMintAmount(address _minter, uint256 _quantity) { require(addressHasMinted[_minter] + _quantity <= defaultMaxPerWallet, "You cannot mint this many"); _; } /** * CONTRACT STUFF */ function _startTokenId() internal pure override returns(uint256) { return 1; } function withdraw() public onlyOwner nonReentrant { (bool os, ) = payable(owner()).call{value: address(this).balance}(""); require(os); } function contractURI() public view returns(string memory) { return contractMetadataUrl; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override(ERC721A, IERC721A) returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId), ".json")) : ""; } function _baseURI() internal view override returns (string memory) { return tokenMetadataUrlRoot; } /** * SNAPSHOT */ function deploySnapshot() private { stakerSnapshot[0x0066A1C2137Ee60fEc2ac1f51E26DCd78Ae0f42d] = 6; stakerSnapshot[0x0071e278144a040EE373331d1c3d9e6fD3BB7339] = 2; stakerSnapshot[0x01850e6686a222edc136f11C93D824cDa433e364] = 4; stakerSnapshot[0x0287E8dfC37544995fb75af20fdaB57c74f4860D] = 2; stakerSnapshot[0x045e6833Fa2B7BBd1a6cfc3CC2630A6e20Ff9E87] = 6; stakerSnapshot[0x06E5D82B5A8dF0435CE8046bc15290594bC0c710] = 2; stakerSnapshot[0x07035d0e0cFb5e89218be943507694526A4EBE54] = 4; stakerSnapshot[0x074DB7F6c8dbD545e53411795B182529f494779A] = 2; stakerSnapshot[0x08132a6899DdcfD77bAA15990D96f6645a9390da] = 2; stakerSnapshot[0x08834D1ac96cb6D533C5a742511C759EE83B0d61] = 8; stakerSnapshot[0x08e6c66Ce1fdEE6004a63B06cA0Ff324b8aa5826] = 2; stakerSnapshot[0x090459ae119b904A0808568E763A4f5556B49FE0] = 2; stakerSnapshot[0x0945BE11418b180Ec8DfE0447a9bE1c15FB1BeaD] = 2; stakerSnapshot[0x09Cb303EcAba558422d63B7392d095C7ffE37D36] = 2; stakerSnapshot[0x0aAB45d1B9C821EBfd03a77117c12355e8739c85] = 13; stakerSnapshot[0x0bC8801f28baf3F5cEbA2bC3f0Cdfcaf37C2846e] = 6; stakerSnapshot[0x0bE9F7f7a5d1e19311989bbE307c4796A534d6E8] = 4; stakerSnapshot[0x0c4DB5ECb43303d925EDa8F11Fe592D59d3C6cC3] = 7; stakerSnapshot[0x0C645D0c6Ec9ec7DDe5BB8f5E655e11775f44277] = 2; stakerSnapshot[0x0d47A223Fd09C174184131a9a539562b4a026E57] = 4; stakerSnapshot[0x0dd201E9243320cb0651AcdCb134e086f4582645] = 2; stakerSnapshot[0x0DfAb02678695f56E9373aA072A59fbDA5938a49] = 2; stakerSnapshot[0x0E96cC0F0001Ab39659d48050d5e5A4361330a4B] = 2; stakerSnapshot[0x1059650DC09681949F7686974F61D95c2135B091] = 2; stakerSnapshot[0x105c9EF0a0531a3B1B692508EFe7994880d942B7] = 4; stakerSnapshot[0x106aBAfcD4C1F615eBF14EFDD7e52EDFb33217aB] = 2; stakerSnapshot[0x134aed007F8935746749Ab25bD3CE88231BF555a] = 2; stakerSnapshot[0x139734BaAd745912286B55cE07a6D113C19A9AD9] = 2; stakerSnapshot[0x142875238256444be2243b01CBe613B0Fac3f64E] = 2; stakerSnapshot[0x14573a0484D8639e024264e0159905AC1eB9B453] = 2; stakerSnapshot[0x15384d0578CFcBA6C9E29777599871c8E0878513] = 4; stakerSnapshot[0x167f12fEFB578f29bEd2585e84ae6C5A72fF21Cd] = 2; stakerSnapshot[0x169eB0789887fedA30DcBD91b4002089A98Ab241] = 2; stakerSnapshot[0x190237dcED5114bD6c482772ce20faD0Be407b4A] = 6; stakerSnapshot[0x1a2f95a9dc750b581632C567a2d7B96650D6e019] = 6; stakerSnapshot[0x1Ba3a102D292e988E8eE55d30ad98e5B4BdA32dc] = 2; stakerSnapshot[0x1E50CA5bfc75d6B4af207503E3A6D4A4c5ec05cd] = 4; stakerSnapshot[0x205BBBE1b5EE65efFe19c5DD59b84AD1413BBB77] = 4; stakerSnapshot[0x2129bCA7cA8B37956ec24c5b7411fd5424370DBF] = 15; stakerSnapshot[0x2245Ec2b9773e5B6A457F883c3183374Fe4D0864] = 4; stakerSnapshot[0x23f3c4dD6297A36A2140d5478188D9e773D3Ac9E] = 2; stakerSnapshot[0x252723A88a9c2279E998D4eD363DB120553C715C] = 5; stakerSnapshot[0x252d74d7d69f5cC3Bb2Cd2fdbE3b37DC1F1edC2f] = 4; stakerSnapshot[0x2581F074fDA1454a2869862D61429Dd5871cE4DA] = 2; stakerSnapshot[0x25A1Cfac8c9eADAB7c12FB59d54144593Aa96436] = 4; stakerSnapshot[0x2735B84B6AfB1328EA7809ce212589C5175D71Fb] = 2; stakerSnapshot[0x2760F7d38377AcF2Fc26c08915B4669eBeE1420A] = 4; stakerSnapshot[0x27f0A1677a3185d360ac5985f3BbC766ca34b00E] = 14; stakerSnapshot[0x29adfe4efD359939322493eD8B386d45877E7749] = 8; stakerSnapshot[0x2A9a201B97305F52E3771ACDbFbaDc015fbD155F] = 2; stakerSnapshot[0x2b604baEe38Fd5d9eF2b236e4d8462C27A66aD5d] = 2; stakerSnapshot[0x2bEcCB8975aEee773b03a3CB29a81304D5AC6122] = 2; stakerSnapshot[0x2c82C2B69d7B56EE7f475d1320e362e87b51Ae4d] = 6; stakerSnapshot[0x2FE38f5092E76b27e278bf2417e2a56375bB6b8B] = 8; stakerSnapshot[0x3020136b9958642cf8E3972E06DB21F3884DF56A] = 2; stakerSnapshot[0x31aBDFd780A044b034270862F46853d1e34Dd6aE] = 2; stakerSnapshot[0x31B685C06590d72c67609C2d940C41C79966D2E3] = 6; stakerSnapshot[0x31e4662AAE7529E0A95BeD463c48d8B398cfAB73] = 12; stakerSnapshot[0x34A0c4799a177a95EA6611aEbf377639f551eaa3] = 33; stakerSnapshot[0x3578234C0FD2d531E84eEc84CAbf64FF5B246c30] = 2; stakerSnapshot[0x3609840fb53EBEa9F39c2c97e4A39438a825a89e] = 20; stakerSnapshot[0x36214d560aaa853d5c0853920FFe27779803419D] = 7; stakerSnapshot[0x362DC61A04cb099aB6b912DB07e0D6270342f16D] = 25; stakerSnapshot[0x3765A89463A19D5c2413544808Cb8b537Ac406eF] = 2; stakerSnapshot[0x37FFe79d00C8c33E3f9622ac940e46BFa56d70a7] = 5; stakerSnapshot[0x39E121297240Ac7F72E7487D799a0fC06422e216] = 2; stakerSnapshot[0x3A410941d1A1f9d6d09a2F479Be991C237DD2A68] = 2; stakerSnapshot[0x3a95e5407E32A1CC7f6923F3297aF09D2279bBDC] = 2; stakerSnapshot[0x3Aa17002F448bee09284dDe391A595E51DCd8c39] = 5; stakerSnapshot[0x3cbE9F5d49a2b92FA49cc01B4547C0860Bae4f99] = 2; stakerSnapshot[0x3ccc9E75E6C63fcb68E30B81A3bc3209dB09A9f9] = 8; stakerSnapshot[0x3d5A925EeD67A613778d7Ad9254aB75241348EBc] = 6; stakerSnapshot[0x3E311f18653300f9441aC0D886DFF51e1278aAEB] = 3; stakerSnapshot[0x3E6D9477BA6b136bAb6FA4BE2E40373de2eC704F] = 2; stakerSnapshot[0x3ec6d18f4A52dd8dBCb013eE920f935738C6223C] = 79; stakerSnapshot[0x3eC8A6f383Fdda0A21996b4233946717f9EacB26] = 2; stakerSnapshot[0x3eddd4CC257564889Ba377f5Fdb9e827e9503F96] = 2; stakerSnapshot[0x3Ff0df7EC6Ab47725272691a030c22a59bc87B1D] = 2; stakerSnapshot[0x419D36f006Ba8933fFb99B5BC8d189505c0836d3] = 2; stakerSnapshot[0x42B83becC570F4e2D9b40544d59984541Aa52168] = 2; stakerSnapshot[0x433eE230C45Fd079E60CF5d428b76Caa0055558c] = 22; stakerSnapshot[0x434eD1DecDE9dCB0ca6c9E5c29C95D22f085400F] = 1; stakerSnapshot[0x4526E96ceDb7A4F570944c37A544B0E44b946ea4] = 69; stakerSnapshot[0x46A8E8B740292775F036da3Bd279f1994864bf53] = 2; stakerSnapshot[0x46bE8E0a5e919E1A174978636B6be161b21E2f1A] = 6; stakerSnapshot[0x47e44738be0732119E0687EaA3BC18F5c8e58399] = 2; stakerSnapshot[0x47F740c1Ea213A267B483640c1C3aEC8B262f25e] = 26; stakerSnapshot[0x48ec7Fe34E0C7843133c0e7571c2f17AB8C7bf32] = 4; stakerSnapshot[0x49a15aD9eCa0d7aDc9dABe42869DFc304C26FD53] = 2; stakerSnapshot[0x4aC3728c8C2CCAAf89784ea9C9Ae886A9a30B56c] = 6; stakerSnapshot[0x4ae0e898A9E0deE985E7f35F5630e2eDe0cD6216] = 4; stakerSnapshot[0x4bf1fF6D70a2ECe1cBA5Bb18FDC2444f3D40Aa1d] = 2; stakerSnapshot[0x4C0aCA1031913e3C0cA7A1147F39A8588E04c55d] = 2; stakerSnapshot[0x4C981C345e9047524f793e8b5E15f2089320842b] = 2; stakerSnapshot[0x4Ce8BDc18e257dB9ea29D11E290DfbA99431dDd9] = 7; stakerSnapshot[0x4F4567044DE8f48A70e9e17Bd80fFA3F8e80C836] = 4; stakerSnapshot[0x4f56215bFB5E76fA6849Ae3FdEf417C19cD9AA23] = 4; stakerSnapshot[0x4F94eE0B6d2a31cb9BeFEEF2d95bF19F3a63E7Dd] = 4; stakerSnapshot[0x535FF5ACFeE41Fd02F01667dDd25772D8f8A231D] = 1; stakerSnapshot[0x53965cd7992BC61b4807Aa7aCe3Bec0062c90dE2] = 2; stakerSnapshot[0x542B659331442eAcFE2EF1a135F31aF1c107FE3A] = 4; stakerSnapshot[0x5615bCb489147674E6bceb3Cda97342B654aBA81] = 3; stakerSnapshot[0x5709D86f9946D93a2e1c6b2B6C15D6e25F37B19B] = 3; stakerSnapshot[0x57140a5EC315C7193DeFA29356B1cBd9a1393435] = 7; stakerSnapshot[0x575543b79Ab9913FA322295e322B08ef6C023a88] = 2; stakerSnapshot[0x5758bc7DcBcb32E6eBDa8Fe951E5a588e8a7A097] = 2; stakerSnapshot[0x578D7d391B4F34E35B4ca669F6a1dC18c04bB451] = 2; stakerSnapshot[0x581ddECBf2E27a06A069D67Fc7fb185eFB3c3d5f] = 3; stakerSnapshot[0x584a1d14920A49C8d19110636A2b435670CAf367] = 1; stakerSnapshot[0x5970F4d785A81b774D58330f47cD470fc3599848] = 3; stakerSnapshot[0x59b8130B9b1Aa6313776649B17326AA668f7b7a6] = 6; stakerSnapshot[0x5A512866D6E2a5d34BcdA0C4a28e207D2a310B60] = 2; stakerSnapshot[0x5C55F7eD0CDfE0928b19CA0B076C26F98080a136] = 2; stakerSnapshot[0x5Da07C2959C9815FEcEaC21FD7547C7E684c2431] = 2; stakerSnapshot[0x5DF596aa9315cd8B56e5C1213762F5b482Cb8aDA] = 1; stakerSnapshot[0x5f5B53E9e65CEbDc9085A73B017451f79B9d0158] = 2; stakerSnapshot[0x5fa19516d4A9AB74B89CeBc4E739f9AbdF69d7Bd] = 4; stakerSnapshot[0x5FDC2E1c58308289d8dD719Db2f952258e28ec96] = 1; stakerSnapshot[0x600cFB1736626C03dF54964ef481861eD092A7a0] = 2; stakerSnapshot[0x60cF1FCb21F08E538B16B0579009EF35107fDd53] = 1; stakerSnapshot[0x612E900a95Cd662D6c7434ECcCaA92C5CDf05F25] = 12; stakerSnapshot[0x61D7f4Dd8b5D8E9416fE8Fd81224171cAA32112b] = 2; stakerSnapshot[0x62e0C4336370184873224EC5ebeE4B6567d5602d] = 2; stakerSnapshot[0x62E725f096666Ef2f05fF3AAF4d0b042b3Eef5B8] = 7; stakerSnapshot[0x63E80354A787f7C876eb3C862BC93e36fCC1F310] = 4; stakerSnapshot[0x64Bc737b1A030aaC323c073f11939DB7b9e8F347] = 10; stakerSnapshot[0x6576082983708D32418d7abe400E2Df4360aa550] = 1; stakerSnapshot[0x657C61B33779B526BBbd6d5A24D82a569717dCeE] = 3; stakerSnapshot[0x668ca185c3cDfA625115b0A5b0d35BCDADfe0327] = 81; stakerSnapshot[0x6868B90BA68E48b3571928A7727201B9efE1D374] = 30; stakerSnapshot[0x68E9D76F37bE57387CF6b9E1835b04CC957aa2E7] = 20; stakerSnapshot[0x695f28D97aDF81DE4C8081aEf62d16d7B60fD35B] = 10; stakerSnapshot[0x697Dc0e8A3b3e3758f59f32BE847b2290823dBC1] = 42; stakerSnapshot[0x698f345481Fc1007C5094D8495b01DF375E4E4a7] = 2; stakerSnapshot[0x69B2803c04fec9505113038E1F91257A337DF63e] = 2; stakerSnapshot[0x69fD02C1Cf7659D3D095c4Ce73B5d5C23886B5f6] = 3; stakerSnapshot[0x6b140e5a9F6B6967Af30F789414840E2FFe1bdE9] = 2; stakerSnapshot[0x6B703CbB3cA5FE26cA9054F95c808facD7B57bCA] = 2; stakerSnapshot[0x6bA9BAb89e215DA976776788630Bce75E331B87d] = 1; stakerSnapshot[0x6C719836105879783760EAef03A8E004482eD33C] = 7; stakerSnapshot[0x6C87622a5de8cf0B5E7d4Dd2e6d9EBedBBF6289C] = 6; stakerSnapshot[0x6c9E0941eD2Fe399bfdd30Afb91A89db3f719f78] = 20; stakerSnapshot[0x6D28439B6c5A022B8C50C1AA0b8a8dA4B416FA6f] = 1; stakerSnapshot[0x6F8a67326832E81F0c13c69EcC9Bec618F707526] = 6; stakerSnapshot[0x6F9fc508dC77FD4ABEa9d72c91E7133703a2F38F] = 20; stakerSnapshot[0x7270B7aC52ee19a1c07EFE24574B0360f9bCaa76] = 2; stakerSnapshot[0x72b113664DEC5094Efb4431C39Ed4da003De59cd] = 74; stakerSnapshot[0x7357f081E79760e157E6C4215a35ad0233260f66] = 1; stakerSnapshot[0x74F499133eD684dA42B83afb1592aEc92F48228a] = 2; stakerSnapshot[0x75f9406bb829b6ad1313dB7FFf421E1E959D010b] = 8; stakerSnapshot[0x76239D6b1D37E0058D89C06c21BE4A14C492b301] = 2; stakerSnapshot[0x76E8D76759Acd20220F17f0dCdeb5768Be535152] = 2; stakerSnapshot[0x76F8a5c06857b44E1D459671b00708c7502c7999] = 2; stakerSnapshot[0x7836989949554501AC5D021b7BaeF6c992f1B854] = 3; stakerSnapshot[0x798A7D6F30DCaa0c060c8514E461c005A0400458] = 2; stakerSnapshot[0x79adc74978a81EB68D11Ab69558b11BECDD88DeC] = 6; stakerSnapshot[0x79c837F954CaEae493FaA298B0e0DcF0d5BAb20d] = 2; stakerSnapshot[0x7A0AB4A019f5B9626db6590F02d07f8Ee504Ae8A] = 2; stakerSnapshot[0x7a600C045eF72CE5483f7E76d4Fe5bEfFCdEE6aC] = 7; stakerSnapshot[0x7A60A3f8377a202E31d9Ff70A9Ebaee6c60D8db8] = 2; stakerSnapshot[0x7a6651c84D768c8c6cB380B229e65590c0BD4D78] = 13; stakerSnapshot[0x7b9D9cD877784D19A0977Aedb9f8697Bf7aaad9E] = 2; stakerSnapshot[0x7C68f66C70836c9745AC42a5Ab2A5C3f8F3D3294] = 2; stakerSnapshot[0x7CdA50Bed220eA0860d60095B27Ee4F744511bb9] = 1; stakerSnapshot[0x7D198D4643DB60Fd6E772470B03A079e920EcC19] = 31; stakerSnapshot[0x7E5F3d3C54B4185b3430005E2354817331F23550] = 3; stakerSnapshot[0x7Efbcb80C47514a78Cdf167f8D0eed3d8a1D7a00] = 6; stakerSnapshot[0x812005457367912B4FcCf527a13b4947d177E8c6] = 1; stakerSnapshot[0x816F81C3fA8368CDB1EaaD755ca50c62fdA9b60D] = 3; stakerSnapshot[0x82023a7bf582E1C772a1BcD749e10C0AFD7aB04E] = 2; stakerSnapshot[0x824189a4C3bc22089bC771b5c9D60131Fd1252a7] = 20; stakerSnapshot[0x82e928D20c021cAbBd150E7335f751F71A30cBcA] = 2; stakerSnapshot[0x83A9e7FCCb02a20E7ba0803a6dc74600803BB320] = 8; stakerSnapshot[0x849f03ACc35C6F4A861b76e1F271d217CD24b18C] = 2; stakerSnapshot[0x854C162aA246Ffe344262FC1175B6F064dB7250E] = 20; stakerSnapshot[0x870Bf9b18227aa0d28C0f21689A21931aA4FE3DE] = 2; stakerSnapshot[0x87cF0dd1272a6827df5659758859a96De9837EC5] = 8; stakerSnapshot[0x8902B48123201dBBadC20c40B1005C5Ad6250cc5] = 6; stakerSnapshot[0x89B91536A411D97837163987f3a33C15C5599479] = 2; stakerSnapshot[0x89d687021563f1A62DCD3AcaDDc64feF948F8fcb] = 40; stakerSnapshot[0x8a4892a38196d4A284e585eBC5D1545E5085583a] = 2; stakerSnapshot[0x8C2Bf3a4504888b0DE9688AEccf38a905DcEC940] = 4; stakerSnapshot[0x8c2Db300315DcB15e0A8869eA94F843E218a78B4] = 4; stakerSnapshot[0x8C409C76690F16a0C520EF4ECECBB8ad71017480] = 20; stakerSnapshot[0x8c7e78d32CB350D7B560372285610b5E46e67981] = 4; stakerSnapshot[0x8cCc7DA43DcbA6FEf07a318f88965e7aEEdB5eBc] = 12; stakerSnapshot[0x8D757F5675405271de9DDff392f7E7A717b5bddb] = 4; stakerSnapshot[0x8D98139512ac57459A468BC10ccf30Fd9dd6149A] = 12; stakerSnapshot[0x8f0CaCC1B3d0066A31Fc97c6CF1db1b0F56f073f] = 2; stakerSnapshot[0x8Fa3e7cb0c9C14FfBe750080A97ee678AD71a216] = 2; stakerSnapshot[0x8fd974089B612041C37eB643980C2A9C9BA85058] = 1; stakerSnapshot[0x9251af98d5649d1BC949f62E955095938897289d] = 2; stakerSnapshot[0x92aC315cb47B620F84238C57d3b3cc7F42078781] = 4; stakerSnapshot[0x92b398370dda6392cf5b239561aB1bD3ba393CB6] = 6; stakerSnapshot[0x92B99779Bc3471706A8f9Eb0F3975331e6664678] = 4; stakerSnapshot[0x93d751d48693AD3384C5021F821122bc4192B504] = 7; stakerSnapshot[0x945A81369C1bc7E73eb2D509AF1f7a067A253702] = 4; stakerSnapshot[0x95e3C7af64fFCDdA13630C7C10646775dc638275] = 27; stakerSnapshot[0x960A84baf0Ac4162a83D421CDB7a00Cc2777b22D] = 2; stakerSnapshot[0x964afBC4d4a80346861bB87dbC31a8610AE87fC4] = 4; stakerSnapshot[0x97111A057171E93aa7b2d63B4f6B5b7Bdc33EF8D] = 4; stakerSnapshot[0x995B7FABDae160217F378BbB05669Aa4bDcdc81f] = 1; stakerSnapshot[0x9B687413591Ad92cC1BC5cD5Fd442c04872D97DB] = 6; stakerSnapshot[0x9C9964733479a6E0758d97A7B89DcE81C20b19d7] = 1; stakerSnapshot[0x9e01852683b88D829551895C7BFd1799b121fdBC] = 4; stakerSnapshot[0x9f137fb2330e499607E1b1233dE2C1b90b1A7a85] = 4; stakerSnapshot[0x9FC7EdAC9dF5bCc75671EFF5A2c2898Fc4242636] = 22; stakerSnapshot[0x9Fe697f4d0D447409331681e0401a4f7E756fdD7] = 5; stakerSnapshot[0xA01D7E4e848467CBD2CA864150f27A9D286C86C8] = 9; stakerSnapshot[0xa07cb2c3861D34FA5686d52018dC401FF413F05D] = 7; stakerSnapshot[0xA0843Cf5DbEaf1EB3d7Cd31B372d6Cc06180b1Ab] = 2; stakerSnapshot[0xa0C737617b7E63e1CbF87C45c11cd766CF57Bd9D] = 2; stakerSnapshot[0xA1bE91b15E959294Cb6eFD7891c846cAf7ef7602] = 4; stakerSnapshot[0xa235Fbd83AD5B143bCd18719834C60BA7c925C52] = 2; stakerSnapshot[0xA2bff178071A266D14e360e3f3CE226B19D3F809] = 2; stakerSnapshot[0xa55F7eA2F6001DC6d046cFe799c3Ec4dC79cc5b8] = 3; stakerSnapshot[0xa62CBb35f5a51695F1cC550f3a8506Fc458D681D] = 2; stakerSnapshot[0xA6E3F06461A5d34fB3344FF6b45d6C92D207c35d] = 38; stakerSnapshot[0xa731325b4D01250Fe8852Fe76974F084d968e75D] = 20; stakerSnapshot[0xa784224c2F3c82c47abEda5D640e911633Cd24Da] = 4; stakerSnapshot[0xA8047DcE2A42968379E68870274ED2F534082Edd] = 3; stakerSnapshot[0xa8ad3C8D9039a0D10040d187C44336e57456fecE] = 2; stakerSnapshot[0xAa5B7f29C81B7409A021a2Bfe1E0FCec27EAD33E] = 2; stakerSnapshot[0xAaCDB53292F7703A608926799C9A02C9662923aa] = 4; stakerSnapshot[0xAb48De856930c018238c226D166Feaed3541Ec7d] = 1; stakerSnapshot[0xab516c4a5A0b705025a079814bDe84e846bCe019] = 20; stakerSnapshot[0xAb532bE7866818326D5A9cf86134eb0C2E95A8cE] = 2; stakerSnapshot[0xABa93498a69373b5E5f72254a513Bfaf77253d16] = 2; stakerSnapshot[0xACa79E56C92DeD769D2B773C8bab2aB552Ec5172] = 69; stakerSnapshot[0xAdc81042fEc23050b99EA6E08552a2bA439Df481] = 2; stakerSnapshot[0xaF9938ec47EbD29c93208f71f63d27b61E517522] = 20; stakerSnapshot[0xAfC9D3054f3047AA99347f4266a256BF2F6e12ca] = 2; stakerSnapshot[0xB0ea4466D71431E87B4c00fa2AECe86742e507b0] = 23; stakerSnapshot[0xb1ce4373890A21CC3Fd65480D72770496689a7Ba] = 20; stakerSnapshot[0xb1e2E3EA2A52Ee700403fc504429012FD733dD72] = 22; stakerSnapshot[0xB2A7CE5B1fAF0d1f4fF1a59fCa9D7ee24917FF81] = 4; stakerSnapshot[0xb37e6F4F7E3f74e447d860aAeB0E8783320c66bF] = 6; stakerSnapshot[0xb3C4fC3a65C2DF5d0f4e748BdC563bAB49d0399d] = 8; stakerSnapshot[0xB47832cA65E661b2b54dE39F24775C1d82C216f9] = 2; stakerSnapshot[0xb5048a3518C05F2dD51976e941047B54b0539ECD] = 2; stakerSnapshot[0xb5cA180081211730DD00d4fac6f4bEDF74e932Da] = 71; stakerSnapshot[0xB666A384e23da54C7DA222a2c3dE69a009Fae620] = 2; stakerSnapshot[0xB7Afe2297B5756B740193076e5CB2753aC582543] = 2; stakerSnapshot[0xB84404f79EbeF00233E1AEdB273c67c917B8840f] = 40; stakerSnapshot[0xB8545d529234eB2848C85c0CcC0a5Ce9B30a3C0b] = 6; stakerSnapshot[0xb87c4158b4A5766D67aA8591064bbe5126823514] = 2; stakerSnapshot[0xb908B613d695c350BF8b88007F3f2799b91f86c4] = 1; stakerSnapshot[0xBaB80520D514Df65B765A1f8990cc195559E6778] = 2; stakerSnapshot[0xBd50C7a6CF80A5221FCb798a7F3305A036303d2D] = 2; stakerSnapshot[0xBde69E440Bd3AbC059db71cE0bb75f31b92F37E1] = 2; stakerSnapshot[0xBE331A01056066311C9989437c58293AF56b59cA] = 4; stakerSnapshot[0xBe546e6a5CA1c2CfcB486Bb9de4baD98C88e7109] = 2; stakerSnapshot[0xBeaa9B4b26aEA31459dCA6E64e12A0b83e21A0dd] = 12; stakerSnapshot[0xBfEcB5bD1726Afa7095f924374f3cE5d6375F24A] = 2; stakerSnapshot[0xC25cea4227fA68348F025A8C09768378D338F8d6] = 2; stakerSnapshot[0xC261c472a5fea6f1002dA278d55D2D4463f000ef] = 4; stakerSnapshot[0xc3cf1A2962b750eb552C4A1A61259Fd35063e74e] = 2; stakerSnapshot[0xc42480b588Aff1B9f15Db3845fb74299195C8FCE] = 6; stakerSnapshot[0xC800391fDDcC6F899DCA185d5B16994B7D0CB13e] = 2; stakerSnapshot[0xcac8ca2C41b14304906c884DB9603A7B29D98Adb] = 5; stakerSnapshot[0xcB85e96ADE0D281eA3B5B8165cdC808b16Ac13b9] = 2; stakerSnapshot[0xcB91368B760f0d6F2160114b422A93aE50e44542] = 4; stakerSnapshot[0xcBa18510a6336F3975Cea1164B9C5d029E1A7C82] = 2; stakerSnapshot[0xCBc6C9CeF4f3C7cbBb8Eb82A2aD60c00e631A8C1] = 8; stakerSnapshot[0xcC507e6DDc3a6C992BC02019fbEeb8f81Be9FBb2] = 69; stakerSnapshot[0xcCE8A3fb91290071b377FE0EC3df0eb7ceA8AFFC] = 2; stakerSnapshot[0xcd1C78538E3Cc0D2ceadd87b8124357d86566365] = 3; stakerSnapshot[0xcE046B2a56fea1559dB99f7fB4e4570aaaFF9889] = 6; stakerSnapshot[0xce83bc7517B8435Eb08EB515Aa3f6c9386b1E2A0] = 6; stakerSnapshot[0xCF0268111e06d26e1B9ea813Fe49c40A4227778D] = 6; stakerSnapshot[0xCf7346Ba8d7D4D2A3A256b2FA00Daf5c7566351b] = 2; stakerSnapshot[0xd03a4E75A730eb5f700dfE71703CbaA99CB67532] = 6; stakerSnapshot[0xd054952345f497F7A9461a202E8f1284b885eE2F] = 6; stakerSnapshot[0xd2A41a1Aa5698f88f947b6ba9Ce4d3109623c223] = 2; stakerSnapshot[0xD4658C7c5b42cAd999b5b881305D60A72590f247] = 7; stakerSnapshot[0xd696d9f21f2bC4aE97d351E9C14Fa1928C886c61] = 2; stakerSnapshot[0xd69A21f89c463a96F9E916F84a7AA5ca8A9DD595] = 1; stakerSnapshot[0xd76A10B1916404eE78f48571c1a5Fa913aaAF72b] = 21; stakerSnapshot[0xD7d28e62b7221A82094292Ed59F1d9D86D32c39c] = 7; stakerSnapshot[0xD9AF96861dE6992b299e9aC004Aa4c68771d0815] = 2; stakerSnapshot[0xD9C925E7dB3c6F64c2b347107CAfDc75390A8744] = 4; stakerSnapshot[0xDafF72174cf270D194f79C4d5F1e1cDAb748fE14] = 6; stakerSnapshot[0xdb955C787Ea67964e1d47b752657C307283aE8c2] = 6; stakerSnapshot[0xDBbce16eDeE36909115d374a886aE0cD6be56EB6] = 2; stakerSnapshot[0xdc5B1B4A9730C4d980FE4e9d5E7355c501480d73] = 2; stakerSnapshot[0xDC6eB1077c9D84260b2c7a5b5F1926273Ae54578] = 2; stakerSnapshot[0xDD262F615BfAc068C640269E53A797C58410bAFc] = 42; stakerSnapshot[0xdDd1918AC0D873eb02feD2ac24251da75d983Fed] = 2; stakerSnapshot[0xE11D08e4EA85dc79d63020d99f02f659B17F36DB] = 3; stakerSnapshot[0xE18ff984BdDD7DbE2E1D83B6B4C5B8ab6BC7Daf6] = 2; stakerSnapshot[0xE2F7c36A7cFC5F54CfEA051900117695Cb3c6b2f] = 6; stakerSnapshot[0xe367B61Ab9bC05100fDA392fec1B6Ff2b226cF6E] = 23; stakerSnapshot[0xe54DEBc68b0676d8F800Aff820Dfe63E5C854091] = 2; stakerSnapshot[0xe5A923B2Db4b828Ab1592D10C53cfeA7080245B3] = 71; stakerSnapshot[0xE5b0e824DA704b77f5190895b17b990024a22A3E] = 2; stakerSnapshot[0xe66a52474370E0CbDa0F867da4D25471aA3C1615] = 9; stakerSnapshot[0xe717472C2683B6bca8688f030b9e0C65cFc52c99] = 2; stakerSnapshot[0xE7b770c6cf75325A6525E79A6Afae60888f3F498] = 2; stakerSnapshot[0xE8969399b899244291cE9AB2f175B3229Cd42ECd] = 6; stakerSnapshot[0xE9275ac6c2378c0Fb93C738fF55D54a80b3E2d8a] = 2; stakerSnapshot[0xe978aE285E6ca04Ef40Af882371A2E4A97cFC812] = 7; stakerSnapshot[0xEa02AB878834bA9551987CbA64B94C514DDe194F] = 2; stakerSnapshot[0xEA99a428D69aa84aD9a20D782Cde4a1e6c3E9017] = 6; stakerSnapshot[0xEa9f6ec11914703227A737A670c4Fc5A7b20CBFc] = 65; stakerSnapshot[0xECA576463eA8aFB5A21e0335f0c4F4e4a414156b] = 2; stakerSnapshot[0xeCBCeA720dAc9dCFaA7024B80DB92755b8836785] = 4; stakerSnapshot[0xeE2020eeD81905C8964A4B236B858A1A6eB5889e] = 2; stakerSnapshot[0xEf85AB7726Fb85CEf041F1e035AbD5e6844B660E] = 2; stakerSnapshot[0xeFeb821368e89336f7110390A12c98fF95794fa8] = 2; stakerSnapshot[0xF1595c576370A794d2Ef783624cd521d5C614b62] = 2; stakerSnapshot[0xF2557A90C56CbB18b1955237b212A0f86A834909] = 4; stakerSnapshot[0xf2cfA31187616a4669369CD64853D96739ef999C] = 7; stakerSnapshot[0xf39C00D5bCDF098bAB69385b56ee8140EeB105a1] = 2; stakerSnapshot[0xF3D47f776F035333Aaf3847eBB41EA8955a149F4] = 2; stakerSnapshot[0xf416526650C9596Ed5A5aAFEd2880A6b3f9daEfc] = 4; stakerSnapshot[0xF45bE2e48dFD057eB700653aDA23d95108928FEF] = 2; stakerSnapshot[0xF7f9eF971B6377493Da1CD7a7206F603f190CDa5] = 2; stakerSnapshot[0xF90A20105A8EE1C7cc00466ebcC72060887cc099] = 12; stakerSnapshot[0xf944f5715314af4D0c882A868599d7849AAC266F] = 6; stakerSnapshot[0xF98DA3CC07028722547Bb795ce57D96bEbA936bd] = 4; stakerSnapshot[0xfb5D7141feaCBBd6678fD37D58EE9D19e01Df8EE] = 2; stakerSnapshot[0xfBBAc3c308799E744C939eaB11449E3649C1e52D] = 20; stakerSnapshot[0xFCc36706699c5cB1C324681e826992969dbE0dBA] = 6; stakerSnapshot[0xfE3Cf487565A3Cd275cb2cbf96a395F023637D86] = 2; stakerSnapshot[0xFeb244CDc87A2f3Feb9B10908B89fEd816E67B5a] = 70; stakerSnapshot[0xFECE31D9eD6B02F774eB559C503f75fc9b0bcE4E] = 2; } }