处理事务时出现 VM 异常:还原
Posted
技术标签:
【中文标题】处理事务时出现 VM 异常:还原【英文标题】:VM Exception while processing transaction: revert 【发布时间】:2021-11-23 12:24:45 【问题描述】:我有 2 个合同。一种是 ERC721 令牌 (NFTCollectables
)。另一个是包含拍卖系统的市场 (NFTMarket
)。
拍卖结束后只能由出价最高的人申领。
在进行拍卖时,调用NFTCollectables
合约的transfer
方法将NFT 从市场地址转移到出价最高者的地址。
我不完全理解为什么会出现异常,但它发生在 NFTCollectables
合约的 transfer
方法中/内部。奇怪的是,即使transfer
方法中的最后一行代码也被执行(通过在_transfer(msg.sender, to, nftId)
之后放置require(false, 'test')
进行测试)。但ctr.transfer(auction.highestBid.bidder, auction.nftId)
之后没有任何内容被执行(通过在其后放置require(false, 'test')
进行测试)。
会不会和gas限制有关?
感谢任何想法,谢谢!
NFT 市场
function claimAuction(uint auctionIndex) external
require(auctionIndex < auctions.length, "no auction");
Auction memory auction = auctions[auctionIndex];
require(block.timestamp <= auction.end, "auction still active");
NFTCollectables ctr = NFTCollectables(nftCollectablesAddress);
ctr.transfer(auction.highestBid.bidder, auction.nftId);
// deleting auction from active auctions list
for (uint i; i < activeAuctionIndexes.length; i++)
if (activeAuctionIndexes[i] == auctionIndex)
delete activeAuctionIndexes[i];
break;
emit AuctionEnd(auction.highestBid.bidder, auction.highestBid.price, auction.nftId);
NFTCollectables
function transfer(address payable to, uint nftId) external payable
require(_exists(nftId), "transfer of non existing token");
require(_isApprovedOrOwner(msg.sender, nftId), "Sender not approved nor owner");
_transfer(msg.sender, to, nftId);
【问题讨论】:
如果你确定“transfer”的最后一行都被执行了,这意味着你的配置有错误。 【参考方案1】:如果您已将合约部署在公共网络上,如主网或测试网,请使用https://tenderly.co 或 EtherScan 调试恢复原因。
如果您正在使用单元测试运行合同,请继续修改合同,例如通过删除行来查看它何时开始失败。或者使用更好的智能合约开发框架,例如Brownie,它可以让您立即恢复。
【讨论】:
奇怪的是,当transfer
方法为空时,我仍然会收到回复事件...您知道这可能会做什么吗?关于布朗尼的想法;我明天测试一下
因为问题不包含可重复的例子,所以你的猜测和我的一样好。我建议自己学习如何调试此类问题,这样您就可以系统地确定还原原因,而无需进行猜测。【参考方案2】:
我们已经在我们的代码库上实现了一个功能,我可以与您分享。此函数用于将 nft 的所有权转让给赢得拍卖的人。
function transferNFTtoNewOwner(NFTItem memory t,address oldOwner, address newOwner) internal
require(newOwner != address(0), "New owner can't be address zero.");
XXXX storage r = creatureList[t.tokenAddress][t.tokenId];
IERC721 nft = IERC721(t.tokenAddress);
nft.safeTransferFrom(oldOwner, newOwner, t.tokenId);
address currOwner = nft.ownerOf(t.tokenId);
require(newOwner == currOwner, "Problem on nft transfer");
r.owner = newOwner;
主要区别在于我们从这里使用了安全转移。如果你的合约拥有 NFT,那么你可以调用 safeTransfer。之后我们用 require 语句检查了 nft 所有者。如果您输入此语句并将您的传输功能更改为 safetransfer 并且交易仍然恢复并且在 etherscan 上没有给出任何错误,那么您可以调查您的 nft 合约。
【讨论】:
以上是关于处理事务时出现 VM 异常:还原的主要内容,如果未能解决你的问题,请参考以下文章
有些交易有效,有些则无效。处理事务时出现 UnhandledPromiseRejectionWarning 和 VM 异常