diff --git a/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx b/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx index b5ca5ae0..3d553e3d 100644 --- a/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx +++ b/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx @@ -1,2634 +1,223 @@ --- title: "Build A Custom Chain" -description: "Create your own blockchain by forking and customizing the Cosmos EVM referece chain. Covers the entire process from initial fork to running network, including parameter configuration, genesis setup, and validator coordination." +description: "Create your own blockchain by forking and customizing the Cosmos EVM reference chain (evmd). This guide covers the example chain configuration, running the chain locally, and understanding the foundation for building your custom blockchain." --- -## Understanding the Cosmos SDK Application Structure +# Example Cosmos EVM Chain + +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. - Cosmos EVM is built on the Cosmos SDK, a modular framework for building - application-specific blockchains. Understanding this structure helps you +This 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 - customize your chain effectively. +You can use evmd as the starting point for building your own custom chain. -A Cosmos SDK application consists of several key components: - -- **App Module**: The core application logic (`evmd/app.go`) that composes various modules -- **Modules**: Functional units handling specific blockchain features (staking, governance, EVM, etc.) -- **Keeper**: Each module's state management and business logic handler -- **Genesis**: Initial state and configuration for each module - -- **CLI Commands**: User interface for interacting with the chain - -The `evmd` directory contains the example chain implementation that you'll fork and customize for your own blockchain. +## Building Your Custom Chain -## Forking and Initial Setup +The `evmd` implementation serves as the foundation for building your own custom blockchain. To create your chain: - - -Begin by forking the Cosmos EVM repository and cloning your fork: + + +Start by forking the Cosmos EVM repository: ```bash git clone https://github.com/YOUR-ORG/YOUR-CHAIN.git - cd YOUR-CHAIN - ``` + -The repository structure provides everything needed to build a custom chain. The `evmd` directory contains the example implementation you'll modify. - - - - -Replace `evmd` references throughout the codebase with your chain's name: + +Rename the `evmd` directory and update all references: ```bash -# Rename the directory - +# Rename directory mv evmd yourchain -# Update imports and references +# Update imports and binary name find . -type f -name "*.go" -exec sed -i 's/evmd/yourchain/g' {} \; -find . -type f -name "*.md" -exec sed -i 's/evmd/yourchain/g' {} \; - -``` - -Update module paths in `go.mod` to reflect your repository. - - - - -Update application metadata in `yourchain/cmd/yourchain/cmd/root.go`: - -```go -// Update these constants - -const ( - NodeDir = ".yourchain" // Change from ".evmd" -) - -// In initRootCmd() -rootCmd := &cobra.Command{ - Use: "yourchain", // Change from "evmd" - Short: "Your Chain Daemon", // Update description - Long: `Your custom blockchain built with Cosmos EVM`, // Update description - -} - -``` - -**Other files to update**: -- `Makefile` - Build targets and binary names -- `README.md` - Documentation and installation instructions - -- `go.mod` - Module path to your repository -- `*.proto` files - Package names if creating custom modules - - - - - -**Post-Fork Checklist**: -- [ ] Repository cloned and `evmd` directory renamed -- [ ] All Go imports updated to new module path - -- [ ] go.mod updated with new module name -- [ ] Makefile updated with new binary name - -- [ ] README and documentation updated -- [ ] Run `go mod tidy` to verify dependencies - -- [ ] Test build with `make build` - - -## Core Configuration Parameters - - -Some parameters must be set before genesis and cannot be changed later without -significant migration effort. Choose carefully based on your requirements. - - - -**Quick Reference**: For a complete list of all configurable parameters with defaults and validation rules, see [Configuration Parameters](/docs/evm/next/documentation/getting-started/build-a-chain/configuration-parameters). - - - -**Configuration Workflow**: -1. **Pre-Genesis**: Configure these parameters in code (Bech32 prefix, BIP44 coin type) -2. **Initialize**: Run `yourchain init --chain-id ` to create initial genesis -3. **Customize Genesis**: Edit `~/.yourchain/config/genesis.json` with your parameters - -4. **Runtime Config**: Configure `~/.yourchain/config/app.toml` for node operations -5. **Launch**: Start the chain with coordinated genesis - - -This section covers step 1 (Pre-Genesis). See [Genesis Configuration](#genesis-configuration) for steps 2-3. - - -### Chain Identity Configuration - -These fundamental parameters define your chain's identity and must be configured before initialization. - - - -**File Location**: [`config/config.go`](https://github.com/cosmos/evm/blob/main/config/config.go#L62) - -**What It Does**: Defines the human-readable prefix for all addresses on your chain, used for account addresses, validator addresses, and consensus addresses. - -**Valid Values**: Any alphanumeric string (lowercase recommended). Common examples: -• `cosmos`, `osmosis`, `juno`, `noble`, `yourchain` - -**Configuration**: - -```go -const ( - // Bech32Prefix defines the Bech32 prefix for accounts - Bech32Prefix = "yourchain" // Line 62 - Change from "cosmos" - - // Generated prefixes (do not modify these) - Bech32PrefixAccAddr = Bech32Prefix // yourchain1... - Bech32PrefixAccPub = Bech32Prefix + sdk.PrefixPublic // yourchainpub1... - Bech32PrefixValAddr = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixOperator // yourchainvaloper1... - Bech32PrefixValPub = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixOperator + sdk.PrefixPublic // yourchainvaloperpub1... - Bech32PrefixConsAddr = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixConsensus // yourchainvalcons1... - Bech32PrefixConsPub = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixConsensus + sdk.PrefixPublic // yourchainvalconspub1... -) - -``` - -**Impact**: -• User account addresses: `yourchain1abc...` -• Validator addresses: `yourchainvaloper1abc...` -• Cannot be changed after genesis without breaking all addresses - - - - - **File Location**: [`crypto/hd/hdpath.go`](https://github.com/cosmos/evm/blob/main/crypto/hd/hdpath.go#L9) - -**What It Does**: Sets the BIP44 coin type for hierarchical deterministic wallet derivation. This affects how hardware wallets (Ledger, Trezor) and software wallets derive addresses from seed phrases. - -**Valid Values**: -• `60` - Ethereum coin type (default, EIP-84 compliant) - **Recommended for EVM compatibility** -• `118` - Cosmos coin type (for pure Cosmos chains) -• Custom registered coin type from [SLIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) - -**Configuration**: - -```go -var ( - // Bip44CoinType satisfies EIP84 for Ethereum compatibility - Bip44CoinType uint32 = 60 // Line 9 - Use 60 for EVM, 118 for Cosmos - - - // BIP44HDPath is automatically set based on coin type - BIP44HDPath = ethaccounts.DefaultBaseDerivationPath.String() // m/44'/60'/0'/0 - -) - ``` -**Impact**: -• Determines HD wallet derivation path -• Affects hardware wallet compatibility - -• Must match user expectations (use 60 for EVM-focused chains) +Update `go.mod` to reflect your repository path. + - + +Modify the default configuration in your chain: - - **What It Does**: Your chain uses TWO different chain IDs for different purposes. +- **Chain IDs**: Update Cosmos chain ID and EVM chain ID +- **Bech32 Prefix**: Set your address prefix in `config/config.go` +- **Token Denomination**: Configure in genesis +- **Precompiles**: Enable only the precompiles you need +- **Modules**: Add or remove modules based on requirements -**1. Cosmos Chain ID** (string format): -• **What**: Identifies your chain in the Cosmos ecosystem for IBC and governance -• **Format**: `{name}-{version}` (e.g., `osmosis-1`, `noble-1`, `yourchain-1`) -• **Where**: Set during initialization via CLI -• **Can Change**: Yes, through coordinated network upgrade + +For detailed configuration guidance, see the comprehensive [Configuration Parameters](/docs/evm/next/documentation/getting-started/build-a-chain/configuration-parameters) documentation. + + + +Use the local node script to test your changes: ```bash -yourchain init mynode --chain-id yourchain-1 - +./local_node.sh -y ``` -**2. EVM Chain ID** (uint64 number): -• **What**: EIP-155 replay protection for Ethereum transactions -• **Format**: Unsigned 64-bit integer (e.g., `262144`, `1`, `137`) -• **Where**: Set in genesis `vm.chain_config.chain_id` -• **Can Change**: No, changing breaks Ethereum transaction replay protection -• **Registry**: Register at [chainlist.org](https://chainlist.org) for public chains - - -**Reserved EVM Chain IDs**: -• `1` - Ethereum Mainnet -• `137` - Polygon - -• `262144` - Cosmos EVM default (testing only) -• `1-999` - Reserved by Ethereum Foundation - -**Recommendation**: Choose EVM Chain ID > 1000000 for production to avoid conflicts. - - - - -### Token Economics Configuration - - - **Default Configuration**: Cosmos EVM now uses 18 decimals by default with the - standard bank module. The precisebank module is only needed for chains using +Verify that: +- The chain starts successfully +- JSON-RPC is accessible +- Wallets can connect +- Transactions work as expected + - non-18-decimal tokens (like 6 decimals). - + +Once testing is complete, prepare for testnet deployment: - -For chains using 6-decimal or other non-18-decimal tokens, you need to add the precisebank module to handle fractional amounts. +- Set up validator infrastructure +- Configure persistent peers +- Coordinate genesis with validators +- Launch the network -For comprehensive PreciseBank Module documentation including mathematical foundations, state management, and complete examples, see the [PreciseBank Module Documentation](/evm/next/documentation/cosmos-sdk/modules/precisebank). +For production deployment guidance, see the [Node Configuration](/docs/evm/next/documentation/getting-started/node-configuration) documentation. + + -**In `yourchain/app.go`:** - -```go -import ( - // Add precisebank imports - "github.com/cosmos/evm/x/precisebank" - precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" - - // Standard bank is already imported - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -// In app struct, add PreciseBankKeeper -type YourApp struct { - // ... other keepers - BankKeeper bankkeeper.Keeper - - PreciseBankKeeper precisebankkeeper.Keeper // Add this line - EVMKeeper *evmkeeper.Keeper - - // ... other keepers -} - -// In NewApp function: -// 1. Add precisebank store key -keys := storetypes.NewKVStoreKeys( - // ... other keys - evmtypes.StoreKey, - feemarkettypes.StoreKey, - erc20types.StoreKey, - precisebanktypes.StoreKey, // Add this line -) - -// 2. Initialize PreciseBankKeeper after BankKeeper -app.PreciseBankKeeper = precisebankkeeper.NewKeeper( - appCodec, - keys[precisebanktypes.StoreKey], - app.BankKeeper, - app.AccountKeeper, -) - -// 3. Update EVMKeeper to use PreciseBankKeeper instead of BankKeeper -app.EVMKeeper = evmkeeper.NewKeeper( - appCodec, - keys[evmtypes.StoreKey], - tkeys[evmtypes.TransientKey], - keys, - authtypes.NewModuleAddress(govtypes.ModuleName), - app.AccountKeeper, - app.PreciseBankKeeper, // Use PreciseBankKeeper instead of BankKeeper - app.StakingKeeper, - app.FeeMarketKeeper, - &app.ConsensusParamsKeeper, - &app.Erc20Keeper, - evmChainID, - tracer, -) - -// 4. Add precisebank to ModuleManager -app.ModuleManager = module.NewManager( - // ... other modules - precisebank.NewAppModule(app.PreciseBankKeeper, app.AccountKeeper), // Add this line - - vm.NewAppModule(app.EVMKeeper, app.AccountKeeper, app.BankKeeper, app.AccountKeeper.AddressCodec()), - feemarket.NewAppModule(app.FeeMarketKeeper), - erc20.NewAppModule(app.Erc20Keeper, app.AccountKeeper), -) - -// 5. Add to genesis order (MUST be after bank and before vm) -genesisModuleOrder := []string{ - // ... other modules - banktypes.ModuleName, - precisebanktypes.ModuleName, // Add after bank, before vm - evmtypes.ModuleName, - feemarkettypes.ModuleName, - erc20types.ModuleName, - // ... rest -} - -``` - -**Why precisebank is required for non-18-decimal tokens:** -• **6-decimal tokens**: Tracks fractional amounts in EVM (1 utoken = 10^12 wei) -• **12-decimal tokens**: Handles 10^6 wei conversions -• **Prevents dust**: Ensures no loss of fractional amounts during conversions - -• **Wraps bank module**: Provides seamless integration while tracking remainders - -**If using 18 decimals (default):** -• No changes needed - standard bank module handles everything -• Direct 1:1 mapping between native token and EVM representation - -• Simpler architecture without extra module complexity -• Any non-18: Prevents dust accumulation from precision differences - - - - -Native token configuration is set in genesis through a combination of bank module metadata and VM parameters. The VM module reads this configuration during initialization and stores it as `EvmCoinInfo` in its state: - - -```json 6-decimal-token.json -{ - "bank": { - "denom_metadata": [ - { - "description": "The native staking token for evmd.", - "denom_units": [ - { - "denom": "utest", // Base denomination (6 decimals = micro prefix) - "exponent": 0, - "aliases": [] - }, - { - "denom": "test", // Display denomination - "exponent": 6, // 6 decimals from base - - "aliases": [] - } - ], - "base": "utest", // Must match vm.params.evm_denom - "display": "test", // Human-readable name - - "name": "Test Token", - "symbol": "TEST" - } - ] - }, - "evm": { - "params": { - "evm_denom": "utest", // References bank metadata base denom - "extended_denom_options": { - "extended_denom": "atest" // Required: 18-decimal representation for EVM - } - } - } -} - -``` - -```json 18-decimal-token.json -{ - "bank": { - "denom_metadata": [ - { - "description": "The native staking token for evmd.", - "denom_units": [ - { - "denom": "atest", // Base denomination (18 decimals = atto prefix) - "exponent": 0, - "aliases": ["attotest"] - }, - { - "denom": "test", // Display denomination - "exponent": 18, // 18 decimals from base - - "aliases": [] - } - ], - "base": "atest", // Base denom with 18 decimals - "display": "test", // Human-readable name - - "name": "Test Token", - "symbol": "TEST" - } - ] - }, - "evm": { - "params": { - "evm_denom": "atest" // References bank metadata base denom - // No extended_denom_options needed for 18-decimal chains - - } - } -} - -``` - -```bash genesis-setup-example.sh -# Real example from local_node.sh showing how to configure genesis - -# This sets up an 18-decimal token using jq commands - -# Set the base denom in all modules -jq '.app_state["staking"]["params"]["bond_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["gov"]["params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["mint"]["params"]["mint_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Set bank metadata (18 decimals) -jq '.app_state["bank"]["denom_metadata"]=[{"description":"The native staking token for evmd.","denom_units":[{"denom":"atest","exponent":0,"aliases":["attotest"]},{"denom":"test","exponent":18,"aliases":[]}],"base":"atest","display":"test","name":"Test Token","symbol":"TEST","uri":"","uri_hash":""}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Enable precompiles (see x/vm/types/precompiles.go for complete list) -jq '.app_state["vm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805","0x0000000000000000000000000000000000000806"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Set up ERC20 native token representation -# For details on ERC20 module configuration, see: -# /evm/next/documentation/cosmos-sdk/modules/erc20 -jq '.app_state.erc20.native_precompiles=["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state.erc20.token_pairs=[{contract_owner:1,erc20_address:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",denom:"atest",enabled:true}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -``` - - +## Default Configuration -The VM module's `SetGlobalConfigVariables` function (called during PreBlock) reads this configuration and: +The example chain (`evmd`) comes with the following default configuration: -1. Fetches bank metadata for the specified `evm_denom` -2. Extracts decimal precision from the denom units -3. Creates `EvmCoinInfo` with appropriate extended denom: - - For 18-decimal tokens: `extended_denom` = `evm_denom` (direct mapping) - - For non-18-decimal tokens: Uses `extended_denom_options.extended_denom` for EVM representation -4. Stores this configuration in VM keeper state via `SetEvmCoinInfo()` +| Option | Value | Description | +|---------------------|------------------------|-------------| +| **Binary** | `evmd` | The compiled chain binary name | +| **Chain ID** | `cosmos_262144-1` | Default Cosmos chain ID (format: `name_evmChainID-version`) | +| **EVM Chain ID** | `262144` | EVM chain ID for transaction replay protection | +| **Custom Opcodes** | - | No custom opcodes by default | +| **Token Pairs** | 1 (native token) | Default ERC20 token pair for the native denomination | +| **Denomination** | `atest` | Native token denomination (18 decimals, atto-prefix) | +| **EVM Permissioning** | Permissionless | Anyone can deploy and call contracts | +| **Enabled Precompiles** | All | All nine static precompiles are enabled by default | -**Decimal Precision Guidelines:** -• **18 decimals**: Direct EVM compatibility, uses standard bank module by default -• **6 decimals**: Common in Cosmos, requires adding precisebank for fractional amounts - -• **Other values**: Test conversion logic thoroughly with precisebank - -**Module Selection Based on Decimals:** -• `decimals: 18` → Use standard `x/bank` module -• `decimals: 6` or other → Use `x/precisebank` wrapper around bank - - +The default configuration uses an 18-decimal token (`atest`) which provides direct EVM compatibility without requiring the precisebank module. This is the recommended setup for new chains. -## Genesis Configuration +## Running The Chain -After completing the pre-genesis configuration in code, initialize your chain to create the default genesis file: +To run the example chain locally, use the provided local node script from the repository root: ```bash -# Initialize your chain (creates ~/.yourchain/config/ directory) -yourchain init --chain-id yourchain-1 - -# This creates: -# - ~/.yourchain/config/genesis.json (chain parameters and initial state) -# - ~/.yourchain/config/app.toml (node runtime configuration) -# - ~/.yourchain/config/config.toml (CometBFT configuration) -# - ~/.yourchain/data/ (blockchain data directory) - -``` - -The genesis file (`~/.yourchain/config/genesis.json`) contains all initial chain parameters and state. After initialization, customize these sections: - - -**Working Example**: The [`local_node.sh`](https://github.com/cosmos/evm/blob/main/local_node.sh#L234-L248) script in the Cosmos EVM repository shows a complete working example of genesis configuration using `jq` commands. Refer to this script for real-world configuration patterns. - - -### VM Module Parameters - -**File Location**: Genesis file at `~/.yourchain/config/genesis.json` under `app_state.vm.params` - -**Code Reference**: [`x/vm/types/params.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go) - - -For comprehensive VM Module documentation including all configuration methods, parameter details, and integration examples, see the [VM Module Documentation](/evm/next/documentation/cosmos-sdk/modules/vm). - - - - - - -**What It Does**: Specifies which bank module denomination to use as the native EVM token. - -**Type**: `string` - -**Valid Values**: Must match a base denomination from bank metadata (`app_state.bank.denom_metadata[].base`) - -**Examples**: -• `"atest"` - 18 decimal token -• `"utest"` - 6 decimal token - -• `"ustake"` - 6 decimal token -• Any custom bank denom - - -**Default**: `"uatom"` (see [`x/vm/types/params.go:21`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L21)) - -```json -"evm_denom": "ustake" - -``` - - - - -**What It Does**: Enables additional Ethereum Improvement Proposals beyond the default fork activations. - -**Type**: `[]int64` (array of EIP numbers) - -**Valid Values**: Only EIPs that are activatable in go-ethereum. Check available EIPs at runtime with `vm.ActivateableEips()` - -**Common EIPs**: -• `2200` - Net gas metering -• `2929` - Gas cost increases for state access opcodes - -• `3198` - BASEFEE opcode -• `3529` - Reduction in refunds - -• `3541` - Reject new contract code starting with 0xEF byte - -**Default**: `[]` (empty - all EIPs come from fork config) - -**Code Reference**: [`x/vm/types/params.go:182-200`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L182-L200) - -```json -"extra_eips": [2200, 2929] - -``` - -**Validation**: Automatically checks if EIP is valid and not duplicate - - - -**What It Does**: Enables specific Cosmos module precompiles accessible from Solidity. - -**Type**: `[]string` (array of hex addresses) - -**Valid Values**: Must be from available precompile addresses (see [`x/vm/types/precompiles.go:4-15`](https://github.com/cosmos/evm/blob/main/x/vm/types/precompiles.go#L4-L15)) - -**Available Addresses**: -• `"0x0000000000000000000000000000000000000100"` - P256 cryptography -• `"0x0000000000000000000000000000000000000400"` - Bech32 conversion - -• `"0x0000000000000000000000000000000000000800"` - Staking operations -• `"0x0000000000000000000000000000000000000801"` - Distribution/rewards - -• `"0x0000000000000000000000000000000000000802"` - ICS20 (IBC transfers) -• `"0x0000000000000000000000000000000000000803"` - Vesting accounts -• `"0x0000000000000000000000000000000000000804"` - Bank transfers - -• `"0x0000000000000000000000000000000000000805"` - Governance -• `"0x0000000000000000000000000000000000000806"` - Slashing info - - -**Default**: `[]` (none enabled) - -```json -"active_static_precompiles": [ - "0x0000000000000000000000000000000000000100", - "0x0000000000000000000000000000000000000800" -] - -``` - -**Security Note**: Only enable precompiles your chain needs to reduce attack surface - - - -**What It Does**: Lists IBC channel IDs that connect to other EVM-compatible chains (like Injective or Cronos) for special IBC token handling. - -**Type**: `[]string` (array of IBC channel identifiers) - -**Valid Values**: Valid IBC channel IDs (format: `channel-N` where N is a number) - -**Default**: `[]` (empty) - -```json -"evm_channels": ["channel-0", "channel-5"] - -``` - -**Validation**: Checks IBC channel identifier format (see [`x/vm/types/params.go:80-96`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L80-L96)) - - - -**What It Does**: Controls who can deploy smart contracts (`create`) and call existing contracts (`call`). - -**Type**: Object with `create` and `call` fields - -**Access Types** (from [`x/vm/types/access_control.pb.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/access_control.pb.go)): -• `0` - `AccessTypePermissionless`: Anyone can perform the action -• `1` - `AccessTypeRestricted`: Block addresses in the list - -• `2` - `AccessTypePermissioned`: Only addresses in the list allowed - -**Default**: `AccessTypePermissionless` for both - -```json -"access_control": { - "create": { - "access_type": 0, // 0=permissionless, 1=restricted, 2=permissioned - "access_control_list": [] // Hex addresses - - }, - "call": { - "access_type": 0, - "access_control_list": [] - } -} - -``` - -**Example - Permissioned Contract Deployment**: - -```json -"create": { - "access_type": 2, // Only allowlist can deploy - "access_control_list": [ - "0x1234567890123456789012345678901234567890", - "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" - ] -} - +./local_node.sh [FLAGS] ``` -**Validation**: See [`x/vm/types/params.go:140-180`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L140-L180) - - - -**What It Does**: Number of historical blocks to keep for historical state queries (affects disk usage and query capabilities). +### Available Flags -**Type**: `uint64` (string in JSON) +- `-y`: Overwrite previous database (fresh start) +- `-n`: Do **not** overwrite previous database (resume from previous state) +- `--no-install`: Skip installation of the binary (use existing binary) +- `--remote-debugging`: Build a binary suitable for remote debugging -**Valid Values**: Any positive integer - -**Default**: `8192` (same as EIP-2935) - -**Impact**: -• Higher values: More historical data, larger disk usage -• Lower values: Less disk usage, limited historical queries - -• `0`: No historical state (only current block) + +The `local_node.sh` script handles all the setup including: +- Building the `evmd` binary +- Initializing the chain configuration +- Setting up genesis parameters +- Starting the chain with JSON-RPC enabled + -```json -"history_serve_window": "8192" +### Example Usage + +```bash Fresh Start +# Start with a clean slate +./local_node.sh -y ``` -**Recommendation**: Use `8192` for standard chains, increase for archive nodes - - - -**What It Does**: Specifies the 18-decimal EVM representation for non-18 decimal native tokens. - -**Type**: Object with `extended_denom` field - -**When Required**: -• **18-decimal chains**: NOT required (EVM denom = base denom) -• **6-decimal chains**: REQUIRED (e.g., `utoken` → `atoken`) -• **Other decimals**: REQUIRED with precisebank module - -**Valid Values**: Any string that represents the 18-decimal denomination - -**Common Patterns**: -• 6-decimal `utoken` → 18-decimal `atoken` (atto-prefix) -• 6-decimal `ustake` → 18-decimal `astake` - -```json -"extended_denom_options": { - "extended_denom": "astake" // 18-decimal EVM representation -} - +```bash Resume Previous State +# Continue from where you left off +./local_node.sh -n ``` -**Omit for 18-decimal chains**: -```json -// For 18-decimal chains, either omit or set to null - -"extended_denom_options": null - +```bash Development Mode +# Skip rebuild if binary already exists +./local_node.sh --no-install ``` - - - -**Complete Configuration Example**: - -```json -{ - "app_state": { - "vm": { - "params": { - "evm_denom": "ustake", - "extra_eips": [], - "active_static_precompiles": [ - "0x0000000000000000000000000000000000000100", - "0x0000000000000000000000000000000000000400", - "0x0000000000000000000000000000000000000800", - "0x0000000000000000000000000000000000000804" - ], - "evm_channels": [], - "access_control": { - "create": { - "access_type": 0, - "access_control_list": [] - }, - "call": { - "access_type": 0, - "access_control_list": [] - } - }, - "history_serve_window": "8192", - "extended_denom_options": { - "extended_denom": "astake" - } - } - } - } -} - +```bash Debug Mode +# Build with debugging symbols +./local_node.sh --remote-debugging ``` + - - -### Available Precompiles - -Precompiles provide native chain functionality access from EVM contracts. Nine static precompiles are available at addresses 0x100, 0x400, and 0x800-0x806, covering cryptography (P256), addressing (Bech32), and Cosmos SDK modules (Staking, Distribution, ICS20, Vesting, Bank, Governance, Slashing). - -For complete details on each precompile including Solidity interfaces, gas costs, and usage examples, see the [Precompiles Overview](/docs/evm/next/documentation/smart-contracts/precompiles/overview). - -## Precompiles vs Predeployed Contracts - - -Understanding the difference between precompiles and predeployed contracts is crucial for properly configuring your chain: - -**Precompiles** - Native Go implementations exposed as EVM contracts at specific addresses (0x0100-0x0806). These provide gas-efficient access to Cosmos SDK modules. - -**Predeployed Contracts** - Regular Solidity contracts deployed at genesis to standard addresses. These include essential infrastructure like Create2, Multicall3, and Permit2. - - - -### Configuring Precompiles - -Precompiles must be explicitly enabled in your genesis configuration. The default evmd example enables ALL precompiles, but production chains should only enable what they need. +## Connect to Wallet - -For complete documentation on all available precompiles, see the [Precompiles Overview](/docs/evm/next/documentation/smart-contracts/precompiles/overview). - +Once the chain is running, you can connect using any Ethereum-compatible wallet. The example below uses MetaMask: - - -```json - { - "app_state": { - "vm": { - "params": { - "active_static_precompiles": [ - "0x0000000000000000000000000000000000000100", // P256 - "0x0000000000000000000000000000000000000400", // Bech32 +### MetaMask Setup - "0x0000000000000000000000000000000000000800", // Staking - "0x0000000000000000000000000000000000000804" // Bank + + +Use the following seed phrase when adding a new wallet in MetaMask: - ] - } - } - } - } ``` - - - - -```go - // In your custom genesis.go (e.g., evmd/genesis.go) - func NewEVMGenesisState() *evmtypes.GenesisState { - evmGenState := evmtypes.DefaultGenesisState() - // Enable ALL available precompiles (not recommended for production) - evmGenState.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles - return evmGenState - - } +gesture inject test cycle original hollow east ridge hen combine +junk child bacon zero hope comfort vacuum milk pitch cage oppose +unhappy lunar seat ``` - Enabling all precompiles increases the attack surface and gas overhead. Production chains should enable only the precompiles they need. +**Security Notice**: This is a well-known test seed phrase. **Never** use it for mainnet or with real funds. It's provided solely for local development and testing purposes. - - - -```json - { - "app_state": { - "vm": { - "params": { - "active_static_precompiles": [] - } - } - } - } -``` - - -Disabling all precompiles limits access to Cosmos SDK functionality from EVM contracts. Most chains will want at least the Bank and ERC20 precompiles enabled. - - - - -### Configuring Predeployed Contracts - - -The evmd example chain includes these predeployed contracts by default (defined in [`x/vm/types/preinstall.go:13-39`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L13-L39)): - -| Contract | Address | Description | Status | -| - | -- | | - | -| **Create2** | `0x4e59b44847b379578588920ca78fbf26c0b4956c` | Deterministic contract deployment | ✓ Verified | -| **Multicall3** | `0xcA11bde05977b3631167028862bE2a173976CA11` | Batch multiple calls in one transaction | ✓ Verified | -| **Permit2** | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | Token permit and transfer management | ✓ Verified | -| **Safe Factory** | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | Deploy Safe multisig contracts | ⚠️ Bytecode Issue | -| **EIP-2935** | `0x0b` | Historical block hash storage | ✓ System Contract | + - -**Safe Factory Bytecode Issue**: The Safe Singleton Factory bytecode in `DefaultPreinstalls` is currently a duplicate of the Create2 bytecode. This will not function correctly for deploying Safe wallets. If you need Safe Factory functionality, manually update the bytecode in your genesis configuration. See the [Safe Factory documentation](/docs/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory) for details. - + +1. Click the **Network** button on the top left of MetaMask +2. Click **Add custom network** at the bottom of the modal +3. Configure the network with these settings: -These are automatically included when using the evmd example genesis via `evmtypes.DefaultPreinstalls`. +| Setting | Value | +|---------|-------| +| **Network Name** | Cosmos EVM Local | +| **RPC URL** | `http://localhost:8545` | +| **Chain ID** | `262144` | +| **Currency Symbol** | `TEST` | +| **Block Explorer URL** | (leave empty for local) | - + +Make sure your local chain is running before adding the network. The RPC URL must be accessible from your browser. + + - - -```go - // In evmd/genesis.go + +After adding the network: +- Switch to the "Cosmos EVM Local" network in MetaMask +- You should see your account balance (if the test account was funded in genesis) +- You can now interact with the chain through MetaMask + + - func NewEVMGenesisState() *evmtypes.GenesisState { - evmGenState := evmtypes.DefaultGenesisState() - evmGenState.Preinstalls = evmtypes.DefaultPreinstalls // Includes all default contracts - return evmGenState +### Recommended Reading - } -``` + + +Complete reference for all chain configuration options + - + +Production deployment and validator setup + - -```json - { - "app_state": { - "vm": { - "preinstalls": [ - { - "name": "MyCustomContract", - "address": "0x1234567890123456789012345678901234567890", - "code": "0x608060405234801561001057600080fd5b50..." // Contract bytecode - } - ] - } - } - } -``` + +EVM execution and parameter configuration + - - When adding custom predeployed contracts: - - Ensure the address doesn't conflict with existing contracts or precompile addresses (0x1-0x9FF reserved) - - Use standard addresses when possible (e.g., Create2 should always be at its standard address) - - Test thoroughly as these contracts are immutable after genesis - - Verify bytecode matches the source code you intend to deploy + +Available precompiled contracts and integration + + - - - - For detailed implementation guidance, see the [Predeployed Contracts Integration](/docs/evm/next/documentation/migrations/predeployed-contracts-integration) guide. - - - - - -```json - { - "app_state": { - "vm": { - "preinstalls": [] - } - } - } -``` - - - Removing default preinstalls may break ecosystem compatibility: - - Many tools and dApps expect Create2 at `0x4e59b44847b379578588920ca78fbf26c0b4956c` - - Multicall3 is expected at `0xcA11bde05977b3631167028862bE2a173976CA11` by most frontends - - Permit2 support is increasingly common in DeFi protocols - - - Safe Factory enables multisig wallet deployment - - Only disable preinstalls if you have a specific reason and understand the compatibility implications. - - - - - - -For detailed information about each predeployed contract and their functionality, see the [Predeployed Contracts Overview](/docs/evm/next/documentation/smart-contracts/predeployed-contracts/overview). - - -### Adding Custom Predeployed Contracts - -To add your own predeployed contracts at genesis: - - - - Compile your Solidity contract to get the deployment bytecode: -```bash - solc --bin MyContract.sol - - # Or with Hardhat - npx hardhat compile - -``` - - - -{" "} - - Select a deployment address that won't conflict: - Avoid precompile range - (0x0001-0x0FFF) - Check for ecosystem standards - Consider using Create2 for - - deterministic addresses - - - - Add the contract to your genesis configuration: -```go - // In your custom genesis.go - - var CustomPreinstalls = append(evmtypes.DefaultPreinstalls, evmtypes.Preinstall{ - Name: "MyContract", - Address: "0xYourChosenAddress", - Code: "0xDeploymentBytecode", - }) -``` - - - - - After chain initialization, verify the contract is deployed: -```bash - # Check contract code - - curl -X POST http://localhost:8545 \ - -H "Content-Type: application/json" \ - -d '{ - "jsonrpc": "2.0", - "method": "eth_getCode", - "params": ["0xYourChosenAddress", "latest"], - "id": 1 - }' -``` - - - - -### Fee Market Configuration - -The fee market module implements EIP-1559 dynamic fee pricing for your chain. Configure these parameters in the `feemarket` section of your genesis file. - -**File Location**: Genesis configuration in `~/.evmd/config/genesis.json` under `app_state.feemarket.params` -**Parameter Defaults**: [x/feemarket/types/params.go](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go) - - -For comprehensive Fee Market Module documentation including EIP-1559 algorithm details, monitoring, and governance, see the [Fee Market Module Documentation](/evm/next/documentation/cosmos-sdk/modules/feemarket). - - - - - - -**What It Does**: Disables EIP-1559 dynamic base fee mechanism. When `true`, the chain uses only `min_gas_price` as a fixed minimum fee. - -**Type**: `bool` - -**Valid Values**: -- `false` - Enable EIP-1559 with dynamic base fee (recommended) -- `true` - Disable EIP-1559, use fixed min_gas_price only - -**Default**: `false` (see [params.go:21](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L21)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "no_base_fee": false // Enable EIP-1559 - } - } -} - -``` - -**Impact**: -- When disabled (false), base fee adjusts dynamically based on block utilization -- When enabled (true), behaves like pre-EIP-1559 Ethereum with fixed minimum gas price - -- Disabling EIP-1559 simplifies fee structure but loses congestion-based pricing benefits - - - - - -**What It Does**: Sets the initial base fee per gas in wei. This is the starting point for EIP-1559 fee calculations. - -**Type**: `string` (decimal number representing wei) - -**Valid Values**: Any non-negative decimal value in wei - -**Common Values**: -- `"1000000000"` (1 gwei) - Standard starting point -- `"10000000000"` (10 gwei) - Higher initial fee for congested chains - -- `"100000000"` (0.1 gwei) - Lower initial fee for testing - -**Default**: `"1000000000"` (1 gwei, see [params.go:13](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L13)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "base_fee": "1000000000" // 1 gwei - } - } -} - -``` - -**Impact**: -- Sets floor for transaction fees at launch -- Adjusts up/down based on block fullness after enable_height - -- Should align with expected network usage and token economics - -**Validation**: Must be non-negative (see [params.go:66-68](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L66-L68)) - - - - - -**What It Does**: Controls how quickly the base fee can change per block. Higher values = slower adjustment. - -**Type**: `uint32` - -**Valid Values**: Any positive integer (cannot be 0) - -**Common Values**: -- `8` - Standard EIP-1559 (max ±12.5% per block) -- `50` - Slower adjustment (max ±2% per block) -- `4` - Faster adjustment (max ±25% per block) - -**Default**: `8` (standard EIP-1559) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "base_fee_change_denominator": 8 // Max 12.5% change per block - } - } -} - -``` - -**Impact**: -- Formula: `max_change = base_fee / denominator` -- Higher denominator = more stable fees, slower response to congestion -- Lower denominator = more volatile fees, faster response to congestion - -- Standard Ethereum uses 8 for balanced responsiveness - -**Validation**: Cannot be 0 (see [params.go:62-64](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L62-L64)) - - - - - -**What It Does**: Defines maximum block gas limit as a multiple of target gas. Allows blocks to temporarily exceed target during high demand. - -**Type**: `uint32` - -**Valid Values**: Any positive integer (cannot be 0) - -**Common Values**: -- `2` - Standard EIP-1559 (block can be 2x target) -- `3` - More elastic (block can be 3x target) -- `1` - No elasticity (block limited to target) - -**Default**: `2` (standard EIP-1559) - -**Configuration**: -```json -{ - "feemarket": { - "params": { - "elasticity_multiplier": 2 // Block gas limit = 2 × target gas - } - } -} - -``` - -**Impact**: -- Higher multiplier allows larger temporary throughput spikes -- Block gas limit = target_gas × elasticity_multiplier - -- When blocks exceed target, base fee increases; when below target, base fee decreases -- Standard Ethereum uses 2 for balanced elasticity - - -**Validation**: Cannot be 0 (see [params.go:74-76](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L74-L76)) - - - - - -**What It Does**: Block height at which EIP-1559 base fee mechanism activates. Useful for coordinated mainnet upgrades. - -**Type**: `int64` - -**Valid Values**: Any non-negative integer - -**Common Values**: -- `0` - Enable from genesis (recommended for new chains) -- `100000` - Enable at specific future height for coordinated activation - -**Default**: `0` (enabled from genesis, see [params.go:19](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L19)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "enable_height": 0 // Enable from genesis - } - } -} - -``` - -**Impact**: -- Before this height, base fee mechanism is inactive -- After this height, base fee adjusts dynamically - -- Allows chains to launch with fixed fees then upgrade to dynamic pricing - -**Validation**: Cannot be negative (see [params.go:70-72](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L70-L72)) - - - - - -**What It Does**: Sets a global minimum gas price floor in native token decimals. Provides absolute minimum fee even if base fee drops lower. - -**Type**: `string` (decimal value) - -**Valid Values**: Any non-negative decimal value - -**Common Values**: -- `"0"` - No minimum floor (rely on base fee only) -- `"1000000000"` - 1 gwei minimum floor -- `"10000000000"` - 10 gwei minimum floor - - -**Default**: `"0"` (disabled, see [params.go:17](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L17)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "min_gas_price": "0" // No minimum floor - } - } -} - -``` - -**Impact**: -- When base fee < min_gas_price, min_gas_price is used instead -- Prevents fee races to zero during low usage periods - -- Often set to 0 to rely purely on EIP-1559 dynamics - -**Validation**: Must be non-negative (see [params.go:89-98](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L89-L98)) - - - - - -**What It Does**: Fraction of base fee to use as the effective minimum gas price. Alternative to fixed min_gas_price. - -**Type**: `string` (decimal value between 0 and 1) - -**Valid Values**: Decimal between `0` and `1` (inclusive) - -**Common Values**: -- `"0.5"` - Minimum is 50% of base fee -- `"0.8"` - Minimum is 80% of base fee - -- `"0"` - No multiplier-based minimum - -**Default**: `"0.5"` (50%, see [params.go:15](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L15)) - -**Configuration**: -```json -{ - "feemarket": { - "params": { - "min_gas_multiplier": "0.5" // Min = 50% of base fee - } - } -} - -``` - -**Impact**: -- Creates dynamic minimum that scales with base fee -- Effective minimum = max(min_gas_price, base_fee × min_gas_multiplier) -- Prevents accepting transactions far below current base fee - -**Validation**: Must be between 0 and 1 inclusive (see [params.go:101-114](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L101-L114)) - - - - - -**Complete Configuration Example**: - - -```json EIP-1559 Enabled (Recommended) -{ - "feemarket": { - "params": { - "no_base_fee": false, - "base_fee": "1000000000", // 1 gwei starting base fee - "base_fee_change_denominator": 8, // Standard EIP-1559 adjustment - - "elasticity_multiplier": 2, // Standard EIP-1559 elasticity - "enable_height": 0, // Enable from genesis - - "min_gas_price": "0", // No fixed floor - "min_gas_multiplier": "0.5" // 50% of base fee minimum - - } - } -} - -``` - -```json Simple Fixed Fee -{ - "feemarket": { - "params": { - "no_base_fee": true, // Disable EIP-1559 - "min_gas_price": "1000000000", // Fixed 1 gwei minimum - - "min_gas_multiplier": "0" // No multiplier needed - } - } -} - -``` - -```json High Stability Configuration -{ - "feemarket": { - "params": { - "no_base_fee": false, - "base_fee": "10000000000", // 10 gwei start - "base_fee_change_denominator": 50, // Slow adjustment (±2%/block) - "elasticity_multiplier": 3, // More elastic blocks - "enable_height": 0, - "min_gas_price": "5000000000", // 5 gwei absolute floor - "min_gas_multiplier": "0.8" // 80% of base fee minimum - - } - } -} - -``` - - - -### Ethereum Fork Configuration - -The `chain_config` defines which Ethereum hard fork features are active on your chain. This controls EVM opcode availability and gas costs. - -**File Location**: Genesis configuration in `~/.evmd/config/genesis.json` under `app_state.vm.chain_config` -**Parameter Defaults**: [x/vm/types/chain_config.go:57-108](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L57-L108) - - -**Default Behavior**: All Ethereum forks through Prague are enabled at genesis (block/timestamp 0). This gives you full Ethereum compatibility out-of-the-box. - -**When to Customize**: Only modify fork activations if you need to: -- Delay fork activation for coordinated network upgrade -- Disable specific opcodes for security/compatibility reasons - -- Match fork schedule of a specific Ethereum network - -For most chains, the defaults are appropriate. - - - - - - -**Block-Based Forks** (Pre-Merge): -Forks activate when block height reaches specified value. Used for all forks before The Merge. - -**Time-Based Forks** (Post-Merge): -Forks activate when block timestamp reaches specified Unix timestamp. Used for Shanghai, Cancun, Prague, and future forks. - -**Configuration Format**: -```json -{ - "vm": { - "chain_config": { - "homestead_block": "0", // Block-based (string int) - "shanghai_time": "0", // Time-based (string Unix timestamp) - "osaka_time": null // Not activated (null or negative) - } - } -} - -``` - - - - - -These forks are enabled at genesis by default ([chain_config.go:62-103](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L62-L103)): - -**Block-Based Forks** (all at block 0): -| Fork | Block Parameter | Key Changes | -||-|-| -| **Homestead** | `homestead_block` | Basic contract functionality | -| **DAO Fork** | `dao_fork_block` | DAO rescue (support enabled) | -| **EIP-150** | `eip150_block` | Gas cost changes for I/O operations | -| **EIP-155** | `eip155_block` | Replay protection (simple signing) | -| **EIP-158** | `eip158_block` | State clearing, account cleanup | -| **Byzantium** | `byzantium_block` | REVERT opcode, STATICCALL | -| **Constantinople** | `constantinople_block` | Bitwise shifting, CREATE2 | -| **Petersburg** | `petersburg_block` | Constantinople fix | -| **Istanbul** | `istanbul_block` | ChainID opcode, cheaper gas | -| **MuirGlacier** | `muir_glacier_block` | Difficulty bomb delay | -| **Berlin** | `berlin_block` | BASEFEE opcode, access lists | -| **London** | `london_block` | EIP-1559 fee market | -| **ArrowGlacier** | `arrow_glacier_block` | Difficulty bomb delay | -| **GrayGlacier** | `gray_glacier_block` | Difficulty bomb delay | -| **MergeNetsplit** | `merge_netsplit_block` | Merge transition marker | - -**Time-Based Forks** (all at timestamp 0): -| Fork | Time Parameter | Key Changes | -|||-| -| **Shanghai** | `shanghai_time` | PUSH0 opcode, warm COINBASE | -| **Cancun** | `cancun_time` | Transient storage (TSTORE/TLOAD), blob transactions, EIP-2935 block hash history | -| **Prague** | `prague_time` | EIP-7702 account abstraction, updated blob config | - - - - - -These forks are not yet activated by default and are set to `nil` ([chain_config.go:104-105](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L104-L105)): - -| Fork | Parameter | Status | -||--|--| -| **Osaka** | `osaka_time` | Future Ethereum fork (not finalized) | -| **Verkle** | `verkle_time` | Verkle tree state transition (research) | - -**To Activate Future Fork**: - -```json -{ - "vm": { - "chain_config": { - "osaka_time": "1700000000" // Unix timestamp when fork activates - } - } -} - -``` - - - - - -**Delay Fork Activation**: -```json -{ - "vm": { - "chain_config": { - "chain_id": "262144", - "homestead_block": "0", - "london_block": "0", - "shanghai_time": "1704067200", // Activate Shanghai at specific time - "cancun_time": "1710000000", // Activate Cancun later - - "prague_time": null // Don't activate Prague yet - } - } -} - -``` - -**Disable Specific Fork** (not recommended): - -```json -{ - "vm": { - "chain_config": { - "istanbul_block": null, // Skip Istanbul features - "berlin_block": "1000000" // Activate Berlin at block 1M - - } - } -} - -``` - -**Validation**: -- Forks must activate in chronological order (see [chain_config.go:190](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L190)) -- Block/timestamp values cannot be negative (see [chain_config.go:196-209](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L196-L209)) -- `nil` or negative values disable the fork - - - - - -**dao_fork_support**: -- **Type**: `bool` -- **Default**: `true` -- **Purpose**: Whether to support the DAO rescue fork (historical Ethereum event) -- **Recommendation**: Leave as `true` for Ethereum compatibility - -**denom** and **decimals** (Deprecated): -- These fields in chain_config are deprecated -- Use `vm.params.evm_denom` and bank metadata instead - -- Present for backward compatibility only - - - - - -**Complete Configuration Example**: - - -```json Default (All Forks Enabled) -{ - "vm": { - "chain_config": { - "chain_id": "262144", - "denom": "", - "decimals": "0", - "homestead_block": "0", - "dao_fork_block": "0", - "dao_fork_support": true, - "eip150_block": "0", - "eip155_block": "0", - "eip158_block": "0", - "byzantium_block": "0", - "constantinople_block": "0", - "petersburg_block": "0", - "istanbul_block": "0", - "muir_glacier_block": "0", - "berlin_block": "0", - "london_block": "0", - "arrow_glacier_block": "0", - "gray_glacier_block": "0", - "merge_netsplit_block": "0", - "shanghai_time": "0", - "cancun_time": "0", - "prague_time": "0", - "osaka_time": null, - "verkle_time": null - } - } -} - -``` - -```json Staged Fork Rollout -{ - "vm": { - "chain_config": { - "chain_id": "262144", - "homestead_block": "0", - "dao_fork_block": "0", - "dao_fork_support": true, - "eip150_block": "0", - "eip155_block": "0", - "eip158_block": "0", - "byzantium_block": "0", - "constantinople_block": "0", - "petersburg_block": "0", - "istanbul_block": "0", - "muir_glacier_block": "0", - "berlin_block": "0", - "london_block": "0", - "arrow_glacier_block": "0", - "gray_glacier_block": "0", - "merge_netsplit_block": "0", - "shanghai_time": "0", - "cancun_time": "1735689600", // Jan 1, 2025 - "prague_time": "1767225600", // Jan 1, 2026 - - "osaka_time": null, - "verkle_time": null - } - } -} - -``` - - - -### Standard Cosmos Modules - -Configure standard Cosmos SDK modules that provide staking, governance, token inflation, and fee distribution functionality. - -**File Location**: Genesis configuration in `~/.evmd/config/genesis.json` under `app_state..params` -**Documentation**: [Cosmos SDK Modules](https://docs.cosmos.network/main/build/modules) - - - - - -The staking module handles validator delegation, undelegation, and slashing parameters. - -**Genesis Path**: `app_state.staking.params` -**Module Docs**: [x/staking](https://docs.cosmos.network/main/build/modules/staking) - -**Parameters**: - -**unbonding_time**: -- **What It Does**: Time required for tokens to fully undelegate before being withdrawable -- **Type**: `string` (duration with suffix like "s" for seconds) -- **Valid Values**: Any positive duration (typically days) -- **Common Values**: - - `"1814400s"` - 21 days (Cosmos Hub standard) - - `"604800s"` - 7 days (faster for testnets) - - `"2592000s"` - 30 days (longer security period) -- **Impact**: Longer unbonding time = more security but less liquidity for delegators -- **Recommendation**: 21 days is industry standard for mainnets - - -**max_validators**: -- **What It Does**: Maximum number of active validators in the consensus set -- **Type**: `uint32` -- **Valid Values**: Any positive integer (typically 50-300) -- **Common Values**: - - `100` - Balanced decentralization - - `175` - Cosmos Hub active set - - - `50` - Smaller chains or testnets -- **Impact**: More validators = more decentralization but higher overhead - -- **Consideration**: Must balance security, performance, and decentralization - -**max_entries**: -- **What It Does**: Maximum simultaneous unbonding/redelegation entries per delegator-validator pair -- **Type**: `uint32` -- **Valid Values**: Typically 5-10 -- **Default**: `7` (Cosmos SDK standard) -- **Impact**: Limits how many concurrent unbonding operations a user can have -- **Recommendation**: Use default unless you have specific UX requirements - - -**bond_denom**: -- **What It Does**: The denomination used for staking (bonding) to validators -- **Type**: `string` -- **Valid Values**: Must match a denomination from bank metadata -- **Critical**: **MUST match your base denom** (e.g., `atest` for 18 decimals, `ustake` for 6 decimals) -- **Impact**: This is the token validators stake and delegators delegate -- **Example**: If your base denom is `atest`, set `"bond_denom": "atest"` - -**Configuration Example**: -```json -{ - "staking": { - "params": { - "unbonding_time": "1814400s", // 21 days - "max_validators": 100, // 100 active validators - - "max_entries": 7, // 7 concurrent unbondings - "bond_denom": "atest", // Must match your base denom - - "historical_entries": 10000, // Historical entries for IBC - "min_commission_rate": "0.050000000000000000" // 5% minimum commission - - } - } -} - -``` - - - - - -The governance module enables on-chain parameter changes and community proposals. - -**Genesis Path**: `app_state.gov.params` -**Module Docs**: [x/gov](https://docs.cosmos.network/main/build/modules/governance) - -**Parameters**: - -**min_deposit**: -- **What It Does**: Minimum deposit required for a proposal to enter voting period -- **Type**: Array of coin objects `[{"denom": "string", "amount": "string"}]` -- **Valid Values**: Any amount in base denomination -- **Common Values**: - - `[{"denom": "ustake", "amount": "10000000"}]` - 10 tokens (6 decimals) - - `[{"denom": "atest", "amount": "10000000000000000000"}]` - 10 tokens (18 decimals) -- **Impact**: Higher deposit = spam protection, but may limit community participation -- **Must Match**: Denom must match your bond_denom - - -**expedited_min_deposit**: -- **What It Does**: Higher deposit for expedited proposals (faster voting) -- **Type**: Array of coin objects -- **Typical**: 4-5x the standard min_deposit - -- **Example**: `[{"denom": "atest", "amount": "50000000000000000000"}]` - 50 tokens - -**max_deposit_period**: -- **What It Does**: Time window for reaching min_deposit before proposal is rejected -- **Type**: `string` (duration) -- **Common Values**: - - `"172800s"` - 2 days (Cosmos Hub) - - `"604800s"` - 7 days (longer window) -- **Impact**: Longer period gives more time to crowdfund deposits - -**voting_period**: -- **What It Does**: Duration of voting once proposal enters voting period -- **Type**: `string` (duration) -- **Common Values**: - - `"172800s"` - 2 days (fast decisions) - - `"1209600s"` - 14 days (Cosmos Hub) -- **Impact**: Longer period ensures participation, shorter enables faster upgrades -- **Recommendation**: 7-14 days for mainnet, 1-2 days for testnets - - -**expedited_voting_period**: -- **What It Does**: Faster voting period for expedited proposals -- **Type**: `string` (duration) -- **Typical**: 1/7th of normal voting_period -- **Example**: `"86400s"` - 24 hours - - -**quorum**: -- **What It Does**: Minimum percentage of bonded tokens that must vote -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.334000000000000000"` - 33.4% (Cosmos Hub) - - `"0.400000000000000000"` - 40% (higher participation requirement) -- **Impact**: Higher quorum = harder to pass proposals but more representative - -**threshold**: -- **What It Does**: Minimum percentage of Yes votes (excluding abstain) to pass -- **Type**: `string` (decimal between 0 and 1) -- **Standard**: `"0.500000000000000000"` - 50% majority - -**veto_threshold**: -- **What It Does**: Percentage of NoWithVeto votes needed to veto (and burn deposits) -- **Type**: `string` (decimal between 0 and 1) -- **Standard**: `"0.334000000000000000"` - 33.4% -- **Impact**: Protects against malicious proposals - -**Configuration Example**: -```json -{ - "gov": { - "params": { - "min_deposit": [{"denom": "atest", "amount": "10000000000000000000"}], - "expedited_min_deposit": [{"denom": "atest", "amount": "50000000000000000000"}], - "max_deposit_period": "172800s", // 2 days - "voting_period": "1209600s", // 14 days - - "expedited_voting_period": "86400s", // 1 day - "quorum": "0.334000000000000000", // 33.4% - "threshold": "0.500000000000000000", // 50% - "expedited_threshold": "0.667000000000000000", // 66.7% for expedited - "veto_threshold": "0.334000000000000000", // 33.4% - "min_initial_deposit_ratio": "0.200000000000000000", // 20% initial deposit - "burn_vote_quorum": false, - "burn_proposal_deposit_prevote": false, - "burn_vote_veto": true // Burn deposits on veto - } - } -} - -``` - - - - - -The mint module controls token inflation and block reward minting. - -**Genesis Path**: `app_state.mint.minter` and `app_state.mint.params` -**Module Docs**: [x/mint](https://docs.cosmos.network/main/build/modules/mint) - -**Minter State**: - -**inflation**: -- **What It Does**: Current inflation rate (changes dynamically based on bonded ratio) -- **Type**: `string` (decimal between 0 and 1) -- **Initial Value**: Typically set to your starting inflation rate -- **Example**: `"0.130000000000000000"` - 13% annual inflation - - -**annual_provisions**: -- **What It Does**: Auto-calculated based on total supply and inflation -- **Type**: `string` (decimal) -- **Genesis Value**: `"0.000000000000000000"` - will be calculated after chain starts -- **Note**: This value is computed automatically, don't need to set manually - - -**Parameters**: - -**mint_denom**: -- **What It Does**: Denomination of tokens to mint as block rewards -- **Type**: `string` -- **Critical**: **MUST match your bond_denom** (same as staking module) -- **Example**: `"atest"` for 18 decimals, `"ustake"` for 6 decimals - -**inflation_rate_change**: -- **What It Does**: Maximum annual change in inflation rate -- **Type**: `string` (decimal) -- **Common Values**: - - `"0.130000000000000000"` - 13% max change (Cosmos Hub) - - `"0.200000000000000000"` - 20% faster adjustment -- **Impact**: Higher value = inflation adjusts faster to meet goal_bonded target - - -**inflation_max**: -- **What It Does**: Maximum annual inflation rate ceiling -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.200000000000000000"` - 20% maximum (Cosmos Hub) - - `"0.100000000000000000"` - 10% for lower inflation chains -- **Impact**: Caps maximum inflation regardless of bonded ratio - - -**inflation_min**: -- **What It Does**: Minimum annual inflation rate floor -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.070000000000000000"` - 7% minimum (Cosmos Hub) - - `"0.000000000000000000"` - 0% for no minimum -- **Impact**: Ensures minimum block rewards even at high bonded ratios - - -**goal_bonded**: -- **What It Does**: Target percentage of tokens that should be bonded (staked) -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.670000000000000000"` - 67% target (Cosmos Hub) - - `"0.500000000000000000"` - 50% for more liquid chains -- **How It Works**: - - If bonded ratio < goal: inflation increases (incentivize staking) - - If bonded ratio > goal: inflation decreases (reduce selling pressure) - -**blocks_per_year**: -- **What It Does**: Expected number of blocks per year (for inflation calculation) -- **Type**: `uint64` -- **Calculation**: `(365.25 * 24 * 60 * 60) / block_time_seconds` -- **Common Values**: - - `6311520` - For ~5 second blocks - - `3155760` - For ~10 second blocks - -- **Note**: Adjust based on your actual block time - -**Configuration Example**: -```json -{ - "mint": { - "minter": { - "inflation": "0.130000000000000000", // Starting at 13% - "annual_provisions": "0.000000000000000000" // Auto-calculated - }, - "params": { - "mint_denom": "atest", // Must match bond_denom - "inflation_rate_change": "0.130000000000000000", // 13% max change/year - - "inflation_max": "0.200000000000000000", // 20% ceiling - "inflation_min": "0.070000000000000000", // 7% floor - - "goal_bonded": "0.670000000000000000", // 67% target bonded - "blocks_per_year": "6311520" // ~5 second blocks - - } - } -} - -``` - - - - - -The distribution module manages fee distribution to validators, delegators, and community pool. - -**Genesis Path**: `app_state.distribution.params` -**Module Docs**: [x/distribution](https://docs.cosmos.network/main/build/modules/distribution) - -**Parameters**: - -**community_tax**: -- **What It Does**: Percentage of block rewards and fees sent to community pool -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.020000000000000000"` - 2% to community pool (Cosmos Hub) - - `"0.100000000000000000"` - 10% for chains with active governance - - `"0.000000000000000000"` - 0% to disable community pool funding - -- **Impact**: Funds governance-controlled treasury for ecosystem development -- **Remaining**: (100% - community_tax) goes to validators and delegators - - -**base_proposer_reward** (Deprecated): -- **Type**: `string` (decimal) -- **Standard**: `"0.000000000000000000"` - Set to 0 (deprecated in recent SDK versions) -- **Note**: Modern chains use only block rewards from mint module - -**bonus_proposer_reward** (Deprecated): -- **Type**: `string` (decimal) -- **Standard**: `"0.000000000000000000"` - Set to 0 (deprecated in recent SDK versions) -- **Note**: Proposer bonus now handled differently in consensus - -**withdraw_addr_enabled**: -- **What It Does**: Allow delegators to set a different address for reward withdrawal -- **Type**: `bool` -- **Common Values**: - - `true` - Allow reward forwarding (standard) - - `false` - Disable for security (rare) -- **Impact**: Enables features like auto-compounding services -- **Recommendation**: Leave `true` for flexibility - - -**Configuration Example**: -```json -{ - "distribution": { - "params": { - "community_tax": "0.020000000000000000", // 2% to community pool - "base_proposer_reward": "0.000000000000000000", // Deprecated - - "bonus_proposer_reward": "0.000000000000000000", // Deprecated - "withdraw_addr_enabled": true // Allow reward forwarding - - } - } -} - -``` - - - - - -**Token Denomination Consistency**: - - -**Critical Configuration Requirement**: The following denominations MUST all match: - -- `staking.params.bond_denom` - What validators stake -- `mint.params.mint_denom` - What gets minted as rewards - -- `gov.params.min_deposit[0].denom` - What's deposited for governance -- `bank.denom_metadata[0].base` - Base denomination in metadata - - -All four must use the same base denom (e.g., `atest` for 18 decimals or `ustake` for 6 decimals). - -See the [Token Configuration Guide](/docs/evm/next/documentation/getting-started/build-a-chain/token-configuration-guide) for complete details on setting up token economics. - -For detailed information about the ERC20 module that handles token representation between Cosmos and EVM, see the [ERC20 Module Documentation](/evm/next/documentation/cosmos-sdk/modules/erc20). - - -### Initial Token Distribution - -Add initial account balances in the `bank` section: - -```json -{ - "bank": { - "balances": [ - { - "address": "yourchain1...", - "coins": [ - { - "denom": "ustake", - "amount": "1000000000000" - } - ] - } - ] - } -} - -``` - -## Runtime Configuration (app.toml) - -The `app.toml` file contains node-specific settings that can be changed without affecting consensus. These are node-operator configurations that don't require network-wide coordination. - - -For complete `app.toml` configuration details, see the [Node Configuration Documentation](/docs/evm/next/documentation/getting-started/node-configuration). The sections below show key settings for chain builders. - - -### JSON-RPC Configuration - - -```toml -############################################################################### -### JSON-RPC Configuration ### -############################################################################### - -[json-rpc] - -# Enable JSON-RPC server - -enable = true - -# Address to bind the HTTP server - -address = "0.0.0.0:8545" - -# Address to bind WebSocket server - -ws-address = "0.0.0.0:8546" - -# API namespaces to enable - -# Available: web3, eth, personal, net, txpool, debug, miner - -api = ["eth", "net", "web3", "txpool"] - -# Gas cap for eth_call/estimateGas (0=default) - -gas-cap = 25000000 - -# Timeout for eth_call - -evm-timeout = "5s" - -# Transaction fee cap (in ether) - -txfee-cap = 1.0 - -# Maximum number of filters - -filter-cap = 200 - -# Maximum blocks for fee history - -feehistory-cap = 100 - -# Maximum logs per query - -logs-cap = 10000 - -# Maximum block range for eth_getLogs - -block-range-cap = 10000 - -# HTTP server timeouts - -http-timeout = "30s" -http-idle-timeout = "120s" - -# Allow non-EIP155 signed transactions - -allow-unprotected-txs = false - -# Batch request settings - -batch-request-limit = 1000 -batch-response-max-size = 25000000 - - -# Connection limit (0 = unlimited) - -max-open-connections = 0 - -# Enable custom indexer - -enable-indexer = false - -# Metrics server - -metrics-address = "127.0.0.1:6065" - -# WebSocket allowed origins - -ws-origins = ["localhost", "127.0.0.1"] - -# Dangerous: only for development - -allow-insecure-unlock = false -enable-profiling = false - - -```` - - -### EVM Configuration - -```toml -[evm] -# EVM tracer ("" | "json" | "struct" | "access_list" | "markdown") -tracer = "" - -# Maximum gas wanted for a transaction -max-tx-gas-wanted = 0 - - -# Track SHA3 preimages -cache-preimage = false - - -# Minimum priority fee (tip) in wei -min-tip = 1000000000 - - -# Geth metrics server -geth-metrics-address = "127.0.0.1:8100" -```` - -## Genesis Coordination for Multi-Validator Networks - -A production network requires multiple validators for decentralization and fault tolerance. The genesis coordinator must collect signed genesis transactions (gentx files) from each validator and combine them into the final genesis file. - - -For detailed validator setup instructions including key generation and operational security, please refer to the [Validator Nodes Guide](/docs/evm/next/documentation/getting-started/node-configuration#validator-nodes). - - -### Collecting Genesis Transactions from Validators - - - The genesis coordinator combines signed validator transactions but cannot - modify them without invalidating signatures. It's still good practice to: - - Verify the final genesis.json hash before starting your node - Ensure all - expected validators are included - Confirm token allocations match - - expectations - - - - - Validators send their genesis transactions to the coordinator: - - 1. Each validator shares their `gentx-*.json` file from `~/.yourchain/config/gentx/` - 2. Coordinator places all files in their `~/.yourchain/config/gentx/` directory - 3. Coordinator runs: - -```bash - yourchain genesis collect-gentxs - - yourchain genesis validate-genesis -``` - - - - - Use a repository for transparent coordination: - - 1. Create a genesis repository - 2. Validators submit PRs with their gentx files - - 3. Verify validator identities before merging - 4. Generate final genesis from collected transactions - - - - - - For larger networks, use automation: - -```bash - # Example script for collecting via HTTP - - for validator in "${VALIDATORS[@]}"; do - curl -O "https://${validator}/gentx.json" - mv gentx.json ~/.yourchain/config/gentx/gentx-${validator}.json - done - - - yourchain genesis collect-gentxs -``` - - - - -### Distributing the Final Genesis - -Once the genesis file is complete with all validator transactions: - -1. **Calculate genesis hash** for verification: - -```bash - sha256sum ~/.yourchain/config/genesis.json - -``` - -2. **Distribute to all validators** who replace their local genesis: - -```bash - # Each validator downloads and verifies - - curl -O https://genesis.yourchain.com/genesis.json - sha256sum genesis.json # Verify hash matches - - mv genesis.json ~/.yourchain/config/ -``` - -3. **Share peer information** for network discovery: -```bash - # Get node ID and IP - - yourchain tendermint show-node-id - # Share: nodeID@IP:26656 - -``` - -## Starting the Network - -### Coordinated Network Launch - - - - Each validator adds peers to `config.toml`: - -```toml - # Persistent peers - - persistent_peers = "nodeID1@IP1:26656,nodeID2@IP2:26656,..." - - # Recommended settings for new networks - addr_book_strict = false - - max_num_inbound_peers = 100 - max_num_outbound_peers = 100 - -``` - - - - - Coordinate the genesis time (usually set in genesis.json): - -```json - { - "genesis_time": "2024-01-15T15:00:00Z" - } -``` - - All genesis validators must start their nodes before this time: - -```bash - # For validators (no RPC exposed) - yourchain start \ - --minimum-gas-prices 0.025ustake \ - --log_level info - - # For RPC nodes (separate from validators) - yourchain start \ - --minimum-gas-prices 0.025ustake \ - --json-rpc.enable \ - --json-rpc.api eth,net,web3,txpool \ - --evm.tracer "" \ - --log_level info -``` - - - - -### Monitoring Network Health - -After launch, monitor these critical metrics: - - - -```bash - # Check latest block - - yourchain status | jq .sync_info - - # Monitor block time - yourchain query block | jq .block.header.time - -``` - - - - -```bash - # Check consensus state - - yourchain status | jq .sync_info.catching_up - - # View active validator count - yourchain query staking validators --output json | jq '.validators | length' -``` - - - - -```bash - # Check connected peers - - yourchain status | jq .node_info.network - - # Monitor peer count - curl http://localhost:26657/net_info | jq '.result.n_peers' -``` - - - - -## Post-Launch Operations - -### Governance Parameter Updates - -Most parameters can be modified through governance after launch: - - -```json param-change-proposal.json -{ - "title": "Update EVM Parameters", - "description": "Enable additional precompiles", - "changes": [ - { - "subspace": "vm", - "key": "ActiveStaticPrecompiles", - "value": ["0x0000000000000000000000000000000000000800", "0x0000000000000000000000000000000000000805"] - } - ], - "deposit": "10000000ustake" -} - -``` - -```bash submit-proposal.sh -yourchain tx gov submit-proposal param-change proposal.json \ - --from validator \ - --chain-id yourchain-1 \ - --keyring-backend file -``` - - - -### Software Upgrades - -For breaking changes requiring new binary versions: - - -**1. Implement upgrade handler** in `yourchain/upgrades.go`: -```go -const UpgradeName = "v1.0.0-to-v2.0.0" - -func (app EVMD) RegisterUpgradeHandlers() { -app.UpgradeKeeper.SetUpgradeHandler( -UpgradeName, -func(ctx context.Context, \_ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { -sdkCtx := sdk.UnwrapSDKContext(ctx) - - // Perform any state migrations here - // For example, setting bank metadata for token configuration: - app.BankKeeper.SetDenomMetaData(ctx, banktypes.Metadata{ - DenomUnits: []*banktypes.DenomUnit{ - {Denom: "ustake", Exponent: 0}, - {Denom: "stake", Exponent: 6}, - }, - Base: "ustake", - Display: "stake", - }) - - // For non-18 decimal chains, set extended denom - if decimals != 18 { - evmParams := app.EVMKeeper.GetParams(sdkCtx) - evmParams.ExtendedDenomOptions = &types.ExtendedDenomOptions{ - ExtendedDenom: "astake", - } - app.EVMKeeper.SetParams(sdkCtx, evmParams) - } - - return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) - }, - ) - -} - -```` - -**2. Propose upgrade** via governance: -```bash -yourchain tx gov submit-proposal software-upgrade v1.0.0-to-v2.0.0 \ - --title "Upgrade to v2.0.0" \ - --description "Upgrade with new features" \ - --upgrade-height 1000000 \ - --from validator \ - --chain-id yourchain-1 -```` - -**3. Validators prepare** by installing new binary before upgrade height - -**4. Automatic upgrade** at specified height using Cosmovisor or manual restart - - - -## Advanced Customization - -### Module Architecture Decisions - - -The choice between standard bank and precisebank depends on your tokens decimal precision: - -**Standard Bank Module (DEFAULT - 18-decimal chains):** - -```go -// Module initialization order in app.go - -genesisModuleOrder := []string{ - authtypes.ModuleName, - banktypes.ModuleName, - distrtypes.ModuleName, - stakingtypes.ModuleName, - slashingtypes.ModuleName, - govtypes.ModuleName, - minttypes.ModuleName, - ibcexported.ModuleName, - evmtypes.ModuleName, - feemarkettypes.ModuleName, - erc20types.ModuleName, - // No precisebank needed for 18-decimal chains - ibctransfertypes.ModuleName, - genutiltypes.ModuleName, - evidencetypes.ModuleName, - authz.ModuleName, - feegrant.ModuleName, - upgradetypes.ModuleName, - vestingtypes.ModuleName, -} - -// EVM keeper initialization (using standard bank) -app.EVMKeeper = evmkeeper.NewKeeper( - appCodec, - keys[evmtypes.StoreKey], - tkeys[evmtypes.TransientKey], - keys, - authtypes.NewModuleAddress(govtypes.ModuleName), - app.AccountKeeper, - app.BankKeeper, // Use standard bank keeper directly - app.StakingKeeper, - app.FeeMarketKeeper, - &app.ConsensusParamsKeeper, - &app.Erc20Keeper, - evmChainID, - tracer, -) - -``` - -**Precisebank Module (OPTIONAL - for non-18 decimal chains):** - -```go -// Module initialization order with precisebank - -genesisModuleOrder := []string{ - authtypes.ModuleName, - banktypes.ModuleName, - distrtypes.ModuleName, - stakingtypes.ModuleName, - slashingtypes.ModuleName, - govtypes.ModuleName, - minttypes.ModuleName, - ibcexported.ModuleName, - evmtypes.ModuleName, - feemarkettypes.ModuleName, - erc20types.ModuleName, - precisebanktypes.ModuleName, // Added for non-18 decimal chains - ibctransfertypes.ModuleName, - // ... rest of modules -} - -// Precisebank wraps standard bank -app.PreciseBankKeeper = precisebankkeeper.NewKeeper( - appCodec, - keys[precisebanktypes.StoreKey], - app.BankKeeper, // Wraps standard bank keeper - app.AccountKeeper, -) - -// EVM keeper uses precisebank -app.EVMKeeper = evmkeeper.NewKeeper( - appCodec, - keys[evmtypes.StoreKey], - tkeys[evmtypes.TransientKey], - keys, - authtypes.NewModuleAddress(govtypes.ModuleName), - app.AccountKeeper, - app.PreciseBankKeeper, // Precisebank wrapper instead of bank directly - app.StakingKeeper, - app.FeeMarketKeeper, - &app.ConsensusParamsKeeper, - &app.Erc20Keeper, - evmChainID, - tracer, -) - -``` - -**Key Differences:** - -- **18-decimal (default)**: EVM interacts directly with bank module, simpler architecture -- **Non-18 decimal**: EVM interacts through precisebank wrapper to handle fractional amounts - -- **Genesis order**: When using precisebank, it must initialize after bank but before modules that use it -- **Keeper dependencies**: VM keeper takes different keeper type based on decimal configuration - - - - -### Custom Precompiles - - - Teams can implement custom precompiled contracts for chain-specific - functionality. - - -Create custom precompiles by: - -1. Implementing the precompile interface -2. Registering in the VM keeper - -3. Adding to available precompiles list -4. Enabling in genesis configuration - - -### Access Control Configurations - - - - Default - anyone can deploy and call contracts: -```json - { - "access_control": { - "create": { - "access_type": 0, // ACCESS_TYPE_PERMISSIONLESS - "access_control_list": [] - }, - "call": { - "access_type": 0, // ACCESS_TYPE_PERMISSIONLESS - "access_control_list": [] - } - } - } -``` - - - - - Only allowlisted addresses can deploy/call: -```json - { - "access_control": { - "create": { - "access_type": 2, // ACCESS_TYPE_PERMISSIONED - "access_control_list": ["0xallowed1", "0xallowed2"] - }, - "call": { - "access_type": 0, // Keep calls permissionless - "access_control_list": [] - } - } - } -``` - - - - - Block all contract deployment: -```json - { - "access_control": { - "create": { - "access_type": 1, // ACCESS_TYPE_RESTRICTED - blocks all - "access_control_list": [] // Ignored for restricted type - - }, - "call": { - "access_type": 0, // Keep calls permissionless - "access_control_list": [] - } - } - } -``` - - - - -## Best Practices and Recommendations - - - - - Enable only necessary precompiles to minimize attack surface - - Implement proper key management procedures - - - Regular security audits for custom modifications - - Monitor for unusual activity or governance proposals - - - Carefully review governance proposals before voting - - -{" "} - - - - Adjust block size and gas limits based on network capacity - - Configure appropriate peer connections for node operators - - - Monitor and adjust mempool settings (see [Mempool Integration](/evm/next/documentation/cosmos-sdk/modules/mempool-integration)) - - Consider pruning strategies for long-term sustainability - - Use appropriate storage solutions for node infrastructure - - - - - - Start with conservative parameters - - Gradually increase limits through governance - - - Encourage geographic and infrastructure diversity among network participants - - Implement monitoring and alerting systems - - - Plan for emergency response procedures - - Document upgrade procedures clearly - - - - -## Conclusion - -Building a custom chain with Cosmos EVM provides the flexibility to create an application-specific blockchain with full EVM compatibility. The modular architecture allows you to enable only the features you need while maintaining the security and decentralization of the Cosmos ecosystem. - -### Next Steps - -After completing this guide, you should have: -- ✓ Forked and renamed the Cosmos EVM reference implementation -- ✓ Configured your chain's identity (Bech32 prefix, BIP44 coin type, Chain IDs) -- ✓ Set up token economics (decimals, denoms, extended denom options) -- ✓ Configured all genesis parameters (VM, Fee Market, Precompiles, Cosmos modules) -- ✓ Set up runtime configuration (app.toml) -- ✓ Coordinated genesis with validators -- ✓ Launched your network - - -**Recommended Next Actions**: - -1. **Test Thoroughly**: Run a private testnet to verify all configurations before mainnet launch -2. **Review Module Docs**: Deep dive into module-specific documentation: - - [VM Module](/evm/next/documentation/cosmos-sdk/modules/vm) - Precompiles and EVM parameters - - [Fee Market Module](/evm/next/documentation/cosmos-sdk/modules/feemarket) - EIP-1559 tuning and monitoring - - - [ERC20 Module](/evm/next/documentation/cosmos-sdk/modules/erc20) - Token representation and IBC integration - - [PreciseBank Module](/evm/next/documentation/cosmos-sdk/modules/precisebank) - Fractional balance handling (if using non-18-decimal tokens) - - [Mempool Integration](/evm/next/documentation/cosmos-sdk/modules/mempool-integration) - Transaction prioritization - -3. **Set Up Infrastructure**: - - Configure monitoring and alerting systems - - Set up RPC nodes separate from validators (see [Node Configuration](/docs/evm/next/documentation/getting-started/node-configuration)) - - Implement backup and recovery procedures - -4. **Security Hardening**: - - Conduct security audits of any custom modifications - - Review access control configurations - - - Test upgrade procedures on testnet - -5. **Community Engagement**: - - Register your chain on [chainlist.org](https://chainlist.org) - - Update ecosystem documentation - - Engage with the Cosmos EVM community for support +--- +For additional support and community resources, visit the [Cosmos EVM GitHub repository](https://github.com/cosmos/evm) or join the Cosmos developer community. \ No newline at end of file diff --git a/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx.bak b/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx.bak deleted file mode 100644 index f9466487..00000000 --- a/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx.bak +++ /dev/null @@ -1,2430 +0,0 @@ ---- -title: "Build A Custom Chain" -description: "Create your own blockchain by forking and customizing the Cosmos EVM referece chain. Covers the entire process from initial fork to running network, including parameter configuration, genesis setup, and validator coordination." ---- - -## Understanding the Cosmos SDK Application Structure - - - Cosmos EVM is built on the Cosmos SDK, a modular framework for building - application-specific blockchains. Understanding this structure helps you - customize your chain effectively. - - -A Cosmos SDK application consists of several key components: - -- **App Module**: The core application logic (`evmd/app.go`) that composes various modules -- **Modules**: Functional units handling specific blockchain features (staking, governance, EVM, etc.) -- **Keeper**: Each module's state management and business logic handler -- **Genesis**: Initial state and configuration for each module -- **CLI Commands**: User interface for interacting with the chain - -The `evmd` directory contains the example chain implementation that you'll fork and customize for your own blockchain. - -## Forking and Initial Setup - - - -Begin by forking the Cosmos EVM repository and cloning your fork: - -```bash -git clone https://github.com/YOUR-ORG/YOUR-CHAIN.git -cd YOUR-CHAIN -``` - -The repository structure provides everything needed to build a custom chain. The `evmd` directory contains the example implementation you'll modify. - - - - -Replace `evmd` references throughout the codebase with your chain's name: - -```bash -# Rename the directory -mv evmd yourchain - -# Update imports and references -find . -type f -name "*.go" -exec sed -i 's/evmd/yourchain/g' {} \; -find . -type f -name "*.md" -exec sed -i 's/evmd/yourchain/g' {} \; -``` - -Update module paths in `go.mod` to reflect your repository. - - - - -Update application metadata in `yourchain/cmd/yourchain/cmd/root.go`: - -```go -// Update these constants -const ( - NodeDir = ".yourchain" // Change from ".evmd" -) - -// In initRootCmd() -rootCmd := &cobra.Command{ - Use: "yourchain", // Change from "evmd" - Short: "Your Chain Daemon", // Update description - Long: `Your custom blockchain built with Cosmos EVM`, // Update description -} -``` - -**Other files to update**: -- `Makefile` - Build targets and binary names -- `README.md` - Documentation and installation instructions -- `go.mod` - Module path to your repository -- `*.proto` files - Package names if creating custom modules - - - - -**Post-Fork Checklist**: -- [ ] Repository cloned and `evmd` directory renamed -- [ ] All Go imports updated to new module path -- [ ] go.mod updated with new module name -- [ ] Makefile updated with new binary name -- [ ] README and documentation updated -- [ ] Run `go mod tidy` to verify dependencies -- [ ] Test build with `make build` - - -## Core Configuration Parameters - - -Some parameters must be set before genesis and cannot be changed later without -significant migration effort. Choose carefully based on your requirements. - - - -**Quick Reference**: For a complete list of all configurable parameters with defaults and validation rules, see [Configuration Parameters](/docs/evm/next/documentation/getting-started/build-a-chain/configuration-parameters). - - - -**Configuration Workflow**: -1. **Pre-Genesis**: Configure these parameters in code (Bech32 prefix, BIP44 coin type) -2. **Initialize**: Run `yourchain init --chain-id ` to create initial genesis -3. **Customize Genesis**: Edit `~/.yourchain/config/genesis.json` with your parameters -4. **Runtime Config**: Configure `~/.yourchain/config/app.toml` for node operations -5. **Launch**: Start the chain with coordinated genesis - -This section covers step 1 (Pre-Genesis). See [Genesis Configuration](#genesis-configuration) for steps 2-3. - - -### Chain Identity Configuration - -These fundamental parameters define your chain's identity and must be configured before initialization. - - - -**File Location**: [`config/config.go`](https://github.com/cosmos/evm/blob/main/config/config.go#L62) - -**What It Does**: Defines the human-readable prefix for all addresses on your chain, used for account addresses, validator addresses, and consensus addresses. - -**Valid Values**: Any alphanumeric string (lowercase recommended). Common examples: -• `cosmos`, `osmosis`, `juno`, `noble`, `yourchain` - -**Configuration**: - -```go -const ( - // Bech32Prefix defines the Bech32 prefix for accounts - Bech32Prefix = "yourchain" // Line 62 - Change from "cosmos" - - // Generated prefixes (do not modify these) - Bech32PrefixAccAddr = Bech32Prefix // yourchain1... - Bech32PrefixAccPub = Bech32Prefix + sdk.PrefixPublic // yourchainpub1... - Bech32PrefixValAddr = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixOperator // yourchainvaloper1... - Bech32PrefixValPub = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixOperator + sdk.PrefixPublic // yourchainvaloperpub1... - Bech32PrefixConsAddr = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixConsensus // yourchainvalcons1... - Bech32PrefixConsPub = Bech32Prefix + sdk.PrefixValidator + sdk.PrefixConsensus + sdk.PrefixPublic // yourchainvalconspub1... -) -``` - -**Impact**: -• User account addresses: `yourchain1abc...` -• Validator addresses: `yourchainvaloper1abc...` -• Cannot be changed after genesis without breaking all addresses - - - - - **File Location**: [`crypto/hd/hdpath.go`](https://github.com/cosmos/evm/blob/main/crypto/hd/hdpath.go#L9) - -**What It Does**: Sets the BIP44 coin type for hierarchical deterministic wallet derivation. This affects how hardware wallets (Ledger, Trezor) and software wallets derive addresses from seed phrases. - -**Valid Values**: -• `60` - Ethereum coin type (default, EIP-84 compliant) - **Recommended for EVM compatibility** -• `118` - Cosmos coin type (for pure Cosmos chains) -• Custom registered coin type from [SLIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) - -**Configuration**: - -```go -var ( - // Bip44CoinType satisfies EIP84 for Ethereum compatibility - Bip44CoinType uint32 = 60 // Line 9 - Use 60 for EVM, 118 for Cosmos - - // BIP44HDPath is automatically set based on coin type - BIP44HDPath = ethaccounts.DefaultBaseDerivationPath.String() // m/44'/60'/0'/0 -) -``` - -**Impact**: -• Determines HD wallet derivation path -• Affects hardware wallet compatibility -• Must match user expectations (use 60 for EVM-focused chains) - - - - - **What It Does**: Your chain uses TWO different chain IDs for different purposes. - -**1. Cosmos Chain ID** (string format): -• **What**: Identifies your chain in the Cosmos ecosystem for IBC and governance -• **Format**: `{name}-{version}` (e.g., `osmosis-1`, `noble-1`, `yourchain-1`) -• **Where**: Set during initialization via CLI -• **Can Change**: Yes, through coordinated network upgrade - -```bash -yourchain init mynode --chain-id yourchain-1 -``` - -**2. EVM Chain ID** (uint64 number): -• **What**: EIP-155 replay protection for Ethereum transactions -• **Format**: Unsigned 64-bit integer (e.g., `262144`, `1`, `137`) -• **Where**: Set in genesis `vm.chain_config.chain_id` -• **Can Change**: No, changing breaks Ethereum transaction replay protection -• **Registry**: Register at [chainlist.org](https://chainlist.org) for public chains - -**Reserved EVM Chain IDs**: -• `1` - Ethereum Mainnet -• `137` - Polygon -• `262144` - Cosmos EVM default (testing only) -• `1-999` - Reserved by Ethereum Foundation - -**Recommendation**: Choose EVM Chain ID > 1000000 for production to avoid conflicts. - - - - -### Token Economics Configuration - - - **Default Configuration**: Cosmos EVM now uses 18 decimals by default with the - standard bank module. The precisebank module is only needed for chains using - non-18-decimal tokens (like 6 decimals). - - - -For chains using 6-decimal or other non-18-decimal tokens, you need to add the precisebank module to handle fractional amounts. - - -For comprehensive PreciseBank Module documentation including mathematical foundations, state management, and complete examples, see the [PreciseBank Module Documentation](/evm/next/documentation/cosmos-sdk/modules/precisebank). - - -**In `yourchain/app.go`:** - -```go -import ( - // Add precisebank imports - "github.com/cosmos/evm/x/precisebank" - precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" - precisebanktypes "github.com/cosmos/evm/x/precisebank/types" - - // Standard bank is already imported - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -// In app struct, add PreciseBankKeeper -type YourApp struct { - // ... other keepers - BankKeeper bankkeeper.Keeper - PreciseBankKeeper precisebankkeeper.Keeper // Add this line - EVMKeeper *evmkeeper.Keeper - // ... other keepers -} - -// In NewApp function: -// 1. Add precisebank store key -keys := storetypes.NewKVStoreKeys( - // ... other keys - evmtypes.StoreKey, - feemarkettypes.StoreKey, - erc20types.StoreKey, - precisebanktypes.StoreKey, // Add this line -) - -// 2. Initialize PreciseBankKeeper after BankKeeper -app.PreciseBankKeeper = precisebankkeeper.NewKeeper( - appCodec, - keys[precisebanktypes.StoreKey], - app.BankKeeper, - app.AccountKeeper, -) - -// 3. Update EVMKeeper to use PreciseBankKeeper instead of BankKeeper -app.EVMKeeper = evmkeeper.NewKeeper( - appCodec, - keys[evmtypes.StoreKey], - tkeys[evmtypes.TransientKey], - keys, - authtypes.NewModuleAddress(govtypes.ModuleName), - app.AccountKeeper, - app.PreciseBankKeeper, // Use PreciseBankKeeper instead of BankKeeper - app.StakingKeeper, - app.FeeMarketKeeper, - &app.ConsensusParamsKeeper, - &app.Erc20Keeper, - evmChainID, - tracer, -) - -// 4. Add precisebank to ModuleManager -app.ModuleManager = module.NewManager( - // ... other modules - precisebank.NewAppModule(app.PreciseBankKeeper, app.AccountKeeper), // Add this line - vm.NewAppModule(app.EVMKeeper, app.AccountKeeper, app.BankKeeper, app.AccountKeeper.AddressCodec()), - feemarket.NewAppModule(app.FeeMarketKeeper), - erc20.NewAppModule(app.Erc20Keeper, app.AccountKeeper), -) - -// 5. Add to genesis order (MUST be after bank and before vm) -genesisModuleOrder := []string{ - // ... other modules - banktypes.ModuleName, - precisebanktypes.ModuleName, // Add after bank, before vm - evmtypes.ModuleName, - feemarkettypes.ModuleName, - erc20types.ModuleName, - // ... rest -} -``` - -**Why precisebank is required for non-18-decimal tokens:** -• **6-decimal tokens**: Tracks fractional amounts in EVM (1 utoken = 10^12 wei) -• **12-decimal tokens**: Handles 10^6 wei conversions -• **Prevents dust**: Ensures no loss of fractional amounts during conversions -• **Wraps bank module**: Provides seamless integration while tracking remainders - -**If using 18 decimals (default):** -• No changes needed - standard bank module handles everything -• Direct 1:1 mapping between native token and EVM representation -• Simpler architecture without extra module complexity -• Any non-18: Prevents dust accumulation from precision differences - - - -Native token configuration is set in genesis through a combination of bank module metadata and VM parameters. The VM module reads this configuration during initialization and stores it as `EvmCoinInfo` in its state: - - -```json 6-decimal-token.json -{ - "bank": { - "denom_metadata": [ - { - "description": "The native staking token for evmd.", - "denom_units": [ - { - "denom": "utest", // Base denomination (6 decimals = micro prefix) - "exponent": 0, - "aliases": [] - }, - { - "denom": "test", // Display denomination - "exponent": 6, // 6 decimals from base - "aliases": [] - } - ], - "base": "utest", // Must match vm.params.evm_denom - "display": "test", // Human-readable name - "name": "Test Token", - "symbol": "TEST" - } - ] - }, - "evm": { - "params": { - "evm_denom": "utest", // References bank metadata base denom - "extended_denom_options": { - "extended_denom": "atest" // Required: 18-decimal representation for EVM - } - } - } -} -``` - -```json 18-decimal-token.json -{ - "bank": { - "denom_metadata": [ - { - "description": "The native staking token for evmd.", - "denom_units": [ - { - "denom": "atest", // Base denomination (18 decimals = atto prefix) - "exponent": 0, - "aliases": ["attotest"] - }, - { - "denom": "test", // Display denomination - "exponent": 18, // 18 decimals from base - "aliases": [] - } - ], - "base": "atest", // Base denom with 18 decimals - "display": "test", // Human-readable name - "name": "Test Token", - "symbol": "TEST" - } - ] - }, - "evm": { - "params": { - "evm_denom": "atest" // References bank metadata base denom - // No extended_denom_options needed for 18-decimal chains - } - } -} -``` - -```bash genesis-setup-example.sh -# Real example from local_node.sh showing how to configure genesis -# This sets up an 18-decimal token using jq commands - -# Set the base denom in all modules -jq '.app_state["staking"]["params"]["bond_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["gov"]["params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["mint"]["params"]["mint_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Set bank metadata (18 decimals) -jq '.app_state["bank"]["denom_metadata"]=[{"description":"The native staking token for evmd.","denom_units":[{"denom":"atest","exponent":0,"aliases":["attotest"]},{"denom":"test","exponent":18,"aliases":[]}],"base":"atest","display":"test","name":"Test Token","symbol":"TEST","uri":"","uri_hash":""}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Enable precompiles (see x/vm/types/precompiles.go for complete list) -jq '.app_state["vm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805","0x0000000000000000000000000000000000000806"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Set up ERC20 native token representation -# For details on ERC20 module configuration, see: -# /evm/next/documentation/cosmos-sdk/modules/erc20 -jq '.app_state.erc20.native_precompiles=["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state.erc20.token_pairs=[{contract_owner:1,erc20_address:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",denom:"atest",enabled:true}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -``` - - - -The VM module's `SetGlobalConfigVariables` function (called during PreBlock) reads this configuration and: - -1. Fetches bank metadata for the specified `evm_denom` -2. Extracts decimal precision from the denom units -3. Creates `EvmCoinInfo` with appropriate extended denom: - - For 18-decimal tokens: `extended_denom` = `evm_denom` (direct mapping) - - For non-18-decimal tokens: Uses `extended_denom_options.extended_denom` for EVM representation -4. Stores this configuration in VM keeper state via `SetEvmCoinInfo()` - - -**Decimal Precision Guidelines:** -• **18 decimals**: Direct EVM compatibility, uses standard bank module by default -• **6 decimals**: Common in Cosmos, requires adding precisebank for fractional amounts -• **Other values**: Test conversion logic thoroughly with precisebank - -**Module Selection Based on Decimals:** -• `decimals: 18` → Use standard `x/bank` module -• `decimals: 6` or other → Use `x/precisebank` wrapper around bank - - - -## Genesis Configuration - -After completing the pre-genesis configuration in code, initialize your chain to create the default genesis file: - -```bash -# Initialize your chain (creates ~/.yourchain/config/ directory) -yourchain init --chain-id yourchain-1 - -# This creates: -# - ~/.yourchain/config/genesis.json (chain parameters and initial state) -# - ~/.yourchain/config/app.toml (node runtime configuration) -# - ~/.yourchain/config/config.toml (CometBFT configuration) -# - ~/.yourchain/data/ (blockchain data directory) -``` - -The genesis file (`~/.yourchain/config/genesis.json`) contains all initial chain parameters and state. After initialization, customize these sections: - - -**Working Example**: The [`local_node.sh`](https://github.com/cosmos/evm/blob/main/local_node.sh#L234-L248) script in the Cosmos EVM repository shows a complete working example of genesis configuration using `jq` commands. Refer to this script for real-world configuration patterns. - - -### VM Module Parameters - -**File Location**: Genesis file at `~/.yourchain/config/genesis.json` under `app_state.vm.params` - -**Code Reference**: [`x/vm/types/params.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go) - - -For comprehensive VM Module documentation including all configuration methods, parameter details, and integration examples, see the [VM Module Documentation](/evm/next/documentation/cosmos-sdk/modules/vm). - - - - - - -**What It Does**: Specifies which bank module denomination to use as the native EVM token. - -**Type**: `string` - -**Valid Values**: Must match a base denomination from bank metadata (`app_state.bank.denom_metadata[].base`) - -**Examples**: -• `"atest"` - 18 decimal token -• `"utest"` - 6 decimal token -• `"ustake"` - 6 decimal token -• Any custom bank denom - -**Default**: `"uatom"` (see [`x/vm/types/params.go:21`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L21)) - -```json -"evm_denom": "ustake" -``` - - - -**What It Does**: Enables additional Ethereum Improvement Proposals beyond the default fork activations. - -**Type**: `[]int64` (array of EIP numbers) - -**Valid Values**: Only EIPs that are activatable in go-ethereum. Check available EIPs at runtime with `vm.ActivateableEips()` - -**Common EIPs**: -• `2200` - Net gas metering -• `2929` - Gas cost increases for state access opcodes -• `3198` - BASEFEE opcode -• `3529` - Reduction in refunds -• `3541` - Reject new contract code starting with 0xEF byte - -**Default**: `[]` (empty - all EIPs come from fork config) - -**Code Reference**: [`x/vm/types/params.go:182-200`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L182-L200) - -```json -"extra_eips": [2200, 2929] -``` - -**Validation**: Automatically checks if EIP is valid and not duplicate - - - -**What It Does**: Enables specific Cosmos module precompiles accessible from Solidity. - -**Type**: `[]string` (array of hex addresses) - -**Valid Values**: Must be from available precompile addresses (see [`x/vm/types/precompiles.go:4-15`](https://github.com/cosmos/evm/blob/main/x/vm/types/precompiles.go#L4-L15)) - -**Available Addresses**: -• `"0x0000000000000000000000000000000000000100"` - P256 cryptography -• `"0x0000000000000000000000000000000000000400"` - Bech32 conversion -• `"0x0000000000000000000000000000000000000800"` - Staking operations -• `"0x0000000000000000000000000000000000000801"` - Distribution/rewards -• `"0x0000000000000000000000000000000000000802"` - ICS20 (IBC transfers) -• `"0x0000000000000000000000000000000000000803"` - Vesting accounts -• `"0x0000000000000000000000000000000000000804"` - Bank transfers -• `"0x0000000000000000000000000000000000000805"` - Governance -• `"0x0000000000000000000000000000000000000806"` - Slashing info - -**Default**: `[]` (none enabled) - -```json -"active_static_precompiles": [ - "0x0000000000000000000000000000000000000100", - "0x0000000000000000000000000000000000000800" -] -``` - -**Security Note**: Only enable precompiles your chain needs to reduce attack surface - - - -**What It Does**: Lists IBC channel IDs that connect to other EVM-compatible chains (like Injective or Cronos) for special IBC token handling. - -**Type**: `[]string` (array of IBC channel identifiers) - -**Valid Values**: Valid IBC channel IDs (format: `channel-N` where N is a number) - -**Default**: `[]` (empty) - -```json -"evm_channels": ["channel-0", "channel-5"] -``` - -**Validation**: Checks IBC channel identifier format (see [`x/vm/types/params.go:80-96`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L80-L96)) - - - -**What It Does**: Controls who can deploy smart contracts (`create`) and call existing contracts (`call`). - -**Type**: Object with `create` and `call` fields - -**Access Types** (from [`x/vm/types/access_control.pb.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/access_control.pb.go)): -• `0` - `AccessTypePermissionless`: Anyone can perform the action -• `1` - `AccessTypeRestricted`: Block addresses in the list -• `2` - `AccessTypePermissioned`: Only addresses in the list allowed - -**Default**: `AccessTypePermissionless` for both - -```json -"access_control": { - "create": { - "access_type": 0, // 0=permissionless, 1=restricted, 2=permissioned - "access_control_list": [] // Hex addresses - }, - "call": { - "access_type": 0, - "access_control_list": [] - } -} -``` - -**Example - Permissioned Contract Deployment**: - -```json -"create": { - "access_type": 2, // Only allowlist can deploy - "access_control_list": [ - "0x1234567890123456789012345678901234567890", - "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" - ] -} -``` - -**Validation**: See [`x/vm/types/params.go:140-180`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L140-L180) - - - -**What It Does**: Number of historical blocks to keep for historical state queries (affects disk usage and query capabilities). - -**Type**: `uint64` (string in JSON) - -**Valid Values**: Any positive integer - -**Default**: `8192` (same as EIP-2935) - -**Impact**: -• Higher values: More historical data, larger disk usage -• Lower values: Less disk usage, limited historical queries -• `0`: No historical state (only current block) - -```json -"history_serve_window": "8192" -``` - -**Recommendation**: Use `8192` for standard chains, increase for archive nodes - - - -**What It Does**: Specifies the 18-decimal EVM representation for non-18 decimal native tokens. - -**Type**: Object with `extended_denom` field - -**When Required**: -• **18-decimal chains**: NOT required (EVM denom = base denom) -• **6-decimal chains**: REQUIRED (e.g., `utoken` → `atoken`) -• **Other decimals**: REQUIRED with precisebank module - -**Valid Values**: Any string that represents the 18-decimal denomination - -**Common Patterns**: -• 6-decimal `utoken` → 18-decimal `atoken` (atto-prefix) -• 6-decimal `ustake` → 18-decimal `astake` - -```json -"extended_denom_options": { - "extended_denom": "astake" // 18-decimal EVM representation -} -``` - -**Omit for 18-decimal chains**: -```json -// For 18-decimal chains, either omit or set to null -"extended_denom_options": null -``` - - - -**Complete Configuration Example**: - -```json -{ - "app_state": { - "vm": { - "params": { - "evm_denom": "ustake", - "extra_eips": [], - "active_static_precompiles": [ - "0x0000000000000000000000000000000000000100", - "0x0000000000000000000000000000000000000400", - "0x0000000000000000000000000000000000000800", - "0x0000000000000000000000000000000000000804" - ], - "evm_channels": [], - "access_control": { - "create": { - "access_type": 0, - "access_control_list": [] - }, - "call": { - "access_type": 0, - "access_control_list": [] - } - }, - "history_serve_window": "8192", - "extended_denom_options": { - "extended_denom": "astake" - } - } - } - } -} -``` - - - -### Available Precompiles - -Precompiles provide native chain functionality access from EVM contracts. Nine static precompiles are available at addresses 0x100, 0x400, and 0x800-0x806, covering cryptography (P256), addressing (Bech32), and Cosmos SDK modules (Staking, Distribution, ICS20, Vesting, Bank, Governance, Slashing). - -For complete details on each precompile including Solidity interfaces, gas costs, and usage examples, see the [Precompiles Overview](/docs/evm/next/documentation/smart-contracts/precompiles/overview). - -## Precompiles vs Predeployed Contracts - - -Understanding the difference between precompiles and predeployed contracts is crucial for properly configuring your chain: - -**Precompiles** - Native Go implementations exposed as EVM contracts at specific addresses (0x0100-0x0806). These provide gas-efficient access to Cosmos SDK modules. - -**Predeployed Contracts** - Regular Solidity contracts deployed at genesis to standard addresses. These include essential infrastructure like Create2, Multicall3, and Permit2. - - - -### Configuring Precompiles - -Precompiles must be explicitly enabled in your genesis configuration. The default evmd example enables ALL precompiles, but production chains should only enable what they need. - - -For complete documentation on all available precompiles, see the [Precompiles Overview](/docs/evm/next/documentation/smart-contracts/precompiles/overview). - - - - - ```json - { - "app_state": { - "vm": { - "params": { - "active_static_precompiles": [ - "0x0000000000000000000000000000000000000100", // P256 - "0x0000000000000000000000000000000000000400", // Bech32 - "0x0000000000000000000000000000000000000800", // Staking - "0x0000000000000000000000000000000000000804" // Bank - ] - } - } - } - } -``` - - - -```go - // In your custom genesis.go (e.g., evmd/genesis.go) - func NewEVMGenesisState() *evmtypes.GenesisState { - evmGenState := evmtypes.DefaultGenesisState() - // Enable ALL available precompiles (not recommended for production) - evmGenState.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles - return evmGenState - } - ``` - - - Enabling all precompiles increases the attack surface and gas overhead. Production chains should enable only the precompiles they need. - - - - - ```json - { - "app_state": { - "vm": { - "params": { - "active_static_precompiles": [] - } - } - } - } - ``` - - -Disabling all precompiles limits access to Cosmos SDK functionality from EVM contracts. Most chains will want at least the Bank and ERC20 precompiles enabled. - - - - -### Configuring Predeployed Contracts - - -The evmd example chain includes these predeployed contracts by default (defined in [`x/vm/types/preinstall.go:13-39`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L13-L39)): - -| Contract | Address | Description | Status | -| - | -- | | - | -| **Create2** | `0x4e59b44847b379578588920ca78fbf26c0b4956c` | Deterministic contract deployment | ✓ Verified | -| **Multicall3** | `0xcA11bde05977b3631167028862bE2a173976CA11` | Batch multiple calls in one transaction | ✓ Verified | -| **Permit2** | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | Token permit and transfer management | ✓ Verified | -| **Safe Factory** | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | Deploy Safe multisig contracts | ⚠️ Bytecode Issue | -| **EIP-2935** | `0x0b` | Historical block hash storage | ✓ System Contract | - - -**Safe Factory Bytecode Issue**: The Safe Singleton Factory bytecode in `DefaultPreinstalls` is currently a duplicate of the Create2 bytecode. This will not function correctly for deploying Safe wallets. If you need Safe Factory functionality, manually update the bytecode in your genesis configuration. See the [Safe Factory documentation](/docs/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory) for details. - - -These are automatically included when using the evmd example genesis via `evmtypes.DefaultPreinstalls`. - - - - - - ```go - // In evmd/genesis.go - func NewEVMGenesisState() *evmtypes.GenesisState { - evmGenState := evmtypes.DefaultGenesisState() - evmGenState.Preinstalls = evmtypes.DefaultPreinstalls // Includes all default contracts - return evmGenState - } - ``` - - - - ```json - { - "app_state": { - "vm": { - "preinstalls": [ - { - "name": "MyCustomContract", - "address": "0x1234567890123456789012345678901234567890", - "code": "0x608060405234801561001057600080fd5b50..." // Contract bytecode - } - ] - } - } - } - ``` - - - When adding custom predeployed contracts: - - Ensure the address doesn't conflict with existing contracts or precompile addresses (0x1-0x9FF reserved) - - Use standard addresses when possible (e.g., Create2 should always be at its standard address) - - Test thoroughly as these contracts are immutable after genesis - - Verify bytecode matches the source code you intend to deploy - - - - For detailed implementation guidance, see the [Predeployed Contracts Integration](/docs/evm/next/documentation/migrations/predeployed-contracts-integration) guide. - - - - - - ```json - { - "app_state": { - "vm": { - "preinstalls": [] - } - } - } - ``` - - - Removing default preinstalls may break ecosystem compatibility: - - Many tools and dApps expect Create2 at `0x4e59b44847b379578588920ca78fbf26c0b4956c` - - Multicall3 is expected at `0xcA11bde05977b3631167028862bE2a173976CA11` by most frontends - - Permit2 support is increasingly common in DeFi protocols - - Safe Factory enables multisig wallet deployment - - Only disable preinstalls if you have a specific reason and understand the compatibility implications. - - - - - - -For detailed information about each predeployed contract and their functionality, see the [Predeployed Contracts Overview](/docs/evm/next/documentation/smart-contracts/predeployed-contracts/overview). - - -### Adding Custom Predeployed Contracts - -To add your own predeployed contracts at genesis: - - - - Compile your Solidity contract to get the deployment bytecode: - ```bash - solc --bin MyContract.sol - # Or with Hardhat - npx hardhat compile - ``` - - -{" "} - - Select a deployment address that won't conflict: - Avoid precompile range - (0x0001-0x0FFF) - Check for ecosystem standards - Consider using Create2 for - deterministic addresses - - - - Add the contract to your genesis configuration: -```go - // In your custom genesis.go - var CustomPreinstalls = append(evmtypes.DefaultPreinstalls, evmtypes.Preinstall{ - Name: "MyContract", - Address: "0xYourChosenAddress", - Code: "0xDeploymentBytecode", - }) -``` - - - - After chain initialization, verify the contract is deployed: - ```bash - # Check contract code - curl -X POST http://localhost:8545 \ - -H "Content-Type: application/json" \ - -d '{ - "jsonrpc": "2.0", - "method": "eth_getCode", - "params": ["0xYourChosenAddress", "latest"], - "id": 1 - }' - ``` - - - -### Fee Market Configuration - -The fee market module implements EIP-1559 dynamic fee pricing for your chain. Configure these parameters in the `feemarket` section of your genesis file. - -**File Location**: Genesis configuration in `~/.evmd/config/genesis.json` under `app_state.feemarket.params` -**Parameter Defaults**: [x/feemarket/types/params.go](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go) - - -For comprehensive Fee Market Module documentation including EIP-1559 algorithm details, monitoring, and governance, see the [Fee Market Module Documentation](/evm/next/documentation/cosmos-sdk/modules/feemarket). - - - - - - -**What It Does**: Disables EIP-1559 dynamic base fee mechanism. When `true`, the chain uses only `min_gas_price` as a fixed minimum fee. - -**Type**: `bool` - -**Valid Values**: -- `false` - Enable EIP-1559 with dynamic base fee (recommended) -- `true` - Disable EIP-1559, use fixed min_gas_price only - -**Default**: `false` (see [params.go:21](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L21)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "no_base_fee": false // Enable EIP-1559 - } - } -} -``` - -**Impact**: -- When disabled (false), base fee adjusts dynamically based on block utilization -- When enabled (true), behaves like pre-EIP-1559 Ethereum with fixed minimum gas price -- Disabling EIP-1559 simplifies fee structure but loses congestion-based pricing benefits - - - - - -**What It Does**: Sets the initial base fee per gas in wei. This is the starting point for EIP-1559 fee calculations. - -**Type**: `string` (decimal number representing wei) - -**Valid Values**: Any non-negative decimal value in wei - -**Common Values**: -- `"1000000000"` (1 gwei) - Standard starting point -- `"10000000000"` (10 gwei) - Higher initial fee for congested chains -- `"100000000"` (0.1 gwei) - Lower initial fee for testing - -**Default**: `"1000000000"` (1 gwei, see [params.go:13](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L13)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "base_fee": "1000000000" // 1 gwei - } - } -} -``` - -**Impact**: -- Sets floor for transaction fees at launch -- Adjusts up/down based on block fullness after enable_height -- Should align with expected network usage and token economics - -**Validation**: Must be non-negative (see [params.go:66-68](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L66-L68)) - - - - - -**What It Does**: Controls how quickly the base fee can change per block. Higher values = slower adjustment. - -**Type**: `uint32` - -**Valid Values**: Any positive integer (cannot be 0) - -**Common Values**: -- `8` - Standard EIP-1559 (max ±12.5% per block) -- `50` - Slower adjustment (max ±2% per block) -- `4` - Faster adjustment (max ±25% per block) - -**Default**: `8` (standard EIP-1559) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "base_fee_change_denominator": 8 // Max 12.5% change per block - } - } -} -``` - -**Impact**: -- Formula: `max_change = base_fee / denominator` -- Higher denominator = more stable fees, slower response to congestion -- Lower denominator = more volatile fees, faster response to congestion -- Standard Ethereum uses 8 for balanced responsiveness - -**Validation**: Cannot be 0 (see [params.go:62-64](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L62-L64)) - - - - - -**What It Does**: Defines maximum block gas limit as a multiple of target gas. Allows blocks to temporarily exceed target during high demand. - -**Type**: `uint32` - -**Valid Values**: Any positive integer (cannot be 0) - -**Common Values**: -- `2` - Standard EIP-1559 (block can be 2x target) -- `3` - More elastic (block can be 3x target) -- `1` - No elasticity (block limited to target) - -**Default**: `2` (standard EIP-1559) - -**Configuration**: -```json -{ - "feemarket": { - "params": { - "elasticity_multiplier": 2 // Block gas limit = 2 × target gas - } - } -} -``` - -**Impact**: -- Higher multiplier allows larger temporary throughput spikes -- Block gas limit = target_gas × elasticity_multiplier -- When blocks exceed target, base fee increases; when below target, base fee decreases -- Standard Ethereum uses 2 for balanced elasticity - -**Validation**: Cannot be 0 (see [params.go:74-76](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L74-L76)) - - - - - -**What It Does**: Block height at which EIP-1559 base fee mechanism activates. Useful for coordinated mainnet upgrades. - -**Type**: `int64` - -**Valid Values**: Any non-negative integer - -**Common Values**: -- `0` - Enable from genesis (recommended for new chains) -- `100000` - Enable at specific future height for coordinated activation - -**Default**: `0` (enabled from genesis, see [params.go:19](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L19)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "enable_height": 0 // Enable from genesis - } - } -} -``` - -**Impact**: -- Before this height, base fee mechanism is inactive -- After this height, base fee adjusts dynamically -- Allows chains to launch with fixed fees then upgrade to dynamic pricing - -**Validation**: Cannot be negative (see [params.go:70-72](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L70-L72)) - - - - - -**What It Does**: Sets a global minimum gas price floor in native token decimals. Provides absolute minimum fee even if base fee drops lower. - -**Type**: `string` (decimal value) - -**Valid Values**: Any non-negative decimal value - -**Common Values**: -- `"0"` - No minimum floor (rely on base fee only) -- `"1000000000"` - 1 gwei minimum floor -- `"10000000000"` - 10 gwei minimum floor - -**Default**: `"0"` (disabled, see [params.go:17](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L17)) - -**Configuration**: - -```json -{ - "feemarket": { - "params": { - "min_gas_price": "0" // No minimum floor - } - } -} -``` - -**Impact**: -- When base fee < min_gas_price, min_gas_price is used instead -- Prevents fee races to zero during low usage periods -- Often set to 0 to rely purely on EIP-1559 dynamics - -**Validation**: Must be non-negative (see [params.go:89-98](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L89-L98)) - - - - - -**What It Does**: Fraction of base fee to use as the effective minimum gas price. Alternative to fixed min_gas_price. - -**Type**: `string` (decimal value between 0 and 1) - -**Valid Values**: Decimal between `0` and `1` (inclusive) - -**Common Values**: -- `"0.5"` - Minimum is 50% of base fee -- `"0.8"` - Minimum is 80% of base fee -- `"0"` - No multiplier-based minimum - -**Default**: `"0.5"` (50%, see [params.go:15](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L15)) - -**Configuration**: -```json -{ - "feemarket": { - "params": { - "min_gas_multiplier": "0.5" // Min = 50% of base fee - } - } -} -``` - -**Impact**: -- Creates dynamic minimum that scales with base fee -- Effective minimum = max(min_gas_price, base_fee × min_gas_multiplier) -- Prevents accepting transactions far below current base fee - -**Validation**: Must be between 0 and 1 inclusive (see [params.go:101-114](https://github.com/cosmos/evm/blob/main/x/feemarket/types/params.go#L101-L114)) - - - - - -**Complete Configuration Example**: - - -```json EIP-1559 Enabled (Recommended) -{ - "feemarket": { - "params": { - "no_base_fee": false, - "base_fee": "1000000000", // 1 gwei starting base fee - "base_fee_change_denominator": 8, // Standard EIP-1559 adjustment - "elasticity_multiplier": 2, // Standard EIP-1559 elasticity - "enable_height": 0, // Enable from genesis - "min_gas_price": "0", // No fixed floor - "min_gas_multiplier": "0.5" // 50% of base fee minimum - } - } -} -``` - -```json Simple Fixed Fee -{ - "feemarket": { - "params": { - "no_base_fee": true, // Disable EIP-1559 - "min_gas_price": "1000000000", // Fixed 1 gwei minimum - "min_gas_multiplier": "0" // No multiplier needed - } - } -} -``` - -```json High Stability Configuration -{ - "feemarket": { - "params": { - "no_base_fee": false, - "base_fee": "10000000000", // 10 gwei start - "base_fee_change_denominator": 50, // Slow adjustment (±2%/block) - "elasticity_multiplier": 3, // More elastic blocks - "enable_height": 0, - "min_gas_price": "5000000000", // 5 gwei absolute floor - "min_gas_multiplier": "0.8" // 80% of base fee minimum - } - } -} -``` - - -### Ethereum Fork Configuration - -The `chain_config` defines which Ethereum hard fork features are active on your chain. This controls EVM opcode availability and gas costs. - -**File Location**: Genesis configuration in `~/.evmd/config/genesis.json` under `app_state.vm.chain_config` -**Parameter Defaults**: [x/vm/types/chain_config.go:57-108](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L57-L108) - - -**Default Behavior**: All Ethereum forks through Prague are enabled at genesis (block/timestamp 0). This gives you full Ethereum compatibility out-of-the-box. - -**When to Customize**: Only modify fork activations if you need to: -- Delay fork activation for coordinated network upgrade -- Disable specific opcodes for security/compatibility reasons -- Match fork schedule of a specific Ethereum network - -For most chains, the defaults are appropriate. - - - - - - -**Block-Based Forks** (Pre-Merge): -Forks activate when block height reaches specified value. Used for all forks before The Merge. - -**Time-Based Forks** (Post-Merge): -Forks activate when block timestamp reaches specified Unix timestamp. Used for Shanghai, Cancun, Prague, and future forks. - -**Configuration Format**: -```json -{ - "vm": { - "chain_config": { - "homestead_block": "0", // Block-based (string int) - "shanghai_time": "0", // Time-based (string Unix timestamp) - "osaka_time": null // Not activated (null or negative) - } - } -} -``` - - - - - -These forks are enabled at genesis by default ([chain_config.go:62-103](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L62-L103)): - -**Block-Based Forks** (all at block 0): -| Fork | Block Parameter | Key Changes | -||-|-| -| **Homestead** | `homestead_block` | Basic contract functionality | -| **DAO Fork** | `dao_fork_block` | DAO rescue (support enabled) | -| **EIP-150** | `eip150_block` | Gas cost changes for I/O operations | -| **EIP-155** | `eip155_block` | Replay protection (simple signing) | -| **EIP-158** | `eip158_block` | State clearing, account cleanup | -| **Byzantium** | `byzantium_block` | REVERT opcode, STATICCALL | -| **Constantinople** | `constantinople_block` | Bitwise shifting, CREATE2 | -| **Petersburg** | `petersburg_block` | Constantinople fix | -| **Istanbul** | `istanbul_block` | ChainID opcode, cheaper gas | -| **MuirGlacier** | `muir_glacier_block` | Difficulty bomb delay | -| **Berlin** | `berlin_block` | BASEFEE opcode, access lists | -| **London** | `london_block` | EIP-1559 fee market | -| **ArrowGlacier** | `arrow_glacier_block` | Difficulty bomb delay | -| **GrayGlacier** | `gray_glacier_block` | Difficulty bomb delay | -| **MergeNetsplit** | `merge_netsplit_block` | Merge transition marker | - -**Time-Based Forks** (all at timestamp 0): -| Fork | Time Parameter | Key Changes | -|||-| -| **Shanghai** | `shanghai_time` | PUSH0 opcode, warm COINBASE | -| **Cancun** | `cancun_time` | Transient storage (TSTORE/TLOAD), blob transactions, EIP-2935 block hash history | -| **Prague** | `prague_time` | EIP-7702 account abstraction, updated blob config | - - - - - -These forks are not yet activated by default and are set to `nil` ([chain_config.go:104-105](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L104-L105)): - -| Fork | Parameter | Status | -||--|--| -| **Osaka** | `osaka_time` | Future Ethereum fork (not finalized) | -| **Verkle** | `verkle_time` | Verkle tree state transition (research) | - -**To Activate Future Fork**: - -```json -{ - "vm": { - "chain_config": { - "osaka_time": "1700000000" // Unix timestamp when fork activates - } - } -} -``` - - - - - -**Delay Fork Activation**: -```json -{ - "vm": { - "chain_config": { - "chain_id": "262144", - "homestead_block": "0", - "london_block": "0", - "shanghai_time": "1704067200", // Activate Shanghai at specific time - "cancun_time": "1710000000", // Activate Cancun later - "prague_time": null // Don't activate Prague yet - } - } -} -``` - -**Disable Specific Fork** (not recommended): - -```json -{ - "vm": { - "chain_config": { - "istanbul_block": null, // Skip Istanbul features - "berlin_block": "1000000" // Activate Berlin at block 1M - } - } -} -``` - -**Validation**: -- Forks must activate in chronological order (see [chain_config.go:190](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L190)) -- Block/timestamp values cannot be negative (see [chain_config.go:196-209](https://github.com/cosmos/evm/blob/main/x/vm/types/chain_config.go#L196-L209)) -- `nil` or negative values disable the fork - - - - - -**dao_fork_support**: -- **Type**: `bool` -- **Default**: `true` -- **Purpose**: Whether to support the DAO rescue fork (historical Ethereum event) -- **Recommendation**: Leave as `true` for Ethereum compatibility - -**denom** and **decimals** (Deprecated): -- These fields in chain_config are deprecated -- Use `vm.params.evm_denom` and bank metadata instead -- Present for backward compatibility only - - - - - -**Complete Configuration Example**: - - -```json Default (All Forks Enabled) -{ - "vm": { - "chain_config": { - "chain_id": "262144", - "denom": "", - "decimals": "0", - "homestead_block": "0", - "dao_fork_block": "0", - "dao_fork_support": true, - "eip150_block": "0", - "eip155_block": "0", - "eip158_block": "0", - "byzantium_block": "0", - "constantinople_block": "0", - "petersburg_block": "0", - "istanbul_block": "0", - "muir_glacier_block": "0", - "berlin_block": "0", - "london_block": "0", - "arrow_glacier_block": "0", - "gray_glacier_block": "0", - "merge_netsplit_block": "0", - "shanghai_time": "0", - "cancun_time": "0", - "prague_time": "0", - "osaka_time": null, - "verkle_time": null - } - } -} -``` - -```json Staged Fork Rollout -{ - "vm": { - "chain_config": { - "chain_id": "262144", - "homestead_block": "0", - "dao_fork_block": "0", - "dao_fork_support": true, - "eip150_block": "0", - "eip155_block": "0", - "eip158_block": "0", - "byzantium_block": "0", - "constantinople_block": "0", - "petersburg_block": "0", - "istanbul_block": "0", - "muir_glacier_block": "0", - "berlin_block": "0", - "london_block": "0", - "arrow_glacier_block": "0", - "gray_glacier_block": "0", - "merge_netsplit_block": "0", - "shanghai_time": "0", - "cancun_time": "1735689600", // Jan 1, 2025 - "prague_time": "1767225600", // Jan 1, 2026 - "osaka_time": null, - "verkle_time": null - } - } -} -``` - - -### Standard Cosmos Modules - -Configure standard Cosmos SDK modules that provide staking, governance, token inflation, and fee distribution functionality. - -**File Location**: Genesis configuration in `~/.evmd/config/genesis.json` under `app_state..params` -**Documentation**: [Cosmos SDK Modules](https://docs.cosmos.network/main/build/modules) - - - - - -The staking module handles validator delegation, undelegation, and slashing parameters. - -**Genesis Path**: `app_state.staking.params` -**Module Docs**: [x/staking](https://docs.cosmos.network/main/build/modules/staking) - -**Parameters**: - -**unbonding_time**: -- **What It Does**: Time required for tokens to fully undelegate before being withdrawable -- **Type**: `string` (duration with suffix like "s" for seconds) -- **Valid Values**: Any positive duration (typically days) -- **Common Values**: - - `"1814400s"` - 21 days (Cosmos Hub standard) - - `"604800s"` - 7 days (faster for testnets) - - `"2592000s"` - 30 days (longer security period) -- **Impact**: Longer unbonding time = more security but less liquidity for delegators -- **Recommendation**: 21 days is industry standard for mainnets - -**max_validators**: -- **What It Does**: Maximum number of active validators in the consensus set -- **Type**: `uint32` -- **Valid Values**: Any positive integer (typically 50-300) -- **Common Values**: - - `100` - Balanced decentralization - - `175` - Cosmos Hub active set - - `50` - Smaller chains or testnets -- **Impact**: More validators = more decentralization but higher overhead -- **Consideration**: Must balance security, performance, and decentralization - -**max_entries**: -- **What It Does**: Maximum simultaneous unbonding/redelegation entries per delegator-validator pair -- **Type**: `uint32` -- **Valid Values**: Typically 5-10 -- **Default**: `7` (Cosmos SDK standard) -- **Impact**: Limits how many concurrent unbonding operations a user can have -- **Recommendation**: Use default unless you have specific UX requirements - -**bond_denom**: -- **What It Does**: The denomination used for staking (bonding) to validators -- **Type**: `string` -- **Valid Values**: Must match a denomination from bank metadata -- **Critical**: **MUST match your base denom** (e.g., `atest` for 18 decimals, `ustake` for 6 decimals) -- **Impact**: This is the token validators stake and delegators delegate -- **Example**: If your base denom is `atest`, set `"bond_denom": "atest"` - -**Configuration Example**: -```json -{ - "staking": { - "params": { - "unbonding_time": "1814400s", // 21 days - "max_validators": 100, // 100 active validators - "max_entries": 7, // 7 concurrent unbondings - "bond_denom": "atest", // Must match your base denom - "historical_entries": 10000, // Historical entries for IBC - "min_commission_rate": "0.050000000000000000" // 5% minimum commission - } - } -} -``` - - - - - -The governance module enables on-chain parameter changes and community proposals. - -**Genesis Path**: `app_state.gov.params` -**Module Docs**: [x/gov](https://docs.cosmos.network/main/build/modules/governance) - -**Parameters**: - -**min_deposit**: -- **What It Does**: Minimum deposit required for a proposal to enter voting period -- **Type**: Array of coin objects `[{"denom": "string", "amount": "string"}]` -- **Valid Values**: Any amount in base denomination -- **Common Values**: - - `[{"denom": "ustake", "amount": "10000000"}]` - 10 tokens (6 decimals) - - `[{"denom": "atest", "amount": "10000000000000000000"}]` - 10 tokens (18 decimals) -- **Impact**: Higher deposit = spam protection, but may limit community participation -- **Must Match**: Denom must match your bond_denom - -**expedited_min_deposit**: -- **What It Does**: Higher deposit for expedited proposals (faster voting) -- **Type**: Array of coin objects -- **Typical**: 4-5x the standard min_deposit -- **Example**: `[{"denom": "atest", "amount": "50000000000000000000"}]` - 50 tokens - -**max_deposit_period**: -- **What It Does**: Time window for reaching min_deposit before proposal is rejected -- **Type**: `string` (duration) -- **Common Values**: - - `"172800s"` - 2 days (Cosmos Hub) - - `"604800s"` - 7 days (longer window) -- **Impact**: Longer period gives more time to crowdfund deposits - -**voting_period**: -- **What It Does**: Duration of voting once proposal enters voting period -- **Type**: `string` (duration) -- **Common Values**: - - `"172800s"` - 2 days (fast decisions) - - `"1209600s"` - 14 days (Cosmos Hub) -- **Impact**: Longer period ensures participation, shorter enables faster upgrades -- **Recommendation**: 7-14 days for mainnet, 1-2 days for testnets - -**expedited_voting_period**: -- **What It Does**: Faster voting period for expedited proposals -- **Type**: `string` (duration) -- **Typical**: 1/7th of normal voting_period -- **Example**: `"86400s"` - 24 hours - -**quorum**: -- **What It Does**: Minimum percentage of bonded tokens that must vote -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.334000000000000000"` - 33.4% (Cosmos Hub) - - `"0.400000000000000000"` - 40% (higher participation requirement) -- **Impact**: Higher quorum = harder to pass proposals but more representative - -**threshold**: -- **What It Does**: Minimum percentage of Yes votes (excluding abstain) to pass -- **Type**: `string` (decimal between 0 and 1) -- **Standard**: `"0.500000000000000000"` - 50% majority - -**veto_threshold**: -- **What It Does**: Percentage of NoWithVeto votes needed to veto (and burn deposits) -- **Type**: `string` (decimal between 0 and 1) -- **Standard**: `"0.334000000000000000"` - 33.4% -- **Impact**: Protects against malicious proposals - -**Configuration Example**: -```json -{ - "gov": { - "params": { - "min_deposit": [{"denom": "atest", "amount": "10000000000000000000"}], - "expedited_min_deposit": [{"denom": "atest", "amount": "50000000000000000000"}], - "max_deposit_period": "172800s", // 2 days - "voting_period": "1209600s", // 14 days - "expedited_voting_period": "86400s", // 1 day - "quorum": "0.334000000000000000", // 33.4% - "threshold": "0.500000000000000000", // 50% - "expedited_threshold": "0.667000000000000000", // 66.7% for expedited - "veto_threshold": "0.334000000000000000", // 33.4% - "min_initial_deposit_ratio": "0.200000000000000000", // 20% initial deposit - "burn_vote_quorum": false, - "burn_proposal_deposit_prevote": false, - "burn_vote_veto": true // Burn deposits on veto - } - } -} -``` - - - - - -The mint module controls token inflation and block reward minting. - -**Genesis Path**: `app_state.mint.minter` and `app_state.mint.params` -**Module Docs**: [x/mint](https://docs.cosmos.network/main/build/modules/mint) - -**Minter State**: - -**inflation**: -- **What It Does**: Current inflation rate (changes dynamically based on bonded ratio) -- **Type**: `string` (decimal between 0 and 1) -- **Initial Value**: Typically set to your starting inflation rate -- **Example**: `"0.130000000000000000"` - 13% annual inflation - -**annual_provisions**: -- **What It Does**: Auto-calculated based on total supply and inflation -- **Type**: `string` (decimal) -- **Genesis Value**: `"0.000000000000000000"` - will be calculated after chain starts -- **Note**: This value is computed automatically, don't need to set manually - -**Parameters**: - -**mint_denom**: -- **What It Does**: Denomination of tokens to mint as block rewards -- **Type**: `string` -- **Critical**: **MUST match your bond_denom** (same as staking module) -- **Example**: `"atest"` for 18 decimals, `"ustake"` for 6 decimals - -**inflation_rate_change**: -- **What It Does**: Maximum annual change in inflation rate -- **Type**: `string` (decimal) -- **Common Values**: - - `"0.130000000000000000"` - 13% max change (Cosmos Hub) - - `"0.200000000000000000"` - 20% faster adjustment -- **Impact**: Higher value = inflation adjusts faster to meet goal_bonded target - -**inflation_max**: -- **What It Does**: Maximum annual inflation rate ceiling -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.200000000000000000"` - 20% maximum (Cosmos Hub) - - `"0.100000000000000000"` - 10% for lower inflation chains -- **Impact**: Caps maximum inflation regardless of bonded ratio - -**inflation_min**: -- **What It Does**: Minimum annual inflation rate floor -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.070000000000000000"` - 7% minimum (Cosmos Hub) - - `"0.000000000000000000"` - 0% for no minimum -- **Impact**: Ensures minimum block rewards even at high bonded ratios - -**goal_bonded**: -- **What It Does**: Target percentage of tokens that should be bonded (staked) -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.670000000000000000"` - 67% target (Cosmos Hub) - - `"0.500000000000000000"` - 50% for more liquid chains -- **How It Works**: - - If bonded ratio < goal: inflation increases (incentivize staking) - - If bonded ratio > goal: inflation decreases (reduce selling pressure) - -**blocks_per_year**: -- **What It Does**: Expected number of blocks per year (for inflation calculation) -- **Type**: `uint64` -- **Calculation**: `(365.25 * 24 * 60 * 60) / block_time_seconds` -- **Common Values**: - - `6311520` - For ~5 second blocks - - `3155760` - For ~10 second blocks -- **Note**: Adjust based on your actual block time - -**Configuration Example**: -```json -{ - "mint": { - "minter": { - "inflation": "0.130000000000000000", // Starting at 13% - "annual_provisions": "0.000000000000000000" // Auto-calculated - }, - "params": { - "mint_denom": "atest", // Must match bond_denom - "inflation_rate_change": "0.130000000000000000", // 13% max change/year - "inflation_max": "0.200000000000000000", // 20% ceiling - "inflation_min": "0.070000000000000000", // 7% floor - "goal_bonded": "0.670000000000000000", // 67% target bonded - "blocks_per_year": "6311520" // ~5 second blocks - } - } -} -``` - - - - - -The distribution module manages fee distribution to validators, delegators, and community pool. - -**Genesis Path**: `app_state.distribution.params` -**Module Docs**: [x/distribution](https://docs.cosmos.network/main/build/modules/distribution) - -**Parameters**: - -**community_tax**: -- **What It Does**: Percentage of block rewards and fees sent to community pool -- **Type**: `string` (decimal between 0 and 1) -- **Common Values**: - - `"0.020000000000000000"` - 2% to community pool (Cosmos Hub) - - `"0.100000000000000000"` - 10% for chains with active governance - - `"0.000000000000000000"` - 0% to disable community pool funding -- **Impact**: Funds governance-controlled treasury for ecosystem development -- **Remaining**: (100% - community_tax) goes to validators and delegators - -**base_proposer_reward** (Deprecated): -- **Type**: `string` (decimal) -- **Standard**: `"0.000000000000000000"` - Set to 0 (deprecated in recent SDK versions) -- **Note**: Modern chains use only block rewards from mint module - -**bonus_proposer_reward** (Deprecated): -- **Type**: `string` (decimal) -- **Standard**: `"0.000000000000000000"` - Set to 0 (deprecated in recent SDK versions) -- **Note**: Proposer bonus now handled differently in consensus - -**withdraw_addr_enabled**: -- **What It Does**: Allow delegators to set a different address for reward withdrawal -- **Type**: `bool` -- **Common Values**: - - `true` - Allow reward forwarding (standard) - - `false` - Disable for security (rare) -- **Impact**: Enables features like auto-compounding services -- **Recommendation**: Leave `true` for flexibility - -**Configuration Example**: -```json -{ - "distribution": { - "params": { - "community_tax": "0.020000000000000000", // 2% to community pool - "base_proposer_reward": "0.000000000000000000", // Deprecated - "bonus_proposer_reward": "0.000000000000000000", // Deprecated - "withdraw_addr_enabled": true // Allow reward forwarding - } - } -} -``` - - - - - -**Token Denomination Consistency**: - - -**Critical Configuration Requirement**: The following denominations MUST all match: - -- `staking.params.bond_denom` - What validators stake -- `mint.params.mint_denom` - What gets minted as rewards -- `gov.params.min_deposit[0].denom` - What's deposited for governance -- `bank.denom_metadata[0].base` - Base denomination in metadata - -All four must use the same base denom (e.g., `atest` for 18 decimals or `ustake` for 6 decimals). - -See the [Token Configuration Guide](/docs/evm/next/documentation/getting-started/build-a-chain/token-configuration-guide) for complete details on setting up token economics. - -For detailed information about the ERC20 module that handles token representation between Cosmos and EVM, see the [ERC20 Module Documentation](/evm/next/documentation/cosmos-sdk/modules/erc20). - - -### Initial Token Distribution - -Add initial account balances in the `bank` section: - -```json -{ - "bank": { - "balances": [ - { - "address": "yourchain1...", - "coins": [ - { - "denom": "ustake", - "amount": "1000000000000" - } - ] - } - ] - } -} -``` - -## Runtime Configuration (app.toml) - -The `app.toml` file contains node-specific settings that can be changed without affecting consensus. These are node-operator configurations that don't require network-wide coordination. - - -For complete `app.toml` configuration details, see the [Node Configuration Documentation](/docs/evm/next/documentation/getting-started/node-configuration). The sections below show key settings for chain builders. - - -### JSON-RPC Configuration - - -```toml -############################################################################### -### JSON-RPC Configuration ### -############################################################################### - -[json-rpc] - -# Enable JSON-RPC server - -enable = true - -# Address to bind the HTTP server - -address = "0.0.0.0:8545" - -# Address to bind WebSocket server - -ws-address = "0.0.0.0:8546" - -# API namespaces to enable - -# Available: web3, eth, personal, net, txpool, debug, miner - -api = ["eth", "net", "web3", "txpool"] - -# Gas cap for eth_call/estimateGas (0=default) - -gas-cap = 25000000 - -# Timeout for eth_call - -evm-timeout = "5s" - -# Transaction fee cap (in ether) - -txfee-cap = 1.0 - -# Maximum number of filters - -filter-cap = 200 - -# Maximum blocks for fee history - -feehistory-cap = 100 - -# Maximum logs per query - -logs-cap = 10000 - -# Maximum block range for eth_getLogs - -block-range-cap = 10000 - -# HTTP server timeouts - -http-timeout = "30s" -http-idle-timeout = "120s" - -# Allow non-EIP155 signed transactions - -allow-unprotected-txs = false - -# Batch request settings - -batch-request-limit = 1000 -batch-response-max-size = 25000000 - -# Connection limit (0 = unlimited) - -max-open-connections = 0 - -# Enable custom indexer - -enable-indexer = false - -# Metrics server - -metrics-address = "127.0.0.1:6065" - -# WebSocket allowed origins - -ws-origins = ["localhost", "127.0.0.1"] - -# Dangerous: only for development - -allow-insecure-unlock = false -enable-profiling = false - -```` - - -### EVM Configuration - -```toml -[evm] -# EVM tracer ("" | "json" | "struct" | "access_list" | "markdown") -tracer = "" - -# Maximum gas wanted for a transaction -max-tx-gas-wanted = 0 - -# Track SHA3 preimages -cache-preimage = false - -# Minimum priority fee (tip) in wei -min-tip = 1000000000 - -# Geth metrics server -geth-metrics-address = "127.0.0.1:8100" -```` - -## Genesis Coordination for Multi-Validator Networks - -A production network requires multiple validators for decentralization and fault tolerance. The genesis coordinator must collect signed genesis transactions (gentx files) from each validator and combine them into the final genesis file. - - -For detailed validator setup instructions including key generation and operational security, please refer to the [Validator Nodes Guide](/docs/evm/next/documentation/getting-started/node-configuration#validator-nodes). - - -### Collecting Genesis Transactions from Validators - - - The genesis coordinator combines signed validator transactions but cannot - modify them without invalidating signatures. It's still good practice to: - - Verify the final genesis.json hash before starting your node - Ensure all - expected validators are included - Confirm token allocations match - expectations - - - - - Validators send their genesis transactions to the coordinator: - - 1. Each validator shares their `gentx-*.json` file from `~/.yourchain/config/gentx/` - 2. Coordinator places all files in their `~/.yourchain/config/gentx/` directory - 3. Coordinator runs: - - ```bash - yourchain genesis collect-gentxs - yourchain genesis validate-genesis - ``` - - - - - Use a repository for transparent coordination: - - 1. Create a genesis repository - 2. Validators submit PRs with their gentx files - 3. Verify validator identities before merging - 4. Generate final genesis from collected transactions - - - - - For larger networks, use automation: - - ```bash - # Example script for collecting via HTTP - for validator in "${VALIDATORS[@]}"; do - curl -O "https://${validator}/gentx.json" - mv gentx.json ~/.yourchain/config/gentx/gentx-${validator}.json - done - - yourchain genesis collect-gentxs - ``` - - - - -### Distributing the Final Genesis - -Once the genesis file is complete with all validator transactions: - -1. **Calculate genesis hash** for verification: - - ```bash - sha256sum ~/.yourchain/config/genesis.json - ``` - -2. **Distribute to all validators** who replace their local genesis: - - ```bash - # Each validator downloads and verifies - curl -O https://genesis.yourchain.com/genesis.json - sha256sum genesis.json # Verify hash matches - mv genesis.json ~/.yourchain/config/ - ``` - -3. **Share peer information** for network discovery: - ```bash - # Get node ID and IP - yourchain tendermint show-node-id - # Share: nodeID@IP:26656 - ``` - -## Starting the Network - -### Coordinated Network Launch - - - - Each validator adds peers to `config.toml`: - - ```toml - # Persistent peers - persistent_peers = "nodeID1@IP1:26656,nodeID2@IP2:26656,..." - - # Recommended settings for new networks - addr_book_strict = false - max_num_inbound_peers = 100 - max_num_outbound_peers = 100 - ``` - - - - - Coordinate the genesis time (usually set in genesis.json): - - ```json - { - "genesis_time": "2024-01-15T15:00:00Z" - } - ``` - - All genesis validators must start their nodes before this time: - - ```bash - # For validators (no RPC exposed) - yourchain start \ - --minimum-gas-prices 0.025ustake \ - --log_level info - - # For RPC nodes (separate from validators) - yourchain start \ - --minimum-gas-prices 0.025ustake \ - --json-rpc.enable \ - --json-rpc.api eth,net,web3,txpool \ - --evm.tracer "" \ - --log_level info - ``` - - - - -### Monitoring Network Health - -After launch, monitor these critical metrics: - - - - ```bash - # Check latest block - yourchain status | jq .sync_info - - # Monitor block time - yourchain query block | jq .block.header.time - ``` - - - - - ```bash - # Check consensus state - yourchain status | jq .sync_info.catching_up - - # View active validator count - yourchain query staking validators --output json | jq '.validators | length' - ``` - - - - - ```bash - # Check connected peers - yourchain status | jq .node_info.network - - # Monitor peer count - curl http://localhost:26657/net_info | jq '.result.n_peers' - ``` - - - - -## Post-Launch Operations - -### Governance Parameter Updates - -Most parameters can be modified through governance after launch: - - -```json param-change-proposal.json -{ - "title": "Update EVM Parameters", - "description": "Enable additional precompiles", - "changes": [ - { - "subspace": "vm", - "key": "ActiveStaticPrecompiles", - "value": ["0x0000000000000000000000000000000000000800", "0x0000000000000000000000000000000000000805"] - } - ], - "deposit": "10000000ustake" -} -``` - -```bash submit-proposal.sh -yourchain tx gov submit-proposal param-change proposal.json \ - --from validator \ - --chain-id yourchain-1 \ - --keyring-backend file -``` - - - -### Software Upgrades - -For breaking changes requiring new binary versions: - - -**1. Implement upgrade handler** in `yourchain/upgrades.go`: -```go -const UpgradeName = "v1.0.0-to-v2.0.0" - -func (app EVMD) RegisterUpgradeHandlers() { -app.UpgradeKeeper.SetUpgradeHandler( -UpgradeName, -func(ctx context.Context, \_ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { -sdkCtx := sdk.UnwrapSDKContext(ctx) - - // Perform any state migrations here - // For example, setting bank metadata for token configuration: - app.BankKeeper.SetDenomMetaData(ctx, banktypes.Metadata{ - DenomUnits: []*banktypes.DenomUnit{ - {Denom: "ustake", Exponent: 0}, - {Denom: "stake", Exponent: 6}, - }, - Base: "ustake", - Display: "stake", - }) - - // For non-18 decimal chains, set extended denom - if decimals != 18 { - evmParams := app.EVMKeeper.GetParams(sdkCtx) - evmParams.ExtendedDenomOptions = &types.ExtendedDenomOptions{ - ExtendedDenom: "astake", - } - app.EVMKeeper.SetParams(sdkCtx, evmParams) - } - - return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) - }, - ) - -} - -```` - -**2. Propose upgrade** via governance: -```bash -yourchain tx gov submit-proposal software-upgrade v1.0.0-to-v2.0.0 \ - --title "Upgrade to v2.0.0" \ - --description "Upgrade with new features" \ - --upgrade-height 1000000 \ - --from validator \ - --chain-id yourchain-1 -```` - -**3. Validators prepare** by installing new binary before upgrade height - -**4. Automatic upgrade** at specified height using Cosmovisor or manual restart - - - -## Advanced Customization - -### Module Architecture Decisions - - -The choice between standard bank and precisebank depends on your token's decimal precision: - -**Standard Bank Module (DEFAULT - 18-decimal chains):** - -```go -// Module initialization order in app.go -genesisModuleOrder := []string{ - authtypes.ModuleName, - banktypes.ModuleName, - distrtypes.ModuleName, - stakingtypes.ModuleName, - slashingtypes.ModuleName, - govtypes.ModuleName, - minttypes.ModuleName, - ibcexported.ModuleName, - evmtypes.ModuleName, - feemarkettypes.ModuleName, - erc20types.ModuleName, - // No precisebank needed for 18-decimal chains - ibctransfertypes.ModuleName, - genutiltypes.ModuleName, - evidencetypes.ModuleName, - authz.ModuleName, - feegrant.ModuleName, - upgradetypes.ModuleName, - vestingtypes.ModuleName, -} - -// EVM keeper initialization (using standard bank) -app.EVMKeeper = evmkeeper.NewKeeper( - appCodec, - keys[evmtypes.StoreKey], - tkeys[evmtypes.TransientKey], - keys, - authtypes.NewModuleAddress(govtypes.ModuleName), - app.AccountKeeper, - app.BankKeeper, // Use standard bank keeper directly - app.StakingKeeper, - app.FeeMarketKeeper, - &app.ConsensusParamsKeeper, - &app.Erc20Keeper, - evmChainID, - tracer, -) -``` - -**Precisebank Module (OPTIONAL - for non-18 decimal chains):** - -```go -// Module initialization order with precisebank -genesisModuleOrder := []string{ - authtypes.ModuleName, - banktypes.ModuleName, - distrtypes.ModuleName, - stakingtypes.ModuleName, - slashingtypes.ModuleName, - govtypes.ModuleName, - minttypes.ModuleName, - ibcexported.ModuleName, - evmtypes.ModuleName, - feemarkettypes.ModuleName, - erc20types.ModuleName, - precisebanktypes.ModuleName, // Added for non-18 decimal chains - ibctransfertypes.ModuleName, - // ... rest of modules -} - -// Precisebank wraps standard bank -app.PreciseBankKeeper = precisebankkeeper.NewKeeper( - appCodec, - keys[precisebanktypes.StoreKey], - app.BankKeeper, // Wraps standard bank keeper - app.AccountKeeper, -) - -// EVM keeper uses precisebank -app.EVMKeeper = evmkeeper.NewKeeper( - appCodec, - keys[evmtypes.StoreKey], - tkeys[evmtypes.TransientKey], - keys, - authtypes.NewModuleAddress(govtypes.ModuleName), - app.AccountKeeper, - app.PreciseBankKeeper, // Precisebank wrapper instead of bank directly - app.StakingKeeper, - app.FeeMarketKeeper, - &app.ConsensusParamsKeeper, - &app.Erc20Keeper, - evmChainID, - tracer, -) -``` - -**Key Differences:** - -- **18-decimal (default)**: EVM interacts directly with bank module, simpler architecture -- **Non-18 decimal**: EVM interacts through precisebank wrapper to handle fractional amounts -- **Genesis order**: When using precisebank, it must initialize after bank but before modules that use it -- **Keeper dependencies**: VM keeper takes different keeper type based on decimal configuration - - - -### Custom Precompiles - - - Teams can implement custom precompiled contracts for chain-specific - functionality. - - -Create custom precompiles by: - -1. Implementing the precompile interface -2. Registering in the VM keeper -3. Adding to available precompiles list -4. Enabling in genesis configuration - -### Access Control Configurations - - - - Default - anyone can deploy and call contracts: - ```json - { - "access_control": { - "create": { - "access_type": 0, // ACCESS_TYPE_PERMISSIONLESS - "access_control_list": [] - }, - "call": { - "access_type": 0, // ACCESS_TYPE_PERMISSIONLESS - "access_control_list": [] - } - } - } - ``` - - - - Only allowlisted addresses can deploy/call: - ```json - { - "access_control": { - "create": { - "access_type": 2, // ACCESS_TYPE_PERMISSIONED - "access_control_list": ["0xallowed1", "0xallowed2"] - }, - "call": { - "access_type": 0, // Keep calls permissionless - "access_control_list": [] - } - } - } - ``` - - - - Block all contract deployment: - ```json - { - "access_control": { - "create": { - "access_type": 1, // ACCESS_TYPE_RESTRICTED - blocks all - "access_control_list": [] // Ignored for restricted type - }, - "call": { - "access_type": 0, // Keep calls permissionless - "access_control_list": [] - } - } - } - ``` - - - -## Best Practices and Recommendations - - - - - Enable only necessary precompiles to minimize attack surface - - Implement proper key management procedures - - Regular security audits for custom modifications - - Monitor for unusual activity or governance proposals - - Carefully review governance proposals before voting - - -{" "} - - - - Adjust block size and gas limits based on network capacity - - Configure appropriate peer connections for node operators - - Monitor and adjust mempool settings (see [Mempool Integration](/evm/next/documentation/cosmos-sdk/modules/mempool-integration)) - - Consider pruning strategies for long-term sustainability - - Use appropriate storage solutions for node infrastructure - - - - - Start with conservative parameters - - Gradually increase limits through governance - - Encourage geographic and infrastructure diversity among network participants - - Implement monitoring and alerting systems - - Plan for emergency response procedures - - Document upgrade procedures clearly - - - -## Conclusion - -Building a custom chain with Cosmos EVM provides the flexibility to create an application-specific blockchain with full EVM compatibility. The modular architecture allows you to enable only the features you need while maintaining the security and decentralization of the Cosmos ecosystem. - -### Next Steps - -After completing this guide, you should have: -- ✓ Forked and renamed the Cosmos EVM reference implementation -- ✓ Configured your chain's identity (Bech32 prefix, BIP44 coin type, Chain IDs) -- ✓ Set up token economics (decimals, denoms, extended denom options) -- ✓ Configured all genesis parameters (VM, Fee Market, Precompiles, Cosmos modules) -- ✓ Set up runtime configuration (app.toml) -- ✓ Coordinated genesis with validators -- ✓ Launched your network - -**Recommended Next Actions**: - -1. **Test Thoroughly**: Run a private testnet to verify all configurations before mainnet launch -2. **Review Module Docs**: Deep dive into module-specific documentation: - - [VM Module](/evm/next/documentation/cosmos-sdk/modules/vm) - Precompiles and EVM parameters - - [Fee Market Module](/evm/next/documentation/cosmos-sdk/modules/feemarket) - EIP-1559 tuning and monitoring - - [ERC20 Module](/evm/next/documentation/cosmos-sdk/modules/erc20) - Token representation and IBC integration - - [PreciseBank Module](/evm/next/documentation/cosmos-sdk/modules/precisebank) - Fractional balance handling (if using non-18-decimal tokens) - - [Mempool Integration](/evm/next/documentation/cosmos-sdk/modules/mempool-integration) - Transaction prioritization - -3. **Set Up Infrastructure**: - - Configure monitoring and alerting systems - - Set up RPC nodes separate from validators (see [Node Configuration](/docs/evm/next/documentation/getting-started/node-configuration)) - - Implement backup and recovery procedures - -4. **Security Hardening**: - - Conduct security audits of any custom modifications - - Review access control configurations - - Test upgrade procedures on testnet - -5. **Community Engagement**: - - Register your chain on [chainlist.org](https://chainlist.org) - - Update ecosystem documentation - - Engage with the Cosmos EVM community for support diff --git a/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx.tmp b/docs/evm/next/documentation/getting-started/build-a-chain/building-your-chain-guide.mdx.tmp deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/evm/next/documentation/getting-started/build-a-chain/configuration-parameters.mdx b/docs/evm/next/documentation/getting-started/build-a-chain/configuration-parameters.mdx index 6d794fc2..47b05700 100644 --- a/docs/evm/next/documentation/getting-started/build-a-chain/configuration-parameters.mdx +++ b/docs/evm/next/documentation/getting-started/build-a-chain/configuration-parameters.mdx @@ -1,291 +1,1086 @@ --- -title: "Configuration Parameters" -description: "A complete list of configurable parameters for Cosmos EVM networks, categorized by the stage at which they can be set and modified." +title: "Chain Configuration Guide" +description: "Step-by-step guide to configuring your Cosmos EVM chain. Learn how to customize the binary name, chain IDs, token denomination, precompiles, and permissions based on the evmd reference implementation." --- -## Chain Initialization Parameters +# Chain Configuration Guide -These parameters must be set before the chain is initialized and CANNOT be changed after genesis without significant effort. +When building your custom chain based on `evmd`, you'll need to configure several key parameters. This guide walks through each configuration option from the evmd default setup and shows you how to customize it for your chain. -### Chain Identity + +This guide focuses on the practical configuration steps. For comprehensive parameter references and advanced topics, see the [migration guides](/docs/evm/next/documentation/migrations/migration-v0.4-to-v0.5) and module-specific documentation. + -| Parameter | Location | Default | Valid Values | Description | -|--|-||--|-| -| `chain-id` | Genesis / CLI | `"cosmos-1"` | Any string | Cosmos chain ID (different from EVM Chain ID) | -| `bech32-prefix` | `config/config.go` | `"cosmos"` | Any string | Address prefix for Bech32 encoding | -| `coin-type` | `config/config.go` | `60` (Ethereum) | Any uint32 | BIP44 coin type for HD wallets | +## evmd Default Configuration -### Token Configuration +The reference implementation (`evmd`) comes with these defaults: -Token configuration is set in genesis through bank metadata and VM parameters. +| Configuration | Default Value | Customizable | +|---------------|---------------|--------------| +| **Binary Name** | `evmd` | ✓ Yes (rename) | +| **Cosmos Chain ID** | `cosmos_262144-1` | ✓ Yes (genesis) | +| **EVM Chain ID** | `262144` | ✓ Yes (genesis) | +| **Custom Opcodes** | None | ✓ Yes (advanced) | +| **Token Pairs** | 1 (native token) | ✓ Yes (genesis) | +| **Denomination** | `atest` (18 decimals) | ✓ Yes (genesis) | +| **EVM Permissioning** | Permissionless | ✓ Yes (genesis) | +| **Enabled Precompiles** | All 9 precompiles | ✓ Yes (genesis) | -The token configuration is derived from: -1. **Bank Metadata** (`genesis.json`: `bank.denom_metadata`): Defines the token denominations and decimal precision -2. **VM Parameters** (`genesis.json`: `vm.params.evm_denom`): Specifies which bank denom to use as the native EVM token -3. **Extended Denom Options** (`genesis.json`: `vm.params.extended_denom_options`): Required only for non-18 decimal chains +Let's configure each of these for your custom chain. -| Derived Parameter | Source | Description | -|-||-| -| `Denom` | `vm.params.evm_denom` | Base denomination from bank metadata | -| `ExtendedDenom` | Auto/Options | 18-decimal denomination for EVM (same as denom for 18-decimal chains) | -| `DisplayDenom` | Bank metadata `display` field | Human-readable denomination | -| `Decimals` | Bank metadata denom units | Decimal precision (exponent of display denom) | +--- + +## 1. Binary Name -**Important**: The decimal precision affects how balances are represented in the EVM and which modules you need: +**What It Is**: The name of your compiled blockchain executable. -**Common configurations:** -- **18 decimals (DEFAULT)**: Direct 1:1 mapping with EVM - - Uses standard Cosmos SDK `x/bank` module by default - - No additional modules required - - Simplest architecture (recommended) +**Default**: `evmd` -- **6 decimals**: Common in Cosmos ecosystem - - Must add `x/precisebank` module for fractional tracking - - Precisebank wraps standard bank module - - Handles conversion: 1 utoken = 10^12 wei +### How to Change -- **Other values**: - - Must add `x/precisebank` module - - Test conversion logic thoroughly - - Consider implications for UI/UX + + +```bash +cd /path/to/cosmos-evm +mv evmd yourchain +``` + + + +```bash +# Update all references in Go files +find . -type f -name "*.go" -exec sed -i 's/evmd/yourchain/g' {} \; +``` + -**Module addition for non-18 decimal chains:** + +Edit the module path in `go.mod`: ```go -// Add to app.go: -import precisebanktypes "github.com/cosmos/evm/x/precisebank/types" -import precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" +module github.com/your-org/your-chain -// Initialize PreciseBankKeeper: -app.PreciseBankKeeper = precisebankkeeper.NewKeeper( - appCodec, - keys[precisebanktypes.StoreKey], - app.BankKeeper, - app.AccountKeeper, -) +// Update import paths that reference evmd +``` + -// Update VM keeper to use precisebank: -app.VMKeeper = evmkeeper.NewKeeper( - // ... - app.PreciseBankKeeper, // Use PreciseBankKeeper wrapper - // ... -) + +Edit the Makefile to use your binary name: +```makefile +BINARY_NAME := yourchain + +install: + go install ./yourchain/cmd/yourchain +``` + + + +```bash +go mod tidy +make install + +# Or build directly +go build -o yourchain ./yourchain/cmd/yourchain ``` + + + + +After renaming, your binary will be `yourchain` instead of `evmd`. All CLI commands will use this new name (e.g., `yourchain start` instead of `evmd start`). + + +--- + +## 2. Cosmos Chain ID + +**What It Is**: The unique identifier for your blockchain in the Cosmos ecosystem. Used for IBC connections and governance. + +**Default**: `cosmos_262144-1` + +**Format**: `{name}_{evmChainID}-{version}` + +### How to Change + +Set during chain initialization: + +```bash +yourchain init mynode --chain-id yourchain_262144-1 +``` + +**Recommended Formats**: +- Testnet: `yourchain_262144-1` +- Mainnet: `yourchain-1` (after registering a unique EVM chain ID) + + +The Cosmos chain ID is separate from the EVM chain ID. The format `name_evmChainID-version` helps maintain consistency between both IDs, but it's not required. + + +### Changing After Genesis + +While technically possible through a coordinated upgrade, changing the Cosmos chain ID requires all nodes to update and restart simultaneously. Plan your chain ID carefully before launch. + +--- + +## 3. EVM Chain ID +**What It Is**: The EIP-155 chain ID used for Ethereum transaction replay protection. +**Default**: `262144` -## Genesis Parameters - -These parameters are set in the genesis file and can be modified through governance proposals after chain launch. - -### VM Module (`vm`) - -| Parameter | Default | Valid Values | Modifiable | Description | -|--||--||-| -| `evm_chain_id` | `262144` | Any uint64 | Via Governance* | EIP-155 chain ID for EVM transactions | -| `extra_eips` | `[]` | Valid EIP numbers | Yes | Additional EIPs to activate | -| `active_static_precompiles` | `[]` | Precompile addresses | Yes | Enabled precompiled contracts | -| `evm_channels` | `[]` | IBC channel IDs | Yes | Channels connected to EVM chains | -| `access_control.create.type` | `"permissionless"` | `permissionless`, `restricted`, `permissioned` | Yes | Contract creation access control | -| `access_control.create.list` | `[]` | Ethereum addresses | Yes | Allowlist/blocklist for creation | -| `access_control.call.type` | `"permissionless"` | `permissionless`, `restricted`, `permissioned` | Yes | Contract call access control | -| `access_control.call.list` | `[]` | Ethereum addresses | Yes | Allowlist/blocklist for calls | -| `history_serve_window` | `8192` | Any uint64 | Yes | Number of blocks to serve historical data | - -#### Available Static Precompiles - -All precompiles can be individually enabled/disabled in genesis: - -| Address | Name | Description | -|||-| -| `0x0000...0100` | P256 | P256 curve operations | -| `0x0000...0400` | Bech32 | Bech32 address conversion | -| `0x0000...0800` | Staking | Cosmos staking operations | -| `0x0000...0801` | Distribution | Reward distribution | -| `0x0000...0802` | ICS20 | IBC token transfers | -| `0x0000...0803` | Vesting | Vesting account operations | -| `0x0000...0804` | Bank | Token transfers | -| `0x0000...0805` | Gov | Governance operations | -| `0x0000...0806` | Slashing | Validator slashing info | - -#### Chain Configuration (Ethereum Forks) - -All Ethereum hard fork activations. Set to `0` to activate at genesis, `null` to never activate: - -| Parameter | Default | Description | -|--||-| -| `homestead_block` | `0` | Homestead fork | -| `dao_fork_block` | `0` | DAO fork | -| `dao_fork_support` | `true` | Support DAO fork | -| `eip150_block` | `0` | EIP-150 (Gas cost changes) | -| `eip155_block` | `0` | EIP-155 (Replay protection) | -| `eip158_block` | `0` | EIP-158 (State trie clearing) | -| `byzantium_block` | `0` | Byzantium fork | -| `constantinople_block` | `0` | Constantinople fork | -| `petersburg_block` | `0` | Petersburg fork | -| `istanbul_block` | `0` | Istanbul fork | -| `muir_glacier_block` | `0` | Muir Glacier fork | -| `berlin_block` | `0` | Berlin fork | -| `london_block` | `0` | London fork (EIP-1559) | -| `arrow_glacier_block` | `0` | Arrow Glacier fork | -| `gray_glacier_block` | `0` | Gray Glacier fork | -| `merge_netsplit_block` | `0` | Merge fork | -| `shanghai_time` | `0` | Shanghai fork (timestamp-based) | -| `cancun_time` | `0` | Cancun fork (timestamp-based) | -| `prague_time` | `0` | Prague fork (timestamp-based) | -| `osaka_time` | `null` | Osaka fork (future) | -| `verkle_time` | `null` | Verkle fork (future) | - -### Fee Market Module (`feemarket`) - -| Parameter | Default | Valid Values | Modifiable | Description | -|--||--||-| -| `no_base_fee` | `false` | true/false | Yes | Disable EIP-1559 base fee | -| `base_fee` | `1000000000` | Any positive | Yes | Initial base fee (in wei) | -| `base_fee_change_denominator` | `8` | > 0 | Yes | Controls base fee adjustment speed | -| `elasticity_multiplier` | `2` | > 0 | Yes | Maximum block gas increase factor | -| `enable_height` | `0` | >= 0 | Yes | Block height to enable fee market | -| `min_gas_price` | `0` | >= 0 | Yes | Minimum gas price | -| `min_gas_multiplier` | `0.5` | 0-1 | Yes | Multiplier for minimum gas price | - -### ERC20 Module (`erc20`) - -| Parameter | Default | Valid Values | Modifiable | Description | -|--||--||-| -| `enable_erc20` | `true` | true/false | Yes | Enable ERC20 module | -| `permissionless_registration` | `true` | true/false | Yes | Allow anyone to register token pairs | -| `token_pairs` | `[]` | Array of pairs | Yes | Pre-registered IBC/ERC20 pairs | -| `native_precompiles` | `[]` | Contract addresses | Yes | Native token wrappers | - -### Standard Cosmos SDK Modules - -Standard parameters for mint, staking, distribution, gov, etc. follow Cosmos SDK defaults and can be modified through governance. - - -## Runtime Configuration (app.toml) - -These parameters can be changed by validators in their local `app.toml` file and take effect after node restart. - -### EVM Configuration - -| Parameter | Default | Valid Values | Description | -|--||--|-| -| `evm.tracer` | `""` | `"json"`, `"markdown"`, `"struct"`, `"access_list"` | EVM execution tracer | -| `evm.max-tx-gas-wanted` | `0` (unlimited) | Any uint64 | Maximum gas for a single transaction | -| `evm.cache-preimage` | `false` | true/false | Enable SHA3 preimage recording | -| `evm.min-tip` | `0` | Any uint64 | Minimum priority fee (tip) in wei | -| `evm.geth-metrics-address` | `"127.0.0.1:8100"` | IP:port | Geth metrics server address | - -### JSON-RPC Configuration - -| Parameter | Default | Valid Values | Description | -|--||--|-| -| `json-rpc.enable` | `false` | true/false | Enable JSON-RPC server | -| `json-rpc.address` | `"127.0.0.1:8545"` | IP:port | HTTP server address | -| `json-rpc.ws-address` | `"127.0.0.1:8546"` | IP:port | WebSocket server address | -| `json-rpc.api` | `["eth", "net", "web3"]` | Array of namespaces | Enabled API namespaces | -| `json-rpc.gas-cap` | `25000000` | Any uint64 | Gas cap for eth_call | -| `json-rpc.evm-timeout` | `"5s"` | Duration string | Timeout for eth_call | -| `json-rpc.txfee-cap` | `1.0` | Any float | Transaction fee cap in ether | -| `json-rpc.filter-cap` | `200` | Any int32 | Maximum number of filters | -| `json-rpc.feehistory-cap` | `100` | Any int32 | Maximum blocks in fee history | -| `json-rpc.logs-cap` | `10000` | Any int32 | Maximum logs per query | -| `json-rpc.block-range-cap` | `10000` | Any int32 | Maximum block range for logs | -| `json-rpc.http-timeout` | `"30s"` | Duration string | HTTP read/write timeout | -| `json-rpc.http-idle-timeout` | `"120s"` | Duration string | HTTP idle timeout | -| `json-rpc.allow-unprotected-txs` | `false` | true/false | Allow non-EIP155 transactions | -| `json-rpc.batch-request-limit` | `1000` | Any int | Maximum batch size | -| `json-rpc.batch-response-max-size` | `25000000` | Any int | Maximum batch response bytes | -| `json-rpc.max-open-connections` | `0` (unlimited) | Any int | Connection limit | -| `json-rpc.enable-indexer` | `false` | true/false | Enable custom indexer | -| `json-rpc.metrics-address` | `"127.0.0.1:6065"` | IP:port | Metrics server address | -| `json-rpc.ws-origins` | `["127.0.0.1", "localhost"]` | Array of origins | Allowed WebSocket origins | -| `json-rpc.allow-insecure-unlock` | `true` | true/false | Allow account unlocking via HTTP | -| `json-rpc.enable-profiling` | `false` | true/false | Enable debug profiling | - -#### Available JSON-RPC Namespaces - -- `web3`: Web3 specific methods -- `eth`: Ethereum JSON-RPC methods -- `net`: Network information -- `txpool`: Transaction pool inspection -- `debug`: Debugging methods (use with caution) -- `personal`: Account management (use with caution) -- `miner`: Mining methods (limited functionality) - -### TLS Configuration - -| Parameter | Default | Valid Values | Description | -|--||--|-| -| `tls.certificate-path` | `""` | File path | TLS certificate (.pem) | -| `tls.key-path` | `""` | File path | TLS private key (.pem) | - -### Standard Cosmos SDK Configuration - -Standard Cosmos SDK configurations in app.toml (API, gRPC, etc.) remain unchanged. - - -## Governance Modifiable Parameters - -These parameters can be changed through governance proposals after chain launch: - -### Standard Parameters (Immediately Effective) -- VM Module: `extra_eips`, `active_static_precompiles`, `evm_channels`, `access_control`, `history_serve_window` -- Fee Market: All parameters -- ERC20: All parameters -- Standard Cosmos SDK module parameters +**Where Configured**: Retrieved from app options in `app.go` -### Sensitive Parameters (Require Careful Coordination) -- `evm_chain_id` - Affects replay protection, requires validator coordination -- Token configuration (denom, decimals) - Core economic parameters, typically not changed -- Ethereum fork activation blocks/timestamps - Requires coordinated activation - - -## Custom EIPs and Extensions +### How to Change -Teams can implement custom EIPs by: -1. Creating activator functions in `eips/` directory -2. Registering in `DefaultCosmosEVMActivators` map -3. Adding EIP number to `extra_eips` in genesis + +The EVM chain ID **cannot** be changed after genesis without breaking transaction replay protection. Choose carefully before launch. + + +The EVM chain ID is retrieved from app options in `app.go`: + +```go +// evmd/app.go line ~216 +evmChainID := cast.ToUint64(appOpts.Get(srvflags.EVMChainID)) +``` + +You can set it via CLI flag when starting the chain: +```bash +yourchain start --evm.chain-id 262144 +``` + +Or configure it in `app.toml`: +```toml +[evm] +chain-id = 262144 +``` + +### Choosing an EVM Chain ID + + + +**Avoid these ranges**: +- `1` - Ethereum Mainnet +- `2-10` - Ethereum testnets +- `1-999` - Generally reserved by Ethereum Foundation +- `137` - Polygon +- Common production chains - Check [chainlist.org](https://chainlist.org) + + + +**For local development and testnets**: +- Use `262144` (evmd default) +- Or any high number unlikely to conflict +- No registration needed + + + +**For mainnet launches**: +- Choose a unique ID > 1,000,000 +- Register at [chainlist.org](https://chainlist.org) +- Verify no conflicts with existing chains +- Document your choice publicly + + + +--- + +## 4. Custom Opcodes + +**What It Is**: Custom EVM operations beyond standard Ethereum opcodes. + +**Default**: None + + +Custom opcodes are an advanced feature. Most chains should use standard Ethereum opcodes with the optional `extra_eips` parameter instead. + + +### Adding Extra EIPs + +Instead of custom opcodes, enable additional Ethereum Improvement Proposals: + +```json +{ + "app_state": { + "vm": { + "params": { + "extra_eips": [2200, 2929, 3198] + } + } + } +} +``` + +**Common EIPs**: +- `2200` - Net gas metering +- `2929` - Gas cost increases for state access +- `3198` - BASEFEE opcode +- `3529` - Reduction in refunds + + +For teams that need custom EVM functionality: + +1. Create activator functions in your chain's `eips/` directory +2. Register in the activators map +3. Add to `extra_eips` in genesis -Example: ```go -// x/vm/types/activators.go -var DefaultCosmosEVMActivators = map[int]func(*vm.JumpTable){ - 9999: myCustomEIP9999, +// yourchain/eips/custom.go +func ActivateMyCustomOpcode(jt *vm.JumpTable) { + // Define custom opcode behavior +} + +// Register in activators +var CustomActivators = map[int]func(*vm.JumpTable){ + 9999: ActivateMyCustomOpcode, } ``` -## Configuration Examples +Then in genesis: +```json +{ + "extra_eips": [9999] +} +``` + +This is rarely needed - consider if standard EVM functionality meets your needs first. + + +--- + +## 5. Token Pairs (ERC20 Module) + +**What It Is**: Mappings between Cosmos native tokens and ERC20 contract representations. + +**Default**: 1 pair for the native token + +### How to Configure + + +For comprehensive ERC20 module configuration, see the [ERC20 Module Documentation](/evm/next/documentation/cosmos-sdk/modules/erc20). + + +Token pairs are configured in genesis under the `erc20` module: + +```json +{ + "app_state": { + "erc20": { + "native_precompiles": [ + "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" + ], + "token_pairs": [ + { + "erc20_address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + "denom": "atest", + "enabled": true, + "contract_owner": 1 + } + ] + } + } +} +``` + +### Default Native Token Pair + +The evmd example uses a special ERC20 address for the native token: +- **Address**: `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` +- **Denom**: `atest` (or your chain's native denom) +- **Purpose**: Allows native tokens to be used in EVM contracts as ERC20 + + +**Default Setup**: Most chains start with just the native token pair. Additional pairs can be registered after launch through governance or permissionless registration (if enabled). + + +--- + +## 6. Token Denomination + +**What It Is**: Your chain's native token denomination and decimal precision. + +**Default**: `atest` (18 decimals, atto-prefix) + +### Understanding Token Configuration + +Token configuration involves three components: + +1. **Bank Metadata** - Defines denominations and decimals +2. **VM Parameters** - Specifies which denom is the EVM native token +3. **Extended Denom Options** - Required only for non-18 decimal tokens + + + +**Direct EVM Compatibility - No Extra Modules Needed** + +```json +{ + "app_state": { + "bank": { + "denom_metadata": [ + { + "description": "The native staking token", + "denom_units": [ + { + "denom": "atoken", // atto-prefix (18 decimals) + "exponent": 0, + "aliases": ["attotoken"] + }, + { + "denom": "token", // Display denomination + "exponent": 18 + } + ], + "base": "atoken", + "display": "token", + "name": "Token", + "symbol": "TOKEN" + } + ] + }, + "vm": { + "params": { + "evm_denom": "atoken" // Must match base + // No extended_denom_options needed! + } + } + } +} +``` + +**Benefits**: +- ✓ Direct 1:1 EVM mapping +- ✓ Uses standard `x/bank` module +- ✓ Simpler architecture +- ✓ No additional modules required + + + +**Requires PreciseBank Module** + +```json +{ + "app_state": { + "bank": { + "denom_metadata": [ + { + "denom_units": [ + { + "denom": "utoken", // micro-prefix (6 decimals) + "exponent": 0 + }, + { + "denom": "token", + "exponent": 6 + } + ], + "base": "utoken", + "display": "token" + } + ] + }, + "vm": { + "params": { + "evm_denom": "utoken", + "extended_denom_options": { + "extended_denom": "atoken" // 18-decimal EVM representation + } + } + } + } +} +``` + +**Additional Setup Required**: +- Must add `x/precisebank` module to `app.go` +- Precisebank handles fractional amounts (1 utoken = 10^12 wei) +- See [PreciseBank Module Docs](/evm/next/documentation/cosmos-sdk/modules/precisebank) + + +When using non-18 decimal tokens, you **must** add the precisebank module and configure the extended denom. Failure to do so will result in precision loss and incorrect balances. + + + + +**Also Requires PreciseBank** + +For chains using other decimal precisions (e.g., 8 decimals for Bitcoin compatibility): + +```json +{ + "bank": { + "denom_metadata": [{ + "denom_units": [ + {"denom": "sats", "exponent": 0}, // 8 decimals + {"denom": "btc", "exponent": 8} + ], + "base": "sats" + }] + }, + "vm": { + "params": { + "evm_denom": "sats", + "extended_denom_options": { + "extended_denom": "asats" // 18-decimal for EVM + } + } + } +} +``` + +Requires precisebank module with custom conversion factor. + + + +### Common Denomination Prefixes + +| Prefix | Decimals | Example | Used For | +|--------|----------|---------|----------| +| `a` (atto) | 18 | `atoken` | **EVM-compatible chains (recommended)** | +| `u` (micro) | 6 | `uatom`, `ustake` | Traditional Cosmos chains | +| Base | 0-8 | `sats` | Bitcoin-style | + + +**Recommendation**: Use 18 decimals (`atto` prefix) for new chains. This provides: +- Direct EVM compatibility +- Simpler codebase (no precisebank needed) +- Better UX for Ethereum users +- Standard across EVM ecosystems + + +### Setting Denomination in Genesis + +The denomination is set in multiple places that must be consistent: + +```bash +# After initializing your chain +GENESIS=~/.yourchain/config/genesis.json + +# Set denomination in all modules +jq '.app_state["staking"]["params"]["bond_denom"]="atoken"' $GENESIS > tmp && mv tmp $GENESIS +jq '.app_state["gov"]["params"]["min_deposit"][0]["denom"]="atoken"' $GENESIS > tmp && mv tmp $GENESIS +jq '.app_state["vm"]["params"]["evm_denom"]="atoken"' $GENESIS > tmp && mv tmp $GENESIS +jq '.app_state["mint"]["params"]["mint_denom"]="atoken"' $GENESIS > tmp && mv tmp $GENESIS + +# Set bank metadata +jq '.app_state["bank"]["denom_metadata"]=[{ + "description": "The native staking token", + "denom_units": [ + {"denom": "atoken", "exponent": 0, "aliases": ["attotoken"]}, + {"denom": "token", "exponent": 18, "aliases": []} + ], + "base": "atoken", + "display": "token", + "name": "Token", + "symbol": "TOKEN" +}]' $GENESIS > tmp && mv tmp $GENESIS +``` + + +**Critical**: The following must all use the same base denomination: +- `staking.params.bond_denom` +- `mint.params.mint_denom` +- `gov.params.min_deposit[0].denom` +- `vm.params.evm_denom` +- `bank.denom_metadata[0].base` + + +--- + +## 7. EVM Permissioning + +**What It Is**: Access control for deploying and calling smart contracts. + +**Default**: Permissionless (anyone can deploy and call contracts) + +### How to Configure + +EVM permissions are set in genesis under `vm.params.access_control`: + + + +```json +{ + "app_state": { + "vm": { + "params": { + "access_control": { + "create": { + "access_type": 0, // 0 = PERMISSIONLESS + "access_control_list": [] + }, + "call": { + "access_type": 0, + "access_control_list": [] + } + } + } + } + } +} +``` + +**Use Case**: Public chains, testnets, open ecosystems + + + +```json +{ + "access_control": { + "create": { + "access_type": 2, // 2 = PERMISSIONED (allowlist) + "access_control_list": [ + "0x1234567890123456789012345678901234567890", + "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" + ] + }, + "call": { + "access_type": 0, // Keep calls open + "access_control_list": [] + } + } +} +``` + +**Use Case**: Enterprise chains, regulated environments, controlled contract deployment + + + +```json +{ + "access_control": { + "create": { + "access_type": 1, // 1 = RESTRICTED (blocklist) + "access_control_list": [ + "0xbadaddr1234567890123456789012345678901234" + ] + }, + "call": { + "access_type": 0, + "access_control_list": [] + } + } +} +``` + +**Use Case**: Blocking known malicious addresses while keeping chain open + + + +```json +{ + "access_control": { + "create": { + "access_type": 1, // RESTRICTED with empty list = block all + "access_control_list": [] + }, + "call": { + "access_type": 1, + "access_control_list": [] + } + } +} +``` + +**Use Case**: Chains that only use predeployed contracts, no user deployments + + + +### Access Control Types + +| Type | Value | Behavior | access_control_list | +|------|-------|----------|---------------------| +| **Permissionless** | `0` | Anyone can perform action | Ignored | +| **Restricted** | `1` | Block addresses in list | Blocklist | +| **Permissioned** | `2` | Only addresses in list | Allowlist | + + +**Recommendation**: Start with permissionless for testnets. For mainnets, consider permissioned deployment initially, then transition to permissionless through governance once the chain is stable. + + +### Modifying After Genesis + +Access control can be changed through governance proposals: + +```bash +# Example: Enable permissionless deployment via governance +yourchain tx gov submit-proposal param-change proposal.json \ + --from validator \ + --chain-id yourchain-1 +``` + +--- + +## 8. Enabled Precompiles + +**What It Is**: Native Cosmos SDK functionality exposed as EVM smart contracts. + +**Default**: All 9 static precompiles enabled + +### Available Precompiles + + +For complete precompile documentation including Solidity interfaces and usage examples, see the [Precompiles Overview](/docs/evm/next/documentation/smart-contracts/precompiles/overview). + + +| Address | Name | Description | Typical Use Case | +|---------|------|-------------|------------------| +| `0x0100` | **P256** | P256 cryptographic operations | Web3 auth, secure signing | +| `0x0400` | **Bech32** | Cosmos ↔ Ethereum address conversion | Cross-chain operations | +| `0x0800` | **Staking** | Validator staking operations | Liquid staking, auto-compounding | +| `0x0801` | **Distribution** | Reward distribution queries | Reward dashboards, auto-claiming | +| `0x0802` | **ICS20** | IBC token transfers | Cross-chain DeFi | +| `0x0803` | **Vesting** | Vesting account management | Token vesting contracts | +| `0x0804` | **Bank** | Native token transfers | Payment contracts | +| `0x0805` | **Governance** | On-chain voting | DAO integration | +| `0x0806` | **Slashing** | Validator slashing info | Validator monitoring | + +### How to Configure + + + +```json +{ + "app_state": { + "vm": { + "params": { + "active_static_precompiles": [ + "0x0000000000000000000000000000000000000100", + "0x0000000000000000000000000000000000000400", + "0x0000000000000000000000000000000000000800", + "0x0000000000000000000000000000000000000801", + "0x0000000000000000000000000000000000000802", + "0x0000000000000000000000000000000000000803", + "0x0000000000000000000000000000000000000804", + "0x0000000000000000000000000000000000000805", + "0x0000000000000000000000000000000000000806" + ] + } + } + } +} +``` + +**Use Case**: Maximum Cosmos SDK integration, full-featured chains + + + +```json +{ + "active_static_precompiles": [ + "0x0000000000000000000000000000000000000100", // P256 + "0x0000000000000000000000000000000000000400", // Bech32 + "0x0000000000000000000000000000000000000800", // Staking + "0x0000000000000000000000000000000000000804" // Bank + ] +} +``` + +**Use Case**: Minimal attack surface, only enable what you need + + + +```json +{ + "active_static_precompiles": [] +} +``` + +**Use Case**: Pure EVM chains with no Cosmos SDK integration + + + +Set defaults in your chain's genesis configuration: + +```go +// yourchain/genesis.go +func NewDefaultVMGenesisState() *vmtypes.GenesisState { + evmGenState := vmtypes.DefaultGenesisState() + + // Enable only specific precompiles + evmGenState.Params.ActiveStaticPrecompiles = []string{ + "0x0000000000000000000000000000000000000100", // P256 + "0x0000000000000000000000000000000000000800", // Staking + "0x0000000000000000000000000000000000000804", // Bank + } + + return evmGenState +} +``` + + + + +**Security Consideration**: Only enable precompiles your chain actually needs. Each enabled precompile increases the attack surface and testing complexity. + + +### Modifying After Genesis + +Precompiles can be enabled or disabled through governance: + +```bash +# Propose adding a precompile +yourchain tx gov submit-proposal param-change proposal.json \ + --from validator +``` + +--- + +## Configuration Workflow + +Here's the recommended order for configuring your chain: + + + +Decide on: +- Binary name +- Chain IDs (Cosmos and EVM) +- Token denomination and decimals +- Precompiles needed +- Access control policy + + + +```bash +# Rename binary +mv evmd yourchain + +# Update references +find . -type f -name "*.go" -exec sed -i 's/evmd/yourchain/g' {} \; + +# Update go.mod +# Edit module path +``` + + + +```bash +yourchain init mynode --chain-id yourchain-1 +``` + + + +Edit `~/.yourchain/config/genesis.json`: + +```bash +GENESIS=~/.yourchain/config/genesis.json + +# Set denominations +jq '.app_state.staking.params.bond_denom="atoken"' $GENESIS > tmp && mv tmp $GENESIS +jq '.app_state.vm.params.evm_denom="atoken"' $GENESIS > tmp && mv tmp $GENESIS + +# Set bank metadata +# Set precompiles +# Set access control +``` + + + +Edit `~/.yourchain/config/app.toml`: -### Minimal Production Configuration ```toml -# app.toml [evm] -min-tip = 1000000000 # 1 gwei minimum tip +chain-id = 262144 # Set EVM chain ID +min-tip = 1000000000 [json-rpc] enable = true -api = ["eth", "net", "web3"] address = "0.0.0.0:8545" -gas-cap = 50000000 -allow-unprotected-txs = false ``` + + + +```bash +yourchain start +``` + +Verify: +- Chain starts successfully +- RPC is accessible +- Precompiles are enabled +- Token denomination is correct + + + +For production: +- Coordinate genesis with validators +- Distribute final genesis file +- Launch at coordinated time + + + +--- + +## Configuration Examples + +### Reference: local_node.sh + + +**Looking for a real-world example?** The `local_node.sh` script in the Cosmos EVM repository is the best reference for complete chain configuration. It demonstrates how evmd sets up genesis and app.toml for local development. + + +The `local_node.sh` script performs all the configuration steps automatically. Here's what it does: + + + +The script modifies `genesis.json` to configure: + +- **Chain ID**: Sets to `cosmos_262144-1` +- **Token denomination**: Configures `atest` (18 decimals) across all modules +- **Bank metadata**: Sets up denom metadata with proper exponents +- **Precompiles**: Enables all 9 static precompiles by default +- **Validator configuration**: Creates genesis validator with initial stake +- **Genesis accounts**: Funds test accounts for development + + +View the genesis configuration logic in `local_node.sh` to see exactly how evmd modifies genesis parameters for local development. + + + + +The script configures `app.toml` with development-friendly settings: -### Development Configuration ```toml -# app.toml [evm] -tracer = "json" +chain-id = 262144 +tracer = "json" # Enable EVM tracing for debugging +min-tip = 0 # No minimum tip for local testing [json-rpc] enable = true -api = ["eth", "net", "web3", "txpool", "debug", "personal"] address = "0.0.0.0:8545" ws-address = "0.0.0.0:8546" -allow-unprotected-txs = true -enable-indexer = true +api = ["eth", "net", "web3", "txpool", "debug"] # All APIs for testing +allow-unprotected-txs = true # Allow unsigned txs locally +enable-indexer = true # Enable transaction indexing ``` -## Additional Resources +These settings are optimized for local development and should be adjusted for production. + + + +The `local_node.sh` script accepts flags that control configuration: + +- **`-y`**: Overwrites previous database (fresh genesis) +- **`-n`**: Preserves previous database (resume) +- **`--no-install`**: Skips binary rebuild +- **`--remote-debugging`**: Builds with debug symbols + +Example usage: +```bash +# Fresh start with all default configurations +./local_node.sh -y + +# Resume from previous state +./local_node.sh -n +``` + + + +To use `local_node.sh` as a template for your chain: + +1. **Copy the script**: `cp local_node.sh my_chain_setup.sh` +2. **Update chain name**: Change `evmd` to your binary name +3. **Modify genesis values**: Update denom, chain ID, precompiles +4. **Adjust app.toml settings**: Configure for your use case (testnet/mainnet) +5. **Add custom logic**: Include any chain-specific setup + +The script serves as a complete example of the configuration workflow described in this guide. + + + + +**Production Considerations**: The `local_node.sh` configuration is optimized for local development. For testnets and mainnets: +- Disable debug APIs in JSON-RPC +- Require transaction signatures (`allow-unprotected-txs = false`) +- Set appropriate `min-tip` value +- Use secure key management (not test keys) +- Configure proper peer discovery and networking + + +--- + +### Complete 18-Decimal Chain + + +```bash init.sh +#!/bin/bash +# Initialize and configure an 18-decimal chain + +BINARY="yourchain" +CHAIN_ID="yourchain-1" +EVM_CHAIN_ID="262144" +DENOM="atoken" +GENESIS=~/.yourchain/config/genesis.json + +# Initialize +$BINARY init mynode --chain-id $CHAIN_ID + +# Configure denominations +jq ".app_state.staking.params.bond_denom=\"$DENOM\"" $GENESIS > tmp && mv tmp $GENESIS +jq ".app_state.mint.params.mint_denom=\"$DENOM\"" $GENESIS > tmp && mv tmp $GENESIS +jq ".app_state.gov.params.min_deposit[0].denom=\"$DENOM\"" $GENESIS > tmp && mv tmp $GENESIS +jq ".app_state.vm.params.evm_denom=\"$DENOM\"" $GENESIS > tmp && mv tmp $GENESIS + +# Set bank metadata (18 decimals) +jq ".app_state.bank.denom_metadata=[{ + \"description\": \"The native staking token\", + \"denom_units\": [ + {\"denom\": \"$DENOM\", \"exponent\": 0, \"aliases\": [\"attotoken\"]}, + {\"denom\": \"token\", \"exponent\": 18, \"aliases\": []} + ], + \"base\": \"$DENOM\", + \"display\": \"token\", + \"name\": \"Token\", + \"symbol\": \"TOKEN\" +}]" $GENESIS > tmp && mv tmp $GENESIS + +# Enable specific precompiles +jq '.app_state.vm.params.active_static_precompiles=[ + "0x0000000000000000000000000000000000000100", + "0x0000000000000000000000000000000000000400", + "0x0000000000000000000000000000000000000800", + "0x0000000000000000000000000000000000000804" +]' $GENESIS > tmp && mv tmp $GENESIS + +echo "Configuration complete!" +``` + +```toml app.toml +[evm] +chain-id = 262144 +min-tip = 1000000000 # 1 gwei +cache-preimage = false + +[json-rpc] +enable = true +address = "0.0.0.0:8545" +ws-address = "0.0.0.0:8546" +api = ["eth", "net", "web3", "txpool"] +gas-cap = 25000000 +allow-unprotected-txs = false +``` + + +### Complete 6-Decimal Chain with PreciseBank + + +```bash init-6-decimal.sh +#!/bin/bash +# Initialize and configure a 6-decimal chain + +BINARY="yourchain" +CHAIN_ID="yourchain-1" +EVM_CHAIN_ID="262144" +BASE_DENOM="utoken" +EXTENDED_DENOM="atoken" +GENESIS=~/.yourchain/config/genesis.json + +# Initialize +$BINARY init mynode --chain-id $CHAIN_ID + +# Configure denominations +jq ".app_state.staking.params.bond_denom=\"$BASE_DENOM\"" $GENESIS > tmp && mv tmp $GENESIS +jq ".app_state.mint.params.mint_denom=\"$BASE_DENOM\"" $GENESIS > tmp && mv tmp $GENESIS +jq ".app_state.gov.params.min_deposit[0].denom=\"$BASE_DENOM\"" $GENESIS > tmp && mv tmp $GENESIS +jq ".app_state.vm.params.evm_denom=\"$BASE_DENOM\"" $GENESIS > tmp && mv tmp $GENESIS + +# Set bank metadata (6 decimals) +jq ".app_state.bank.denom_metadata=[{ + \"description\": \"The native staking token\", + \"denom_units\": [ + {\"denom\": \"$BASE_DENOM\", \"exponent\": 0}, + {\"denom\": \"token\", \"exponent\": 6} + ], + \"base\": \"$BASE_DENOM\", + \"display\": \"token\", + \"name\": \"Token\", + \"symbol\": \"TOKEN\" +}]" $GENESIS > tmp && mv tmp $GENESIS + +# Set extended denom options (REQUIRED for 6 decimals) +jq ".app_state.vm.params.extended_denom_options={ + \"extended_denom\": \"$EXTENDED_DENOM\" +}" $GENESIS > tmp && mv tmp $GENESIS + +echo "Configuration complete! Remember to add precisebank module to app.go" +``` + +```go app.go +// In app.go, you must add precisebank module: + +import ( + precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper" + precisebanktypes "github.com/cosmos/evm/x/precisebank/types" +) + +// Add to store keys +keys := storetypes.NewKVStoreKeys( + // ... other keys + precisebanktypes.StoreKey, +) + +// Initialize PreciseBankKeeper +app.PreciseBankKeeper = precisebankkeeper.NewKeeper( + appCodec, + keys[precisebanktypes.StoreKey], + app.BankKeeper, + app.AccountKeeper, +) + +// Use PreciseBankKeeper in EVMKeeper +app.EVMKeeper = evmkeeper.NewKeeper( + // ... + app.PreciseBankKeeper, // Not app.BankKeeper! + // ... +) + +// Add to module manager +app.ModuleManager = module.NewManager( + // ... other modules + precisebank.NewAppModule(app.PreciseBankKeeper, app.AccountKeeper), + // ... +) + +// Add to genesis order (after bank, before vm) +genesisModuleOrder := []string{ + // ... + banktypes.ModuleName, + precisebanktypes.ModuleName, + evmtypes.ModuleName, + // ... +} +``` + + +--- + +## Next Steps + +Now that your chain is configured: + +1. **Test Locally**: Use `./local_node.sh` to test all configurations +2. **Deploy Contracts**: Verify precompiles work as expected +3. **Set Up Validators**: Prepare for testnet/mainnet launch +4. **Document Configuration**: Share configuration choices with users +5. **Plan Governance**: Determine which parameters may change post-launch + +### Further Reading + + + +Complete guide to forking and customizing evmd + + + +Detailed migration instructions for v0.5 + + + +VM module configuration and parameters + + + +Fractional balance tracking for non-18-decimal chains + + + +--- -- [GitHub Repository](https://github.com/cosmos/evm) \ No newline at end of file +For additional support, visit the [Cosmos EVM GitHub repository](https://github.com/cosmos/evm) or join the Cosmos developer community. diff --git a/docs/evm/next/documentation/migrations/migration-v0.4-to-v0.5.mdx b/docs/evm/next/documentation/migrations/migration-v0.4-to-v0.5.mdx index 38534311..ce4d6f67 100644 --- a/docs/evm/next/documentation/migrations/migration-v0.4-to-v0.5.mdx +++ b/docs/evm/next/documentation/migrations/migration-v0.4-to-v0.5.mdx @@ -1,50 +1,18 @@ --- title: "Migration: v0.4.x to v0.5.0" ------- - - -**This migration contains breaking changes that require code updates** - -v0.5.0 introduces significant changes to precompile interfaces, VM parameters, mempool architecture, and ante handlers. Review all breaking changes before upgrading. - - -## Breaking Changes Summary - -- [VM Parameters](#vm-parameter-changes): `allow_unprotected_txs` removed, `history_serve_window` added -- [Precompile Interfaces](#precompile-interface-changes): All constructors now use keeper interfaces -- [Mempool Architecture](#mempool-changes): Configuration-based approach replaces pre-built pools -- [Ante Handler Optimization](#ante-handler-changes): EVM instance removal and performance improvements -- [Global Mempool Removal](#global-mempool-removal): Direct injection replaces singleton pattern - -## New Features - -- [EIP-7702 Support](#eip-7702-eoa-code-delegation): EOA code delegation for account abstraction -- [EIP-2935 Support](#eip-2935-block-hash-storage): Block hash storage implementation -- [eth_createAccessList](#new-rpc-methods): Access list creation RPC method -- [Performance Optimizations](#performance-improvements): Gas estimation and state management improvements - --- -## 0) Preparation - -Create an upgrade branch and prepare your environment: +## 0) Prep -```bash -git switch -c upgrade/evm-v0.5 -go test ./... -evmd export > pre-upgrade-genesis.json -``` +- Create a branch: `git switch -c upgrade/evm-v0.5`. +- Ensure a clean build + tests green pre-upgrade. +- Snapshot your current params/genesis for comparison later. --- -## 1) Dependency Updates +## 1) Dependency bumps (go.mod) -### Update go.mod - -```diff -- github.com/cosmos/evm v0.4.1 -+ github.com/cosmos/evm v0.5.0 -``` +- Bump `github.com/cosmos/evm` to v0.5.0 and run: ```bash go mod tidy @@ -52,593 +20,316 @@ go mod tidy --- -## 2) VM Parameter Changes - -### BREAKING: allow_unprotected_txs Parameter Removed - -The `allow_unprotected_txs` parameter has been removed from VM module parameters. Non-EIP-155 transaction acceptance is now managed per-node. +## 2) Fix `"github.com/cosmos/evm/types" imports` -**Migration Required:** +`v0.5.0` removes `github.com/cosmos/evm/types` and moves files to their folders, respective to function. +For a complete list of changes, refer to [this PR](https://github.com/cosmos/evm/pull/639). The +following list includes references within `evmd` that have been moved. -1. **Update Genesis Files:** +### Summary of import changes in `evmd`: +**Removed import:** ```diff -{ - "app_state": { - "vm": { - "params": { - "evm_denom": "atest", - "extra_eips": [], -- "allow_unprotected_txs": false, - "evm_channels": [], - "access_control": {...}, - "active_static_precompiles": [...], -+ "history_serve_window": 8192 - } - } - } -} +- cosmosevmtypes "github.com/cosmos/evm/types" ``` -2. **Update Parameter Validation:** - -If you have custom parameter validation logic, remove references to `allow_unprotected_txs`: - +**Added imports:** ```diff -// Remove any code referencing AllowUnprotectedTxs -- if !params.AllowUnprotectedTxs { -- // validation logic -- } -``` - -### NEW: history_serve_window Parameter ++ antetypes "github.com/cosmos/evm/ante/types" ++ evmaddress "github.com/cosmos/evm/encoding/address" ++ "github.com/cosmos/evm/utils" +``` + +### Detailed mapping of moved items: + +- **`AttoPowerReduction`** → moved to `"github.com/cosmos/evm/utils"` + ```diff + - sdk.DefaultPowerReduction = cosmosevmtypes.AttoPowerReduction + + sdk.DefaultPowerReduction = utils.AttoPowerReduction + ``` + +- **`HasDynamicFeeExtensionOption`** → moved to `"github.com/cosmos/evm/ante/types"` + ```diff + - ExtensionOptionChecker: cosmosevmtypes.HasDynamicFeeExtensionOption, + + ExtensionOptionChecker: antetypes.HasDynamicFeeExtensionOption, + ``` + +- **Address Codec functions** → new package `"github.com/cosmos/evm/encoding/address"` + + Use `evmaddress.NewEvmCodec()` for address codec initialization: + ```go + app.AccountKeeper = authkeeper.NewAccountKeeper( + appCodec, + runtime.NewKVStoreService(keys[authtypes.StoreKey]), + authtypes.ProtoBaseAccount, + evmconfig.GetMaccPerms(), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + sdk.GetConfig().GetBech32AccountAddrPrefix(), + authAddr, + ) + ``` -Added for EIP-2935 block hash storage support. +- **`Bip44CoinType`, `BIP44HDPath`** → moved to `"github.com/cosmos/evm/crypto/hd"` -- **Default value:** `8192` blocks -- **Purpose:** Controls how many historical block hashes to serve -- **Range:** Must be > 0, recommended ≤ 8192 for optimal performance +- **`GenesisState`** → removed as a duplicate object can be found in the `evmd` folder and a testing version is in `"github.com/cosmos/evm/testutil"` --- -## 3) Precompile Interface Changes - -### BREAKING: Constructor Interface Updates - -All precompile constructors now accept keeper interfaces instead of concrete implementations for better decoupling. - -**New Interface Definitions:** - -```go New Interface Definitions expandable -// precompiles/common/interfaces.go -type BankKeeper interface { - IterateAccountBalances(ctx context.Context, account sdk.AccAddress, cb func(coin sdk.Coin) bool) - GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin - SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error - // ... other methods -} - -type StakingKeeper interface { - BondDenom(ctx context.Context) (string, error) - GetDelegatorValidators(ctx context.Context, delegatorAddr sdk.AccAddress, maxRetrieve uint32) (stakingtypes.Validators, error) - // ... other methods -} -``` - -**Migration Steps:** - -1. **Update Precompile Assembly:** - -```diff Precompile Assembly Update expandable -// evmd/precompiles.go or app/precompiles.go -func NewAvailableStaticPrecompiles( - // ... other params -) map[common.Address]vm.PrecompiledContract { - precompiles := make(map[common.Address]vm.PrecompiledContract) - - // Bank precompile - interface now required -- bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, ...) -+ bankPrecompile, err := bankprecompile.NewPrecompile( -+ common.BankKeeper(bankKeeper), // Cast to interface -+ // ... other params -+ ) - - // Distribution precompile - simplified parameters -- distributionPrecompile, err := distributionprecompile.NewPrecompile( -- distributionKeeper, stakingKeeper, authzKeeper, cdc, options.AddressCodec -- ) -+ distributionPrecompile, err := distributionprecompile.NewPrecompile( -+ common.DistributionKeeper(distributionKeeper), -+ cdc, options.AddressCodec -+ ) - - // Staking precompile - keeper interface -- stakingPrecompile, err := stakingprecompile.NewPrecompile(stakingKeeper, ...) -+ stakingPrecompile, err := stakingprecompile.NewPrecompile( -+ common.StakingKeeper(stakingKeeper), -+ // ... other params -+ ) - - return precompiles -} -``` - -2. **Update Custom Precompiles:** - -If you have custom precompiles, update their constructors to accept interfaces: - -```diff -// Custom precompile constructor -- func NewMyPrecompile(bankKeeper bankkeeper.Keeper, stakingKeeper stakingkeeper.Keeper) (*MyPrecompile, error) { -+ func NewMyPrecompile(bankKeeper common.BankKeeper, stakingKeeper common.StakingKeeper) (*MyPrecompile, error) { - return &MyPrecompile{ - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - }, nil -} -``` - ---- +## 3) App wiring in `app.go` -## 4) Mempool Changes +### Mempool -### Configuration-Based Architecture +#### Minimal setups: nothing to change -The mempool now uses configuration objects instead of pre-built pools for better flexibility. +If you use the default mempool wiring (no custom pools), your existing code continues to work. If `BlockGasLimit` is 0, it defaults to `100_000_000`. If `BroadCastTxFn` is not set, it's also set to a default value. -**Migration for Standard Setups:** - -If you use default mempool configuration, minimal changes are needed: - -```go Standard Mempool Setup expandable -// Existing code continues to work +```go mempoolConfig := &evmmempool.EVMMempoolConfig{ AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, // or 0 for default + BlockGasLimit: 100_000_000, // or 0 to use default } evmMempool := evmmempool.NewExperimentalEVMMempool( - app.CreateQueryContext, - logger, - app.EVMKeeper, - app.FeeMarketKeeper, - app.txConfig, - app.clientCtx, - mempoolConfig + app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, app.clientCtx, mempoolConfig ) ``` -**Migration for Advanced Setups:** +#### Advanced setups: migrate your customizations + +PR [#496](https://github.com/cosmos/evm/pull/496) replaced pre-built pools with configs in `EVMMempoolConfig`: + +- Replace pools with configs + - Removed: `TxPool *txpool.TxPool`, `CosmosPool sdkmempool.ExtMempool` + - Added: `LegacyPoolConfig *legacypool.Config`, `CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int]` -If you previously built custom pools: +If you built custom pools yourself: -```diff Advanced Mempool Configuration expandable +```diff mempoolConfig := &evmmempool.EVMMempoolConfig{ -- TxPool: customTxPool, -- CosmosPool: customCosmosPool, -+ LegacyPoolConfig: &legacypool.Config{ -+ PriceLimit: 2, -+ // ... other legacy pool settings -+ }, -+ CosmosPoolConfig: &sdkmempool.PriorityNonceMempoolConfig[math.Int]{ -+ TxPriority: sdkmempool.TxPriority[math.Int]{ -+ GetTxPriority: customPriorityFunc, -+ Compare: math.IntComparator, -+ MinValue: math.ZeroInt(), -+ }, -+ }, +- TxPool: customTxPool, +- CosmosPool: customCosmosPool, ++ LegacyPoolConfig: &legacyCfg, // or nil for defaults ++ CosmosPoolConfig: &cosmosCfg, // or nil for defaults AnteHandler: app.GetAnteHandler(), - BroadcastTxFn: customBroadcastFunc, // optional - BlockGasLimit: 100_000_000, + BroadCastTxFn: myBroadcast, // optional } ``` ---- - -## 5) Ante Handler Changes - -### Performance Optimizations - -The ante handler system has been optimized to remove unnecessary EVM instance creation. +Example custom configs: -**What Changed:** -- `CanTransfer` ante decorator no longer creates StateDB instances -- EVM instance removal improves performance for balance checks -- Signature verification optimizations - -**Migration Impact:** -- **Standard setups:** No changes required -- **Custom ante handlers:** Verify compatibility with new `CanTransfer` behavior - -**Custom Ante Handler Updates:** - -If you have custom ante handlers that depend on EVM instance creation during balance checks: - -```diff -// Custom ante handler example -func (d MyCustomDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { - // Balance checking now optimized - no EVM instance creation -- evm := d.evmKeeper.NewEVM(ctx, ...) -- stateDB := evm.StateDB -- balance := stateDB.GetBalance(address) - - // Use keeper method instead -+ balance := d.evmKeeper.GetBalance(ctx, address) - - return next(ctx, tx, simulate) +```go +// EVM legacy txpool tuning +legacyCfg := legacypool.DefaultConfig +legacyCfg.PriceLimit = 2 +mempoolConfig.LegacyPoolConfig = &legacyCfg + +// Cosmos priority mempool tuning +cosmosCfg := sdkmempool.PriorityNonceMempoolConfig[math.Int]{} +cosmosCfg.TxPriority = sdkmempool.TxPriority[math.Int]{ + GetTxPriority: func(goCtx context.Context, tx sdk.Tx) math.Int { + // Custom priority function + }, + Compare: func(a, b math.Int) int { return a.BigInt().Cmp(b.BigInt()) }, + MinValue: math.ZeroInt(), } -``` - -#### Field Mapping (v0.4.x → v0.5.0) +mempoolConfig.CosmosPoolConfig = &cosmosCfg -- Removed fields: - - `TxPool` (pre-built EVM pool) - - `CosmosPool` (pre-built Cosmos pool) - -- New/Replacement fields: - - `LegacyPoolConfig` (configure legacy EVM txpool behavior) - - `CosmosPoolConfig` (configure Cosmos `PriorityNonceMempool` behavior) - - `BlockGasLimit` (required; `0` uses fallback `100_000_000`) - - `BroadcastTxFn` (optional callback; defaults to broadcasting via `clientCtx`) - - `MinTip` (optional minimum tip for EVM selection) - ---- - -## 6) Global Mempool Removal - -### BREAKING: Singleton Pattern Eliminated - -The global mempool registry has been removed in favor of direct injection. - -**What Was Removed:** -- `mempool.SetGlobalEVMMempool()` -- `mempool.GetGlobalEVMMempool()` -- Global mempool singleton pattern - -**Migration Steps:** - -1. **Update JSON-RPC Server Initialization:** - -```diff JSON-RPC Server Update expandable -// server/start.go or equivalent -- mempool.SetGlobalEVMMempool(evmMempool) - - jsonRPCServer, err := jsonrpc.StartJSONRPC( - ctx, - clientCtx, - logger.With("module", "jsonrpc"), -+ evmMempool, // Pass mempool directly - config, - indexer, - ) +// Custom EVM broadcast (optional) +mempoolConfig.BroadCastTxFn = func(txs []*ethtypes.Transaction) error { return nil } ``` -2. **Update RPC Backend:** +#### New Configuration Options -If you have custom RPC backends: +PR [#698](https://github.com/cosmos/evm/pull/698) adds new configuration options for the EVM mempool that can be set via `app.toml` or CLI flags. These options allow fine-tuning of the EVM legacy pool behavior. -```diff Custom RPC Backend Update expandable -// Custom RPC backend -func NewCustomBackend( - // ... other params -+ mempool *evmmempool.ExperimentalEVMMempool, -) *CustomBackend { -- mempool := mempool.GetGlobalEVMMempool() +##### Configuration via `app.toml` - return &CustomBackend{ - mempool: mempool, - // ... other fields - } -} -``` +The following mempool configuration options are now available in `app.toml` under the `[evm.mempool]` section: ---- +```toml +[evm.mempool] +# PriceLimit is the minimum gas price to enforce for acceptance into the pool (in wei) +price-limit = 1 -## 7) EIP-7702 EOA Code Delegation +# PriceBump is the minimum price bump percentage to replace an already existing transaction (nonce) +price-bump = 10 -### NEW FEATURE: Account Abstraction for EOAs +# AccountSlots is the number of executable transaction slots guaranteed per account +account-slots = 16 -EIP-7702 enables externally owned accounts to temporarily execute smart contract code through authorization lists. +# GlobalSlots is the maximum number of executable transaction slots for all accounts +global-slots = 5120 -**What's New:** -- **SetCodeTx Transaction Type:** New transaction type supporting code delegation -- **Authorization Signatures:** Signed permissions for code delegation -- **Temporary Execution:** EOAs can execute contract logic for single transactions -- **Account Abstraction:** Multi-sig, time-locks, automated strategies +# AccountQueue is the maximum number of non-executable transaction slots permitted per account +account-queue = 64 -**Implementation:** [`x/vm/keeper/state_transition.go:426+`](https://github.com/cosmos/evm/blob/main/x/vm/keeper/state_transition.go#L426) +# GlobalQueue is the maximum number of non-executable transaction slots for all accounts +global-queue = 1024 -**Usage Example:** -```javascript -// Enable EOA to execute as multicall contract -const authorization = await signAuthorization({ - chainId: 9000, - address: multicallContractAddress, - nonce: await wallet.getNonce(), -}, wallet); - -const tx = { - type: 4, // SetCodeTxType - authorizationList: [authorization], - to: wallet.address, - data: multicall.interface.encodeFunctionData("batchCall", [calls]), - gasLimit: 500000, -}; - -await wallet.sendTransaction(tx); +# Lifetime is the maximum amount of time non-executable transaction are queued +lifetime = "3h0m0s" ``` -**Developer Impact:** -- **Enhanced Wallets:** EOAs can have programmable features -- **Better UX:** Batched operations, custom validation logic -- **Account Abstraction:** Multi-sig and advanced security features -- **No Migration:** Existing EOAs enhanced without changes +##### Configuration via CLI Flags ---- +These options can also be set via CLI flags: -## 8) EIP-2935 Block Hash Storage +- `--evm.mempool.price-limit` (default: 1) +- `--evm.mempool.price-bump` (default: 10) +- `--evm.mempool.account-slots` (default: 16) +- `--evm.mempool.global-slots` (default: 5120) +- `--evm.mempool.account-queue` (default: 64) +- `--evm.mempool.global-queue` (default: 1024) +- `--evm.mempool.lifetime` (default: 3h0m0s) -### NEW FEATURE: Historical Block Hash Access +##### Cosmos Mempool Max Transactions -EIP-2935 provides standardized access to historical block hashes via contract storage. +A new flag `--mempool.max-txs` allows limiting the maximum number of transactions in the Cosmos mempool. Set to 0 or -1 for unbounded (default: 0). -**What's New:** -- `BLOCKHASH` opcode now queries contract storage for historical hashes -- New `history_serve_window` parameter controls storage depth -- Compatible with Ethereum's EIP-2935 specification +##### Simplified Mempool Setup -**Configuration:** +The mempool configuration can now be handled by a helper function. If you prefer to use the configuration from `app.toml` and CLI flags, you can refactor your mempool setup: ```go -// Genesis parameter -"history_serve_window": 8192 // Default: 8192 blocks -``` - -**Usage for Developers:** - -```solidity -// Smart contract can now reliably access historical block hashes -contract HistoryExample { - function getRecentBlockHash(uint256 blockNumber) public view returns (bytes32) { - // Works for blocks within history_serve_window range - return blockhash(blockNumber); - } -} -``` - -**Performance Considerations:** -- Larger `history_serve_window` values increase storage requirements -- Default of 8192 provides good balance of utility and performance -- Values > 8192 may impact node performance - ---- - -## 8) New RPC Methods - -### eth_createAccessList - -New JSON-RPC method for creating access lists to optimize transaction costs. - -**Usage:** - -```bash -curl -X POST \ - -H "Content-Type: application/json" \ - --data '{ - "jsonrpc": "2.0", - "method": "eth_createAccessList", - "params": [{ - "to": "0x...", - "data": "0x...", - "gas": "0x...", - "gasPrice": "0x..." - }, "latest"], - "id": 1 - }' \ - http://localhost:8545 -``` - -**Response:** - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "accessList": [ - { - "address": "0x...", - "storageKeys": ["0x..."] - } - ], - "gasUsed": "0x..." - } +// Before: Manual configuration in app.go +mempoolConfig := &evmmempool.EVMMempoolConfig{ + AnteHandler: app.GetAnteHandler(), + BlockGasLimit: blockGasLimit, + MinTip: minTip, } -``` - ---- - -## 9) Performance Improvements - -### Gas Estimation Optimization - -- **Short-circuit plain transfers:** Simple ETH transfers now bypass complex gas estimation -- **Optimistic bounds:** Uses `MaxUsedGas` for better initial estimates -- **Result:** Significantly faster `eth_estimateGas` performance - -### State Management - -- **Reduced EVM instances:** Fewer unnecessary EVM instance creations -- **Storage optimizations:** Empty storage checks implemented per EIP standards -- **Block notifications:** Improved timing prevents funding errors - -### Mempool Enhancements - -- **Nonce gap handling:** Better error handling for transaction sequencing -- **Configuration flexibility:** Tunable parameters for different network conditions - ---- - -## 10) Testing Your Migration - -### Pre-Upgrade Checklist - -```bash Pre-Upgrade Checklist expandable -# 1. Backup current state -evmd export > pre-upgrade-state.json - -# 2. Document existing parameters -evmd query vm params > pre-upgrade-params.json - -# 3. Note active precompiles -evmd query erc20 token-pairs > pre-upgrade-token-pairs.json -``` - -### Post-Upgrade Verification - -```bash Post-Upgrade Verification expandable -# 1. Verify node starts successfully -evmd start - -# 2. Test EVM functionality -cast send --rpc-url http://localhost:8545 --private-key $PRIVATE_KEY \ - 0x... "transfer(address,uint256)" 0x... 1000 - -# 3. Verify new RPC methods -curl -X POST \ - -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_createAccessList","params":[...],"id":1}' \ - http://localhost:8545 - -# 4. Test precompile functionality -cast call 0x... "balanceOf(address)" 0x... --rpc-url http://localhost:8545 - -# 5. Verify EIP-2935 support -cast call --rpc-url http://localhost:8545 \ - $CONTRACT_ADDRESS "getBlockHash(uint256)" $BLOCK_NUMBER -``` +evmMempool := evmmempool.NewExperimentalEVMMempool( + app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, + app.txConfig, app.clientCtx, mempoolConfig, +) -### Integration Tests - -```go Integration Test Example expandable -// Example integration test -func TestV050Migration(t *testing.T) { - // Test mempool configuration - config := &evmmempool.EVMMempoolConfig{ - AnteHandler: anteHandler, - BlockGasLimit: 100_000_000, - } - mempool := evmmempool.NewExperimentalEVMMempool(...) - require.NotNil(t, mempool) - - // Test precompile interfaces - bankPrecompile, err := bankprecompile.NewPrecompile( - common.BankKeeper(bankKeeper), - ) - require.NoError(t, err) - - // Test parameter validation - params := vmtypes.NewParams(...) - require.Equal(t, uint64(8192), params.HistoryServeWindow) - require.False(t, hasAllowUnprotectedTxs(params)) // Should be removed +// After: Using helper function (optional) +// See evmd/mempool.go for reference implementation +if err := app.configureEVMMempool(appOpts, logger); err != nil { + panic(fmt.Sprintf("failed to configure EVM mempool: %s", err.Error())) } ``` ---- - -## 11) Rollback Plan - -If issues arise during migration: +The helper function reads configuration from `appOpts` and applies defaults where needed. Note that `NewExperimentalEVMMempool` now takes an additional `cosmosPoolMaxTx` parameter. -```bash -# 1. Stop the upgraded node -systemctl stop evmd +### Default Precompiles -# 2. Restore pre-upgrade binary -cp evmd-v0.4.1 /usr/local/bin/evmd +Default precompiles have been moved to `/evm/precompiles/types/defaults.go` and the function name was +changed to `DefaultStaticPrecompiles`. The function signature has also changed, and now takes pointers +as inputs for the `Erc20Keeper` and `TransferKeeper`. Finally, the `WithStaticPrecompiles` builder +function can now happen *alongside the keeper instantiation*, and not after. The new wiring is shown below: -# 3. Restore pre-upgrade genesis (if needed) -cp pre-upgrade-genesis.json ~/.evmd/config/genesis.json +```go + app.EVMKeeper = evmkeeper.NewKeeper( + appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys, + authtypes.NewModuleAddress(govtypes.ModuleName), + app.AccountKeeper, + app.PreciseBankKeeper, + app.StakingKeeper, + app.FeeMarketKeeper, + &app.ConsensusParamsKeeper, + &app.Erc20Keeper, + tracer, + ).WithStaticPrecompiles( + precompiletypes.DefaultStaticPrecompiles( + *app.StakingKeeper, + app.DistrKeeper, + app.PreciseBankKeeper, + &app.Erc20Keeper, // UPDATED + &app.TransferKeeper, // UPDATED + app.IBCKeeper.ChannelKeeper, + app.GovKeeper, + app.SlashingKeeper, + appCodec, + ), + ) +``` + +### Denom Configs + +[#661](https://github.com/cosmos/evm/pull/661) removes the instantiation of chain configs via app.go +and moves them to state or genesis. +It is critical to remove any use of EvmAppOptions as calling the configurator will panic the chain +at runtime during startup. + +#### EVM Chain ID + +The EVM chain ID is now retrieved directly from `appOpts` instead of being passed as a parameter. In `app.go`, the chain ID is obtained using: -# 4. Restart with previous version -systemctl start evmd +```go +evmChainID := cast.ToUint64(appOpts.Get(srvflags.EVMChainID)) ``` ---- - -## 12) Common Migration Issues - -### Issue: Precompile Constructor Errors +See `evmd/app.go:216` for the reference implementation. -``` -error: cannot use bankKeeper (type bankkeeper.Keeper) as type common.BankKeeper -``` +#### Function Signature Changes -**Solution:** Cast concrete keepers to interfaces: +In `app.go`, remove evmChainID and evmAppOptions from the NewApp signature. -```go -bankPrecompile, err := bankprecompile.NewPrecompile( - common.BankKeeper(bankKeeper), // Add interface cast -) +```diff +// NewExampleApp returns a reference to an initialized EVMD. +func NewExampleApp( + logger log.Logger, + db dbm.DB, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, +- evmChainID uint64, +- evmAppOptions evmconfig.EVMOptionsFn, + baseAppOptions ...func(*baseapp.BaseApp), +) *EVMD { ``` -### Issue: Genesis Validation Failure +Afterwards, fix any reference to the function by removing the inputs. -``` -error: unknown field 'allow_unprotected_txs' in vm params -``` +Then, remove any reference of evmAppOptions being called: -**Solution:** Remove the parameter from genesis: - -```bash -# Update genesis.json to remove allow_unprotected_txs -# Add history_serve_window with default value 8192 +`app.go` +```diff +- if err := evmAppOptions(evmChainID); err != nil { +- panic(err) +- } ``` -### Issue: Mempool Initialization Panic - +`root.go` +```diff +- noOpEvmAppOptions := func(_ uint64) error { +- return nil +- } ``` -panic: config must not be nil +```diff +- if initClientCtx.ChainID != "" { +- if err := config.EvmAppOptions(config.EVMChainID); err != nil { +- panic(err) +- } +- } ``` -**Solution:** Always provide mempool configuration: +`evmd_config.go`, `chain_id.go`, `config.go`, `constants.go` have been moved to +`github.com/cosmos/evm/config` and may be removed to your repo. -```go -config := &evmmempool.EVMMempoolConfig{ - AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, -} -``` +#### UpgradeHandler -### Issue: Global Mempool Access +As the configs have been moved to state and genesis, you must include an UpgradeHandler if your chain does +not satisfy the following conditions. +1. Your EVM Denom set in the `x/vm` params must have `DenomMetadata` registered for it in `x/bank`. +2. Your EVM Denom must have a display denom associated with it in `DenomMetadata`. + 1. The display denom for the EVM Denom must have an accurate decimal value (i.e. for `uatom`, `atom` must have a decimal value of 6. +3. Your chain is an 18-decimal chain. -``` -error: undefined: mempool.GetGlobalEVMMempool -``` +In your UpgradeHandler: -**Solution:** Pass mempool directly instead of using global access: +- **If your chain does not have DenomMetadata set for the EVM Denom, you must include it.** +- **If your chain's EVM denom is *not* 18 decimals, you must add ExtendedDenomOptions to your `x/vm` params.** -```go -// Pass mempool as parameter -func NewRPCService(mempool *evmmempool.ExperimentalEVMMempool) { - // Use injected mempool -} -``` +Please refer to the [upgrade example](https://github.com/cosmos/evm/blob/0995962c2fd77a7a23e93001d5a531abbb1b61e5/evmd/upgrades.go) for more information. --- -## 13) Summary +## 3) Build & quick tests -v0.5.0 introduces significant improvements in performance, EVM compatibility, and code architecture: - -- **EIP-2935** enables reliable historical block hash access -- **Precompile interfaces** improve modularity and testing -- **Mempool optimizations** provide better configurability -- **Performance improvements** reduce gas estimation latency -- **New RPC methods** enhance developer experience - -Review all breaking changes carefully and test thoroughly before deploying to production. +```bash +go build ./... +``` -For additional support, refer to: -- [Precompiles Documentation](../smart-contracts/precompiles/overview) -- [EVM Compatibility Guide](../evm-compatibility/overview) -- [Performance Optimization Guide](../concepts/performance) +Smoke test on a single node: +- Send a few EVM txs; confirm promotion/broadcast (or your `BroadCastTxFn`). +- Send Cosmos txs; confirm ordering reflects your `CosmosPoolConfig` (if customized). \ No newline at end of file