Safe智能合约交易执行:如何绕过预检机制直接获取交易哈希

在使用Gnosis Safe等多签钱包进行智能合约交互时,我们经常会遇到交易失败但无法获得明确错误信息的情况。通过设置适当的gas参数,我们可以改变这一行为模式,跳过某些预检验证,直接获取交易哈希。本文将深入探讨这一机制。

问题背景

在Safe多签钱包中执行交易时,通常会经过以下流程:
  1. 预估gas费用
  1. 进行交易预检(simulation)
  1. 如果预检通过,提交交易并返回哈希
  1. 如果预检失败,返回错误信息
问题在于,有时预检机制过于严格,safe走计算gasfee流程
// 创建交易
    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参数,我们可以绕过预检机制,直接将交易提交到链上:
 
 
 

这种方法如何工作?

在ethers.js和类似库中,当显式设置了gasLimitgasPrice时,库会跳过一些默认的验证和预检步骤:
  1. 跳过gas预估:通常库会尝试预估交易所需的gas,这个预估过程会执行交易模拟,如果模拟失败则交易不会提交
  1. 绕过预执行检查:一些库在发送交易前会进行模拟调用(call),用于检查交易是否可能成功
  1. 强制提交交易:设置了明确的gas参数后,库会直接将交易提交到网络,而不进行这些预检

实现示例

以下是修改Safe服务以支持直接设置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我们就可以分析哪里出了问题, 

何时使用这种方法?

这种方法在以下情况特别有用:
  1. 调试复杂交易:当你需要查看交易在链上实际失败的原因
  1. 绕过过严预检:有时预检机制可能过于保守,阻止了实际可以成功的交易
  1. 获取详细错误:通过提交到链上,可以获得更详细的错误信息
  1. 时间敏感交易:当你确信交易参数正确且希望快速执行时

注意事项和风险

使用这种方法时需要注意:
  1. 费用风险:设置过高的gas费用可能导致不必要的开销
  1. 失败交易:交易仍可能在链上失败,但你会为失败的交易支付gas费
  1. 合约风险:确保你了解正在调用的合约功能,避免不必要的状态更改
  1. 参数验证:在绕过预检的情况下,确保自行验证所有参数的正确性

最佳实践

  1. 先尝试标准方法:只有在标准交易执行方式失败后才使用此方法
  1. 设置合理的gas参数:不要盲目设置过高的值
  1. 监控交易:使用交易哈希在区块浏览器中跟踪交易状态
  1. 记录结果:保存交易哈希和结果,用于后续分析

结论

通过显式设置gas参数绕过预检机制,可以帮助我们在处理复杂的Safe多签交易时更灵活地操作。这不仅有助于调试,也能在某些情况下提高交易的成功率。然而,这应该被视为一种高级技巧,在使用时需谨慎评估潜在的风险和成本。
在安全和效率之间找到平衡,是智能合约交互中的永恒主题。希望这篇文章能帮助你更好地理解和应用这一技巧,提高与Safe合约交互的灵活性和效率。
posted @ 2025-05-15 15:58  若-飞  阅读(54)  评论(0)    收藏  举报