Skip to content

feat: evm 0.6.0 adjustment changes#272

Open
AryaLanjewar3005 wants to merge 2 commits into
audit-fixesfrom
evm-upgrade-0.6.0
Open

feat: evm 0.6.0 adjustment changes#272
AryaLanjewar3005 wants to merge 2 commits into
audit-fixesfrom
evm-upgrade-0.6.0

Conversation

@AryaLanjewar3005

Copy link
Copy Markdown
Collaborator

Summary

push-chain — adjustments for cosmos/evm (push-chain-evm) v0.6.0

This document describes the changes made to the push-chain application
(github.com/pushchain/push-chain-node) so that it builds and runs against the
upgraded push-chain-evm dependency (cosmos/evm v0.6.0, previously
v0.5.1).

It is the companion to the evm-side document
(push-chain-evm/docs/migrations/PUSHCHAIN_v0.5.1_to_v0.6.0.md) and follows the
official cosmos/evm guide:

Migration v0.5 → v0.6:
https://cosmos-docs.mintlify.app/evm/latest/documentation/migrations/migration-v0.5-to-v0.6

Every change below is a direct consequence of a v0.6.0 breaking change unless
marked (general).


1. Dependency reconciliation (go.mod / go.sum)

go mod tidy absorbed push-chain-evm v0.6.0's transitive bumps. The cosmos-sdk
replace pin is deliberately unchanged.

- github.com/cometbft/cometbft        v0.38.19   →  v0.38.21
- github.com/cosmos/ledger-cosmos-go  v0.16.0    →  v1.0.0
- github.com/spf13/viper              v1.20.1    →  v1.21.0
  (+ indirect: sagikazarmark/locafero, sourcegraph/conc, spf13/afero, …)
  github.com/cosmos/cosmos-sdk => v0.50.10        (UNCHANGED)

2. IBC transfer module rewiring — the largest change

Why: cosmos/evm v0.6.0 deletes its custom x/ibc/transfer module. Its
ERC-20 conversion responsibilities move to the standard ibc-go transfer module
wrapped by the erc20 IBC middleware, plus the ICS20 precompile. push-chain's
app imported and wired the now-deleted module, so it had to be re-pointed.

2.1 Imports — app/app.go

- transfer          "github.com/cosmos/evm/x/ibc/transfer"
- ibctransferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper"
+ transfer          "github.com/cosmos/ibc-go/v10/modules/apps/transfer"
+ ibctransferkeeper "github.com/cosmos/ibc-go/v10/modules/apps/transfer/keeper"

(app.TransferKeeper's declared type stays ibctransferkeeper.Keeper — only the
package the alias points to changed, so the field/usages are unaffected.)
precompiles.go had the same import swap for transferkeeper.

ibc-go v10 is used (not v11 as in the "latest" migration page) because
v0.6.0 itself pins ibc-go v10 and push-chain already depends on v10.4.0.

2.2 TransferKeeper construction — app/app.go

The custom keeper took an extra Erc20Keeper and had no legacySubspace
parameter. The standard ibc-go keeper is the reverse:

  app.TransferKeeper = ibctransferkeeper.NewKeeper(
      appCodec,
      runtime.NewKVStoreService(keys[ibctransfertypes.StoreKey]),
+     nil,                  // legacySubspace (standard keeper param; no params subspace)
      app.RatelimitKeeper,  // ICS4Wrapper (push-chain's rate-limit middleware — unchanged)
      app.IBCKeeper.ChannelKeeper,
      app.MsgServiceRouter(),
      app.AccountKeeper,
      app.BankKeeper,
-     app.Erc20Keeper,      // removed — conversion now via the erc20 middleware
      authtypes.NewModuleAddress(govtypes.ModuleName).String(),
  )

SetAddressCodec is intentionally not called. The example app (evmd) sets
an EVM/hex address codec, but push-chain's previous custom keeper used the
default bech32 codec, and the standard keeper also defaults to bech32. Not
calling it therefore preserves push-chain's existing behavior. (Switching to the
hex codec would be a new feature, not a migration requirement.)

2.3 ERC-20 IBC middleware — app/app.go

To preserve the ERC-20 ↔ IBC conversion the custom keeper used to perform in its
OnRecvPacket/msg-server override, the erc20 middleware is inserted directly
above the transfer base app — exactly as evmd v0.6.0 wires it:

  var transferStack porttypes.IBCModule
  transferStack = transfer.NewIBCModule(app.TransferKeeper)
+ // ERC-20 middleware converts IBC vouchers to/from ERC-20 tokens.
+ transferStack = erc20.NewIBCMiddleware(app.Erc20Keeper, transferStack)
  cbStack := ibccallbacks.NewIBCMiddleware(transferStack, app.PacketForwardKeeper, wasmStack, maxCallbackGas)
  transferStack = packetforward.NewIBCMiddleware(cbStack, app.PacketForwardKeeper, 0, …)
  app.TransferKeeper.WithICS4Wrapper(cbStack)

Final stack (bottom→top): transfer → erc20 → callbacks → packet-forward.
The erc20 package was already imported by app, so no new import was needed.
push-chain's packet-forward / callbacks / rate-limit / wasm wiring is untouched.

IBC v2 not applicable. evmd v0.6.0 also wires an IBC-v2 transfer stack
(transferv2 + erc20v2 middleware + ibcRouterV2). push-chain is IBC v1
only
(no SetRouterV2/ibcapi/transferv2 anywhere), so no v2 wiring was
added.


3. ICS20 precompile — new erc20Keeper argument — app/precompiles.go

Why: v0.6.0's ics20.NewPrecompile(...) gained an
erc20Keeper cmn.ERC20Keeper parameter (the precompile now performs ERC-20
conversion itself).

  ibcTransferPrecompile := ics20precompile.NewPrecompile(
      bankKeeper,
      stakingKeeper,
      transferKeeper,
      channelKeeper,
+     erc20Kpr,
  )

erc20Kpr is push-chain's existing *erc20Keeper.Keeper. The v0.6.0
cmn.ERC20Keeper interface adds IsERC20Enabled, GetTokenPairID, and
ConvertERC20IntoCoinsForNativeToken(... stateDB, callFromPrecompile); the real
evm keeper implements all of them, so no push-chain-side implementation was
needed (push-chain passes the real keeper, not a wrapper).


4. EVM call API changes in x/uexecutor

Why: v0.6.0 changed CallEVM to take stateDB *statedb.StateDB and
callFromPrecompile bool, and forbids a nil StateDB (ErrNilStateDB).
push-chain's universal-executor module calls CallEVM extensively.
(DerivedEVMCall is push-chain's own function and its signature is unchanged, so
those call sites were left as-is.)

4.1 EVMKeeper interface — x/uexecutor/types/expected_keepers.go

  type EVMKeeper interface {
+     // NewStateDB returns a fresh StateDB to pass into CallEVM (now required).
+     NewStateDB(ctx sdk.Context) *statedb.StateDB
      CallEVM(
          ctx sdk.Context,
+         stateDB *statedb.StateDB,
          abi abi.ABI,
          from, contract common.Address,
-         commit bool,
+         commit, callFromPrecompile bool,
          gasCap *big.Int,
          method string,
          args ...interface{},
      ) (*types.MsgEthereumTxResponse, error)
      …
  }

NewStateDB(ctx) is a small helper added to the evm keeper
(x/vm/keeper/statedb.go) precisely so push-chain — which holds the EVM keeper
through this interface — can build the now-mandatory StateDB without listing all
of statedb.Keeper's methods on the interface.

4.2 Call sites — x/uexecutor/keeper/evm.go, gas_fee.go

Every k.evmKeeper.CallEVM(ctx, abi, from, contract, commit, gasCap, …) became:

k.evmKeeper.CallEVM(ctx, k.evmKeeper.NewStateDB(ctx), abi, from, contract, commit, false, gasCap, …)

i.e. a fresh per-call StateDB as the 2nd arg and callFromPrecompile = false
(these are module/keeper-context calls, not precompile-context calls).

4.3 Mocks & tests

  • x/uexecutor/mocks/mock_evmkeeper.go — regenerated CallEVM mock for the new
    signature and added a NewStateDB mock method/recorder.
  • x/uexecutor/keeper/msg_server_test.goEXPECT().CallEVM(...) matcher arg
    count updated (9 fixed + varargs), and EXPECT().NewStateDB(...).Return(nil).AnyTimes()
    added (production now calls NewStateDB to build the StateDB arg).
  • The manual partial MockEVMKeeper in keeper_test.go is not assigned to the
    types.EVMKeeper interface, so it needed no change.

5. Test-only call-site updates (mechanical)

The same CallEVM signature change rippled into test helpers and integration
tests that call app.EVMKeeper.CallEVM(...) directly. Each got the
<app>.EVMKeeper.NewStateDB(ctx) StateDB arg and the callFromPrecompile
(false) flag inserted:

  • test/utils/contracts_setup.go
  • test/integration/uexecutor/inbound_cea_gas_and_payload_test.go
  • test/integration/uexecutor/inbound_cea_payload_test.go
  • test/integration/uexecutor/inbound_cea_smart_contract_test.go
  • test/integration/uexecutor/inbound_solana_test.go
  • test/integration/uexecutor/inbound_synthetic_bridge_test.go
  • test/integration/uexecutor/vote_chain_meta_test.go
  • test/integration/utss/fund_migration_test.go

6. Live-network upgrade consideration — transfer module ConsensusVersion 5 → 6

Not a code change, but important for a live upgrade.

push-chain-evm's removed custom transfer module reported ConsensusVersion() = 5.
The standard ibc-go v10 transfer module reports ConsensusVersion() = 6. Both use
the same module name (transfer) and store key, so on a live v0.5 → v0.6
upgrade the SDK module manager will run the standard transfer module's registered
v5 → v6 migration, MigrateDenomTraceToDenom (denomTrace → denom format).

This is inherent to v0.6.0 (the custom module no longer exists) and is handled
automatically by push-chain's existing upgrade pattern — a named handler under
app/upgrades/<name>/ whose CreateUpgradeHandler calls
mm.RunMigrations(ctx, configurator, fromVM). No StoreUpgrades (Added/Deleted)
are needed for the transfer module (same store key).

Action at release time: add the v0.6.0 named upgrade handler (following the
existing app/upgrades/noop pattern). No evm module (x/vm, x/erc20,
x/feemarket, x/precisebank) bumped its ConsensusVersion, so no other evm
state migration is triggered. Fresh-genesis deployments and the test suites need
nothing extra.


7. Building & testing push-chain

push-chain links the native godkls library from the sibling dkls23-rs crate,
so build it first:

cd ../dkls23-rs && cargo build --release -p go-dkls     # produces target/release/libgodkls.dylib

Build:

cd push-chain && go build ./...      # clean (cmd/puniversald links libgodkls)

Test (mirrors the Makefile: native lib on the loader path + the evm build tags;
DYLD_* is the macOS equivalent of LD_LIBRARY_PATH):

LIB=$(pwd)/../dkls23-rs/target/release
LD_LIBRARY_PATH=$LIB DYLD_LIBRARY_PATH=$LIB DYLD_FALLBACK_LIBRARY_PATH=$LIB \
  go test -mod=readonly -tags='ledger test_ledger_mock test' ./...

Result: full suite 43 packages ok / 0 failed, including x/uexecutor
(keeper + msg_server), test/integration/uexecutor, test/integration/utss,
and the app package (which exercises the rewired IBC transfer stack and the new
CallEVM path).


8. Files changed in push-chain

File Change
app/app.go Transfer imports → ibc-go v10; NewKeeper (nil legacySubspace, drop Erc20Keeper); add erc20.NewIBCMiddleware.
app/precompiles.go transferkeeper import → ibc-go v10; pass erc20Kpr to ICS20 precompile.
go.mod / go.sum Dependency reconciliation (go mod tidy); SDK pin unchanged.
x/uexecutor/types/expected_keepers.go EVMKeeper interface: new CallEVM signature + NewStateDB.
x/uexecutor/keeper/evm.go, gas_fee.go CallEVM call sites updated.
x/uexecutor/mocks/mock_evmkeeper.go Mock CallEVM + new NewStateDB.
x/uexecutor/keeper/msg_server_test.go gomock matchers + NewStateDB expectation.
test/utils/contracts_setup.go + 7 test/integration/** files Test CallEVM call sites updated.

Nothing is committed or pushed.

References

  • Fixes #
  • Related issue/PR:

Changes

Testing

  • go test ./...

Checklist

  • Ready for review
  • Docs updated (if applicable)
  • Env vars updated (if applicable)

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.

1 participant