Skip to main content
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.