Transaction Hash:
Block:
21007524 at Oct-20-2024 02:55:47 PM +UTC
Transaction Fee:
0.000360131251544776 ETH
$0.91
Gas Used:
24,212 Gas / 14.874081098 Gwei
Emitted Events:
202 |
Bubki.ApprovalForAll( owner=[Sender] 0xce462c13f461deeb3ec2daadd5e7d5f90bb8f0b2, operator=0xb16c1342...DB289c0A4, approved=False )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x5E96d692...Db9a9810c | |||||
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 5.761207742802225476 Eth | 5.76123306608138128 Eth | 0.000025323279155804 | |
0xCe462C13...90Bb8F0b2 |
0.049945036186655047 Eth
Nonce: 827
|
0.049584904935110271 Eth
Nonce: 828
| 0.000360131251544776 |
Execution Trace
Bubki.setApprovalForAll( operator=0xb16c1342E617A5B6E4b631EB114483FDB289c0A4, approved=False )
setApprovalForAll[ERC721 (ln:118)]
ApprovalForAll[ERC721 (ln:120)]
//SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; import "./Strings.sol"; import "./Ownable.sol"; import "./ERC721.sol"; contract Bubki is ERC721, Ownable { // We are donating to https://unchain.fund/ address public UKRAINE_ETH_ADDRESS = 0x10E1439455BD2624878b243819E31CfEE9eb721C; uint256 public constant MAX_SUPPLY = 10_000; uint256 public tokenCost = 0.05 ether; uint256 public maxMintPerTx = 100; bool public isSaleActive; bool public metadataFrozen; uint256 public totalSupply; string public baseURI; constructor() ERC721("Bubki for Ukraine", "Bubki") {} function mint(uint256 _count) external payable { require(isSaleActive); require(_count <= maxMintPerTx); uint256 currentId = totalSupply; unchecked { require(currentId + _count <= MAX_SUPPLY); require(msg.value == _count * tokenCost); for (uint256 i; i < _count; ++i) { // 99% sure this check is not necessary, // because totalSupply will force mint to always increment to a place where ownerOf == 0x0 // require(ownerOf[id] == address(0), "ALREADY_MINTED"); ownerOf[currentId + i] = msg.sender; emit Transfer(address(0), msg.sender, currentId + i); } balanceOf[msg.sender] += _count; totalSupply += _count; } } function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) { require(ownerOf[_tokenId] != address(0)); return string(abi.encodePacked(baseURI, Strings.toString(_tokenId), ".json")); } function updateTokenCost(uint256 _tokenCost) external onlyOwner { tokenCost = _tokenCost; } function updateMaxMintPerTx(uint256 _maxMintPerTx) external onlyOwner { maxMintPerTx = _maxMintPerTx; } function updateBaseURI(string memory _baseURI) external onlyOwner { require(metadataFrozen == false, "METADATA_FROZEN"); baseURI = _baseURI; } function freezeBaseURI() external onlyOwner { metadataFrozen = true; } function flipSaleState() external onlyOwner { isSaleActive = !isSaleActive; } /** * @dev Allows update to charity address in the event that the deployed address * is incorrect or has to be changed. Only can be called by owner or the charity's * address (if EOA). */ function updateWithdrawAddress(address _newAddress) external onlyReceiverOrOwner { UKRAINE_ETH_ADDRESS = _newAddress; } /** * @dev Throws if not called by owner or withdrawal target */ modifier onlyReceiverOrOwner() { require(msg.sender == UKRAINE_ETH_ADDRESS || msg.sender == owner()); _; } function transferFunds() external { uint256 balance = address(this).balance; (bool transferTx, ) = payable(UKRAINE_ETH_ADDRESS).call{value: balance}(""); require(transferTx); } } // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol) /// @dev Note that balanceOf does not revert if passed the zero address, in defiance of the ERC. /// We have modified this contract to remove unneeded functions (e.g. _mint, _safeMint, _burn) abstract contract ERC721 { /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*/////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*/////////////////////////////////////////////////////////////// ERC721 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => uint256) public balanceOf; mapping(uint256 => address) public ownerOf; mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*/////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*/////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || msg.sender == getApproved[id] || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { balanceOf[from]--; balanceOf[to]++; } ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes memory data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*/////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol) interface ERC721TokenReceiver { function onERC721Received( address operator, address from, uint256 id, bytes calldata data ) external returns (bytes4); } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) // forked from openzeppelin, removed stupid dependency on Context 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 { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(msg.sender); } /** * @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() == msg.sender, "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); } } // SPDX-License-Identifier: MIT // 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); } }