Conversation
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 Issues
Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues. |
There was a problem hiding this comment.
💡 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".
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 settingBIN_DIR=\"\"and continuing, or adding an explicit--no-bin-dir/--skip-binariesmode.
#!/bin/bash
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…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>
There was a problem hiding this comment.
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>
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>
There was a problem hiding this comment.
Re-review of changes since SHA 8a7d1f5. All 19 previously flagged issues are confirmed resolved. Found 3 new observations (1 medium, 2 low).
There was a problem hiding this comment.
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]:
storageTruthIsClassAFaultenforcement 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]:
storageTruthReporterAccountsForEpochfull table scan -- bounded by pruning but could benefit from an epoch-keyed reporter index as the active set grows. - #22 [low]: Dead constant
maxAuditEpochLookbackafter audit metrics refactor.
Approving -- none of the new items are blocking.
There was a problem hiding this comment.
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.
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>
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.mdNew Modules
x/vm(Cosmos EVM v0.6.0)x/feemarket0.0005 ulume/gas) and ~6.25% per-block adjustmentx/precisebankulume↔ 18-decimalalumebridge:EVMBalance(a) = I(a) × 10¹² + F(a)x/erc20x/evmigrationKey Changes
Runtime & Execution
app/evm/ante.go): deterministic tx routing based onExtensionOptions[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 !testindefaults_prod.go)app/evm_mempool.go): Ethereum-like sender ordering, nonce-gap handling, same-nonce replacement with bump rules,max_txs=5000enabled by defaultapp/evm_broadcast.go): decouples txpoolrunReorgpromotion from CometBFTCheckTxvia bounded channel + single background worker, preventing mutex re-entry deadlock — a novel fix no other Cosmos EVM chain has publicly addressedRegisterTxServiceoverride (app/evm_runtime.go): captures the local CometBFT client for the broadcast worker, replacing the stale HTTP client from pre-CometBFTSetClientCtxGetSignersforMsgEthereumTx+ safe early-RPC keeper coin info initialization (SetKeeperDefaults) to prevent panics before genesiswasmd v0.61.6and EVM run in the same runtime — Lumera is the only Cosmos chain shipping both simultaneouslyChain Configuration
76857769eth_secp256k1(default), BIP44 coin type60— MetaMask/Ledger compatible out of the box0.0025 ulume/gas, min gas price floor0.0005 ulume/gas(prevents zero-fee spam that hit Evmos), change denominator16(~6.25%/block vs upstream8at ~12.5%)25,000,000config/bank_metadata.go):ulume/lume/alumemetadata +RegisterExtraInterfacesforeth_secp256k1crypto across all SDK+EVM pathscmd/lumera/cmd/config_migrate.go): pre-EVMapp.tomlfiles auto-gain[evm],[json-rpc], and[evm.mempool]sections with correct chain ID on first startup — no manual interventionPrecompiles (11 static)
Standard (8): P256, Bech32, Staking, Distribution, ICS20, Bank, Gov, Slashing
Custom Lumera precompiles:
0x0901): 11 methods — cascade/sense request+finalize, approve, fee queries, paginated action queries. Seeaction-precompile.mdfor full ABI reference.0x0902): 12 methods — register/deregister, state transitions, metrics reporting (caller-bound auth), XOR distance ranking. Seesupernode-precompile.mdfor full ABI reference.0x0903): 4 methods —execute,query,contractInfo,rawQuery. The EVM→CosmWasm direction of the cross-runtime bridge. Seewasm-precompile.mdfor 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.
IWasmat0x0903)execute/query/contractInfo/rawQueryon any CosmWasm contractevm_callviaCosmosMsg::CustomandQueryRequest::CustomPhase 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.solIBC & 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/allowlistdefault/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
eth,net,web3,txpool,debug,personal,minernamespaces; mainnet auto-blocksdebug/personal/adminviajsonrpc_policy.goapp/evm_jsonrpc_ratelimit.go): token bucket proxy —requests-per-second=50,burst=100,entry-ttl=5m, HTTP 429 with JSON-RPC-32005on limit, stale entries GC'd every 60sapp.toml [evm] tracer—json,struct,access_list,markdown; enablesdebug_traceTransaction,debug_traceBlockByNumber,debug_traceBlockByHash,debug_traceCallrpc_discoverJSON-RPC method (port 8545) +GET/POST /openrpc.jsonHTTP endpoint (port 1317) with CORS; gzip-compressed spec embedded in binary (315 KB → 20 KB); build-time generation viatools/openrpcgenwith Go reflection + AST parsing;POST /openrpc.jsonproxies to JSON-RPC server enabling OpenRPC Playground "Try It" directly; spec version fromgo.modviaruntime/debug.ReadBuildInfo()https://playground.open-rpc.org/?url=http://<node>:1317/openrpc.jsonAccount Migration (
x/evmigration)MsgClaimLegacyAccount: signed by neweth_secp256k1address; legacy signature =secp256k1_sign(SHA256("lumera-evm-migration:<chainID>:<evmChainID>:<legacy_address>:<new_address>"))MsgMigrateValidator: re-keys validator record + all associated module state including delegator referencesante/evmigration_fee_decorator.go): zero-fee migration txs since new address has no balanceenable_migration,migration_end_time,max_migrations_per_block=50,max_validator_delegations=2000MigrationRecord,MigrationRecords,MigrationEstimate(dry-run),MigrationStats,LegacyAccounts,MigratedAccountsUpgrade & Ops
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 policydocs/evm-integration/node-evm-config-guide.md—app.tomltuning,[evm]/[json-rpc]/[evm.mempool]sections, RPC exposure, tracer config, rate limiting, security policiesDevnet
devnet/default-config/devnet-genesis-evm.json)devnet/tests/validator/evm_test.go): fee market, cross-peer tx visibility, mixed Cosmos+EVM blocksdocs/evm-integration/remix-guide.md— MetaMask network config, contract deployment, interaction, event querying, troubleshootingBugs Found & Fixed (25 issues)
Documented in
docs/evm-integration/bugs.mdTest Coverage (~470 tests)
newHeads,logs,pendingTransactionsDevnet 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
main.mdtests.mdbugs.mdroadmap.mdsecurity-audit.mdtune-guide.mdnode-evm-config-guide.mdapp.tomltuning, security policies, rate limitingopenrpc-playground.mdremix-guide.mdprecompiles.mdaction-precompile.md0x0901) ABI reference, 11 methods, design notessupernode-precompile.md0x0902) ABI reference, 12 methods, design noteswasm-precompile.md0x0903) — full cross-runtime bridge architecture, Solidity+Rust interfaces, data flow, gas metering, reentrancy designevmigration-ui.mddevnet-tests.mdblock-explorer.mdlumera-ports.mdWhat Makes This Different
rpc_discover+/openrpc.json+ playground proxy0.0005 ulume/gas(prevents decay to zero)0x0901) + Supernode (0x0902) + Wasm (0x0903) at launchconfig_migrate.goadds[evm]section on startupGas Configuration
Roadmap Status
163/168 items complete (97%) across 15 phases.
Breaking Changes
secp256k1eth_secp256k1keys adddefaults to Ethereum-compatible keys11860feemarket,precisebank,vm,erc20,evmigration[evm]section[evm],[json-rpc],[evm.mempool]inapp.tomlconfig_migrate.go