ERC721合约transfer调用触发VM revert异常 后续代码不执行排查
问题根因分析
1. 你的测试方法存在逻辑误区
你在_transfer之后主动添加require(false, 'test')会直接导致整个transfer调用触发回滚,自然父合约NFTMarket中transfer调用后的所有代码都不会执行,这个测试方式无法验证transfer是否正常执行完毕。建议你在transfer方法末尾添加自定义事件,通过交易日志的事件触发情况判断方法是否正常走完。
2. 最可能的直接原因:权限校验失败
NFTCollectables的transfer方法中有require(_isApprovedOrOwner(msg.sender, nftId))校验,这里的msg.sender是发起调用的NFTMarket合约地址,而非前端发起调用的用户地址。出现回滚大概率是以下两种情况:
- 拍卖上架时,没有将对应NFT的所有权转移到
NFTMarket合约地址,导致市场不是NFT的所有者 - 拍卖上架时,卖家没有给
NFTMarket合约地址授予对应NFT的转移批准权限,导致市场没有资格转移该NFT
3. 业务逻辑存在明显错误
你NFTMarket的claimAuction方法中,校验拍卖状态的条件写反了:
require(block.timestamp <= auction.end, "auction still active");
这个校验的含义是「当前时间小于等于拍卖结束时间才允许执行」,也就是拍卖还没结束就能申领,完全和业务逻辑相反。正常应该改为:
require(block.timestamp > auction.end, "auction not ended yet");
如果你的测试是在拍卖结束后发起的调用,这个条件会直接触发回滚,你可以检查报错的revert信息是不是匹配这个字符串。
4. 其他可能的触发点
- 拍卖没有有效出价,
auction.highestBid.bidder为零地址,调用_transfer时触发零地址校验回滚 - 传入的
auctionIndex对应拍卖的nftId不存在,触发_exists(nftId)校验回滚
是否和gas limit有关?
大概率无关。如果是gas不足,交易报错会明确提示out of gas,而你收到的是通用的revert提示,属于业务逻辑校验触发的回滚。
内容的提问来源于stack exchange,提问作者Sofien
相关产品推荐
相关产品推荐

