Gas parameters
The main difference between Acala EVM+ and legacy EVM is that we need to use pre-computed
gasPrice
and gasLimit
(we will refer them as "gas parameters"). Manually inputting random gas parameters is discouraged.If you just need a quick help with the gas parameters and are not interested in the explanation, you can expand this section.
Most of the gas parameter issues that you might encounter, can be solved in two steps:
- 1.Get valid gas parameters:
curl --location --request GET 'https://eth-rpc-mandala.aca-staging.network' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_getEthGas",
"params": [],
"id": 1
}'
2. Override your transaction parameters with the ones returned as a result of this call.
As Acala EVM+ is running on a substrate chain, gas parameters need to encode three substrate parameters:
gasLimit
, storageLimit
, and validUntil
. We need to provide a delicate ratio of gasPrice
to gasLimit
, so that they can be decoded correctly into the substrate parameters. Randomly changing just one of the gas parameters likely to results in a bad parameter decoding.For example, when user sends token with MetaMask, they will get the gas parameter values of
201.996894218 gwei
for gasPrice
, and a gasLimit
of 342312
. After the user sends this transaction, these gas parameters will be decoded to validUntil
value of 914096
, gasLimit
value of 21000
and storageLimit
value of 641
.Although this part is incompatible with the legacy EVM, it is actually an advantage of the Acala EVM+, which is able to utilise some features that cannot be found in the legacy EVM. By using
validUntil
parameter we can avoid transaction being stuck in the transaction pool indefinitely, and by using storageLimit
we are able to encourage the developers to remove the data they don't need from the chain, in order to reduce the chain bloat.Users don't have to compute gas parameters by themselves:
- When sending tokens, MetaMask will call the RPC endpoint to get the correct gas parameters for them automatically.
- When signing a transaction, dApps should compute the correct gas parameters and pass these values to the MetaMask, so users just sign a valid transaction.
The only thing that need to pay attention to, is to not modify the transaction parameters within MetaMask, otherwise the transaction will fail due to bad decoding. We thus encourage you to add the warning against such actions within the user interface of your dApps.
Developers need to compute correct gas parameters when deploying contracts.
This is because the default gas parameters computed by the tools (MetaMask, Truffle, Hardhat, etc..) have a
storageLimit
of 641
, which is not a limit big enough to store a contract.On the other hand, smart contract calls won't need this step in most cases, since the default parameters are sufficient for most of the smart contract calls. In some cases if a smart contract call uses an amount of storage that is greater than the default
storageLimit
, valid gas parameters have to be computed.There are three ways to get valid gas parameters for a transaction:
- Using an RPC call
- Using hardcoded values
- Using an SDK helper
Getting valid gas parameters is as easy as initiating the following call:
curl --location --request GET 'https://eth-rpc-mandala.aca-staging.network' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_getEthGas",
"params": [],
"id": 1
}'
The following call will return the same result as using default substrate parameters:
curl --location --request GET 'https://eth-rpc-mandala.aca-staging.network' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_getEthGas",
"params": [
{
"gasLimit": 21000000,
"storageLimit": 64100,
"validUntil": current block + 100
}
],
"id": 1
}'
Custom substrate parameters can be passed as well. For example if we want to get the gas parameters for a transaction that should be valid until block
10000000
:curl --location --request GET 'https://eth-rpc-mandala.aca-staging.network' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"method": "eth_getEthGas",
"params": [
{
"gasLimit": 21000000,
"storageLimit": 64100,
"validUntil": 10000000
}
],
"id": 1
}'
This is the result, with is the valid
gasPrice
and gasLimit
for transactions to use:{
"id": 1,
"jsonrpc": "2.0",
"result":{
"gasPrice": "0x33a70303ea",
"gasLimit": "0x329b140"
}
}
Let's use the successfully computed a gas parameters from the previous example:
"result":{
"gasPrice": "0x33a70303ea",
"gasLimit": "0x329b140"
}
these parameters are valid until block number
10000000
and can be reused until this block number is reached.A thorough explanation about this method can be found in the tutorials. This is the snippet of how the sample code that returns the transaction parameters looks like:
import { calcEthereumTransactionParams } from '@acala-network/eth-providers';
const txFeePerGas = '199999946752';
const storageByteDeposit = '100000000000000'; // for Mandala/Karura
// const storageByteDeposit = '300000000000000'; // for Acala
const ethParams = calcEthereumTransactionParams({
gasLimit: 21000000,
validUntil: curblockNumber + 100, // or hardcode a very big number
storageLimit: 64001,
txFeePerGas,
storageByteDeposit
});
console.log({
txGasPrice: txGasPrice.toNumber(),
txGasLimit: txGasLimit.toNumber(),
});
After getting the valid gas parameters, we can override the smart contract deployment transaction gas parameters so that the smart contract gets successfully deployed.
Transaction parameters need to be overriden for each transaction:
- const instance = await HelloWorld.deploy(callParams)
+ const instance = await HelloWorld.deploy(callParams, gasOverrides)
Gas overrides can be specified globally in
truffle-config.js
{
...
gasPrice: xxx,
gas: yyy,
}
Since users are unable to change the gas parameters, we currently don't support speeding up the transactions. In the future we might be able to use EIP-1559 or a new algorithm to support the Substrate
tip
.If you are interested exactly how the gas price is calculated, you are welcome to expand the following section:
- User Inputs
gas_limit
storage_byte_limit
valid_until
- Block number
- Tx data
tx_gas_price
tx_gas_limit
- User input to tx data
block_period = valid_until / 30
storage_entry_limit = storage_byte_limit / 64
- storage_count_limit is u16
- max value 0xffff = 4194240 bytes = 4MB
storage_byte_deposit = 100000000000000
storage_entry_deposit = storage_byte_deposit * 64
tx_fee_per_gas = 200000000000
tx_gas_price = tx_fee_per_gas + block_period << 16 + storage_entry_limit
tx_gas_limit = gas_limit + storage_entry_limit * storage_entry_deposit / tx_fee_per_gas
- Tx data to user input
storage_entry_limit = tx_gas_price | 0xffff
block_period = (tx_gas_price - stroage_entry_limit - tx_fee_per_gas) >> 16
valid_until = block_period * 30
gas_limit = tx_gas_limit - storage_entry_limit * storage_entry_deposit / tx_fee_per_gas
Last modified 4mo ago