Transaction Hash:
Block:
19162530 at Feb-05-2024 02:01:11 PM +UTC
Transaction Fee:
0.003316438150169 ETH
$7.58
Gas Used:
107,000 Gas / 30.994749067 Gwei
Emitted Events:
280 |
CitizenZero.Transfer( from=0x00000000...000000000, to=[Sender] 0x28c0647db1ae7bec8108ed5ec20ed6e48b74c792, tokenId=187 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x28c0647d...48b74c792 |
0.035027285760962264 Eth
Nonce: 194
|
0.031710847610793264 Eth
Nonce: 195
| 0.003316438150169 | ||
0x3b64216A...75Ab7ED67
Miner
| (Boba Builder) | 0.095378572431400915 Eth | 0.095381274107998915 Eth | 0.000002701676598 | |
0xBE6889e5...be878cc93 |
Execution Trace
CitizenZero.CALL( )

-
CitizenZero.STATICCALL( )
//SPDX-License-Identifier: GPL 3 pragma solidity >=0.8.0 <0.9.0; library Counters { struct Counter { uint256 _value; } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } } contract TokenAccessControl { bool public paused = false; address public owner; address public newContractOwner; mapping(address => bool) public authorizedContracts; event Pause(); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); constructor() { owner = msg.sender; } modifier ifNotPaused() { require(!paused, "contract is paused"); _; } modifier onlyOwner() { require(msg.sender == owner, "caller is not an owner"); _; } modifier onlyAuthorizedUser() { require( authorizedContracts[msg.sender], "caller is not an authorized user" ); _; } modifier onlyOwnerOrAuthorizedUser() { require( authorizedContracts[msg.sender] || msg.sender == owner, "caller is not an authorized user or an owner" ); _; } function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(owner, address(0)); owner = address(0); } function transferOwnership(address _newOwner) public onlyOwner { require(_newOwner != address(0)); newContractOwner = _newOwner; } function acceptOwnership() public ifNotPaused { require(msg.sender == newContractOwner); emit OwnershipTransferred(owner, newContractOwner); owner = newContractOwner; newContractOwner = address(0); } function setAuthorizedUser(address _operator, bool _approve) public onlyOwner { if (_approve) { authorizedContracts[_operator] = true; } else { delete authorizedContracts[_operator]; } } function setPause(bool _paused) public onlyOwner { paused = _paused; if (paused) { emit Pause(); } } } interface IERC20 { event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom( address from, address to, uint256 amount ) external returns (bool); } 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); } } } library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v5.0._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v5.0._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v5.0._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v5.0._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v5.0._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds 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); } } } 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)); } } interface IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } interface IERC165 { function supportsInterface(bytes4 interfaceId) external view returns (bool); } interface IERC2981 is IERC165 { function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); } abstract contract ERC165 is IERC165 { function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } abstract contract ERC2981 is IERC2981, ERC165 { struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo; function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual override returns (address, uint256) { RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId]; if (royalty.receiver == address(0)) { royalty = _defaultRoyaltyInfo; } uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator(); return (royalty.receiver, royaltyAmount); } function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { require( feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice" ); require(receiver != address(0), "ERC2981: invalid receiver"); _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } function _setTokenRoyalty( uint256 tokenId, address receiver, uint96 feeNumerator ) internal virtual { require( feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice" ); require(receiver != address(0), "ERC2981: Invalid parameters"); _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } } interface IERC721 is IERC165 { event Transfer( address indexed from, address indexed to, uint256 indexed tokenId ); event Approval( address indexed owner, address indexed approved, uint256 indexed tokenId ); event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); function balanceOf(address owner) external view returns (uint256 balance); function ownerOf(uint256 tokenId) external view returns (address owner); function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; function safeTransferFrom( address from, address to, uint256 tokenId ) external; function transferFrom( address from, address to, uint256 tokenId ) external; function approve(address to, uint256 tokenId) external; function setApprovalForAll(address operator, bool approved) external; function getApproved(uint256 tokenId) external view returns (address operator); function isApprovedForAll(address owner, address operator) external view returns (bool); } interface IERC4906 is IERC165, IERC721 { event MetadataUpdate(uint256 _tokenId); event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); } interface IERC721Metadata is IERC721 { function name() external view returns (string memory); function symbol() external view returns (string memory); function tokenURI(uint256 tokenId) external view returns (string memory); } contract ERC721 is ERC165, IERC721 { string private _name; string private _symbol; string private _baseURI; mapping(uint256 => address) private _owners; mapping(address => uint256) private _balances; mapping(uint256 => address) private _tokenApprovals; mapping(address => mapping(address => bool)) private _operatorApprovals; constructor( string memory name_, string memory symbol_, string memory baseURI_ ) { _name = name_; _symbol = symbol_; _baseURI = baseURI_; } function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } function setBaseUri(string memory baseURI) internal virtual { _baseURI = baseURI; } 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]; } function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } function name() public view virtual returns (string memory) { return _name; } function symbol() public view virtual returns (string memory) { return _symbol; } function tokenURI(uint256 tokenId) public view virtual returns (string memory) { _requireMinted(tokenId); return bytes(_baseURI).length > 0 ? string(abi.encodePacked(_baseURI, Strings.toString(tokenId))) : ""; } function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( msg.sender == owner || isApprovedForAll(owner, msg.sender), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(msg.sender, operator, approved); } function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require( _isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not token owner or approved" ); _transfer(from, to, tokenId); } function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require( _isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not token owner or approved" ); _safeTransfer(from, to, tokenId, data); } 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" ); } function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } 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); } function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } 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" ); } 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); require(!_exists(tokenId), "ERC721: token already minted"); unchecked { _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); owner = ERC721.ownerOf(tokenId); delete _tokenApprovals[tokenId]; unchecked { _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } 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); require( ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner" ); delete _tokenApprovals[tokenId]; unchecked { _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } 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); } function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (isContract(to)) { try IERC721Receiver(to).onERC721Received( msg.sender, 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; } } function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} function _afterTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} function __unsafe_increaseBalance(address account, uint256 amount) internal { _balances[account] += amount; } function isContract(address account) internal view returns (bool) { return account.code.length > 0; } } contract CitizenZero is ERC721, TokenAccessControl, ERC2981, IERC4906 { using Counters for Counters.Counter; string private _contractURI; uint256 public mintLimit; uint64 public whitelistMintStart; uint64 public fcfsMintStart; uint64 public publicMintStart; uint64 public mintEnd; Counters.Counter private _tokenIdCounter; Counters.Counter private _orderCounter; mapping(uint256 => CitizenZeroData) private _citizenZeroData; mapping(address => bool) private _whitelist; mapping(address => bool) private _fcfs; mapping(address => uint16) private _mintedAmount; struct CitizenZeroData { string secretPhrase; uint256 orderNumber; uint16[] achievements; } constructor( string memory name_, string memory symbol_, string memory baseURI_, string memory contractURI_, uint64 whitelistMintStart_, uint64 fcfsMintStart_, uint64 publicMintStart_, uint64 mintEnd_, uint256 mintLimit_, address royaltyReceiver_, uint96 royaltyFeeNumerator_ ) ERC721(name_, symbol_, baseURI_) { _contractURI = contractURI_; whitelistMintStart = whitelistMintStart_; fcfsMintStart = fcfsMintStart_; publicMintStart = publicMintStart_; mintEnd = mintEnd_; mintLimit = mintLimit_; _setDefaultRoyalty(royaltyReceiver_, royaltyFeeNumerator_); _mintCitizenZero(msg.sender); } function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981, IERC165) returns (bool) { return ERC721.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId) || interfaceId == bytes4(0x49064906); } function batchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId) public onlyOwnerOrAuthorizedUser { emit BatchMetadataUpdate(fromTokenId, toTokenId); } function metadataUpdate(uint256 tokenId) public { emit MetadataUpdate(tokenId); } function setDefaultRoyalty(address receiver, uint96 feeNumerator) public onlyOwner { _setDefaultRoyalty(receiver, feeNumerator); } function setWhitelistAddresses( address[] memory whitelistAddresses, bool approval ) public onlyOwnerOrAuthorizedUser { for (uint256 i = 0; i < whitelistAddresses.length; ++i) { _whitelist[whitelistAddresses[i]] = approval; } } function setFcfsAddresses(address[] memory fcfsAddresses, bool approval) public onlyOwnerOrAuthorizedUser { for (uint256 i = 0; i < fcfsAddresses.length; ++i) { _fcfs[fcfsAddresses[i]] = approval; } } function setUri(string memory baseURI) public onlyOwner { setBaseUri(baseURI); } function setContractUri(string memory contractUri) public onlyOwner { _contractURI = contractUri; } function contractURI() public view returns (string memory) { return _contractURI; } function totalSupply() public view virtual returns (uint256) { return _tokenIdCounter.current(); } function mintedAmount(address account) public view returns (uint16) { return _mintedAmount[account]; } function burn(uint256 tokenId) public virtual { require( _isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not token owner or approved" ); _burn(tokenId); } function addAchievement(uint256 tokenId, uint16 achievementId) public onlyOwnerOrAuthorizedUser { _requireMinted(tokenId); _citizenZeroData[tokenId].achievements.push(achievementId); emit MetadataUpdate(tokenId); } function setSecretPhrase(uint256 tokenId, string memory secretPhrase) public onlyOwnerOrAuthorizedUser { _requireMinted(tokenId); _orderCounter.increment(); _citizenZeroData[tokenId] = CitizenZeroData( secretPhrase, _orderCounter.current(), _citizenZeroData[tokenId].achievements ); emit MetadataUpdate(tokenId); } function setMintTimes( uint64 _whitelistMintStart, uint64 _fcfsMintStart, uint64 _publicMintStart, uint64 _mintEnd ) public onlyOwner { whitelistMintStart = _whitelistMintStart; fcfsMintStart = _fcfsMintStart; publicMintStart = _publicMintStart; mintEnd = _mintEnd; } function getCitizenZeroData(uint256 tokenId) public view returns ( string memory secretPhrase, uint256 orderNumber, uint16[] memory achievements ) { _requireMinted(tokenId); return ( _citizenZeroData[tokenId].secretPhrase, _citizenZeroData[tokenId].orderNumber, _citizenZeroData[tokenId].achievements ); } function _mintCitizenZero(address to) internal { _tokenIdCounter.increment(); _mint(to, _tokenIdCounter.current()); } function mint() public ifNotPaused { require( block.timestamp < mintEnd, "CitizenZero: Mint has already ended!" ); require( this.totalSupply() < mintLimit, "CitizenZero: Mint limit reached!" ); require( _mintedAmount[msg.sender] < 1, "CitizenZero: Mint limit already reached for this wallet!" ); require( msg.sender == tx.origin, "CitizenZero: Mint is allowed only for wallets!" ); _mintedAmount[msg.sender]++; if (block.timestamp > publicMintStart) { _mintCitizenZero(msg.sender); } else if ( block.timestamp > fcfsMintStart && _fcfs[msg.sender] == true ) { _mintCitizenZero(msg.sender); } else if ( block.timestamp > whitelistMintStart && _whitelist[msg.sender] == true ) { _mintCitizenZero(msg.sender); } else { revert("CitizenZero: You are not eligible for mint!"); } } function isWhitelisted(address account) public view returns (bool) { return _whitelist[account]; } function isFcfs(address account) public view returns (bool) { return _fcfs[account]; } function withdraw(address contractAddress, uint256 amount) public onlyOwner { if (contractAddress == address(0)) { payable(msg.sender).transfer(amount); } else { if (amount == 0) amount = IERC20(contractAddress).balanceOf(address(this)); IERC20(contractAddress).transfer(msg.sender, amount); } } receive() external payable {} fallback() external payable {} }