VM 模块(x/vm)是核心的 EVM 实现,使 Cosmos 链具备与以太坊兼容的能力。它提供 EVM 运行时、状态管理、预编译合约以及交易处理。

模块概览

用途:在 Cosmos SDK 框架内执行以太坊智能合约并处理 EVM 交易 核心功能:
  • EVM 状态转换与交易执行
  • 以太坊分叉激活管理(Homestead、Berlin、London、Shanghai、Cancun、Prague 等)
  • 用于访问 Cosmos 模块的原生预编译合约
  • EVM 到 Cosmos 以及 Cosmos 到 EVM 的账户桥接
  • Gas 计量与手续费处理
  • 支持可配置保留策略的历史状态查询
源码:x/vm 参数默认值:x/vm/types/params.go

配置方式

VM 模块可在链启动前通过 genesis.json 进行配置。以下是三种主要方式:

方式 1:直接编辑 JSON

直接编辑 ~/.evmd/config/genesis.json:
{
  "app_state": {
    "vm": {
      "params": {
        "evm_denom": "atest",
        "extra_eips": [3855],
        "active_static_precompiles": ["0x0000000000000000000000000000000000000800"],
        "access_control": {
          "create": {"access_type": 0},
          "call": {"access_type": 0}
        }
      }
    }
  }
}

方式 2:使用 jq 命令行工具

使用 jq 以编程方式修改 genesis(如 local_node.sh 所示):

# Set evm_denom
jq '.app_state["vm"]["params"]["evm_denom"]="atest"' genesis.json > tmp.json && mv tmp.json genesis.json


# Enable all precompiles (matches x/vm/types/precompiles.go:22-32)
jq '.app_state["vm"]["params"]["active_static_precompiles"]=[
  "0x0000000000000000000000000000000000000100",  # P256
  "0x0000000000000000000000000000000000000400",  # Bech32
  "0x0000000000000000000000000000000000000800",  # Staking
  "0x0000000000000000000000000000000000000801",  # Distribution
  "0x0000000000000000000000000000000000000802",  # ICS20
  "0x0000000000000000000000000000000000000803",  # Vesting
  "0x0000000000000000000000000000000000000804",  # Bank
  "0x0000000000000000000000000000000000000805",  # Governance
  "0x0000000000000000000000000000000000000806"   # Slashing
]' genesis.json > tmp.json && mv tmp.json genesis.json


# Enable extra EIP
jq '.app_state["vm"]["params"]["extra_eips"]=[3855]' genesis.json > tmp.json && mv tmp.json genesis.json

方式 3:使用 genesis CLI 命令

部分参数可通过 CLI 命令设置(不过大多数 VM 参数仍需编辑 genesis.json):

# Genesis file is created with:
evmd init <moniker> --chain-id <chain-id>


# Then manually edit genesis.json for VM params

# No direct CLI command for VM param modification

参数

evm_denom

作用:指定将哪个 bank 模块面额作为原生 EVM 代币(Gas 代币)。 类型:string 有效值:必须与 bank 元数据配置中的某个基础面额一致 默认值:"uatom"(params.go:21) 配置方式:

# Using jq
jq '.app_state["vm"]["params"]["evm_denom"]="atest"' genesis.json > tmp.json && mv tmp.json genesis.json
{
  "vm": {
    "params": {
      "evm_denom": "atest"
    }
  }
}
关键要求:
  • 必须与 bank.denom_metadata[0].base 一致
  • 必须与 staking.params.bond_denom 一致
  • 必须与 mint.params.mint_denom 一致
影响:这是用户为 EVM Gas 支付的代币,会显示在 MetaMask 余额中,并用于所有 EVM 操作。 示例:
  • "atest" - 适用于 18 位小数代币(atto 前缀:10^18)
  • "ustake" - 适用于 6 位小数代币(micro 前缀:10^6)
常见错误:
  • 与 bank 元数据不一致会导致 EVM 交易失败
  • 小数位设置错误会导致余额显示不正确

extra_eips

作用:启用默认分叉激活之外的额外以太坊改进提案。 类型:[]int64(EIP 编号数组) 有效值:任意可激活的 EIP 编号 默认值:[](空,即所有 EIP 都来自 chain_config 分叉配置)(params.go:22) 配置方式:

# Using jq
jq '.app_state["vm"]["params"]["extra_eips"]=[3855, 2929]' genesis.json > tmp.json && mv tmp.json genesis.json
{
  "vm": {
    "params": {
      "extra_eips": [3855, 2929]
    }
  }
}
常见 EIP:
EIP说明典型用途
3855PUSH0 指令合约的 Gas 优化
2200SSTORE 的净 Gas 计量降低 Gas 成本
2929提高状态访问的 Gas 成本强化安全性
3198BASEFEE 操作码查询 EIP-1559 基础费
3529减少退款Gas 计费规则变更
校验:会对照可激活 EIP 列表进行检查(params.go:182-200) 影响:
  • 启用默认分叉配置中未包含的操作码或特性
  • 适合测试即将到来的以太坊特性
  • 如果管理不当,可能破坏兼容性
建议:除非你需要为自定义合约或测试启用特定 EIP,否则保持为空

active_static_precompiles

作用:列出要启用的预编译合约地址,以便从 EVM 访问 Cosmos 模块。 类型:[]string(十六进制地址数组) 有效值:来自可用预编译列表的地址(precompiles.go:4-15) 默认值:[](空,即不启用任何预编译)(params.go:23) 配置方式:

# Using jq - Enable all precompiles (from local_node.sh:243)
jq '.app_state["vm"]["params"]["active_static_precompiles"]=[
  "0x0000000000000000000000000000000000000100",
  "0x0000000000000000000000000000000000000400",
  "0x0000000000000000000000000000000000000800",
  "0x0000000000000000000000000000000000000801",
  "0x0000000000000000000000000000000000000802",
  "0x0000000000000000000000000000000000000803",
  "0x0000000000000000000000000000000000000804",
  "0x0000000000000000000000000000000000000805",
  "0x0000000000000000000000000000000000000806"
]' genesis.json > tmp.json && mv tmp.json genesis.json
{
  "vm": {
    "params": {
      "active_static_precompiles": [
        "0x0000000000000000000000000000000000000100",
        "0x0000000000000000000000000000000000000400",
        "0x0000000000000000000000000000000000000800"
      ]
    }
  }
}
可用预编译:
地址名称模块说明
0x0100P256密码学P256 椭圆曲线操作
0x0400Bech32地址在 Bech32 与十六进制地址之间转换
0x0800Stakingx/staking委托、取消委托、重委托操作
0x0801Distributionx/distribution领取质押奖励、设置提现地址
0x0802ICS20IBC Transfer通过 EVM 进行 IBC 代币转账
0x0803Vestingx/vesting锁仓账户操作
0x0804Bankx/bank原生 Cosmos 代币转账
0x0805Govx/gov提交并投票治理提案
0x0806Slashingx/slashing查询验证者惩罚信息
生产环境建议:
  • 仅启用必需的预编译,以提升安全性和 Gas 效率
  • 常见启用项:0x0100(P256)、0x0400(Bech32)、0x0800(Staking)、0x0804(Bank)
  • IBC 链:额外启用 0x0802(ICS20)
  • 参与治理:启用 0x0805(Gov)
安全说明:每启用一个预编译都会扩大攻击面。只启用你的应用实际会使用的预编译。 默认 evmd 示例:为方便开发,会启用全部预编译(local_node.sh:243)

evm_channels

作用:ICS20 预编译可用于代币转账的 IBC 通道 ID 白名单。 类型:[]string(通道 ID 数组) 有效值:符合 channel-{N} 格式的通道 ID,其中 N 为非负整数 默认值:[](空,即没有白名单通道)(params.go:24) 配置方式:
{
  "vm": {
    "params": {
      "evm_channels": ["channel-0", "channel-5", "channel-42"]
    }
  }
}
校验:每个通道都必须匹配正则模式(params.go:80-96) 影响:
  • 限制 ICS20 预编译(0x0802)可通过哪些 IBC 通道转移代币
  • 空列表表示 ICS20 预编译不能执行任何 IBC 转账
  • 为跨链代币流动提供安全控制
何时配置:
  • 仅在启用 ICS20 预编译(0x0802)时需要
  • 与其他链建立 IBC 连接后设置
  • 新增 IBC 路由时通过治理进行更新
示例用例:仅允许通过特定通道向受信任链发起 IBC 转账

access_control

作用:定义合约部署(CREATE/CREATE2)和合约调用的权限模型。 类型:包含 create 和 call 字段的对象,每个字段都包含 access_type 和可选的 access_control_list 有效值:
  • access_type:0(无许可)、1(受限)、2(许可制)
  • access_control_list:地址数组(仅在受限或许可制模式下使用)
默认值:两者都为无许可(params.go:30-48) 配置方式:
{
  "vm": {
    "params": {
      "access_control": {
        "create": {
          "access_type": 2,
          "access_control_list": [
            "0x1234567890123456789012345678901234567890",
            "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd"
          ]
        },
        "call": {
          "access_type": 0
        }
      }
    }
  }
}
访问类型: 类型 0 - 无许可(默认):
  • 任何人都可以执行该操作
  • 标准以太坊行为
  • 推荐用于公链
类型 1 - 受限:
  • 除 access_control_list 中地址外,其他人都可以执行该操作
  • 黑名单模型
  • 适合屏蔽特定恶意参与者
类型 2 - 许可制:
  • 只有 access_control_list 中的地址可以执行该操作
  • 白名单模型
  • 适用于私有链、联盟链或分阶段启动
常见配置: 公链(默认):
{
  "create": {"access_type": 0},
  "call": {"access_type": 0}
}
许可部署,公开使用:
{
  "create": {
    "access_type": 2,
    "access_control_list": ["0x..."]
  },
  "call": {"access_type": 0}
}
校验:约束规则定义见(params.go:140-180) 影响:
  • 控制谁可以部署合约(这对链安全非常重要)
  • 控制谁可以调用已有合约(很少会限制)
  • 可在上线后通过治理提案更新
建议:公共 EVM 链使用类型 0(无许可),以保持与以太坊的兼容性

history_serve_window

作用:保留用于历史 EVM 查询(eth_getBlockByNumber、eth_getLogs 等)的最近区块数量。 类型:uint64 有效值:任何非负整数 默认值:8192 个区块(params.go:50) 配置:
{
  "vm": {
    "params": {
      "history_serve_window": 8192
    }
  }
}
影响: 存储:
  • 窗口越大,所需磁盘空间越多
  • 窗口越小,磁盘占用越少
  • 每个区块都会存储 EVM 状态差异和回执
查询能力:
  • 超出 history_serve_window 的查询会失败
  • 区块浏览器需要足够的历史数据来响应用户查询
  • DeFi 分析可能需要更长的历史数据
性能:
  • 非常大的窗口可能会降低状态裁剪速度
  • 会影响数据库大小和同步时间
常见取值:
  • 8192 - 默认值(按 5 秒出块计算,约 11 小时)
  • 100000 - 扩展历史(按 5 秒出块计算,约 5.8 天)
  • 1000000 - 完整历史(按 5 秒出块计算,约 58 天)
  • 0 - 不保留历史(不建议用于 RPC 节点)
建议:
  • 归档节点:设置为非常大的数字或 0(无限制)
  • RPC 节点:100,000 - 1,000,000 个区块
  • 验证者节点:可使用默认值 8192(验证者不提供 RPC)
相关:与 EIP-2935 配合使用,以支持历史区块哈希访问

extended_denom_options

作用:为非 18 位小数的 Cosmos 代币启用 18 位小数的 EVM 表示。像 ustake 这样的 6 位小数代币必须配置。 类型:[]ExtendedDenomOption - 将 Cosmos denom 映射到 EVM 扩展 denom 的对象数组 有效值:每个条目都必须包含符合扩展 denom 模式的有效 denom 对 默认值:[](空,即没有扩展 denom)(params.go:25) 配置:
{
  "vm": {
    "params": {
      "extended_denom_options": [
        {
          "native_denom": "ustake",
          "extended_denom": "astake"
        }
      ]
    }
  }
}
何时必需:
  • 18 位小数:不需要,标准 bank 模块即可工作
  • 6 位小数:必须,必须添加 extended_denom_options
  • 其他小数位:必须,必须添加 extended_denom_options
扩展 Denom 模式:
  • u 前缀(micro,10^6)→ a 前缀(atto,10^18):ustake → astake
  • n 前缀(nano,10^9)→ a 前缀(atto,10^18):ntoken → atoken
  • 其他任意情况 → 添加 evm 前缀:stake → evmstake
工作原理:
  1. 原生 6 位小数代币:ustake(最小单位)
  2. 扩展后的 18 位小数表示:astake(供 EVM 使用)
  3. 1 ustake = 10^12 astake
  4. PreciseBank 模块处理分数换算
示例:6 位小数代币:
{
  "app_state": {
    "vm": {
      "params": {
        "evm_denom": "ustake",
        "extended_denom_options": [
          {
            "native_denom": "ustake",
            "extended_denom": "astake"
          }
        ]
      }
    }
  }
}
相关配置:需要在 app.go 中包含 PreciseBank Module

完整配置示例

基于 local_node.sh:
#!/bin/bash

GENESIS="$HOME/.evmd/config/genesis.json"
TMP_GENESIS="$HOME/.evmd/config/tmp_genesis.json"


# Set EVM denomination
jq '.app_state["vm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"


# Enable all precompiles for development
jq '.app_state["vm"]["params"]["active_static_precompiles"]=[
  "0x0000000000000000000000000000000000000100",
  "0x0000000000000000000000000000000000000400",
  "0x0000000000000000000000000000000000000800",
  "0x0000000000000000000000000000000000000801",
  "0x0000000000000000000000000000000000000802",
  "0x0000000000000000000000000000000000000803",
  "0x0000000000000000000000000000000000000804",
  "0x0000000000000000000000000000000000000805",
  "0x0000000000000000000000000000000000000806"
]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"


# Validate genesis
evmd genesis validate-genesis --home "$HOME/.evmd"
或者直接在 genesis.json 中配置:
{
  "app_state": {
    "vm": {
      "params": {
        "evm_denom": "atest",
        "extra_eips": [],
        "active_static_precompiles": [
          "0x0000000000000000000000000000000000000100",
          "0x0000000000000000000000000000000000000400",
          "0x0000000000000000000000000000000000000800",
          "0x0000000000000000000000000000000000000801",
          "0x0000000000000000000000000000000000000802",
          "0x0000000000000000000000000000000000000803",
          "0x0000000000000000000000000000000000000804",
          "0x0000000000000000000000000000000000000805",
          "0x0000000000000000000000000000000000000806"
        ],
        "evm_channels": [],
        "access_control": {
          "create": {
            "access_type": 0
          },
          "call": {
            "access_type": 0
          }
        },
        "history_serve_window": 8192,
        "extended_denom_options": []
      },
      "chain_config": {
        "chain_id": "9001",
        "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"
      }
    }
  }
}

相关文档


源代码参考


The VM module (x/vm) is the core EVM implementation that enables Ethereum compatibility on Cosmos chains. It provides the EVM runtime, state management, precompiled contracts, and transaction processing.

Module Overview

Purpose: Execute Ethereum smart contracts and process EVM transactions within the Cosmos SDK framework Key Functionality:
  • EVM state transitions and transaction execution
  • Ethereum fork activation management (Homestead, Berlin, London, Shanghai, Cancun, Prague, etc.)
  • Native precompiled contracts for Cosmos module access
  • EVM-to-Cosmos and Cosmos-to-EVM account bridging
  • Gas metering and fee handling
  • Historical state queries with configurable retention
Source Code: x/vm Parameter Defaults: x/vm/types/params.go

Configuration Methods

The VM module can be configured through genesis.json before chain launch. Here are the three primary methods:

Method 1: Direct JSON Editing

Edit ~/.evmd/config/genesis.json directly:
{
  "app_state": {
    "vm": {
      "params": {
        "evm_denom": "atest",
        "extra_eips": [3855],
        "active_static_precompiles": ["0x0000000000000000000000000000000000000800"],
        "access_control": {
          "create": {"access_type": 0},
          "call": {"access_type": 0}
        }
      }
    }
  }
}

Method 2: Using jq Command-Line Tool

Programmatically modify genesis using jq (as seen in local_node.sh):
# Set evm_denom
jq '.app_state["vm"]["params"]["evm_denom"]="atest"' genesis.json > tmp.json && mv tmp.json genesis.json

# Enable all precompiles (matches x/vm/types/precompiles.go:22-32)
jq '.app_state["vm"]["params"]["active_static_precompiles"]=[
  "0x0000000000000000000000000000000000000100",  # P256
  "0x0000000000000000000000000000000000000400",  # Bech32
  "0x0000000000000000000000000000000000000800",  # Staking
  "0x0000000000000000000000000000000000000801",  # Distribution
  "0x0000000000000000000000000000000000000802",  # ICS20
  "0x0000000000000000000000000000000000000803",  # Vesting
  "0x0000000000000000000000000000000000000804",  # Bank
  "0x0000000000000000000000000000000000000805",  # Governance
  "0x0000000000000000000000000000000000000806"   # Slashing
]' genesis.json > tmp.json && mv tmp.json genesis.json

# Enable extra EIP
jq '.app_state["vm"]["params"]["extra_eips"]=[3855]' genesis.json > tmp.json && mv tmp.json genesis.json

Method 3: Using genesis CLI Commands

Some parameters can be set through CLI commands (though most VM params require genesis.json editing):
# Genesis file is created with:
evmd init <moniker> --chain-id <chain-id>

# Then manually edit genesis.json for VM params
# No direct CLI command for VM param modification

Parameters

evm_denom

What It Does: Specifies which bank module denomination to use as the native EVM token (gas token). Type: string Valid Values: Must match a base denomination from bank metadata configuration Default: "uatom" (params.go:21) Configuration:
# Using jq
jq '.app_state["vm"]["params"]["evm_denom"]="atest"' genesis.json > tmp.json && mv tmp.json genesis.json
{
  "vm": {
    "params": {
      "evm_denom": "atest"
    }
  }
}
Critical Requirements:
  • MUST match bank.denom_metadata[0].base
  • MUST match staking.params.bond_denom
  • MUST match mint.params.mint_denom
Impact: This is the token users pay for EVM gas, displayed in MetaMask balances, and used for all EVM operations. Examples:
  • "atest" - For 18 decimal token (atto prefix: 10^18)
  • "ustake" - For 6 decimal token (micro prefix: 10^6)
Common Errors:
  • Mismatch with bank metadata causes EVM transactions to fail
  • Wrong decimal places leads to incorrect balance displays

extra_eips

What It Does: Enables additional Ethereum Improvement Proposals beyond the default fork activations. Type: []int64 (array of EIP numbers) Valid Values: Any activatable EIP number Default: [] (empty - all EIPs come from chain_config fork configuration) (params.go:22) Configuration:
# Using jq
jq '.app_state["vm"]["params"]["extra_eips"]=[3855, 2929]' genesis.json > tmp.json && mv tmp.json genesis.json
{
  "vm": {
    "params": {
      "extra_eips": [3855, 2929]
    }
  }
}
Common EIPs:
EIPDescriptionTypical Use Case
3855PUSH0 instructionGas optimization for contracts
2200Net gas metering for SSTOREReduces gas costs
2929Gas cost increases for state accessSecurity hardening
3198BASEFEE opcodeEIP-1559 base fee queries
3529Reduction in refundsGas accounting changes
Validation: Checked against list of activatable EIPs (params.go:182-200) Impact:
  • Enables opcodes/features not in your default fork configuration
  • Useful for testing upcoming Ethereum features
  • Can break compatibility if not carefully managed
Recommendation: Leave empty unless you need specific EIPs for custom contracts or testing

active_static_precompiles

What It Does: List of precompiled contract addresses to enable for Cosmos module access from EVM. Type: []string (array of hex addresses) Valid Values: Addresses from the available precompiles list (precompiles.go:4-15) Default: [] (empty - no precompiles enabled) (params.go:23) Configuration:
# Using jq - Enable all precompiles (from local_node.sh:243)
jq '.app_state["vm"]["params"]["active_static_precompiles"]=[
  "0x0000000000000000000000000000000000000100",
  "0x0000000000000000000000000000000000000400",
  "0x0000000000000000000000000000000000000800",
  "0x0000000000000000000000000000000000000801",
  "0x0000000000000000000000000000000000000802",
  "0x0000000000000000000000000000000000000803",
  "0x0000000000000000000000000000000000000804",
  "0x0000000000000000000000000000000000000805",
  "0x0000000000000000000000000000000000000806"
]' genesis.json > tmp.json && mv tmp.json genesis.json
{
  "vm": {
    "params": {
      "active_static_precompiles": [
        "0x0000000000000000000000000000000000000100",
        "0x0000000000000000000000000000000000000400",
        "0x0000000000000000000000000000000000000800"
      ]
    }
  }
}
Available Precompiles:
AddressNameModuleDescription
0x0100P256CryptographyP256 elliptic curve operations
0x0400Bech32AddressingConvert between Bech32 and hex addresses
0x0800Stakingx/stakingDelegate, undelegate, redelegate operations
0x0801Distributionx/distributionClaim staking rewards, set withdrawal address
0x0802ICS20IBC TransferIBC token transfers via EVM
0x0803Vestingx/vestingVesting account operations
0x0804Bankx/bankNative Cosmos token transfers
0x0805Govx/govSubmit and vote on governance proposals
0x0806Slashingx/slashingQuery validator slashing info
Production Recommendations:
  • Enable only needed precompiles for security and gas efficiency
  • Commonly enabled: 0x0100 (P256), 0x0400 (Bech32), 0x0800 (Staking), 0x0804 (Bank)
  • IBC chains: Also enable 0x0802 (ICS20)
  • Governance participation: Enable 0x0805 (Gov)
Security Note: Each enabled precompile increases attack surface. Only enable precompiles your applications will actually use. Default evmd Example: Enables ALL precompiles for development convenience (local_node.sh:243)

evm_channels

What It Does: Whitelisted IBC channel IDs that the ICS20 precompile can use for token transfers. Type: []string (array of channel IDs) Valid Values: Channel IDs matching format channel-{N} where N is a non-negative integer Default: [] (empty - no channels whitelisted) (params.go:24) Configuration:
{
  "vm": {
    "params": {
      "evm_channels": ["channel-0", "channel-5", "channel-42"]
    }
  }
}
Validation: Each channel must match regex pattern (params.go:80-96) Impact:
  • Restricts which IBC channels the ICS20 precompile (0x0802) can transfer tokens through
  • Empty list means ICS20 precompile cannot perform any IBC transfers
  • Provides security control over cross-chain token movements
When to Configure:
  • Only needed if you enable ICS20 precompile (0x0802)
  • Set after establishing IBC connections with other chains
  • Update via governance when adding new IBC routes
Example Use Case: Enable IBC transfers only to trusted chains via specific channels

access_control

What It Does: Defines permission model for contract deployment (CREATE/CREATE2) and contract calls. Type: Object with create and call fields, each containing access_type and optional access_control_list Valid Values:
  • access_type: 0 (Permissionless), 1 (Restricted), 2 (Permissioned)
  • access_control_list: Array of addresses (only used with Restricted or Permissioned)
Default: Permissionless for both (params.go:30-48) Configuration:
{
  "vm": {
    "params": {
      "access_control": {
        "create": {
          "access_type": 2,
          "access_control_list": [
            "0x1234567890123456789012345678901234567890",
            "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd"
          ]
        },
        "call": {
          "access_type": 0
        }
      }
    }
  }
}
Access Types: Type 0 - Permissionless (Default):
  • Anyone can perform the operation
  • Standard Ethereum behavior
  • Recommended for public chains
Type 1 - Restricted:
  • Everyone EXCEPT addresses in access_control_list can perform operation
  • Blacklist model
  • Useful for blocking specific malicious actors
Type 2 - Permissioned:
  • ONLY addresses in access_control_list can perform operation
  • Whitelist model
  • Useful for private/consortium chains or phased launches
Common Configurations: Public Chain (Default):
{
  "create": {"access_type": 0},
  "call": {"access_type": 0}
}
Permissioned Deployment, Public Usage:
{
  "create": {
    "access_type": 2,
    "access_control_list": ["0x..."]
  },
  "call": {"access_type": 0}
}
Validation: Enforced in (params.go:140-180) Impact:
  • Controls who can deploy contracts (important for chain security)
  • Controls who can call existing contracts (rarely restricted)
  • Can be updated via governance proposals after launch
Recommendation: Use Type 0 (Permissionless) for public EVM chains to maintain Ethereum compatibility

history_serve_window

What It Does: Number of recent blocks to keep for historical EVM queries (eth_getBlockByNumber, eth_getLogs, etc.). Type: uint64 Valid Values: Any non-negative integer Default: 8192 blocks (params.go:50) Configuration:
{
  "vm": {
    "params": {
      "history_serve_window": 8192
    }
  }
}
Impact: Storage:
  • Larger window = more disk space required
  • Smaller window = less disk space usage
  • Each block stores EVM state diffs and receipts
Query Capability:
  • Queries beyond history_serve_window will fail
  • Block explorers need sufficient history for user queries
  • DeFi analytics may require longer history
Performance:
  • Very large windows can slow down state pruning
  • Affects database size and sync time
Common Values:
  • 8192 - Default (roughly 11 hours at 5s blocks)
  • 100000 - Extended history (roughly 5.8 days at 5s blocks)
  • 1000000 - Full history (roughly 58 days at 5s blocks)
  • 0 - No history retention (not recommended for RPC nodes)
Recommendations:
  • Archive Nodes: Set to very large number or 0 (unlimited)
  • RPC Nodes: 100,000 - 1,000,000 blocks
  • Validator Nodes: Can use default 8192 (validators don’t serve RPC)
Related: Works with EIP-2935 for historical block hash access

extended_denom_options

What It Does: Enables 18-decimal EVM representation for non-18-decimal Cosmos tokens. Required for 6-decimal tokens like ustake. Type: []ExtendedDenomOption - Array of objects mapping Cosmos denoms to EVM extended denoms Valid Values: Each entry must have a valid denom pair following the extended denom pattern Default: [] (empty - no extended denoms) (params.go:25) Configuration:
{
  "vm": {
    "params": {
      "extended_denom_options": [
        {
          "native_denom": "ustake",
          "extended_denom": "astake"
        }
      ]
    }
  }
}
When Required:
  • 18 decimals: NOT required - standard bank module works
  • 6 decimals: REQUIRED - must add extended_denom_options
  • Other decimals: REQUIRED - must add extended_denom_options
Extended Denom Patterns:
  • u prefix (micro, 10^6) → a prefix (atto, 10^18): ustake → astake
  • n prefix (nano, 10^9) → a prefix (atto, 10^18): ntoken → atoken
  • Any other → add evm prefix: stake → evmstake
How It Works:
  1. Native 6-decimal token: ustake (smallest unit)
  2. Extended 18-decimal representation: astake (for EVM)
  3. 1 ustake = 10^12 astake
  4. PreciseBank module handles fractional conversions
Example: 6 Decimal Token:
{
  "app_state": {
    "vm": {
      "params": {
        "evm_denom": "ustake",
        "extended_denom_options": [
          {
            "native_denom": "ustake",
            "extended_denom": "astake"
          }
        ]
      }
    }
  }
}
Related Configuration: Requires PreciseBank Module to be included in app.go

Complete Configuration Example

Based on local_node.sh:
#!/bin/bash

GENESIS="$HOME/.evmd/config/genesis.json"
TMP_GENESIS="$HOME/.evmd/config/tmp_genesis.json"

# Set EVM denomination
jq '.app_state["vm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"

# Enable all precompiles for development
jq '.app_state["vm"]["params"]["active_static_precompiles"]=[
  "0x0000000000000000000000000000000000000100",
  "0x0000000000000000000000000000000000000400",
  "0x0000000000000000000000000000000000000800",
  "0x0000000000000000000000000000000000000801",
  "0x0000000000000000000000000000000000000802",
  "0x0000000000000000000000000000000000000803",
  "0x0000000000000000000000000000000000000804",
  "0x0000000000000000000000000000000000000805",
  "0x0000000000000000000000000000000000000806"
]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS"

# Validate genesis
evmd genesis validate-genesis --home "$HOME/.evmd"
Or in genesis.json directly:
{
  "app_state": {
    "vm": {
      "params": {
        "evm_denom": "atest",
        "extra_eips": [],
        "active_static_precompiles": [
          "0x0000000000000000000000000000000000000100",
          "0x0000000000000000000000000000000000000400",
          "0x0000000000000000000000000000000000000800",
          "0x0000000000000000000000000000000000000801",
          "0x0000000000000000000000000000000000000802",
          "0x0000000000000000000000000000000000000803",
          "0x0000000000000000000000000000000000000804",
          "0x0000000000000000000000000000000000000805",
          "0x0000000000000000000000000000000000000806"
        ],
        "evm_channels": [],
        "access_control": {
          "create": {
            "access_type": 0
          },
          "call": {
            "access_type": 0
          }
        },
        "history_serve_window": 8192,
        "extended_denom_options": []
      },
      "chain_config": {
        "chain_id": "9001",
        "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"
      }
    }
  }
}


Source Code References