function mintNFT(uint256 numberOfNfts) public payable { require(totalSupply() < 16384, 'Sale has already ended'); require(numberOfNfts > 0, 'numberOfNfts cannot be 0'); require(numberOfNfts <= 20, 'You may not buy more than 20 NFTs at once'); require(totalSupply().add(numberOfNfts) <= 16384, 'Exceeds NFT supply'); require(getNFTPrice().mul(numberOfNfts) == msg.value, 'Value sent is not correct'); for (uint256 i = 0; i < numberOfNfts; i++) { uint256 mintIndex = totalSupply(); // get number of NFTs issued so far _safeMint(msg.sender, mintIndex); // mint the next one } }
function _safeMint(address to, uint256 tokenId) internal virtual override { // Mint one NFT and assign it to address(to). require(!_exists(tokenId), 'ERC721: token already minted'); _data = _mint(to, tokenId); // mint NFT and assign it to address to _totalSupply++; // increment totalSupply() by one if (to.isContract()) { // Confirm that NFT was recorded properly by calling // the function onERC721Received() at address(to). // The arguments to the function are not important here. // If onERC721Received is implemented correctly at address(to) then // the function returns _ERC721_RECEIVED if all is well. bytes4 memory retval = IERC721Receiver(to).onERC721Received(to, address(0), tokenId, _data); require(retval == _ERC721_RECEIVED, 'NFT Rejected by receiver'); } }
让我们证明 _safeMint 根本不安全(尽管它的名字是安全)。
A) 假设已经铸造了16370个NFT,那么 totalSupply()=16370。请解释恶意合约如何导致超过16384个NFT被伪造。攻击者最多可以造出多少个NFT?
function _safeMint(address to, uint256 tokenId) internal virtual override { // Mint one NFT and assign it to address(to). require(!_exists(tokenId), 'ERC721: token already minted'); _data = _mint(to, tokenId); // mint NFT and assign it to address to if (to.isContract()) { // Confirm that NFT was recorded properly by calling // the function onERC721Received() at address(to). // The arguments to the function are not important here. // If onERC721Received is implemented correctly at address(to) then // the function returns _ERC721_RECEIVED if all is well. bytes4 memory retval = IERC721Receiver(to).onERC721Received(to, address(0), tokenId, _data); require(retval == _ERC721_RECEIVED, 'NFT Rejected by receiver'); } _totalSupply++; // increment totalSupply() by one }
for (uint256 i = 0; i < numberOfNfts; i++) { uint256 mintIndex = totalSupply(); // get number of NFTs issued so far _safeMint(msg.sender, mintIndex); // mint the next one }