The code on this page is example code, not a production-ready implementation. It is not part of cosmos/evm and is not tested or maintained by the Cosmos EVM team. If you adopt this approach, the code lives in your application and you are responsible for auditing and maintaining it going forward.
Applies to: chains on cosmos/evm v0.7.x+ with a 6-decimal staking denom.
Scope: every change lives in your application, no fork of cosmos/evm is needed.
Instead of scaling your 6-decimal denom (ustake) into the EVM, launch the EVM with a
separate, natively 18-decimal gas denom (astake). A precompile is the sole mint/burn
authority for astake, converting against escrowed ustake at a fixed rate:
astake is always fully collateralized. Assert this in your e2e tests (x/crisis is
deprecated):
Staking, governance, inflation, and all existing balances stay on ustake untouched.
Because astake is a plain 18-decimal denom (EvmDenom == ExtendedDenom), x/vm’s
denom validation passes as-is, avoiding the scaled-denom machinery
x/precisebank existed to support.
Solidity interface
Neither method is payable: ustake is not the EVM-native token, so it cannot travel as
msg.value.
Precompile
Standard stateful precompile in your app (the distribution precompile is the
reference structure), at a free address:
withdraw reverses the sequence (collect → BurnCoins → release) after rejecting
amounts not a multiple of ScalingFactor. The mint permission is the entire “module”,
no AppModule, store key, or Msg service:
Ante handlers: own the chain
Assemble your own ante router from the exported cosmos/evm decorators (copy the stock
assembly) and make two changes.
First gas
A ustake-only account cannot pay for the EVM tx that would give it
astake. Front the fee in a decorator ahead of the unmodified mono decorator, whose
balance checks then see the converted funds:
Cosmos tx fees
In your Cosmos-tx chain, substitute a min-gas-price decorator that
quotes both denoms, and a fee checker that prices ustake fees at the fixed rate:
Delegators and relayers then never need astake.
Mempool: wrap the VM keeper you hand to it
cosmos/evm now runs an app-side EVM mempool, and the JSON-RPC server requires it.
EVM txs enter the pool before any ante handler runs, so without this change the
first-gas deposit() dies at the RPC with insufficient funds for gas * price + value: balance 0. Your app chooses the VM keeper the pool reads state through:
Registration and genesis
Caveats
- Balances are split across two denoms permanently:
eth_getBalance shows only
astake; explorers and wallets should present ustake + astake/10¹² as one asset.
- MetaMask pre-checks
eth_getBalance ≥ fee + value locally and blocks zero-astake
senders regardless of chain rules. The ante + mempool changes cover raw-RPC and dApp
flows; wallet-first onboarding still needs a Cosmos-side path (fee-granted helper,
faucet, or dust airdrop at the upgrade).
- Staking/distribution precompiles operate in 6-dec
ustake while the rest of the EVM
is 18-dec astake; EVM stakers must withdraw() first. Rewards arrive in both
denoms (EVM fees in astake, inflation in ustake).
astake is IBC-transferable and becomes a distinct voucher from ustake on remote
chains; decide before launch whether to rate-limit or filter it.
- Circulating supply is just
supply(ustake); adding supply(astake)/10¹² double-counts
the escrow.