x/vm)是核心的 EVM 实现,使 Cosmos 链具备与以太坊兼容的能力。它提供 EVM 运行时、状态管理、预编译合约以及交易处理。
模块概览
用途:在 Cosmos SDK 框架内执行以太坊智能合约并处理 EVM 交易 核心功能:- EVM 状态转换与交易执行
- 以太坊分叉激活管理(Homestead、Berlin、London、Shanghai、Cancun、Prague 等)
- 用于访问 Cosmos 模块的原生预编译合约
- EVM 到 Cosmos 以及 Cosmos 到 EVM 的账户桥接
- Gas 计量与手续费处理
- 支持可配置保留策略的历史状态查询
配置方式
VM 模块可在链启动前通过 genesis.json 进行配置。以下是三种主要方式:方式 1:直接编辑 JSON
直接编辑~/.evmd/config/genesis.json:
方式 2:使用 jq 命令行工具
使用 jq 以编程方式修改 genesis(如 local_node.sh 所示):方式 3:使用 genesis CLI 命令
部分参数可通过 CLI 命令设置(不过大多数 VM 参数仍需编辑 genesis.json):参数
evm_denom
作用:指定将哪个 bank 模块面额作为原生 EVM 代币(Gas 代币)。 类型:string
有效值:必须与 bank 元数据配置中的某个基础面额一致
默认值:"uatom"(params.go:21)
配置方式:
- 必须与
bank.denom_metadata[0].base一致 - 必须与
staking.params.bond_denom一致 - 必须与
mint.params.mint_denom一致
"atest"- 适用于 18 位小数代币(atto 前缀:10^18)"ustake"- 适用于 6 位小数代币(micro 前缀:10^6)
- 与 bank 元数据不一致会导致 EVM 交易失败
- 小数位设置错误会导致余额显示不正确
extra_eips
作用:启用默认分叉激活之外的额外以太坊改进提案。 类型:[]int64(EIP 编号数组)
有效值:任意可激活的 EIP 编号
默认值:[](空,即所有 EIP 都来自 chain_config 分叉配置)(params.go:22)
配置方式:
| EIP | 说明 | 典型用途 |
|---|---|---|
| 3855 | PUSH0 指令 | 合约的 Gas 优化 |
| 2200 | SSTORE 的净 Gas 计量 | 降低 Gas 成本 |
| 2929 | 提高状态访问的 Gas 成本 | 强化安全性 |
| 3198 | BASEFEE 操作码 | 查询 EIP-1559 基础费 |
| 3529 | 减少退款 | Gas 计费规则变更 |
- 启用默认分叉配置中未包含的操作码或特性
- 适合测试即将到来的以太坊特性
- 如果管理不当,可能破坏兼容性
active_static_precompiles
作用:列出要启用的预编译合约地址,以便从 EVM 访问 Cosmos 模块。 类型:[]string(十六进制地址数组)
有效值:来自可用预编译列表的地址(precompiles.go:4-15)
默认值:[](空,即不启用任何预编译)(params.go:23)
配置方式:
| 地址 | 名称 | 模块 | 说明 |
|---|---|---|---|
0x0100 | P256 | 密码学 | P256 椭圆曲线操作 |
0x0400 | Bech32 | 地址 | 在 Bech32 与十六进制地址之间转换 |
0x0800 | Staking | x/staking | 委托、取消委托、重委托操作 |
0x0801 | Distribution | x/distribution | 领取质押奖励、设置提现地址 |
0x0802 | ICS20 | IBC Transfer | 通过 EVM 进行 IBC 代币转账 |
0x0803 | Vesting | x/vesting | 锁仓账户操作 |
0x0804 | Bank | x/bank | 原生 Cosmos 代币转账 |
0x0805 | Gov | x/gov | 提交并投票治理提案 |
0x0806 | Slashing | x/slashing | 查询验证者惩罚信息 |
- 仅启用必需的预编译,以提升安全性和 Gas 效率
- 常见启用项:0x0100(P256)、0x0400(Bech32)、0x0800(Staking)、0x0804(Bank)
- IBC 链:额外启用 0x0802(ICS20)
- 参与治理:启用 0x0805(Gov)
evm_channels
作用:ICS20 预编译可用于代币转账的 IBC 通道 ID 白名单。 类型:[]string(通道 ID 数组)
有效值:符合 channel-{N} 格式的通道 ID,其中 N 为非负整数
默认值:[](空,即没有白名单通道)(params.go:24)
配置方式:
- 限制 ICS20 预编译(0x0802)可通过哪些 IBC 通道转移代币
- 空列表表示 ICS20 预编译不能执行任何 IBC 转账
- 为跨链代币流动提供安全控制
- 仅在启用 ICS20 预编译(0x0802)时需要
- 与其他链建立 IBC 连接后设置
- 新增 IBC 路由时通过治理进行更新
access_control
作用:定义合约部署(CREATE/CREATE2)和合约调用的权限模型。 类型:包含create 和 call 字段的对象,每个字段都包含 access_type 和可选的 access_control_list
有效值:
- access_type:
0(无许可)、1(受限)、2(许可制) - access_control_list:地址数组(仅在受限或许可制模式下使用)
- 任何人都可以执行该操作
- 标准以太坊行为
- 推荐用于公链
- 除
access_control_list中地址外,其他人都可以执行该操作 - 黑名单模型
- 适合屏蔽特定恶意参与者
- 只有
access_control_list中的地址可以执行该操作 - 白名单模型
- 适用于私有链、联盟链或分阶段启动
- 控制谁可以部署合约(这对链安全非常重要)
- 控制谁可以调用已有合约(很少会限制)
- 可在上线后通过治理提案更新
history_serve_window
作用:保留用于历史 EVM 查询(eth_getBlockByNumber、eth_getLogs 等)的最近区块数量。
类型:uint64
有效值:任何非负整数
默认值:8192 个区块(params.go:50)
配置:
- 窗口越大,所需磁盘空间越多
- 窗口越小,磁盘占用越少
- 每个区块都会存储 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)
extended_denom_options
作用:为非 18 位小数的 Cosmos 代币启用 18 位小数的 EVM 表示。像ustake 这样的 6 位小数代币必须配置。
类型:[]ExtendedDenomOption - 将 Cosmos denom 映射到 EVM 扩展 denom 的对象数组
有效值:每个条目都必须包含符合扩展 denom 模式的有效 denom 对
默认值:[](空,即没有扩展 denom)(params.go:25)
配置:
- 18 位小数:不需要,标准 bank 模块即可工作
- 6 位小数:必须,必须添加
extended_denom_options - 其他小数位:必须,必须添加
extended_denom_options
u前缀(micro,10^6)→a前缀(atto,10^18):ustake→astaken前缀(nano,10^9)→a前缀(atto,10^18):ntoken→atoken- 其他任意情况 → 添加
evm前缀:stake→evmstake
- 原生 6 位小数代币:
ustake(最小单位) - 扩展后的 18 位小数表示:
astake(供 EVM 使用) - 1
ustake= 10^12astake - PreciseBank 模块处理分数换算
app.go 中包含 PreciseBank Module
完整配置示例
基于 local_node.sh:genesis.json 中配置:
相关文档
- Building Your Chain Guide - 主要配置流程说明
- Fee Market Module - EIP-1559 费用配置
- local_node.sh - 参考实现
源代码参考
- 模块实现:x/vm
- 参数类型:x/vm/types/params.go
- 预编译地址:x/vm/types/precompiles.go
- 链配置:x/vm/types/chain_config.go
- 创世配置:local_node.sh
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
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:
Method 2: Using jq Command-Line Tool
Programmatically modify genesis using jq (as seen in local_node.sh):Method 3: Using genesis CLI Commands
Some parameters can be set through CLI commands (though most VM params require genesis.json editing):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:
- MUST match
bank.denom_metadata[0].base - MUST match
staking.params.bond_denom - MUST match
mint.params.mint_denom
"atest"- For 18 decimal token (atto prefix: 10^18)"ustake"- For 6 decimal token (micro prefix: 10^6)
- 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:
| EIP | Description | Typical Use Case |
|---|---|---|
| 3855 | PUSH0 instruction | Gas optimization for contracts |
| 2200 | Net gas metering for SSTORE | Reduces gas costs |
| 2929 | Gas cost increases for state access | Security hardening |
| 3198 | BASEFEE opcode | EIP-1559 base fee queries |
| 3529 | Reduction in refunds | Gas accounting changes |
- Enables opcodes/features not in your default fork configuration
- Useful for testing upcoming Ethereum features
- Can break compatibility if not carefully managed
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:
| Address | Name | Module | Description |
|---|---|---|---|
0x0100 | P256 | Cryptography | P256 elliptic curve operations |
0x0400 | Bech32 | Addressing | Convert between Bech32 and hex addresses |
0x0800 | Staking | x/staking | Delegate, undelegate, redelegate operations |
0x0801 | Distribution | x/distribution | Claim staking rewards, set withdrawal address |
0x0802 | ICS20 | IBC Transfer | IBC token transfers via EVM |
0x0803 | Vesting | x/vesting | Vesting account operations |
0x0804 | Bank | x/bank | Native Cosmos token transfers |
0x0805 | Gov | x/gov | Submit and vote on governance proposals |
0x0806 | Slashing | x/slashing | Query validator slashing info |
- 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)
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:
- 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
- Only needed if you enable ICS20 precompile (0x0802)
- Set after establishing IBC connections with other chains
- Update via governance when adding new IBC routes
access_control
What It Does: Defines permission model for contract deployment (CREATE/CREATE2) and contract calls. Type: Object withcreate 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)
- Anyone can perform the operation
- Standard Ethereum behavior
- Recommended for public chains
- Everyone EXCEPT addresses in access_control_list can perform operation
- Blacklist model
- Useful for blocking specific malicious actors
- ONLY addresses in access_control_list can perform operation
- Whitelist model
- Useful for private/consortium chains or phased launches
- 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
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:
- Larger window = more disk space required
- Smaller window = less disk space usage
- Each block stores EVM state diffs and receipts
- Queries beyond history_serve_window will fail
- Block explorers need sufficient history for user queries
- DeFi analytics may require longer history
- Very large windows can slow down state pruning
- Affects database size and sync time
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)
- 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)
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:
- 18 decimals: NOT required - standard bank module works
- 6 decimals: REQUIRED - must add extended_denom_options
- Other decimals: REQUIRED - must add extended_denom_options
uprefix (micro, 10^6) →aprefix (atto, 10^18):ustake→astakenprefix (nano, 10^9) →aprefix (atto, 10^18):ntoken→atoken- Any other → add
evmprefix:stake→evmstake
- Native 6-decimal token:
ustake(smallest unit) - Extended 18-decimal representation:
astake(for EVM) - 1 ustake = 10^12 astake
- PreciseBank module handles fractional conversions
Complete Configuration Example
Based on local_node.sh:Related Documentation
- Building Your Chain Guide - Main configuration walkthrough
- Fee Market Module - EIP-1559 fee configuration
- local_node.sh - Reference implementation
Source Code References
- Module Implementation: x/vm
- Parameter Types: x/vm/types/params.go
- Precompile Addresses: x/vm/types/precompiles.go
- Chain Config: x/vm/types/chain_config.go
- Genesis Setup: local_node.sh