cfx_estimateGasAndCollatory 行为
cfx_estimateGasAndCollateral
接口是 Conflux 区块链中的一个关键组成部分,该接口允许用户可在发起交易前,估算交互所需交易费用和存储抵押费用 本文档旨在清晰地概述 cfx_estimateGasAndCollateral
接口的功能,特别强调其对各种参数配置的响应。
以下描述的行为是由 conflux-rust 实现的,这是Conflux协议的官方Rust实现。
参数缺失或默认情况下的行为
接口的响应取决于输入中特定字段是否存在:
- 如果
from
字段缺失:接口将不会执行与余额
相关的检查。 (然而,因为from
字段缺失,执行可能会失败)。 - 如果
gas_price
缺失:则跳 过与gas相关的交易费用检查和代付gas上限检查。 - 如果
nonce
缺失:接口自动填充当前正确的nonce。 相反,如果提供了nonce
,交易将使用指定的nonce进行,避免由于与nonce相关的错误而失败。 - 如果
value
缺失:默认设置为0。 - 如果
data
缺失:默认为空。 - 如果
to
缺失:接口默认为合约创建。
通常,Conflux SDK(例如,js-conflux-sdk、java-conflux-sdk等)会自动调用 cfx_estimateGasAndCollateral
, 若要发起交易。 如果你没有直接调用 cfx_estimateGasAndCollateral
,上述参数的存在与否将取决于你使用的SDK的行为。
处理多余的参数
虽然 cfx_estimate
的主要功能是用于估算gas和存储抵押,但它也接受由用户输入这些参数。 本节概述了在这些情况下应用的逻辑:
指定gas
- 交易使用指定的
gas
执行。 这是除了gas
消耗超过1500万限制之外,唯一可能出现OutOfGas
错误的情况。 - 如果同时指定了
from
和gas_price
,在估算过程中将扣除交易费用。 否则,费用将在执行后重新检查。
指定存储限制
- 在交易执行估算期间,指定的
storage_limit
会被忽略。 估算后,将评估所指定的存储限制是否足够。
其他考量
存储代付:在存储被代付的情况下,不执行 storage_limit
检查,遵循Conflux的内在逻辑。
错误
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. "
}
遇到此错误意味着接口未能返回估算结果,因为交易被回滚(合约方法代码未能执行)。 这个错误可能有多种原因,例如:相关ERC-20代币或NFT的余额不足;合约方法的参数错 误;缺乏权限或授权等。
如果在合约执行期间抛出错误消息,可以在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
.
解决方案:你应该根据错误提示检查合约的逻辑。 在特定场景下(例如当抛出solidity自定义错误时),错误可能不会在错误字符串中显示。 在这种情况下,使用 cfx_call
与相同的参数将返回对应的十六进制错误字符串。 建议参考Solidity或特定语言的SDK中的自定义错误 ,了解如何解决十六进制错误字符串。
Can not estimate: transaction execution failed, all gas will be charged
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"
}
解决方案:此错误意味着 gas
不足以执行交易,通常意味着gas超过了单个交易的最大金额,即区块气体限制的一半(15,000,000)。 需要优化合约执行逻辑以减少gas消耗。 值得注意的是,如果在估算请求中指定了 gas
,即使所需gas少于1500万,仍然可能发生 OutOfGas
错误。
NotEnoughCash
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32015,
"message": "Can not estimate: transaction execution failed, all gas will be charged (execution error: NotEnoughCash { required: 1000, got: 0, actual_gas_cost: 0, max_storage_limit_cost: 0 })",
"data": "NotEnoughCash { required: 1000, got: 0, actual_gas_cost: 0, max_storage_limit_cost: 0 }"
}
}
此错误意味着 from
账户没有足够的余额来支付交易成本,包括 value
+ gas
+ storage collateral
。
解决方案:
- 如果
to
合约没有代付,请确保from
账户有足够的CFX余额。 - 如果
to
合约被赞助,建议通过调用 cfx_checkBalanceAgainstTransaction RPC检查为什么赞助没有生效。 实际原因可能是:from
账户不在赞助白名单中。 增加SpongoredBalanceForGas
或SpongoredBalanceForboratoral
不足以支付交易成本,其价值可以从 cfx_getSponsorInfo RPC得到。 在这种情况下,追加赞助余额将解决这个问题。- 交易gas成本(
gas limit
*gas price
) 超过代付upperBound
设置,它的价值可以从cfx_getSponsorInfo](../cfx-namespace.md#cfx_getsponsorinfo)中获得。 在这种情况下,您需要调用 setSponsorForGas 来增加 gas 代付上限。
ConflictAddress(0x...)
{
"code": -32015,
"message": "Can not estimate: transaction execution failed, all gas will be charged (execution error: VmError(ConflictAddress(0x87e69792aab04a1e54faa54b41a688335199c1bb)))
",
"data": "VmError(ConflictAddress(0x87e69792aab04a1e54faa54b41a688335199c1bb))"
}
这意味着预估的交易将把合约部署到一个存在合约的地址。 部署的合约地址由部署者地址、部署者的“nonce”和合约的字节代码决定。 而这个问题通常是由于指定了一个已经使用过的nonce。
解决方案:检查估算参数中指定的 nonce
是否被重新使用并使用正确的 nonce
字段。
VmError(BadInstruction 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
字段包含错误的指示。 这个错误的发生通常是因为缺少“to”字段,所以“data”无法按预期解析。
解决方案:检查估算请求中是否缺少to
字段,并填写正确的值。