description |
---|
Fee scheme in Boba Network |
Fees on Boba are, for the most part, significantly lower than on the Ethereum mainnet. The cost of every transaction is the sum of two values:
- Your L2 (execution) fee, and
- Your L1 (security) fee.
At a high level, the L2 fee is the cost to execute your transaction in L2 and the L1 fee is the estimated cost to submit your transaction to L1 (in a rollup batch).
-
L2 execution fee is charged as
tx.gasPrice * l2GasUsed
(up totx.gasLimit
). The L2 gas price will vary depending on network congestion. -
L1 security fee is charged as
l1GasPrice * l1GasUsed
. This is the cost of storing the transaction's data on L1.l1GasPrice
is the same as the normal gas price in L1 Ethereuml1GasUsed
is calculated as1.2*(overhead + calldataGas)
. Thus, more calldata your transaction includes, the more expensive your L1 fee will be. For example, an ETH transfer has no calldata, so it will have the cheapest L1 fee, whereas large contract deployments can have over 25kb of calldata and will result in a high L1 fee. We currently just the overhead value to the L1 fee to ensure the fee paid covers the actual L1 costs.
-
Total cost
We accept BOBA and ETH as the fee token. The total cost for ETH is calculated as
tx.gasPrice * (l2GasUsed + l1GasPrice * l1GasUsed / tx.gasPrice)
. The total cost for BOBA is calculated astx.gasPrice * (l2GasUsed + l1GasPrice * l1GasUsed / tx.gasPrice) * priceRatio
where the price ratio isETH price / BOBA price * discount percentage
. The L2 gas Used is higher than l1, because we add the L1 security fee.- The gas uage of transferring ETH is 26730 on Boba Network. It includes 21000 (l2GasUsed) and 5370 (l1SecurityFee).
To obtain ETH and BOBA on Boba Network you can deposit ETH via https://gateway.boba.network on both Rinkeby or Mainnet. Soon you will be able to also deposit ETH for slightly cheaper via Anyswap.
- You must send your transaction with a tx.gasPrice that is greater than or equal to the sequencer's l2 gas price. You can read this value from the Sequencer by querying the
OVM_GasPriceOracle
contract (OVM_GasPriceOracle.gasPrice
) or by simply making an RPC query toeth_gasPrice
. If you don't specify yourgasPrice
as an override when sending a transaction ,ethers
by default querieseth_gasPrice
which will return the lowest acceptable L2 gas price. - You can set your
tx.gasLimit
however you might normally set it (e.g. viaeth_estimateGas
). The gas usage for transactions on Boba Network will be larger than the gas usage on Ethereum, becuase thel1SecurityFee
is included in the gas usage. - We recommend building error handling around the
Fee too Low
error detailed below, to allow users to re-calculate theirtx.gasLimit
and resend their transaction if L1 gas price spikes.
- We recommend displaying an estimated fee to users using
eth_estimateGas
import { ethers } from 'ethers'
const WETH = new Contract(...) //Contract with no signer
const fee = WETH.estimateGas.transfer(to, amount)
-
You should not allow users to change their
tx.gasLimit
to any number that is smaller than the value frometh_estimateGas
.- If they lower it, their transaction will revert and tx fee will be charged
-
You should not allow users to change their
tx.gasPrice
- If they lower it, their transaction will revert
- If they increase it, they will still have their tx immediately included, but will have overpaid.
-
Users are welcome to change their
tx.gasLimit
as it functions exactly like on L1. You can show the math :ETH Fee: .00098 ETH ($3.94) Boba Fee: 1.96 BOBA ($3.94)
We recommend displaying the right fee token and transaction fee to users by calling
Boba_GasPriceOracle
to calculate total fee and get the fee tokenimport { ethers } from 'ethers' const BobaGasPriceOracleInterface = new utils.Interface([ 'function useBobaAsFeeToken()', 'function useETHAsFeeToken()', 'function bobaFeeTokenUsers(address) view returns (bool)', 'function priceRatio() view returns (uint256)' ]) const Proxy__Boba_GasPriceOracle = new Contract( Proxy__Boba_GasPriceOracleAddress, BobaGasPriceOracleInterface l2Provider ) //Contract with no signer const isBobaAsFeeToken = await Boba_GasPriceOracle.bobaFeeTokenUsers(walletAddress) const priceRatio = await Boba_GasPriceOracle.priceRatio()
If
isBobaAsFeeToken
istrue
, then the user picks BOBA as the fee token and the total Boba transaction fee istx.gasLimit * tx.GasPrice * priceRatio
. -
Might need to regularly refresh the L2 Fee estimate to ensure it is accurate at the time the user sends it (e.g. they get the fee quote and leave for 12 hours then come back)
-
Ideas: If the L2 fee quoted is > X minutes old, could display a warning next to it
There are three common errors that would cause your transaction to be rejected
-
Insufficient funds
ETH as the fee token
- If you are trying to send a transaction and you do not have enough ETH to pay for that L2 fee charged, your transaction will be rejected.
- Error code:
-32000
- Error message:
invalid transaction: insufficient funds for l1Fee + l2Fee + value
BOBA as the fee token
- If you are trying to send a transaction and you do not have enough BOBA to pay for that L2 fee charged, your transaction will be rejected.
- Error code:
-32000
- Error message:
invalid transaction: insufficient Boba funds for l1Fee + l2Fee + value
-
Gas Price to low
- Error code:
-32000
- Error message:
gas price too low: 1000 wei, use at least tx.gasPrice = X wei
wherex
is l2GasPrice.- Note: values in this error message vary based on the tx sent and current L2 gas prices
- It is recommended to build in error handling for this. If a user's transaction is rejected at this level, just set a new
tx.gasPrice
via RPC query ateth_gasPrice
or by callingOVM_GasPriceOracle.gasPrice
- Error code:
-
Fee too large
- Error code:
-32000
- Error message:
gas price too high: 1000000000000000 wei, use at most tx.gasPrice = Y wei
wherex
is 3*l2GasPrice. - When the
tx.gasPrice
provided is ≥3x the expectedtx.gasPrice
, you will get this error^, note this is a runtime config option and is subject to change
- Error code: