Web3.js 1.9.0无法获取失败交易Revert原因求助
问题:Web3.js 1.9.0无法获取失败交易的Revert原因
我使用Web3.js 1.9.0调用投票合约的addVote函数时,交易失败但无法获取具体的Revert原因。已设置web3.eth.handleRevert = true,也尝试过getTransactionReceipt,均无效。
合约核心代码
function addVote(string memory voteName, string memory candidate, address addr) public returns(string memory){ require(candidateVote[voteName].length > 0, "Vote does not exist."); // require(voteCount[voteName][candidate] == 0, "You have already voted for this candidate."); require(!voters[voteName][addr], "Address has already voted!"); voteCount[voteName][candidate]++; voters[voteName][addr] = true; return "Vote successful casted!"; }
Web3.js调用代码
export function addVote(web3:any, contract:any, abi: any,contractAddress:any,voteName:string, candidate:any, fromAccount:any){ return new Promise((resolve, reject) => { contract.methods.addVote(voteName, candidate, fromAccount).send({from:fromAccount,gas:3000000}) .on('confirmation', function(confirmationNumber, receipt){ if(receipt.status){ resolve(receipt) }else{ reject(receipt) } }).on('error', function(error, receipt) { reject(error) }) }) }
错误输出
E:\Docker-project\dvote\node_modules\web3-utils\lib\index.js:49 error = new Error(error); ^ Error: Transaction has been reverted by the EVM: { "transactionHash": "0xd3dc4740bb91d16b94b7214914347531e494c46582dcb69c12bc488133e49d06", "transactionIndex": 0, "blockNumber": 20, "blockHash": "0x3a50b40559ac7e6ae7dad11fe73ec36e8c9be536fa8e5e6b1353cbf7ca3a96fd", "from": "0x5d256d7b2238958831d55d9d6e0d08e51e3dd1d8", "to": "0x25fde715c938ac5a27cd06aa3887981d0457f330", "cumulativeGasUsed": 29872, "gasUsed": 29872, "contractAddress": null, "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "status": false, "effectiveGasPrice": 2570615365, "type": "0x2", "events": {} } at Object._fireError (E:\Docker-project\dvote\node_modules\web3-utils\lib\index.js:49:17) at E:\Docker-project\dvote\node_modules\web3-core-method\lib\index.js:396:39
解决方案
核心原因
send()方法在交易上链后无法直接返回Revert原因,需要通过预执行模拟或节点debug接口获取;同时需确保handleRevert设置时机正确。
方案1:预执行call()捕获Revert原因
在发送交易前用call()模拟执行,直接捕获require的错误信息:
export function addVote(web3:any, contract:any, abi: any,contractAddress:any,voteName:string, candidate:any, fromAccount:any){ return new Promise(async (resolve, reject) => { try { // 预执行call,提前捕获revert原因 await contract.methods.addVote(voteName, candidate, fromAccount).call({from: fromAccount}); // 预执行通过再发送交易 contract.methods.addVote(voteName, candidate, fromAccount) .send({from: fromAccount, gas: 3000000}) .on('confirmation', (confirmationNumber, receipt) => { receipt.status ? resolve(receipt) : reject("Transaction failed without revert reason"); }) .on('error', (error) => { reject(error); }); } catch (callError) { // 这里直接拿到具体的revert提示,比如"Vote does not exist." reject(callError); } }); }
方案2:优化send()的错误监听
Web3.js 1.9.0的error事件包含revert原因,需正确解析:
.on('error', function(error, receipt) { if (error.message.includes('reverted:')) { // 提取具体的revert原因 const revertReason = error.message.split('reverted: ')[1]; reject(new Error(revertReason)); } else { reject(error); } })
方案3:确保handleRevert设置正确
必须在创建合约实例前设置handleRevert,否则不生效:
const web3 = new Web3('http://localhost:8545'); web3.eth.handleRevert = true; // 关键:先设置再创建合约 const contract = new web3.eth.Contract(abi, contractAddress);
方案4:通过节点debug接口获取已上链交易的Revert原因
如果交易已上链且失败,可调用节点的debug_traceTransaction接口获取详情(需节点开启debug功能):
web3.currentProvider.send({ jsonrpc: "2.0", method: "debug_traceTransaction", params: ["0xd3dc4740bb91d16b94b7214914347531e494c46582dcb69c12bc488133e49d06", {tracer: "callTracer"}], id: Date.now() }, (err, result) => { if (err) console.error(err); else console.log("Revert reason:", result.result.error); });
内容的提问来源于stack exchange,提问作者xmrrabbitx
相关产品推荐
相关产品推荐

