Skip to content

Cosmos EVM Integration#108

Open
akobrin1 wants to merge 222 commits intomasterfrom
evm
Open

Cosmos EVM Integration#108
akobrin1 wants to merge 222 commits intomasterfrom
evm

Conversation

@akobrin1
Copy link
Copy Markdown
Contributor

@akobrin1 akobrin1 commented Mar 19, 2026

Cosmos EVM Integration

Summary

First-class Cosmos EVM integration for Lumera, adding full Ethereum transaction execution, JSON-RPC, EIP-1559 fee market, ERC20/IBC middleware, custom module precompiles, the industry's first bidirectional CosmWasm↔EVM cross-runtime bridge, and a purpose-built legacy account migration module — the most comprehensive pre-mainnet EVM integration in the Cosmos ecosystem.

Ships with ~470 EVM-related tests, 25 bugs found and fixed during integration, production-grade operational controls, and features no other Cosmos EVM chain offers: async broadcast queue (deadlock fix), bidirectional CosmWasm↔EVM contract interaction (EVM contracts can execute/query CosmWasm contracts and vice versa), OpenRPC discovery, governance-controlled IBC ERC20 policy with provenance-bound trace verification, and a full account migration module with dual-signature verification.

Full technical documentation: docs/evm-integration/main.md


New Modules

Module Purpose
x/vm (Cosmos EVM v0.6.0) Core EVM execution — Solidity/Vyper contract runtime, receipts, logs, state transitions
x/feemarket EIP-1559 dynamic base fee with min gas price floor (0.0005 ulume/gas) and ~6.25% per-block adjustment
x/precisebank 6-decimal ulume ↔ 18-decimal alume bridge: EVMBalance(a) = I(a) × 10¹² + F(a)
x/erc20 STRv2 token pair registration + IBC middleware for automatic cross-chain ERC20 mapping
x/evmigration Legacy coin-type-118 → 60 account migration with dual-signature verification and atomic 9-module state re-keying

Key Changes

Runtime & Execution

  • Dual-route ante handler (app/evm/ante.go): deterministic tx routing based on ExtensionOptions[0].TypeUrl — Ethereum extension txs route to EVM path (EVMMonoDecorator + pending tx listener), Cosmos txs route through Lumera + EVM-aware Cosmos decorator chain, with build-tag-guarded production isolation (//go:build !test in defaults_prod.go)
  • App-side EVM mempool (app/evm_mempool.go): Ethereum-like sender ordering, nonce-gap handling, same-nonce replacement with bump rules, max_txs=5000 enabled by default
  • Async broadcast queue (app/evm_broadcast.go): decouples txpool runReorg promotion from CometBFT CheckTx via bounded channel + single background worker, preventing mutex re-entry deadlock — a novel fix no other Cosmos EVM chain has publicly addressed
  • RegisterTxService override (app/evm_runtime.go): captures the local CometBFT client for the broadcast worker, replacing the stale HTTP client from pre-CometBFT SetClientCtx
  • Depinject signer wiring: custom GetSigners for MsgEthereumTx + safe early-RPC keeper coin info initialization (SetKeeperDefaults) to prevent panics before genesis
  • CosmWasm coexistence: wasmd v0.61.6 and EVM run in the same runtime — Lumera is the only Cosmos chain shipping both simultaneously

Chain Configuration

  • EVM chain ID: 76857769
  • Key type: eth_secp256k1 (default), BIP44 coin type 60 — MetaMask/Ledger compatible out of the box
  • Fee market: base fee 0.0025 ulume/gas, min gas price floor 0.0005 ulume/gas (prevents zero-fee spam that hit Evmos), change denominator 16 (~6.25%/block vs upstream 8 at ~12.5%)
  • Consensus max gas: 25,000,000
  • Centralized denom metadata (config/bank_metadata.go): ulume/lume/alume metadata + RegisterExtraInterfaces for eth_secp256k1 crypto across all SDK+EVM paths
  • Automatic config migration (cmd/lumera/cmd/config_migrate.go): pre-EVM app.toml files auto-gain [evm], [json-rpc], and [evm.mempool] sections with correct chain ID on first startup — no manual intervention

Precompiles (11 static)

Standard (8): P256, Bech32, Staking, Distribution, ICS20, Bank, Gov, Slashing

Custom Lumera precompiles:

  • Action module (0x0901): 11 methods — cascade/sense request+finalize, approve, fee queries, paginated action queries. See action-precompile.md for full ABI reference.
  • Supernode module (0x0902): 12 methods — register/deregister, state transitions, metrics reporting (caller-bound auth), XOR distance ranking. See supernode-precompile.md for full ABI reference.
  • Wasm (CosmWasm bridge) (0x0903): 4 methods — execute, query, contractInfo, rawQuery. The EVM→CosmWasm direction of the cross-runtime bridge. See wasm-precompile.md for full ABI reference, architecture, and design notes.

Precompile protections: blocked-address send restrictions on all 11 precompile addresses + module accounts

CosmWasm ↔ EVM Cross-Runtime Bridge (Industry First)

Lumera is the only Cosmos EVM chain that also runs CosmWasm. This PR ships the industry's first bidirectional cross-runtime bridge between CosmWasm and an EVM, with no external precedent.

Direction Mechanism Address/Config
EVM → CosmWasm Wasm precompile (IWasm at 0x0903) Solidity contracts call execute/query/contractInfo/rawQuery on any CosmWasm contract
CosmWasm → EVM Custom message handler + query handler decorator CosmWasm contracts send evm_call via CosmosMsg::Custom and QueryRequest::Custom

Phase 1 (shipped): non-payable execute/query in both directions, shared reentrancy guard (max depth 1), per-call gas cap (3M), strict address validation, sender identity preservation (calling contract, not tx.origin), atomic snapshot/revert across runtime boundary.

Key source files: precompiles/wasm/, precompiles/crossruntime/, app/wasm_evm_plugin.go, precompiles/solidity/contracts/interfaces/IWasm.sol

IBC & Cross-Chain

  • IBC ERC20 middleware wired on both v1 and v2 transfer stacks:

  • v1: EVMTransferKeeper → ERC20IBCMiddleware → CallbacksMiddleware → PFM

  • v2: TransferV2Module → CallbacksV2Middleware → ERC20IBCMiddlewareV2

  • Governance-controlled registration policy via MsgSetRegistrationPolicy: 3 modes (all/allowlist default/none) with provenance-bound base-denom allowlisting (full IBC trace verification per base denom). Default entries (uatom, uosmo, uusdc, inj) are inert placeholders until governance binds real IBC channels.

JSON-RPC & Tooling

  • JSON-RPC server enabled by default: eth, net, web3, txpool, debug, personal, miner namespaces; mainnet auto-blocks debug/personal/admin via jsonrpc_policy.go
  • Indexer enabled by default: receipt persistence, tx hash lookup, log indexing, historical state queries (pruning-dependent)
  • Per-IP rate limiting (app/evm_jsonrpc_ratelimit.go): token bucket proxy — requests-per-second=50, burst=100, entry-ttl=5m, HTTP 429 with JSON-RPC -32005 on limit, stale entries GC'd every 60s
  • EVM tracing: runtime-configurable via app.toml [evm] tracerjson, struct, access_list, markdown; enables debug_traceTransaction, debug_traceBlockByNumber, debug_traceBlockByHash, debug_traceCall
  • OpenRPC discovery: rpc_discover JSON-RPC method (port 8545) + GET/POST /openrpc.json HTTP endpoint (port 1317) with CORS; gzip-compressed spec embedded in binary (315 KB → 20 KB); build-time generation via tools/openrpcgen with Go reflection + AST parsing; POST /openrpc.json proxies to JSON-RPC server enabling OpenRPC Playground "Try It" directly; spec version from go.mod via runtime/debug.ReadBuildInfo()
  • Playground URL: https://playground.open-rpc.org/?url=http://<node>:1317/openrpc.json

Account Migration (x/evmigration)

  • MsgClaimLegacyAccount: signed by new eth_secp256k1 address; legacy signature = secp256k1_sign(SHA256("lumera-evm-migration:<chainID>:<evmChainID>:<legacy_address>:<new_address>"))
  • Atomic 9-module migration in single tx: auth (vesting-aware) → bank → staking (delegations + unbonding + redelegations + UnbondingID indexes) → distribution (reward withdrawal) → authz (grant re-keying) → feegrant (allowance re-keying) → supernode → action → claim
  • MsgMigrateValidator: re-keys validator record + all associated module state including delegator references
  • Fee waiving (ante/evmigration_fee_decorator.go): zero-fee migration txs since new address has no balance
  • Governance params: enable_migration, migration_end_time, max_migrations_per_block=50, max_validator_delegations=2000
  • Queries: MigrationRecord, MigrationRecords, MigrationEstimate (dry-run), MigrationStats, LegacyAccounts, MigratedAccounts

Upgrade & Ops

  • v1.20.0 upgrade handler: store additions for feemarket, precisebank, vm, erc20, evmigration; post-migration finalization sets Lumera EVM params + coin info, feemarket params, ERC20 defaults (EnableErc20=true, PermissionlessRegistration=false), and seeds provenance-bound ERC20 registration policy
  • Adaptive store upgrade manager updated for missing stores in dev/test skip-upgrade flows
  • Node operator config guide: docs/evm-integration/node-evm-config-guide.mdapp.toml tuning, [evm]/[json-rpc]/[evm.mempool] sections, RPC exposure, tracer config, rate limiting, security policies

Devnet

  • EVM-aware devnet with EVM genesis template (devnet/default-config/devnet-genesis-evm.json)
  • Devnet port mapping: validators 1–5 map JSON-RPC to 8545/8555/8565/8575/8585; REST API to 1327/1337/1347/1357/1367
  • Hermes IBC relayer updated for EVM-era chains with auto-detection scripts
  • EVM devnet tests (devnet/tests/validator/evm_test.go): fee market, cross-peer tx visibility, mixed Cosmos+EVM blocks
  • Remix IDE guide: docs/evm-integration/remix-guide.md — MetaMask network config, contract deployment, interaction, event querying, troubleshooting

Bugs Found & Fixed (25 issues)

Documented in docs/evm-integration/bugs.md


Test Coverage (~470 tests)

Area Unit Integration Devnet Highlights
Dual-route ante handler 28 3 Both EVM and Cosmos paths verified separately
App-side mempool 12 Ordering, nonce gaps, replacement, capacity, WS subscriptions
Async broadcast queue 4 Deadlock prevention, deduplication, queue-full handling
JSON-RPC 23 Batch requests, persistence across restart, mixed blocks
ERC20/IBC middleware 31 7 Policy modes, provenance-bound trace verification, v1+v2 stacks
Precisebank 39 6 Mint/burn parity, fractional remainder, 6↔18 bridge
Feemarket (EIP-1559) 9 8 Multi-block progression, min floor, dynamic adjustment
Precompiles 42 All 11 precompiles + gas metering + Action + Supernode + Wasm bridge
Cross-runtime bridge 46 Guard, addr conversion, plugin dispatch/passthrough/reentrancy/validation
Account migration 102 14 All 9 module migrations, vesting, validator, edge cases
OpenRPC 15 2 Spec sync, HTTP serving, CORS, playground proxy
WebSocket subscriptions 4 newHeads, logs, pendingTransactions
Devnet multi-validator 12+ Cross-validator propagation, fee market, IBC
Devnet evmigration tool 7 modes prepare → estimate → migrate → migrate-validator → migrate-all → verify → cleanup

Devnet evmigration pipeline (make devnet-evm-upgrade): boots v1.11.1 devnet → prepares legacy state (5 legacy + 5 extra accounts with delegations, unbonding, redelegations, authz, feegrant, supernode, action across all validators) → governance upgrade to v1.20.0 → estimate all accounts → migrate validators → migrate accounts → verify clean state. Idempotent and rerunnable.


Documentation Added

Document Description
main.md Full integration architecture, semantics, gap analysis, cross-chain comparison
tests.md Complete test inventory with per-area coverage assessment and gap analysis
bugs.md 25 bugs: symptom, root cause, fix, tests added
roadmap.md 15-phase roadmap, 163/168 items complete (97%)
security-audit.md Security audit findings, recommendations, and resolution status
tune-guide.md Mainnet parameter tuning guide: fee market, gas limits, mempool, RPC limits
node-evm-config-guide.md Node operator guide: app.toml tuning, security policies, rate limiting
openrpc-playground.md OpenRPC discovery access methods, devnet ports, playground setup
remix-guide.md Remix IDE + MetaMask testing guide with troubleshooting
precompiles.md Precompile overview — 11 static precompiles (8 standard + 3 custom Lumera)
action-precompile.md Action precompile (0x0901) ABI reference, 11 methods, design notes
supernode-precompile.md Supernode precompile (0x0902) ABI reference, 12 methods, design notes
wasm-precompile.md Wasm precompile (0x0903) — full cross-runtime bridge architecture, Solidity+Rust interfaces, data flow, gas metering, reentrancy design
evmigration-ui.md EVM legacy account migration portal UI and wallet rollout
devnet-tests.md Devnet end-to-end migration test tool documentation
block-explorer.md External block explorer (Blockscout) integration plan
lumera-ports.md Full port mapping reference for all node services

What Makes This Different

Capability Lumera Other Cosmos EVM chains at launch
Bidirectional CosmWasm↔EVM bridge Industry first — Solidity contracts call CosmWasm, CosmWasm contracts call EVM No chain has this
CosmWasm + EVM coexistence Yes (wasmd v0.61.6 + Cosmos EVM v0.6.0) No chain has both
OpenRPC discovery rpc_discover + /openrpc.json + playground proxy No chain has this
Async broadcast queue Deadlock-free mempool promotion Not publicly addressed
Min gas price floor 0.0005 ulume/gas (prevents decay to zero) Evmos launched without → spam attack
IBC v2 ERC20 middleware Both v1 and v2 transfer stacks Most only v1
IBC ERC20 registration policy Provenance-bound trace verification per base denom Not standard
Custom module precompiles Action (0x0901) + Supernode (0x0902) + Wasm (0x0903) at launch Usually post-launch
Account migration module Dual-sig, 9-module atomic, validator support No comparable mechanism
Pre-mainnet test coverage ~470 tests (308 unit + 138 integration + 12+ devnet) Typically <100
Bugs fixed pre-launch 25 issues found and resolved Usually found post-mainnet
Automatic config migration config_migrate.go adds [evm] section on startup Manual operator action
JSON-RPC rate limiting Built-in per-IP token bucket at app layer External infra or post-launch

Gas Configuration

Parameter Lumera Evmos Kava Cronos
Default base fee 0.0025 ulume (2.5 gwei equiv) ~10 gwei ~0.25 ukava Variable
Min gas price floor 0.0005 ulume 0 (no floor) N/A N/A
Base fee change denominator 16 (~6.25%/block) 8 (~12.5%) 8 8
Consensus max gas 25,000,000 30M–40M 25,000,000 25,000,000

Roadmap Status

163/168 items complete (97%) across 15 phases.

Status Phases
Complete Core EVM Runtime, Ante Handler, Feemarket, Mempool & Broadcast, JSON-RPC & Indexer, Static Precompiles, IBC+ERC20, OpenRPC, Store Upgrades, Account Migration, Testing, Custom Precompiles, CosmWasm + EVM Interaction (Phase 1)
In Progress Production Hardening (4/8 — security audit done, monitoring runbook pending), Ecosystem & Tooling (2/7 — block explorer, Hardhat guide pending)

Breaking Changes

Change Before After Impact
Key type secp256k1 eth_secp256k1 keys add defaults to Ethereum-compatible keys
BIP44 coin type 118 60 Same mnemonic derives different addresses
Fee behavior Flat gas price EIP-1559 dynamic base fee Wallets must support type-2 txs for optimal UX
New stores feemarket, precisebank, vm, erc20, evmigration v1.20.0 upgrade handler required
Config No [evm] section [evm], [json-rpc], [evm.mempool] in app.toml Auto-migrated on startup via config_migrate.go

@roomote-v0
Copy link
Copy Markdown

roomote-v0 Bot commented Mar 19, 2026

Rooviewer Clock   See task

Reviewed 3fea8c2 (8 changed files since last review at 0263182). All 19 previously resolved issues remain resolved. 3 previously flagged open issues (#20, #21, #22) remain unresolved. No new issues found in this incremental review.

Changes reviewed (3fea8c2): Release workflow hardening (tag-only guard on release job), CHANGELOG additions for v1.12.0 and v1.11.1-hotfix, devnet binary tag bump from v1.12.0-rc to v1.12.0, generate-evm-accounts command in lumera-helper.sh (EVM key derivation from existing cosmos mnemonics with idempotent re-run support), list-accounts rewrite to use user-accounts.json as source of truth, _derive_address_from_mnemonic in evmigration-common.sh (isolated tempdir keyring for mnemonic verification replacing the old in-keyring probe that could leave orphaned keys), expanded migration-scripts documentation with key-reuse example, and project STATUS.md.

Issues

# Severity File Description Fix
1 Critical x/evmigration/keeper/msg_server_migrate_validator.go Validator migration skips operator's own delegations to other validators -- distribution and staking state for those delegations is never re-keyed Resolved in 4c46bf1
2 Medium app/evm_jsonrpc_ratelimit.go extractIP() trusts spoofable X-Forwarded-For / X-Real-IP headers, allowing rate-limit bypass Resolved in a4c786e
3 Low app/openrpc/http.go OpenRPC POST proxy uses http.DefaultClient with no timeout -- a slow upstream can pin goroutines indefinitely Resolved in 4c46bf1
4 Medium app/evm_broadcast.go broadcastBatch returns on first BroadcastTxSync failure, silently dropping all remaining transactions in the batch Resolved in 4c46bf1
5 Low x/evmigration/keeper/migrate_staking.go migrateActiveDelegations reads GetDelegatorStartingInfo after the same key was already deleted, making lines 68-77 dead code Resolved in 4c46bf1
6 Medium .github/workflows/build.yml make openrpc added to integration-tests but missing from system-tests and build jobs that also compile the full binary via ignite chain build -- //go:embed openrpc.json.gz will fail Resolved in 19a2bdb
7 Low x/evmigration/keeper/migrate_staking.go migrateWithdrawAddress doc comment has two overlapping comments spliced together -- first one cut off mid-sentence Resolved in 11a85cb
8 Low tools/openrpcgen/schema.go structProperties iterates requiredSet map without sorting, producing non-deterministic required arrays in the OpenRPC spec -- causes noisy diffs on every regeneration Resolved in 52b099a
9 Low Makefile BUILD_LDFLAGS includes -X ...cmd.ChainID=$(CHAIN_ID) but no var ChainID exists in cmd/lumera/cmd -- the linker silently ignores it, so the chain ID from config.yml is never injected into the binary Resolved in 19a2bdb
10 Medium x/evmigration/keeper/msg_server_claim_legacy.go preChecks does not consult MigrationRecordByNewAddress -- two legacy accounts can migrate to the same destination, silently overwriting the reverse index Resolved in f1f6872
11 Low Makefile.devnet .PHONY declaration devnet-new-1110 out of sync with renamed target devnet-new-1111 Resolved in c7be796
12 Medium app/wasm_evm_plugin.go:82 gasCapForCall computes meter.Limit() - meter.GasConsumed() which can underflow (uint64 wrap) if consumed exceeds limit, handing the EVM a near-MaxUint64 gas budget Resolved in 128cbb3
13 Nit precompiles/wasm/tx.go:55 caller bech32 string computed but only used for logging; actual Execute call uses sdk.AccAddress(contract.Caller().Bytes()) directly -- wasted work + misleading error path Resolved in 128cbb3
14 Nit app/wasm_evm_plugin.go:369 _ = wasmtypes.ErrUnknownMsg suppresses unused import lint for wasmtypes which isn't actually used in the file Resolved in 128cbb3
15 Nit app/wasm_evm_plugin_test.go:450 containsString + searchSubstring reimplement strings.Contains from the standard library Resolved in 128cbb3
16 Nit docs/evm-integration/tests.md:72 ~~Totals row says "Unit: ~297" but individual unit rows sum to ~351 -- appears stale from before EVMigration CLI and JSON-RPC rate limiting rows were added~~ Resolved in 128cbb3
17 Low scripts/evmigration-common.sh:172 lumerad_q() calls _read_keyring_flags but never passes _KRF to the command -- --home and --keyring-dir are silently ignored for all query commands Resolved in 7f380d8
18 Nit x/evmigration/keeper/verify_testhelpers_test.go:56 signNewMigrationMessage truncates 65-byte eth_secp256k1 sig to 64 bytes -- produces invalid new-side proofs Resolved in 7f380d8
19 Low x/evmigration/client/cli/tx_multisig.go:841 upsertSig reuses the backing array of the input slice via filtered := existing[:0] Resolved in 7f380d8
20 Medium x/audit/v1/keeper/enforcement.go:728 storageTruthIsClassAFault treats INDEX artifact failures as Class A regardless of result class (including TIMEOUT), but scoring classifies TIMEOUT-on-INDEX as Class B -- enforcement and scoring disagree on classification Fix
21 Low x/audit/v1/keeper/storage_truth_divergence.go:215 storageTruthReporterAccountsForEpoch does a full table scan of all reporter-result records across all epochs to find reporters for a single epoch -- O(total_records) instead of O(records_in_epoch) Fix
22 Low x/supernode/v1/keeper/audit_metrics.go:6 Dead constant maxAuditEpochLookback with nolint:unused -- no longer needed after audit metrics refactor Fix
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Comment thread x/evmigration/keeper/msg_server_migrate_validator.go
Comment thread app/evm_jsonrpc_ratelimit.go Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d4527beaf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/evm_jsonrpc_ratelimit.go Outdated
Comment thread app/evm_jsonrpc_ratelimit.go Outdated
Comment thread app/openrpc/http.go Outdated
Comment thread app/evm_broadcast.go
Comment thread x/evmigration/keeper/migrate_staking.go Outdated
Comment thread .github/workflows/build.yml Outdated
Comment thread x/evmigration/keeper/migrate_staking.go Outdated
roomote-v0[bot]
roomote-v0 Bot previously approved these changes Mar 20, 2026
Comment thread tools/openrpcgen/schema.go
@akobrin1 akobrin1 requested a review from Copilot March 20, 2026 03:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class Cosmos EVM integration support across Lumera’s node runtime, CLI, devnet tooling, upgrade handlers, JSON-RPC/OpenRPC, and CI pipelines.

Changes:

  • Introduces EVM chain configuration/constants (chain ID, fee market defaults, denom metadata) and wires EVM modules into app/CLI/startup paths.
  • Expands devnet + Hermes automation (upgrade flow, version/key-style detection, JSON-RPC ports, log archiving, test binary distribution).
  • Adds extensive EVM-focused unit/integration tests and updates build/test/lint/release automation (OpenRPC generation, golangci-lint v2 config, workflows).

Reviewed changes

Copilot reviewed 141 out of 516 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
devnet/tests/evmigration/README.md Adds devnet evmigration test tool README
devnet/scripts/wait-for-height.sh Improves height wait UX + upgrade-halt detection
devnet/scripts/upgrade.sh Adds idempotent upgrade flow + version checks
devnet/scripts/upgrade-binaries.sh Verifies binary version + improves compose restart robustness
devnet/scripts/start.sh Archives logs + optional claims CSV start flags
devnet/scripts/restart.sh Archives logs + optional claims CSV start flags
devnet/scripts/configure.sh Improves host-side shared volume/binary setup
devnet/main.go Import ordering tweak
devnet/hermes/scripts/hermes-start.sh Auto-detects key style based on chain version
devnet/hermes/scripts/hermes-configure.sh Hermes address_type derivation based on key style
devnet/hermes/scripts/hermes-channel.sh Uses eth HD path for EVM-era keys
devnet/hermes/config.toml Devnet Hermes tuning (misbehaviour, clear interval)
devnet/hermes/Dockerfile Updates Go base image + IBC-Go version arg
devnet/generators/docker-compose.go Adds chain version detection + JSON-RPC port bindings
devnet/generators/config.go Adds JSON-RPC default ports constants
devnet/dockerfile Sets bash shell + installs ripgrep
devnet/default-config/devnet-genesis.json Adds audit/evmigration genesis params + updates claim end time/amount
devnet/config/validators.json Restructures supernode config + adds per-validator JSON-RPC ports
devnet/config/config.json Adds evm_from_version, JSON-RPC config, and mnemonic lists
devnet/config/config.go Extends devnet config schema (version, JSON-RPC, mnemonics)
devnet/.gitignore Ignores generated compose/bin/logs
config/evm.go Adds EVM chain constants (IDs, fees, gas)
config/config.go Updates chain denom metadata + delegates Bech32/BIP44 setup
config/codec.go Registers SDK + EVM crypto interfaces
config/bip44.go Sets coin type to EVM (60)
config/bech32.go Centralizes Bech32 prefix constants/helpers
config/bank_metadata.go Provides/upserts canonical bank metadata for ulume/lume/alume
cmd/lumera/main.go Treats context cancellation as graceful shutdown
cmd/lumera/cmd/root_test.go Adds CLI wiring tests for EVM flags + key type defaults
cmd/lumera/cmd/root.go Adds EVM modules to CLI basics + keyring options + config migration hook
cmd/lumera/cmd/jsonrpc_policy_test.go Adds mainnet JSON-RPC namespace policy tests
cmd/lumera/cmd/jsonrpc_policy.go Enforces disallowed JSON-RPC namespaces on mainnet
cmd/lumera/cmd/config_test.go Verifies app config EVM/JSON-RPC defaults
cmd/lumera/cmd/config.go Extends app.toml template/config with EVM/JSON-RPC/TLS/Lumera sections
claiming_faucet/main.go Uses EVM keyring options + registers EVM crypto interfaces
app/wasm.go Removes wasm-specific ante/posthandler setup from wasm registration
app/vm_preinstalls_test.go Adds EVM preinstall validation matrix test
app/upgrades/v1_12_0/upgrade_test.go Tests ERC20 params init when InitGenesis skipped
app/upgrades/v1_12_0/upgrade.go Adds v1.12.0 EVM store upgrades + manual params finalization
app/upgrades/upgrades_test.go Adds v1.12.0 to upgrade registry tests
app/upgrades/upgrades.go Registers v1.12.0 upgrade config
app/upgrades/store_upgrade_manager_test.go Adds adaptive store upgrade test for missing EVM stores
app/upgrades/store_upgrade_manager.go Uses shared EnvBool helper
app/upgrades/params/params.go Extends upgrade params with EVM-related keepers
app/test_support.go Import ordering tweak
app/test_helpers.go Adds EVM test-tag guard + denom metadata in genesis + disables fastnode in tests
app/statedb_events_test.go Adds StateDB snapshot/event revert invariant test
app/proto_bridge_test.go Tests proto enum bridge registrations
app/proto_bridge.go Registers Cosmos SDK + EVM enums in proto bridge
app/precisebank_mint_burn_parity_test.go Adds precisebank mint/burn parity tests
app/precisebank_fractional_test.go Adds precisebank fractional balance matrix tests
app/pending_tx_listener_test.go Tests pending tx listener fanout + offline broadcaster error
app/openrpc/spec.go Embeds and serves gzipped OpenRPC spec
app/openrpc/rpc_api.go Exposes rpc.discover service
app/openrpc/register.go Registers rpc namespace on JSON-RPC server
app/openrpc/openrpc_test.go Validates embedded OpenRPC doc and helpers
app/ibc_erc20_middleware_test.go Tests ERC20 IBC middleware wiring (v1/v2)
app/ibc.go Wires ERC20 middleware into IBC transfer stacks
app/evm_test.go Tests EVM module genesis + ordering + module account perms
app/evm_static_precompiles_test.go Tests static precompile registration
app/evm_runtime.go Captures clientCtx via RegisterTxService + shuts down background workers
app/evm_mempool_test.go Tests EVM mempool wiring
app/evm_mempool.go Configures app-side EVM mempool + signer extraction
app/evm_jsonrpc_alias.go Adds JSON-RPC alias reverse proxy + method rewrite
app/evm_erc20_policy_msg.go Implements governance msg server for ERC20 IBC policy
app/evm/testtag_guard.go Adds guard helpers for missing -tags=test
app/evm/reset_testbuild.go Resets EVM global config in test builds
app/evm/reset.go Panics with guidance in non-test builds under testing
app/evm/prod_guard_test.go Documents guard behavior in !test builds
app/evm/precompiles.go Defines Lumera static precompile address list
app/evm/modules.go Registers EVM modules for CLI default genesis generation
app/evm/genesis.go Defines Lumera EVM/feemarket genesis overrides
app/evm/defaults_testbuild.go No-op keeper defaults in test builds
app/evm/defaults_prod.go Sets keeper default coin info in production builds
app/evm/config_modules_genesis_test.go Tests EVM config helpers + genesis overrides + module registration
app/evm/config.go Adds custom signer provider helper
app/evm/ante_sigverify_test.go Tests signature gas consumer matrix
app/evm/ante_nonce_test.go Tests EVM nonce increment matrix
app/evm/ante_internal_test.go Tests genesis-skip decorator behavior
app/evm/ante_gas_wanted_test.go Tests EVM gas-wanted decorator behavior
app/evm/ante_evmigration_fee_test.go Tests reduced ante path for migration-only txs
app/encoding.go Uses EVM test-tag guard when building encoding config in tests
app/blocked_addresses_test.go Tests blocked module/precompile addresses and send restriction
app/params/proto.go Removes legacy encoding config helper
app/amino_codec_test.go Adds legacy amino codec regression test for eth_secp256k1
app/amino_codec.go Registers eth_secp256k1 amino types + syncs legacy codec
ante/evmigration_validate_basic_decorator_test.go Tests ValidateBasic suppression for migration-only txs
ante/evmigration_validate_basic_decorator.go Allows ErrNoSignatures for migration-only txs
ante/evmigration_fee_decorator_test.go Tests fee waiving for migration-only txs
ante/evmigration_fee_decorator.go Clears min-gas-prices for migration-only txs
ante/delayed_claim_fee_decorator.go Removes disabled decorator block comment
Makefile Adds OpenRPC generation, updates lint tool path, adjusts test targets
CHANGELOG.md Adds v1.12.0 changelog entry + fixes formatting issue
.vscode/settings.json Adds terminal tool auto-approve entry
.vscode/launch.json Adds integration test debug configuration
.markdownlint.json Adds markdownlint overrides
.golangci.yml Adds golangci-lint v2 configuration
.github/workflows/test.yml Switches to make targets + reusable ignite action
.github/workflows/systemtests.yml Adds systemtests workflow using shared actions/make targets
.github/workflows/systemtests.yaml Removes old systemtests workflow
.github/workflows/release.yml Simplifies release workflow to reuse build workflow
.github/workflows/lint.yml Adds a dedicated golangci-lint workflow
.github/workflows/build.yml Adds build workflow orchestrating lint/tests/build+artifacts
.github/actions/install-ignite/action.yml Sets default Ignite version input

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/upgrades/params/params.go
Comment thread app/upgrades/v1_20_0/upgrade.go
Comment thread devnet/scripts/configure.sh Outdated
Comment thread devnet/scripts/configure.sh
Comment thread app/amino_codec_test.go Outdated
Comment thread app/upgrades/upgrades_test.go Outdated
Comment thread app/upgrades/upgrades_test.go Outdated
Comment thread devnet/scripts/wait-for-height.sh
Comment thread .vscode/settings.json Outdated
Comment thread Makefile Outdated
roomote-v0[bot]
roomote-v0 Bot previously approved these changes Mar 20, 2026
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 9 previously identified issues are resolved. The three security audit findings (rate-limit proxy bypass, redelegation undercount, chain ID domain separation) have been addressed correctly with well-structured code and comprehensive tests. No new issues found.

roomote-v0[bot]
roomote-v0 Bot previously approved these changes Mar 20, 2026
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New Issue: preChecks does not prevent duplicate destination addresses

Severity: Medium

preChecks verifies that newAddr is not a previously-migrated legacy address (step 6, line 108), but does not check whether newAddr was already used as a destination in a prior migration. The MigrationRecordByNewAddress reverse index exists and is populated in finalizeMigration, but is never consulted during pre-checks.

This means two different legacy accounts could migrate to the same new address. While the bank transfers would be additive (funds accumulate at the destination), the reverse index entry from the first migration would be silently overwritten by the second, making the first legacy address unreachable via MigrationRecordByNewAddress.

Suggested fix -- add a check after step 6:

// 6b. New address must not already be a migration destination
has, err = ms.MigrationRecordByNewAddress.Has(ctx, newAddr.String())
if err != nil {
    return err
}
if has {
    return types.ErrNewAddressAlreadyUsed // new error to define
}

If allowing multiple legacy accounts to converge on one destination is intentional, the reverse index should store a list rather than a single string, or the overwrite should be documented.

Comment thread x/evmigration/keeper/msg_server_claim_legacy.go
roomote-v0[bot]
roomote-v0 Bot previously approved these changes Apr 1, 2026
@akobrin1 akobrin1 requested a review from Copilot April 1, 2026 14:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 137 out of 524 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

devnet/scripts/configure.sh:1

  • The script documentation describes binaries as optional, but BIN_DIR is now required (hard-fails if it can’t auto-detect devnet/bin). This makes config-only workflows (copying config.json/validators.json without host binaries) impossible. Consider allowing a missing BIN_DIR by setting BIN_DIR=\"\" and continuing, or adding an explicit --no-bin-dir / --skip-binaries mode.
#!/bin/bash

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread devnet/config/config.json
Comment thread app/openrpc/http.go Outdated
Comment thread app/evm/testtag_guard.go
roomote-v0[bot]
roomote-v0 Bot previously approved these changes Apr 1, 2026
roomote-v0[bot]
roomote-v0 Bot previously approved these changes Apr 1, 2026
akobrin1 and others added 2 commits April 25, 2026 13:41
…rror tests, fail loudly without -tags=test

Closes the three follow-up findings from the multisig coverage review:

- app/evm/ante_evmigration_fee_test.go: fix block gas limit (was 0; SDK
  SetUpContextDecorator rejected with "tx gas exceeds block gas limit"
  before EVMigrationValidateBasicDecorator could run) and the helper's
  structurally-invalid migration msg (1-byte sigs, missing new-side
  pubkey). Now uses a 100M block-gas ceiling and proofs with correct
  per-side lengths (33-byte pubkeys, 64/65-byte sigs).
- tests/integration/evmigration/migration_test.go: mirror the claim-side
  MirrorSourceMismatch_{Shape,KN,SignerIndices} tests for the validator
  path, using s.msgServer.MigrateValidator directly. Confirms the
  defensive ValidateProofPair in msg_server_migrate_validator.go fires
  for malformed validator proof pairs even when the SDK msg_service_router
  is bypassed.
- tests/integration/evmigration/testtag_required{,_present}_test.go: add
  build-tag sentinel TestMain. Without -tags=test the cosmos-evm
  chainConfig guard makes every subtest silently t.Skip — `go test ...`
  reports "ok" with zero verified coverage. The new TestMain fails the
  binary fast in that case with a clear remediation message; the
  companion file (//go:build test) installs a passthrough TestMain when
  the tag IS present.
- CLAUDE.md: document the evmigration-integration -tags='integration test'
  requirement next to the other integration test invocations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t-of-scope

- migrate-multisig.bats count 38 → 39 (the +1 is the duplicate-sub-key
  propagation test added in commit f976852); description now mentions it.
- Rename "Known multisig test-coverage gaps" → "Multisig test-coverage
  scope" and reclassify the 5-of-7 devnet entry from "low-priority gap"
  to "out of scope by design". 2-of-3 is the accepted devnet scope; the
  consensus rule is K/N-agnostic and is exercised by the existing unit +
  integration tests (TestMigrationEstimate_Multisig_TooManySubKeys,
  TestQueryMigrationEstimate_Multisig_SizeCapped, and
  TestValidateProofPair_MirrorSourceRule). Keep the row so future
  reviewers see the decision rather than re-raise it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
roomote-v0[bot]
roomote-v0 Bot previously approved these changes Apr 27, 2026
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 19 previously flagged issues remain resolved. The 12 changed files in this increment (defense-in-depth ValidateProofPair, mirror-source rule test enforcement, build tag guard, duplicate-sub-key rejection, MigrateValidator mirror-source mismatch tests, orphaned validator record cleanup test, and documentation updates) are clean with no new issues.

…ntext

Mirror scripts/{evmigration-common,migrate-*}.sh into the devnet build
context via a gitignored Makefile target so devnet containers run the
canonical scripts. Refresh devnet evmigration tests, BATS fixtures
(incl. auth-account-not-found.json), CLI multisig polish, and docs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
akobrin1 and others added 6 commits May 1, 2026 12:24
Brings master's LEP-6 audit storage-truth scaffolding (#117), recent devnet
test fixes (#123, #124), and scoped lint cleanup (#125) onto the evm branch.

Conflict resolutions:
- .gitignore: union of both sides, deduped, fixed .codex/.agents (file vs dir)
- devnet/go.mod: master's lumera-only replace, kept evm's local sdk-go replace
  (devnet evmigration tests use BuildAndSignTxWithOptions only on local sdk-go);
  cosmos-sdk pinned to evm's v0.53.6.
- supernode-setup.sh: folded master's EVERLIGHT_TEST_TARGET host_reporter
  bypass into evm's start_supernode_process abstraction so all call sites
  honor the env var.
- audit_peer_ports / audit_recovery system tests: kept evm's wider epoch
  windows + multi-node assignment-aware reporting (the EVM-integrated binary
  is slower; tighter epochs flake).
- distribution_freshness / query_get_reward_eligibility tests: kept evm's
  Bech32-prefixed config constants (master's lcfg.ValidatorAddressPrefix
  doesn't compile on evm).
- metrics_state.go / metrics_validation.go: kept evm's reserved
  STORAGE_FULL helpers (markStorageFull, recoverFromStorageFull,
  lastNonDegradedState) for follow-up audit-enforcement wiring.
- testutil/cryptotestutils → testutil/crypto: rewrote 3 master-side import
  paths to evm's renamed directory.
- Dropped master's duplicate indexOfModule from lep6_module_order_test.go
  in favor of the existing helper in app/evm_test.go.

Lint cleanup applied to bring `make lint` to 0 issues:
- defer it.Close() → defer func() { _ = it.Close() }() across audit module.
- gofmt -w on master-side test/sim files.
- Removed unused //nolint:staticcheck directives on HasInvariants.
- Marked reserved declarations (maxAuditEpochLookback, globalAuditKeeper)
  with //nolint:unused.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reorganize so each doc lives next to siblings of the same kind:
- docs/design/ now holds only design/proposal docs (incl. the Cascade
  Everlight Brief and Feature Proposal moved out of docs/plans/).
- docs/plan/ (new) holds implementation plans previously scattered
  between docs/design/ (three evmigration *-plan.md files) and
  docs/plans/ (Cascade Everlight phase-1, doc-sync BLAKE3, lep5
  incremental, 2026-04-18 multisig plan).
- docs/leps/ gains the LEP-6 storage-truth draft to keep all LEP
  design docs co-located.
- docs/plans/ directory removed.

Internal links inside the moved Cascade-Everlight pair and the
2026-04-18 multisig plan are rewritten to point at the new homes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eout

Two regressions surfaced when master's LEP-6 system tests hit evm's
dynamic-base-fee feemarket on the merged branch:

- Default cli fee bumped 500ulume → 5000ulume so feemarket pushes past
  0.001ulume/gas don't fail txs with "insufficient fee" (TestStorageTruth
  family was barely over the 500ulume ceiling at ~541ulume required).
- audit_peer_ports test's await for block 61 (under evm's 20-block
  epochs) gets a 120s explicit timeout — the default 19s couldn't reach
  it on a fresh chain.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings in master's v1.12.0 upgrade-handler completeness PR (#131):
- 51e191b feat(upgrade/v1.12.0): persist post-1.11.1 defaults and anchor Everlight clock
- 0e04831 Update Everlight genesis configuration and tests
- db436f9 chore(upgrade): clarify required keeper comment

Conflict resolutions:
- x/supernode/v1/mocks/expected_keepers_mock.go: regenerated via go
  generate from the auto-merged expected_keepers.go (HEAD added
  Delete{MetricsState,SuperNode}; master added CountEligibleSNs,
  EnsureModuleAccount, SetLastDistributionHeight — all coexist now).
- docs/plan/S16-devnet-upgrade-test-plan.md: master added it under the
  old docs/plans/ path; routed to docs/plan/ to match the recent split
  of designs vs plans.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drive-by alphabetization picked up by `go generate` while regenerating
mocks during the master merge. The Params method was previously
appended at the end; mockgen now emits it between ListSuperNodes and
PayoutHistory. No semantic change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of changes since SHA 8a7d1f5. All 19 previously flagged issues are confirmed resolved. Found 3 new observations (1 medium, 2 low).

Comment thread x/audit/v1/keeper/enforcement.go
Comment thread x/audit/v1/keeper/storage_truth_divergence.go
Comment thread x/supernode/v1/keeper/audit_metrics.go
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 19 previously flagged issues are resolved. The LEP-6 Storage Truth Enforcement addition is well-structured with thorough test coverage, proper genesis import/export, bounded pruning, and careful score decay mechanics.

3 new non-blocking observations filed:

  • #20 [medium]: storageTruthIsClassAFault enforcement predicate includes INDEX artifact failures as Class A regardless of result class, while scoring classifies TIMEOUT-on-INDEX as Class B. The LEP-6 guide has contradictory statements on this. Worth reconciling.
  • #21 [low]: storageTruthReporterAccountsForEpoch full table scan -- bounded by pruning but could benefit from an epoch-keyed reporter index as the active set grows.
  • #22 [low]: Dead constant maxAuditEpochLookback after audit metrics refactor.

Approving -- none of the new items are blocking.

roomote-v0[bot]
roomote-v0 Bot previously approved these changes May 3, 2026
Copy link
Copy Markdown

@roomote-v0 roomote-v0 Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incremental review of 0263182 (14 changed files since 5f33b76). The v1.12.0 upgrade handler, WithDefaults() param evolution pattern, activation policy pinning tests, expanded keeper interfaces, devnet genesis storage_truth_* params, everlight test hardening, and S16 upgrade test plan all look clean. No new issues found. 3 previously flagged issues (#20, #21, #22) remain open but are pre-existing and non-blocking for this increment.

akobrin1 and others added 11 commits May 5, 2026 10:55
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	docs/design/Cascade-Everlight-Brief.md
#	docs/design/Cascade-Everlight-Feature-Proposal.md
#	docs/leps/LEP-6 Storage-Truth Enforcement-draft.md
#	docs/leps/LEP6 - Storage-Truth Enforcement and Ticket-Driven Self-Healing.md
#	docs/plans/LEP-6 Storage-Truth Enforcement-draft.md
Expand the 1.20.0 entry with previously-omitted items: multisig migration
support (LegacyProof oneof, MaxMultisigSubKeys param, K/N mirror rule,
four-step offline CLI flow), user-facing migration helper scripts, the
CosmWasm <-> EVM cross-runtime bridge (Phase 1), wasmvm v3.0.3, validator
migration jailed-rejection + unjail helper, devnet upgrade targets, the
network-maker -> lumera-uploader rename, and the security-vuln dep bumps.
Fix the stale "10 precompiles" count to 11 and refresh user-guide doc
paths after the docs/evm-integration/user-guides/ reorg.

Also drop scratch file multisig-migration.txt that was left in the tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…icates

Two CI failures on PR #108:

tests/integration/evm/contracts/TestConcurrentMixedEVMOperations:
The cosmos-evm v0.6.0 mempool's Blockchain.CurrentBlock() returns a
zeroHeader (GasLimit=0) until block 1 commits and previousHeaderHash
gets populated by NotifyNewBlock in EVM EndBlock. The test fired five
concurrent eth_sendRawTransaction calls right after StartAndWaitRPC,
racing the first block's EndBlock — every tx hit head.GasLimit < tx.Gas()
and was rejected with the bare "exceeds block gas limit" error, so all
five rejected and t.Fatal fired. Other tests in this package go through
suite_test.go's run-wrapper which calls WaitForBlockNumberAtLeast
between subtests; this top-level test bypassed that warmup. Fix: wait
for block height >= 2 before submitting.

tests/systemtests/TestStorageTruth_SoftMode_PostponesNodeOnHighSuspicion
tests/systemtests/TestStorageTruth_ScoreDecay_TriggersRecovery:
Commit 340e28c made storageTruthIsClassAFault failure-class driven —
HASH_MISMATCH and RECHECK_CONFIRMED_FAIL are Class A, an INDEX-artifact
result class is no longer promoted to Class A. The new internal test
TestStorageTruthIsClassAFault_IndexTimeoutIsClassB asserts the new
behavior intentionally. As a side effect, seedProofTranscripts (which
seeds STORAGE_PROOF_RESULT_CLASS_INVALID_TRANSCRIPT records on the
RECENT bucket) stopped contributing a Class A fact, so postpone
predicates needing recentClassA + secondFailureEvents>=2 stopped firing
in these two tests. Fix: extend the helper with a result-class param
and have only the two postpone-asserting tests seed HASH_MISMATCH —
unambiguously Class A under both old and new semantics. Other callers
keep the existing INVALID_TRANSCRIPT default unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@akobrin1 akobrin1 requested a review from a-ok123 May 6, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants