Migrate to Cosmos EVM and XRPLEVM v9#5
Migrate to Cosmos EVM and XRPLEVM v9#5JordiParraCrespo wants to merge 4 commits intoxrplevm:chains/exrp/devnetfrom
Conversation
f3afbf1 to
89b7577
Compare
There was a problem hiding this comment.
Pull request overview
This PR migrates Callisto to the XRPL EVM v9 stack by moving from the Evmos-based EVM integration to github.com/cosmos/evm and upgrading core Cosmos SDK dependencies, while also updating local dev tooling and configuration to support the new EVM requirements.
Changes:
- Upgrade core dependencies (XRPL EVM node v9, Cosmos SDK v0.53, CometBFT) and switch EVM integration from Evmos to
cosmos/evm. - Introduce an EVM
chain_idconfig loader and wire it into codec initialization. - Update local development setup (docker/hasura settings, Makefile targets) and add ready-to-use mainnet/testnet configs.
Reviewed changes
Copilot reviewed 12 out of 16 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| utils/codec.go | Switches codec/module registration to cosmos/evm and initializes encoding config with configured EVM ChainID. |
| types/evm_config/evm_config.go | Adds EVM config parsing/loading for evm.chain_id from config.yaml. |
| types/evm_config/evm_config_test.go | Adds unit tests for the new EVM config loader/parser. |
| cmd/callisto/main.go | Loads EVM config at startup and sets the global ChainID used by codec initialization. |
| go.mod | Bumps Go/Cosmos dependencies and updates replace directives for the new EVM stack and forks. |
| modules/gov/utils_events_test.go | Updates expectations to match updated vote-option parsing output type. |
| configs/mainnet-config.yaml | Adds a preconfigured mainnet config including evm.chain_id. |
| configs/testnet-config.yaml | Adds a preconfigured testnet config including evm.chain_id. |
| docker-compose.yml | Makes Hasura image arch-selectable via env and updates actions base URL to host.docker.internal. |
| hasura/config.yaml | Updates actions handler base URL to host.docker.internal. |
| Makefile | Adds dev convenience targets (start/start-clean, schema management, env setup). |
| README.md | Major rewrite with quickstart, make targets, and service/docs layout. |
| .gitignore | Ignores .env used by docker-compose/Makefile flow. |
| cmd/parse/slashing/cmd.go, cmd/parse/slashing/params.go | Removes trailing whitespace. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
types/evm_config/evm_config_test.go
Outdated
| tempFile, err := os.CreateTemp("", "config-*.yaml") | ||
| require.NoError(t, err) | ||
| defer os.Remove(tempFile.Name()) | ||
|
|
||
| invalidYaml := []byte(`invalid: yaml: content`) | ||
| _, err = tempFile.Write(invalidYaml) | ||
| require.NoError(t, err) | ||
| require.NoError(t, tempFile.Close()) | ||
|
|
||
| t.Setenv("JUNO_CONFIG", tempFile.Name()) | ||
|
|
||
| cfg := ReadConfigFromFile() |
There was a problem hiding this comment.
TestGetConfig/Missing Config File doesn't set config.HomePath to the temp dir, so it can accidentally read a real config.yaml from the developer's environment and become flaky. Set config.HomePath = tempDir (and restore it) and avoid creating/setting unrelated JUNO_CONFIG state if it isn't used by GetConfig.
| tempFile, err := os.CreateTemp("", "config-*.yaml") | |
| require.NoError(t, err) | |
| defer os.Remove(tempFile.Name()) | |
| invalidYaml := []byte(`invalid: yaml: content`) | |
| _, err = tempFile.Write(invalidYaml) | |
| require.NoError(t, err) | |
| require.NoError(t, tempFile.Close()) | |
| t.Setenv("JUNO_CONFIG", tempFile.Name()) | |
| cfg := ReadConfigFromFile() | |
| originalHomePath := config.HomePath | |
| config.HomePath = tempDir | |
| defer func() { config.HomePath = originalHomePath }() | |
| cfg, err := GetConfig() | |
| require.NoError(t, err) |
| start: setup-env update-config build | ||
| @echo "Starting database services..." | ||
| @docker compose up -d | ||
| @echo "Waiting for database to be ready..." | ||
| @sleep 3 | ||
| @echo "Starting callisto..." | ||
| @./build/callisto start | ||
| .PHONY: start |
There was a problem hiding this comment.
The start/start-clean targets always invoke update-config, but update-config will fail with a cryptic cp error when CONFIG is not set (e.g., make start). Consider adding a guard that errors with a clear message when CONFIG is empty, or set a sensible default.
types/evm_config/evm_config.go
Outdated
| if _, err := os.Stat(file); os.IsNotExist(err) { | ||
| return Config{}, fmt.Errorf("config file does not exist") | ||
| } | ||
|
|
||
| bz, err := os.ReadFile(file) | ||
| if err != nil { | ||
| return Config{}, fmt.Errorf("error while reading config file: %s", err) |
There was a problem hiding this comment.
The errors returned by GetConfig are hard to diagnose because they omit the file path and don't wrap the underlying error. Consider including the resolved file path in the message and using %w when returning the read/stat errors so callers can inspect the cause.
| if _, err := os.Stat(file); os.IsNotExist(err) { | |
| return Config{}, fmt.Errorf("config file does not exist") | |
| } | |
| bz, err := os.ReadFile(file) | |
| if err != nil { | |
| return Config{}, fmt.Errorf("error while reading config file: %s", err) | |
| if _, err := os.Stat(file); err != nil { | |
| if os.IsNotExist(err) { | |
| return Config{}, fmt.Errorf("config file %q does not exist: %w", file, err) | |
| } | |
| return Config{}, fmt.Errorf("failed to stat config file %q: %w", file, err) | |
| } | |
| bz, err := os.ReadFile(file) | |
| if err != nil { | |
| return Config{}, fmt.Errorf("error while reading config file %q: %w", file, err) |
README.md
Outdated
| migrations_directory: migrations | ||
| actions: | ||
| kind: synchronous | ||
| handler_webhook_baseurl: http://localhost:3000 |
There was a problem hiding this comment.
The Hasura config example still shows handler_webhook_baseurl: http://localhost:3000, but the repository configuration now uses http://host.docker.internal:3000. Update this snippet so it matches the actual hasura/config.yaml behavior when running Hasura in Docker.
| handler_webhook_baseurl: http://localhost:3000 | |
| handler_webhook_baseurl: http://host.docker.internal:3000 |
Description
This update migrates callisto from xrplevm/node/v6 to xrplevm/node/v9. The core change in the xrplevm ecosystem is the move from the evmos EVM stack (github.com/evmos/evmos/v20) to the new modular cosmos/evm library (github.com/cosmos/evm), along with a Cosmos SDK bump from v0.50.x to v0.53.x.
Main changes
Go Version
go 1.22.7+toolchain go1.22.9go 1.23.8(no toolchain directive)Direct Dependencies
github.com/xrplevm/node/v6 v6.0.0github.com/xrplevm/node/v9 v9.0.0github.com/evmos/evmos/v20 v20.0.0github.com/cosmos/evm v0.4.0github.com/cosmos/cosmos-sdk v0.50.11github.com/cosmos/cosmos-sdk v0.53.4github.com/cometbft/cometbft v0.38.15github.com/cometbft/cometbft v0.38.21cosmossdk.io/math v1.4.0cosmossdk.io/math v1.5.3cosmossdk.io/store v1.1.1cosmossdk.io/store v1.1.2cosmossdk.io/log v1.4.1cosmossdk.io/log v1.6.1Replace Directives
cosmossdk.io/core => cosmossdk.io/core v0.11.0cosmossdk.io/core => cosmossdk.io/core v0.11.3cosmossdk.io/store => github.com/evmos/cosmos-sdk/store v0.0.0-...github.com/cosmos/cosmos-sdk/store => cosmossdk.io/store v1.1.2github.com/cosmos/cosmos-sdk => github.com/evmos/cosmos-sdk v0.50.9-evmosgithub.com/cosmos/cosmos-sdk => github.com/xrplevm/cosmos-sdk v0.53.4-xrplevm.2github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc4github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v0.0.0-20250806193535-2fc7571efa91github.com/evmos/evmos/v20 => github.com/xrplevm/evmos/v20 v20.0.0-exrp.4github.com/cosmos/evm => github.com/xrplevm/evm v0.4.2-xrplevm.2