Cronos limits are EVM gas ceilings behind out-of-gas transaction reverts
Cronos limits are the EVM transaction gas ceilings that bound how much computation a Cronos EVM call may consume. A wallet estimates the required units, the sender authorizes a higher ceiling and the chain charges only the gas actually used. If execution exhausts that allowance, the transaction's state changes roll back, its receipt records failure and the spent gas remains payable in CRO. This page covers Cronos EVM mainnet, whose EVM chain ID is 25.
Set, submit and verify a Cronos gas ceiling
The operating sequence has four stages: select Cronos EVM, simulate the exact call, add measured headroom and inspect the mined receipt.
Start by confirming chain ID 25 for mainnet or 338 for Cronos EVM testnet. Build the final transaction with the same sender, contract address, CRO value and calldata that will be broadcast. Then call
eth_estimateGas
through MetaMask, ethers or Web3.py. An estimate reproduces the current state path, so changing the amount, recipient, token allowance or contract state invalidates it. Apply a defined buffer to the returned units, submit once and keep the transaction hash. This preparation separates an execution ceiling from the fee quote, which uses a separate field entirely.
After inclusion, open Cronos Explorer or read the receipt through JSON-RPC. Inspect
status
and
gasUsed. Status 1 signals success, while status 0 signals failed top-level execution. Equality between
gasUsed
and the submitted limit strongly points to out of gas. A smaller count points toward
REVERT
or another exception. This verification closes the operational loop in Cronos Explorer.
Fee exposure starts with gas units and price
Gas units define execution capacity, while the effective gas price converts consumed units into a CRO fee.
On Cronos EVM, CRO uses 18 decimal places, so one CRO equals 1,000,000,000,000,000,000 base units. One gwei equals 1,000,000,000 of those units. The maximum authorization for a type 2 transaction is
gasLimit × maxFeePerGas, while the settled execution charge is
gasUsed × effectiveGasPrice. Unused gas units aren't charged. A wallet must still reserve enough CRO for the ceiling before broadcast because EIP-1559 checks fee caps against the sender's balance. The network calculates a base fee for each block and the transaction supplies its priority cap.
A data-free CRO transfer starts at 21,000 gas. At exactly 1 gwei, that count converts to 0.000021 CRO. Multiply this unit rate by the receipt's
effectiveGasPrice
in gwei to calculate the settled fee. The formula handles a changing network quote while preserving the exact 0.000021 CRO conversion.
What happens when the gas limit is too low?
A gas limit below the executed path makes the top-level transaction halt out of gas and roll back its state changes.
The Ethereum Virtual Machine meters each opcode, memory expansion, storage access, log and nested call. Once the remaining gas reaches zero, execution can't reach later instructions. Cronos records a failed receipt with status 0, removes state writes and discards logs created by the reverted transaction. The sender still pays for the consumed units because validators performed that work. A successful receipt uses status 1.
Out of gas and Solidity's
revert
don't leave the same gas pattern.
A top-level out-of-gas halt consumes the transaction allowance, so
gasUsed
normally reaches
gasLimit. An uncaught
REVERT
also produces status 0, yet it returns unused gas after the revert instruction and carries optional reason data. A contract can also contain a failed inner call, inspect its false return value and continue successfully. EIP-150 reserves one sixty-fourth of the parent frame's available gas and forwards at most 63/64 to a child call. That reserve lets the caller handle a failed subcall instead of exhausting the entire parent frame. The receipt then reflects the parent outcome, not every child result.
Rebroadcasting the identical call with more gas fixes allowance exhaustion. If contract conditions trigger
REVERT, a larger ceiling funds the same branch and the receipt remains status 0.
Intrinsic gas sets the entry floor
Intrinsic gas is the non-negotiable entry cost deducted before Cronos runs contract bytecode.
A data-free transfer to an existing account starts at 21,000 gas, while a contract-creation transaction starts at 53,000 gas. Those numbers come before dynamic execution. EIP-2028 charges 4 gas for each zero calldata byte and 16 gas for each non-zero byte. EIP-2930 adds 2,400 gas per listed address and 1,900 gas per listed storage key. A node rejects a submitted limit below this calculated floor before normal execution begins, so the transaction doesn't produce the same mined pattern as a contract that exhausts its runtime allowance.
EIP-3860 adds 2 gas per 32-byte word of initcode during creation. Data shape, access lists and deployment code therefore raise the minimum. The four transaction forms below show only the fixed starting count; contract execution adds more.
| Transaction form | Structure included | Fixed intrinsic gas count |
|---|---|---|
| Plain CRO transfer | Existing account and no calldata | 21,000 gas |
| Contract call | Existing contract and no calldata | 21,000 gas before runtime |
| Access-list call | One address, no keys and no calldata | 23,400 gas before runtime |
| Contract creation | No initcode bytes | 53,000 gas |
Which receipt fields confirm an out-of-gas failure?
A Cronos receipt confirms out of gas when status is 0 and
gasUsed
has reached the submitted gas limit.
Read the transaction object alongside the receipt because the receipt doesn't repeat every submitted field. Compare these four items:
-
Transaction
gas, which records the authorized ceiling. -
Receipt
gasUsed, which records the charged execution units. -
Receipt
status, where 1 means success and 0 means failure. -
Receipt
logs, which excludes events rolled back with failed top-level execution.
On a Cronos node that exposes debug methods,
debug_traceTransaction
identifies the terminal frame. An out-of-gas trace stops where an operation lacks enough remaining units. A
REVERT
trace ends at the explicit instruction and can include return data. If a parent catches a child failure, inspect the nested frames because the top-level receipt can still show status 1. A Geth-style
callTracer
makes that call boundary visible.
Estimation with MetaMask, ethers and Foundry
Gas estimation should reproduce the exact state-changing path, then add headroom for branch changes before signing.
MetaMask requests an estimate from its connected JSON-RPC provider. ethers exposes
estimateGas, Web3.py provides
estimate_gas()
and Foundry offers
cast estimate. Hardhat scripts reach the same RPC method through their provider. Each tool simulates the transaction against a selected block state without committing it, so the sender needs CRO during broadcast rather than simulation.
State-sensitive contracts need repeat estimates. An ERC-20 or CRC20
transfer
changes storage balances; an OpenZeppelin allowance path differs between first approval, updated approval and
transferFrom. Automated market makers inspect pool reserves, while NFT mints inspect supply and per-address counters. Estimate after the immediately preceding transaction is mined, not before a multi-step batch starts. A 20% buffer is a sensible operating rule for deterministic calls with modest branching. Raise it further only after a trace identifies a legitimate higher-cost path, because an arbitrary ceiling can hide a stale estimate in deployment scripts. Continuous integration should fail whenever a Hardhat fixture crosses that ceiling.
Does a higher gas limit make Cronos execution faster?
A higher gas limit doesn't buy priority; it only permits the EVM to execute more metered work. Type 2 EIP-1559 transactions use two fee-cap fields:
maxFeePerGas
and
maxPriorityFeePerGas. Legacy type 0 transactions use one
gasPrice
field. Validators order eligible transactions through fee and mempool rules, while
gasLimit
remains a spending ceiling. Raising 80,000 gas to 120,000 gas won't accelerate a call that consumes 70,000 gas; both settle on the same executed path.
Protocol ceilings beyond the wallet field
Contract deployment faces byte-size ceilings that remain binding even when a wallet supplies ample transaction gas, which is detailed in Using Cronos.
Cronos EVM enforces the EIP-170 runtime code ceiling of 24,576 bytes and the EIP-3860 initcode ceiling of 49,152 bytes. EIP-3860 meters initcode at 2 gas for every 32-byte word, while code deposit costs 200 gas per runtime byte. The EVM call stack stops at depth 1,024. A higher transaction limit can't override these rules. Solidity reports creation bytecode and deployed bytecode separately. Measure both artifacts, then reduce code with the optimizer, linked libraries or separated contracts before Hardhat or Foundry submits the deployment. Deployment sizing belongs in every release build.
Block capacity forms another outer bound. Every block header carries a
gasLimit, and one transaction can't reserve more execution than the block accepts. Read the latest block through
eth_getBlockByNumber
before setting large deployment or migration ceilings because governance and network upgrades can change that value. Cronos EVM doesn't implement EIP-4844 blob execution, so oversized input still travels through ordinary calldata and the EVM ceilings above.
Repeatable maintenance for changing contract paths
Maintenance turns gas limits into a tested release parameter rather than a wallet guess. Record five values for every critical method: estimated gas, configured ceiling, mined
gasUsed, receipt status and
effectiveGasPrice. Run the suite on Cronos EVM testnet chain ID 338 after Solidity, OpenZeppelin or contract configuration changes. Alert when
gasUsed
crosses 80% of the configured ceiling, then re-estimate before the next release. Cronos limits stay reliable when identical input fixtures, state setup and receipt checks remain in continuous integration.
Details worth knowing about Cronos limits
Can I replace a pending Cronos transaction without changing its gas limit?
Yes, a pending Cronos EVM transaction can be replaced by sending another transaction from the same account with the same nonce. The replacement must offer fee terms that the node accepts over the original transaction. Its gas limit can stay unchanged or rise independently. If the first transaction reaches a block before the replacement, the nonce is already consumed and the second submission won't execute.
What changes gas use between repeated CRC20 transfers?
Repeated CRC20 transfers use different gas when token balances, allowances or contract branches change between calls. A transfer that creates a recipient's first nonzero balance performs a different storage transition from one that updates an existing balance. Fee-on-transfer logic, paused-state checks and allowance updates add other paths. Estimate the exact method with the exact sender, recipient and amount after the preceding state change settles.
Is one gas limit shared by every call inside Multicall3?
Yes, one top-level gas limit funds the full Multicall3 execution, including every nested call and the aggregator's own logic. Each inner operation draws from the remaining transaction allowance. Whether one failed inner call cancels the batch follows the selected Multicall3 function and its allow-failure settings. The receipt reports one top-level gasUsed figure for the submitted transaction.
How long should a Cronos gas estimate stay cached?
A Cronos gas estimate should remain cached for zero intervening changes to relevant inputs or state. Re-estimate after a balance, allowance, reserve, supply counter, role or contract configuration changes. Also re-estimate after updating Solidity output, OpenZeppelin dependencies or deployment bytecode. A time interval alone can't preserve accuracy because one preceding transaction can select a more expensive branch before the cached call reaches execution.