cfx_estimateGasAndCollateral Behaviour
The cfx_estimateGasAndCollateral interface is a critical component of the Conflux blockchain, as it allows users to estimate the gas and storage collateral required for their transactions. This document aims to clearly outline the functioning of the cfx_estimateGasAndCollateral interface, with a particular emphasis on its response to various parameter configurations.
The behaviors described below are implemented by conflux-rust, the official Rust implementation of the Conflux protocol.
Behavior in the Absence or Defaulting of Parameters
The response of the interface is contingent on whether specific fields in the input are present or absent:
- If
fromis Absent: The interface will not perform any checks related to thebalance. (However, execution might fail becausefromis absent). - If
gas_priceis Absent: It skips the checks for gas-related transaction fees and the Sponsor Gas Upper Bound. - If
nonceis Absent: The interface automatically fills in the current correct nonce. Conversely, ifnonceis provided, the transaction will proceed with the specified nonce and avoid failing due to nonce-related errors. - If
valueis Absent: The default is set to a value of 0. - If
datais Absent: It defaults to empty. - If
tois Absent: The interface defaults to contract creation.
Typically, the cfx_estimateGasAndCollateral is invoked automatically by the Conflux SDK (e.g., js-conflux-sdk, java-conflux-sdk, etc.) when sending a transaction. If you are not directly invoking cfx_estimateGasAndCollateral, the presence or absence of the above parameters will depend on the behavior of the SDK you are using.
Handling Redundant Parameters
While the primary function of the cfx_estimate is to estimate gas and storage collateral, it also accepts user inputs for these parameters. This section delineates the logic applied in such scenarios:
Gas is Specified
- The transaction executes using the specified
gas. This the only scenario for anOutOfGaserror other than the gas consumption exceeds the 15 million limit. - If both
fromandgas_priceare specified, transaction fees are deducted during the estimation. Otherwise, fees are rechecked post-execution.
Storage Limit is Specified
- The specified
storage_limitis disregarded during transaction execution estimation. After the estimation, it"s assessed whether the provided storage limit suffices.
Other Considerations
Sponsored Storage: In cases where storage is sponsored, the storage_limit check is not performed, adhering to Conflux"s intrinsic logic.
Errors
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. "
}
Encountering this error means that the interface failed to return the estimation result because, because transaction was reverted ( contract method code failed to execute). There are various possible causes for this error, such as: insufficient balance of related ERC-20 tokens or NFTs; parameter errors for the contract method; lack of permission or authorization, and so on.
If an error message is thrown during contract execution, the specific reason for the contract execution failure can be seen in the RPC error message. For example, the following error occurred when transferring NFT (1155), indicating insufficient balance: Estimation isn't accurate: transaction is reverted: ERC1155: insufficient balance for transfer. Innermost error is at xxxx: Vm reverted. ERC1155: insufficient balance for transfer.
Solution: You should review the logic of the contract based on the error message. In specific scenarios (like when a solidity custom error is thrown), the error might not be shown in the error string. In such cases, using cfx_call with identical parameters will return the into the corresponding hex error string. You are advised to refer to Custom Errors in Solidity or language-specific SDKs to understand how to resolve the hex error string.
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"
}
Solution: This error means gas is not enough for transaction execution and it typically means the gas exceeds the maximum amount for a single transaction, which is half of the block gas limit (15,000,000). There's a need to optimize the logic of your contract execution to reduce the gas consumption. Notably, if gas is specified in the estimation request, an OutOfGas error can still occur even though the required gas is less than 15 million.
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 }"
}
}
This error means the from account does not have enough balance to pay for transaction cost, including value + gas cost + storage collateral.
Solution:
- If the
tocontract is not sponsored, ensure thatfromaccount is having enough CFX as balance. - If the
tocontract is sponsored, it is recommended to check why the sponsorship does not take effect by calling cfx_checkBalanceAgainstTransaction RPC. And the actual reason could be:- The
fromaccount is not in sponsor whitelist. Adding SponsoredBalanceForGasorSponsoredBalanceForCollateralis not enough to pay for transaction cost, which value can be get from cfx_getSponsorInfo RPC. In this case, appending sponsored balance will solve the issue.- Transaction gas cost(
gas limit*gas price) exceeds the sponsorshipupperBoundsetting, which value can be get from cfx_getSponsorInfo RPC. In this case, you need to call setSponsorForGas to increase gas sponsorship uppper bound.
- The
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))"
}
This means the operation being estimated will deploy the contract to an address with contract existed. The deployed contract address is determined by the deployer"s address, the deployer"s nonce and the contract"s bytecode. And this issue typically incurred because a nonce already used is specified.
Solution: Check if the nonce specified in the estimation parameters is reused and use the correct nonce field.
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 })"
}
This means the data field contains bad instruction. This error typically occurs because the to field is missing so the data cannot be resolved as expected.
Solution: Check if to field is missing from the estimation request and fill the right value.