Skip to main content
The evmd directory in the Cosmos EVM repository contains an example chain that demonstrates the integration of Cosmos EVM modules. This reference implementation is based on the simapp implementation from the Cosmos SDK repository, which provides a simplified yet complete blockchain foundation.
The evmd chain implementation serves two primary purposes:
  1. Demonstration: Shows how to integrate Cosmos EVM modules into a blockchain
  2. Testing Foundation: Provides a working chain for development and testing
You can use evmd as the starting point for building your own custom chain.

Prerequisites

Make sure you have the following prerequisites:
If you’re new to Go development, ensure your $GOPATH/bin is in your system PATH. Most package managers (Homebrew, apt, pacman) handle this automatically. See the Go environment setup guide for details.

Building evmd

The evmd implementation serves as the foundation for building your own custom blockchain. To create your chain:
  1. Fork the repository — Clone the Cosmos EVM repository:
git clone https://github.com/cosmos/evm.git
cd evm
  1. Run the chain — Run the local node script to start the chain:
./local_node.sh -y
The script runs make install before starting, so the evmd binary will be available in your $GOPATH/bin once it completes. The JSON-RPC server will be available at http://localhost:8545.
evmd status
evmd keys list
evmd query bank balances <address>
evmd --help  # full list of commands

local_node.sh Flags

The following are the available flags for the local node script:
./local_node.sh -y   # fresh start (overwrite previous database)
./local_node.sh -n   # resume from previous state
./local_node.sh --no-install # skip rebuild, use the existing binary
./local_node.sh --remote-debugging # build with debugging symbols (for remote debugging)

Connect a Wallet

Once the chain is running, you can connect using any Ethereum-compatible wallet. The example below uses MetaMask:

MetaMask Setup

1. Import the test account — Add a new wallet in MetaMask using this seed phrase:
gesture inject test cycle original hollow east ridge hen combine
junk child bacon zero hope comfort vacuum milk pitch cage oppose
unhappy lunar seat
This is a well-known test seed phrase. Never use it for mainnet or with real funds.
2. Add the network — Go to Networks → Add custom network and enter:
SettingValue
Network NameCosmos EVM Local
RPC URLhttp://localhost:8545
Chain ID262144
Currency SymbolTEST
Block Explorer URL(leave empty)
3. Verify — Switch to “Cosmos EVM Local” in MetaMask. You should see your account balance and can now send transactions. 4. Send a test transaction — Send 1 TEST to 0x742d35cc6644c068532fddb11B4C36A58D6D3eAb to confirm end-to-end transaction flow is working.

Deploy a Contract with Forge

With the chain running, you can deploy Solidity contracts using Forge. Install it with curl -L https://foundry.paradigm.xyz | bash && foundryup if you haven’t already.
  1. Create a contract — Save the following as Counter.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Counter {
    uint256 public count;
    function increment() public { count++; }
}
  1. Deploy it — Use the dev0 test account private key to deploy:
forge create Counter.sol:Counter \
  --rpc-url http://localhost:8545 \
  --private-key 0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305 \
  --broadcast
This private key is for local development only. Never use it with real funds.
  1. Interact with the contract — Read the current count, send a transaction to increment it, then read again to confirm the state change:
# Read current count (returns 0)
cast call <deployed-address> "count()(uint256)" --rpc-url http://localhost:8545

# Increment the counter
cast send <deployed-address> "increment()" \
  --rpc-url http://localhost:8545 \
  --private-key 0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305

# Read again (returns 1)
cast call <deployed-address> "count()(uint256)" --rpc-url http://localhost:8545

Configuration

Basic Chain Configuration

The following are some examples of basic configuration options for the evmd chain.
SettingDefaultHow to changeReference
Cosmos Chain IDcosmos_262144-1Pass --chain-id at node start
EVM Chain ID262144Pass --evm-chain-id at node startx/vm/types/params.go
Bech32 PrefixcosmosChange Bech32Prefix constantevmd/config/bech32.go
Token DenominationaatomUpdate ExampleAttoDenom, used by NewMintGenesisState()testutil/constants/constants.go
EVM PermissioningPermissionlessSet AccessType in DefaultAccessControlx/vm/types/params.go
PrecompilesAll (9 enabled)Replace AvailableStaticPrecompiles in NewEVMGenesisState()evmd/genesis.go
ModulesStandard SDK setRegister, set the pre-begin-, begin-, and endblockers, genesis module order, and keeper initializationevmd/app.go
Binary nameevmdRename directory and run find . -type f -name "*.go" -exec sed -i 's/evmd/yourchain/g' {} \;, then update go.mod

Advanced Configuration

evmd works out of the box with sensible defaults. The following are optional configurations for chains that need to go further.
ConfigurationDescriptionReference
MempoolCustom transaction prioritization, nonce gap handling, pool size limitsMempool Configuration
Fee MarketDisable base fee, set min gas price, tune base fee adjustment rateFee Market Module
EVM Access ControlRestrict contract deployment/calls to whitelisted addressesVM Module
JSON-RPCEnable/disable namespaces, set resource caps, configure WebSocket originsNode Configuration
Predeployed ContractsDeploy Create2, Multicall3, Permit2, Safe at genesisPredeployed Contracts
For additional support and community resources, visit the Cosmos EVM GitHub repository or join the Cosmos developer community.