交易发送失败常见问题
在发送交易前通常需要调用 estimate 方法获取交易所需的 gas 和 storageLimit 值,然后调用 sendRawTransaction 方法发送交易。因此本章节包含了这两个方法的常见错误
- Can not estimate: NotEnoughCash
- Estimation isn't accurate: transaction is reverted
- Can not estimate: transaction execution failed
- SendRawTx: Invalid parameters: tx
- JS-SDK: Method not found
Can not estimate: NotEnoughCash
如果在发送交易时遇到错误:Can not estimate: transaction execution failed, all gas will be charged (execution error: NotEnoughCash { required: xx, got: xx, actual_gas_cost: xx, max_storage_limit_cost: xx }) 则表示交易的 from 账户余额不足
。此种情况需要检查是否交易的 gasPrice,gas,storageLimit 设置过大,或者给 from 账号准备足够的余额,或给合约设置代付.
错误详情
此错误是由RPC 方法 cfx_estimateGasAndCollateral
返回(从v2.0.2开始),在调用该方法时,如果参数中设置了 from
信息,会使用 from
账户的真实 balance 来模拟执行交易,如果账户的余额不足以支付交易的 value + gas*gasPrice + storage抵押费,则 estimate 操作将会失败,并返回如下错误:
{
"code": -32015,
"message": "Can not estimate: transaction execution failed, all gas will be charged (execution error: NotEnoughCash { required: 18014398509481983999023437515000000, got: 0, actual_gas_cost: 0, max_storage_limit_cost: 18014398509481983999023437500000000 })",
"data": "0x4e6f74456e6f75676843617368207b2072657175697265643a2031383031343339383530393438313938333939393032333433373531353030303030302c20676f743a20302c2061637475616c5f6761735f636f73743a20302c206d61785f73746f726167655f6c696d69745f636f73743a203138303134333938353039343831393833393939303233343337353030303030303030207d"
}
在 estimate 操作检查 balance 可大大减少 pending 交易。目前 TestNet 公开 RPC 节点已完成升级,cfx_estimateGasAndCollateral
该方法参数的默认值如下:
- gasPrice: 1 Drip
- gas: 1500w
另外从 v2.0.2 开始,发送交易的最低 gasPrice 提高到了 1GDrip
如何分析余额不足的具体原因
可通过如下步骤检查具体不足原因:
- 检查发送账户是否有余额
- 如果发送账户有余额,检查是否 gas, gasPrice, storageLimit 设置过大,余额不足有可能是某项设置过大导致的,比如 storageLimit
- 如果交易接受账户是一个合约,且合约有 sponsor,检查
- 燃气费赞助余额,抵押存储赞助余额是否足够
- 发送账户是否在赞助白名单中
- 本笔交易的燃气费是否在燃气费赞助
upperBound
以内
注意:可使用 Scan 的赞助页面查看合约的赞助余额,可通过 SponsorWhitelistControl 合约的读写合约功能,查看白名单设置情况
合约设置了赞助商,为什么还是报此错误
用户可能会遇到此种情况:交易的 to 地址是一个合约,且合约已经设置了赞助商,但发送交易时还是报 NotEnoughCash 错误。此种情况可能是由两个原因导致的:
- 合约代付的白名单可能没有正确设置,交易的 from 地址不在白名单里,所以代付未生效
- 交易的 gasFee(gasPrice * gas) 超过了燃气代付的上限(upperbound), 所以代付未生效
解决办法
解决此错误可使用如下方法之一:
- 可尝试在预估燃气费时将 gasPrice 设为 1Drip,得到预估值后发送交易时再把燃气费设为正确的值比如 1GDrip。
- 直接升级最新版本的 SDK(js,go,java), 目前最新版本的SDK 已针对此 case 做了处理
- 如果条件允许,可提高合约燃气赞助的 upperbound 到 0.05 CFX
Estimation isn't accurate: transaction is reverted
发送交易前通常会调用 cfx_estimateGasAndCollateral 方法,来预估交易执行所需要的 gas
和 storageLimit
。该方法本质是对交易进行了模拟执行,然后统计交易执行完之后实际的 gas 和 storage 使用量。但交易的模拟执行并不是都会成功的,部分交易由于某些原因会执行失败,这时该方法会返回 Estimation isn't accurate: transaction is reverted
错误:
{
"code": -32015,
"message": "Estimation isn't accurate: transaction is reverted. Innermost error is at CFX:TYPE.CONTRACT:ACDUZTJBPM9PPP9F0K5VT3PJU0EJUDNHP2ZM7WS35N: Vm reverted. .",
"data": "CFX:TYPE.CONTRACT:ACDUZTJBPM9PPP9F0K5VT3PJU0EJUDNHP2ZM7WS35N: Vm reverted. \nCFX:TYPE.CONTRACT:ACD5E6SPRGMDVG15FDXF2B8AH7DAN7GMZAGXA10EPZ: Vm reverted. "
}
遇到该错误意味着合约方法代码无法成功执行,交易被 reverted
。导致此错误的可能较多,比如:发送合约代币或 NFT 余额不够;合约方法传参错误;没有权限或授权,等等。
如果合约执行时抛出了错误 message,这时 RPC 的错误信息中可以看到合约执行失败的具体原因,比如如下错误是在进行 NFT(1155)转账时,余额不足合约返回的错误:
Estimation isn't accurate: transaction is reverted: ERC1155: insufficient balance for transfer
. Innermost error is at xxxx: Vm reverted. ERC1155: insufficient balance for transfer
参考
Can not estimate: transaction execution failed
在调用 estimate 的方法的时候,如果方法执行失败,则会报此错误。Can not estimate: transaction execution failed, all gas will be charged
有时后边可能会包含错误的详情,目前已知的有如下几种:
ConflictAddress(0xxxxx)
{
"code": -32015,
"message": "Can not estimate: transaction execution failed, all gas will be charged (execution error: VmError(ConflictAddress(0x87e69792aab04a1e54faa54b41a688335199c1bb)))
",
"data": "VmError(ConflictAddress(0x87e69792aab04a1e54faa54b41a688335199c1bb))"
}
此错误为合约部署地址冲突错误,意味着部署操作将要部署的合约地址,已经有合约存在。
如果某账户的第一笔交易为合约部署交易,且之后用相同的 data 再次 estimate,且不指定 nonce 的情况,会触发此错误。因为 nonce 的默认值为 0
此时在进行 estimate 时指定 nonce 为用户当前 nonce, 即可解决此问题.
BadInstruction { instruction: 214 })
{
"code": -32015,
"message": "Can not estimate: transaction execution failed, all gas will be charged (execution error: VmError(BadInstruction { instruction: 214 }))
",
"data": "VmError(BadInstruction { instruction: 214 })"
}
此错误表示在部署合约时,传递的 data 数据有问题,包含错误的指令。
一种触发此错误的场景为,在调用合约方法时,未指定合约地址,此时会被认为是创建合约的操作,但 data 数据又不正确,导致此错误.
VmError(OutOfGas)
{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Can not estimate: transaction execution failed, all gas will be charged (execution error: VmError(OutOfGas))"
},
"id": "15922956697249514502"
}
此错误产生是由于在进行 estimate 操作时指定的 gas
值较小,不足以支撑交易执行完,因此返回了 OutOfGas 错误。这种情况调大 gas 值,或者不传递 gas 字段(自动预估)即可.
另外一种情况是在 estimate 时虽然未指定 gas 值,但还是遇到了 OutOfGas 错误,此种情况说明合约执行逻辑消耗 gas 过大,超过了单 tx 上限,此时需要优化合约的执行逻辑。
SendRawTx: Invalid parameters: tx
发送交易时,如果构造的交易不正确,会遇到 Invalid parameters: tx 错误。错误的具体原因在 RPC 返回数据的 data
字段中, 大致会有如下几种:
余额不足
Transaction {?} is discarded due to out of balance, needs {?} but account balance is {?}
从 conflux-rust v2.0.2 开始 cfx_sendRawTransaction 方法会拒绝掉 tx.from 余额不足以支付交易 value + gasFee + storageCollateral 的交易。
nonce 设置错误
许多交易发送错误是由于 nonce 未设置正确导致的
tx already exist
此错误表示同 nonce 的交易已经存在于交易池中了,重复发送相同的交易会报错
Tx with same nonce already inserted
此错误亦表示同 nonce 交易已经在交易池中
Transaction 0xxx is discarded due to a too stale nonce
此错误表示发送的交易使用了一个已经被执行过交易的 nonce,通俗点说这个 nonce 已经被用过了,不能再使用,需要使用新的未使用的 nonce 重新发送
Transaction 0xxx is discarded due to in too distant future
此错误表示使用了一个过大的 nonce 构造交易,发送交易时 nonce 只能比用 current nonce - current nonce + 2000 范围内的,如果比当前可用 nonce 大超过 2000 会报此错误
gasPrice 错误
ZeroGasPrice
交易的 gasPrice 设置为 0 会报此错误。交易的 gasPrice 必须会大于 0.
transaction gas price 1000000 less than the minimum value 1000000000
从 conflux-rust v2.0.2 开始交易的最低 gasPrice 改为 1GDrip(9个0),如果gasPrice 小余该值,会报此错误
gas 设置错误
交易的 gas 字段设置过大,或过小也会发送失败
NotEnoughBaseGas { required: 21000, got: 2000 }
如果交易的 gas 小余 21000,则会报此错误
transaction gas 20000000 exceeds the maximum value 15000000, the half of pivot block gas limit
如果交易的 gas 超过 1500w 会报此错误
其他参数设置错误
EpochHeightOutOfBound { block_height: 53800739, set: 0, transaction_epoch_bound: 100000 }
交易 epochHeight 字段设置错误,只能设置 10w epoch 以内的区块号
Unsupported receiver address type
交易接受地址填写错误
ChainIdMismatch { expected: 1, got: 2 }
交易的 chainId 填写错误,与发送链的 chainId 不一致
编码签名错误
RlpIncorrectListLen
交易内容不完整,可能会报 Rlp 错误长度错误
Can not recover pubkey for Ethereum like tx
此错误为交易签名错误
网络拥堵
在网络拥堵的情况下,交易池中的交易可能会达到容量上限,此时发送交易可能会遇到以下错误
txpool is full
表示交易池中交易已满
Failed imported to deferred pool: Transaction Pool is full
表示交易池中交易已满
其他
Request rejected due to still in the catch up mode.
发送交易的节点未同步到最新数据,仍处于 catch up 模式,需等同步到最新数据后,才能发送交易
Failed to read account_cache from storage: {}
节点错误
参考
具体的 RPC 返回错误详情可参看 cfx_sendRawTransaction error 文档
JS-SDK: Method not found
如果使用 js-conflux-sdk 发送交易,且交易的 from 账号未添加到 wallet 中的时候,会遇到此错误。此种情况通过如下方式添加账号即可:
conflux.wallet.addPrivatekey("your account private key");