Safe智能合约交易执行:如何绕过预检机制直接获取交易哈希
问题背景
- 预估gas费用
- 进行交易预检(simulation)
- 如果预检通过,提交交易并返回哈希
- 如果预检失败,返回错误信息
// 创建交易
const transaction = await safeSdk.createTransaction({
transactions: [{
to: domainExpenseAddress,
data: encodedData,
value: '0'
}]
});
// 签名交易
const signedTransaction = await service._multiSignTransaction(
safeSdk,
rpcUrl,
transaction,
deployerPrivateKey,
ownerPrivateKeys
);
// 执行交易
return await safeSdk.executeTransaction(signedTransaction);
The contract function "execTransaction" reverted with the following signature:\n' +
'0x502694e7\n' +
'\n' +
'Unable to decode signature "0x502694e7" as it was not found on the provided ABI.\n' +
'Make sure you are using the correct ABI and that the error exists on it.\n' +
'You can look up the decoded signature here: https://openchain.xyz/signatures?query=0x502694e7.\n' +
' \n' +
'Contract Call:\n' +
' address: 0xc8d85782ad15718c6f2cf99881d4365b569ffe5b\n' +
' function: execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures)\n' +
' args: (0xE299cCdc44063Df50B5a359D64671FB50Eb24723, 0, 0x16f1d0b2000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004dde1af173fa12c206ecd6a0e5de41ea3656e27800000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000068259473, 0, 0, 0, 0, 0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000, 0xc1539c52b2fdaa64569b77ebb56a336d943ddc1592448dfa7bb7bd5bc0ef591c7c251ca08b501bef857cb73ba760b9b6cb440dc88044baebae7bf301751724fb1b)\n' +
' sender: 0xD01e2fb8D83C5058350A6f9014430c2ca7977BDD\n' +
'\n' +
'Docs: https://viem.sh/docs/contract/decodeErrorResult\n' +
'Version: viem@2.22.22',
data: null
}
合约上调用来调用去,不知道哪里的错误
解决方案:直接设置gas参数
这种方法如何工作?
- 跳过gas预估:通常库会尝试预估交易所需的gas,这个预估过程会执行交易模拟,如果模拟失败则交易不会提交
- 绕过预执行检查:一些库在发送交易前会进行模拟调用(call),用于检查交易是否可能成功
- 强制提交交易:设置了明确的gas参数后,库会直接将交易提交到网络,而不进行这些预检
实现示例
// 创建交易
const transaction = await safeSdk.createTransaction({
transactions: [{
to: domainExpenseAddress,
data: encodedData,
value: '0'
}]
});
// 签名交易
const signedTransaction = await service._multiSignTransaction(
safeSdk,
rpcUrl,
transaction,
deployerPrivateKey,
ownerPrivateKeys
);
// 执行交易
return await safeSdk.executeTransaction(
signedTransaction,
{
gasLimit: 5000000,
gasPrice: ethers.parseUnits("50", "gwei").toString()
} // 直接设置gasfee,不进行预测,直接发起交易
);
这样报错以后可以直接返回hash:
API响应: {
success: true,
data: {
txHash: '0xd8d3dd6c894a2ca48a853050c1d334c0913c9c022a92ea9f6b27936fa2ba01fa'
},
message: '批量支付成功'
}
通过hash我们就可以分析哪里出了问题,
何时使用这种方法?
- 调试复杂交易:当你需要查看交易在链上实际失败的原因
- 绕过过严预检:有时预检机制可能过于保守,阻止了实际可以成功的交易
- 获取详细错误:通过提交到链上,可以获得更详细的错误信息
- 时间敏感交易:当你确信交易参数正确且希望快速执行时
注意事项和风险
- 费用风险:设置过高的gas费用可能导致不必要的开销
- 失败交易:交易仍可能在链上失败,但你会为失败的交易支付gas费
- 合约风险:确保你了解正在调用的合约功能,避免不必要的状态更改
- 参数验证:在绕过预检的情况下,确保自行验证所有参数的正确性
最佳实践
- 先尝试标准方法:只有在标准交易执行方式失败后才使用此方法
- 设置合理的gas参数:不要盲目设置过高的值
- 监控交易:使用交易哈希在区块浏览器中跟踪交易状态
- 记录结果:保存交易哈希和结果,用于后续分析

浙公网安备 33010602011771号