我正在尝试烧掉erc721令牌。我继承了ERC721Burnable合同,但是事务得到了failed.While调试--我发现在ERC721URIStorage合同中,它返回到:
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}.Also,我希望契约的所有者能够修改元数据。这是我的合同:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract MyNFT is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Burnable, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
uint MAX_SUPPLY=1;
constructor() ERC721("MyNFT", "MNFT") {}
function safeMint(address to, string memory uri) public onlyOwner {
require(totalSupply() < MAX_SUPPLY, "Can be minted only one time.");
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
// The following functions are overrides required by Solidity.
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}发布于 2022-10-05 06:53:51
如果某个特定tokenId的令牌不是尚未铸造,就是已经铸造和烧掉了,希望这会有所帮助!
发布于 2022-10-05 07:31:05
众所周知,EVM在tx恢复原因方面缺乏明确性。_burn()和burn()函数的源代码显示了可能的错误可能导致还原tx的多个地方:
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvals
delete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred
// out than the owner initially received through minting and transferring in.
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}function burn(uint256 tokenId) public virtual {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_burn(tokenId);
}如果您确信您的代码在以下位置失败:
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}您需要在这个代码块执行阶段进行双重检查,这个实体_tokenURIs[tokenId]仍然存在。
此外,我建议使用“硬帽子”,因为它在tx、恢复的原因响应中更清晰,并在您的合同上实现了_burn()函数,以便为调试目的向控制台添加日志,这可以更好地帮助我找出问题的原因。
https://ethereum.stackexchange.com/questions/126444
复制相似问题