调用buyoutDirectListing触发execution reverted及gas估算失败报错
调用NFT市场直接购买方法报execution reverted、gas估算失败的排查方案
这个报错的核心不是gas设置问题,是节点在本地模拟执行交易时就触发了合约的回滚逻辑,导致ethers无法完成gas预估,按以下优先级排查即可:
- 核对支付金额与支付方式
从报错信息里的交易value字段转十进制可知你本次交易附带发送了0.1ETH,先链上查询对应listingId的挂牌规则:如果挂牌是ERC20代币定价,你转ETH会直接回滚;如果是ETH定价,核对价格计算是否正确,有没有出现wei/ether单位换算错误,导致发送的金额和挂牌价不匹配。 - 核对挂牌状态有效性
确认传入的listingId对应挂牌处于可购买状态:是否被卖家取消、是否已被其他用户买完、是否超出了挂牌设置的有效时间、卖家是否已经将对应NFT从钱包转走导致挂牌失效,以上任意一种情况都会触发购买回滚。 - 核对前置授权是否充足
如果购买的是ERC20定价的挂牌,先确认你的钱包地址已经给市场合约授权了不低于挂牌售价的对应ERC20代币额度,授权额度不足时调用购买方法会直接回滚。 - 核对网络与合约地址匹配性
确认你初始化的marketPlaceModule绑定的合约地址,和当前MetaMask切换的网络完全对应:不要出现教程用测试网合约、你切到主网调用的情况,也不要复制错合约地址,错误地址上不存在对应方法时调用会直接回滚。 - 核对入参格式正确性
确认传入的参数符合合约要求:不要把NFT的tokenId误当成挂牌的listingId传入;购买ERC721类型的NFT时quantityDesired必须传1,传大于1的值会触发回滚;所有数值类参数不要传成带多余字符的字符串格式。
快速定位根因的技巧:调用购买方法时临时传入固定
gasLimit值(比如设为300000),即可跳过本地gas估算步骤强行唤起MetaMask交易弹窗,将交易发送上链后如果失败,去对应区块浏览器查看交易详情,会拿到合约返回的明确回滚原因,比本地报错信息精准很多。
另外你的代码存在逻辑问题:当前写法即使交易触发报错被catch捕获,还是会执行confirmPurchase()弹出购买成功的误导提示,需要把成功逻辑放到交易确认之后,修正后的参考代码如下:
const buyItem = async ( listingId = selectedMarketNft.id, quantityDesired = 1, module = marketPlaceModule ) => { console.log(listingId, quantityDesired, module) try { const tx = await module.buyoutDirectListing({ listingId, quantityDesired, // 排查问题阶段可临时打开下面配置,定位完问题即可删除 // gasLimit: 300000 }) // 等待链上交易确认完成再触发成功提示 await tx.wait() confirmPurchase() } catch (error) { console.error(error) // 此处可添加交易失败的用户提示逻辑 } }
内容的提问来源于stack exchange,提问作者Olesya Petrova
相关产品推荐
相关产品推荐

