Mantle测试网调用buyPlot函数报错求助:两种实现均出问题
调用Mantle测试网合约
buyPlot函数的报错解决 合约详情
合约地址:0xb1DC2063345F6d210AC1f9c9da2aB8131A53b938
ABI:
[ { inputs: [ { internalType: "address", name: "_treasury", type: "address", }, { internalType: "address", name: "_token", type: "address", }, ], stateMutability: "nonpayable", type: "constructor", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "previousOwner", type: "address", }, { indexed: true, internalType: "address", name: "newOwner", type: "address", }, ], name: "OwnershipTransferred", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "buyer", type: "address", }, { indexed: true, internalType: "uint256", name: "coord", type: "uint256", }, { indexed: false, internalType: "uint256", name: "price", type: "uint256", }, { indexed: false, internalType: "uint256", name: "purchaseCount", type: "uint256", }, ], name: "PlotPurchase", type: "event", }, { inputs: [ { internalType: "uint256", name: "coord", type: "uint256", }, ], name: "buyPlot", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [ { internalType: "uint256", name: "startCoord", type: "uint256", }, { internalType: "uint256", name: "endCoord", type: "uint256", }, ], name: "getAllOwners", outputs: [ { internalType: "address[]", name: "", type: "address[]", }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "uint256", name: "startCoord", type: "uint256", }, { internalType: "uint256", name: "endCoord", type: "uint256", }, ], name: "getAllPurchaseCounts", outputs: [ { internalType: "uint256[]", name: "", type: "uint256[]", }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "getOwnerCount", outputs: [ { internalType: "uint256", name: "", type: "uint256", }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "mintPerPlot", outputs: [ { internalType: "uint256", name: "", type: "uint256", }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "owner", outputs: [ { internalType: "address", name: "", type: "address", }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "", type: "address", }, ], name: "plotsOwned", outputs: [ { internalType: "uint256", name: "", type: "uint256", }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "uint256", name: "coord", type: "uint256", }, ], name: "price", outputs: [ { internalType: "uint256", name: "", type: "uint256", }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "renounceOwnership", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "token", outputs: [ { internalType: "contract IERC20", name: "", type: "address", }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "newOwner", type: "address", }, ], name: "transferOwnership", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "treasury", outputs: [ { internalType: "address", name: "", type: "address", }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "tokenAddress", type: "address", }, { internalType: "uint256", name: "amount", type: "uint256", }, ], name: "withdrawTokens", outputs: [], stateMutability: "nonpayable", type: "function", }, { stateMutability: "payable", type: "receive", }, ]
错误实现1及报错
const buyPixel = async (row: number, col: number) => { const { gridContract: contract } = getEthers(); try { const row1 = BigInt(123); await contract.buyPlot(row1); // const column1 = BigInt(c); // let r = ethers.parseUnits(row.toString(), 0); // let c = ethers.parseUnits(col.toString(), 0); // const basePrice = ethers.parseEther("0.1"); // Set the base price in Ether } catch (err) { console.error("Error buying pixel:", err); } }
报错信息:
Error: missing revert data (action="estimateGas", data=null, reason=null, transaction={ "data": "0x7b1949d2000000000000000000000000000000000000000000000000000000000000007b", "from": "0x64627c96aB9d0a24B8bAA3F53336cbb39Bc6A55a", "to": "0xb1DC2063345F6d210AC1f9c9da2aB8131A53b938" }, invocation=null, revert=null, code=CALL_EXCEPTION, version=6.6.7)
错误实现2及报错
const buyPixel = async (row: number, col: number) => { const { gridContract: contract } = getEthers(); let r = ethers.parseUnits(row.toString(), 0); let c = ethers.parseUnits(col.toString(), 0); const pxCount = await contract.owner(); console.log(contract, row, col, r, c, pxCount, "pb"); try { const row1 = BigInt(r); const column1 = BigInt(c); const basePrice = ethers.parseEther("0.1"); // Set the base price in Ether const plotPrice = basePrice * column1 * row1; // Send the transaction with the correct amount of Ether (in Wei) const overrides = { value: ethers.parseUnits(plotPrice + "", 18), }; const result = await contract.buyPlot(row1, column1, overrides); console.log(result, "res"); // Transaction successful, update pixel state // setPixels((prevPixels) => { // const updatedPixels = [...prevPixels]; // updatedPixels[row][col] = true; // return updatedPixels; // }); } catch (err) { console.error("Error buying pixel:", err); } }
报错信息:
Error: no matching fragment (operation="fragment", info={ "args": [ 1, 1, { "value": 100000000000000000000000000000000000 } ], "key": "buyPlot" }, code=UNSUPPORTED_OPERATION, version=6.6.7)
buyPlot合约源码
function buyPlot(uint256 coord) external payable isValidCoord(coord) { Plot storage plot = grid[coord]; uint256 plotPrice = BASE_PRICE << plot.purchaseCount; require(msg.value >= plotPrice, "Not enough ETH sent to buy plot"); if (msg.value > plotPrice) { payable(msg.sender).transfer(msg.value - plotPrice); } address currentOwner = plot.owner; // Ensure the sender is not the contract itself require(msg.sender != address(this), "Contract cannot buy plots"); // protocol takes 25% of the purchase price // 75% goes to the previous owner // if there is no previous owner, 100% goes to the protocol // the protocol is the owner of all plots at the start if (currentOwner != address(0)) { uint256 transferAmount = plotPrice.mul(3) / 4; // Ensure the transfer to the current owner is successful require(payable(currentOwner).send(transferAmount), "Transfer to current owner failed"); if (currentOwner != msg.sender) { plotsOwned[currentOwner] -= 1; plotsOwned[msg.sender] += 1; plot.owner = msg.sender; } } else { plot.owner = msg.sender; plotsOwned[msg.sender] += 1; } // Transfer the purchase price to the contract owner if (address(this).balance > 0) { require(payable(treasury).send(address(this).balance), "Transfer to treasury failed"); } plot.purchaseCount += 1; // mint tokens for the buyer token.safeTransfer(msg.sender, mintPerPlot); emit PlotPurchase(msg.sender, coord, plotPrice, plot.purchaseCount); }
问题分析与解决方案
错误实现2的核心问题
从ABI和合约源码可知,buyPlot仅接受单个coord参数,但实现2传入了row1、column1两个参数+overrides,参数数量不匹配,直接触发no matching fragment错误。
错误实现1的核心问题
实现1仅传入了coord参数,但未附带ETH金额,合约要求msg.value >= plotPrice,交易因金额不足被revert;missing revert data通常是节点未返回具体revert原因,但本质是交易不符合合约规则。
正确实现步骤
- 将row和col转换为单个coord值:合约用单个uint256类型的
coord标识地块位置,需根据合约isValidCoord的规则编码(例如coord = row * 网格宽度 + col,需替换为实际网格宽度)。 - 获取地块实时价格:调用合约
price(coord)函数获取当前价格,不要自行计算——价格会随purchaseCount动态翻倍(plotPrice = BASE_PRICE << plot.purchaseCount)。 - 附带正确ETH金额调用:通过overrides传入
value参数,值为获取到的plotPrice。
正确代码示例
const buyPixel = async (row: number, col: number) => { const { gridContract: contract } = getEthers(); try { // 1. 根据网格规则计算coord,此处假设网格宽度为100,需替换为实际值 const gridWidth = 100; const coord = BigInt(row * gridWidth + col); // 2. 获取该地块的当前价格 const plotPrice = await contract.price(coord); // 3. 调用buyPlot并附带对应ETH const overrides = { value: plotPrice }; const tx = await contract.buyPlot(coord, overrides); await tx.wait(); console.log("交易成功:", tx.hash); } catch (err) { console.error("Error buying pixel:", err); } }
额外注意事项
- 确认
isValidCoord修饰器的规则,确保计算出的coord合法,否则会触发revert。 - 若仍出现
missing revert data,可尝试更换Mantle测试网节点,或手动指定gasLimit关闭自动gas估算,但优先保证交易参数正确。
内容的提问来源于stack exchange,提问作者Ishaan Parmar
相关产品推荐
相关产品推荐

