From 7b86780cebb57f02a052bd724b10862d421f0e37 Mon Sep 17 00:00:00 2001 From: "dang.vh" Date: Mon, 14 Jul 2025 09:57:01 +0700 Subject: [PATCH 1/4] replace ibc fee with wasmhooks in ica stack --- .github/workflows/interchaintest.yaml | 51 +++++++---- Makefile | 4 + app/app.go | 3 +- tests/interchaintest/ica_test.go | 125 ++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 20 deletions(-) diff --git a/.github/workflows/interchaintest.yaml b/.github/workflows/interchaintest.yaml index da88cc3346..2f75eda74b 100644 --- a/.github/workflows/interchaintest.yaml +++ b/.github/workflows/interchaintest.yaml @@ -29,7 +29,7 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GH_PAT }} - - name: Build and push + - name: Build and push id: build_push_image uses: docker/build-push-action@v5 with: @@ -43,10 +43,10 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 @@ -58,10 +58,10 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 @@ -73,10 +73,10 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 @@ -88,10 +88,10 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 @@ -103,10 +103,10 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 @@ -118,10 +118,10 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 @@ -133,10 +133,10 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 @@ -148,14 +148,29 @@ jobs: runs-on: ubuntu-latest needs: build-and-push-image # This job must run after build and push image steps: - - name: Set up Go 1.22 + - name: Set up Go 1.23 uses: actions/setup-go@v4 with: - go-version: '1.22.7' + go-version: "1.23.6" - name: checkout code uses: actions/checkout@v4 - run: make ictest-txfees-add-fee-token env: - BRANCH_CI: "latest" \ No newline at end of file + BRANCH_CI: "latest" + ictest-interchain-account-from-gaia: + runs-on: ubuntu-latest + needs: build-and-push-image # This job must run after build and push image + steps: + - name: Set up Go 1.23 + uses: actions/setup-go@v4 + with: + go-version: "1.23.6" + + - name: checkout code + uses: actions/checkout@v4 + + - run: make ictest-interchain-account-from-gaia + env: + BRANCH_CI: "latest" diff --git a/Makefile b/Makefile index 17c7c62625..d7a0632555 100644 --- a/Makefile +++ b/Makefile @@ -166,6 +166,10 @@ ictest-basic: ictest-interchain-account: cd tests/interchaintest && go test -race -v -run TestInterchainAccount . +# Executes interchain account tests via interchaintest +ictest-interchain-account-from-gaia: + cd tests/interchaintest && go test -race -v -run TestInterchainAccountFromGaia . + # Executes token factory param change tests via interchaintest ictest-tf-param-change: cd tests/interchaintest && go test -race -v -run TestTokenfactoryParamChange . diff --git a/app/app.go b/app/app.go index 386274bb50..453d26423a 100644 --- a/app/app.go +++ b/app/app.go @@ -774,7 +774,7 @@ func NewWasmApp( appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), - app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack + app.HooksICS4Wrapper, app.IBCKeeper.ChannelKeeper, app.IBCKeeper.PortKeeper, app.AccountKeeper, @@ -871,7 +871,6 @@ func NewWasmApp( var icaControllerStack porttypes.IBCModule // integration point for custom authentication modules // see https://medium.com/the-interchain-foundation/ibc-go-v6-changes-to-interchain-accounts-and-how-it-impacts-your-chain-806c185300d7 - icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) // RecvPacket, message that originates from core IBC and goes down to app, the flow is: diff --git a/tests/interchaintest/ica_test.go b/tests/interchaintest/ica_test.go index 707c65136d..3c1abf4823 100644 --- a/tests/interchaintest/ica_test.go +++ b/tests/interchaintest/ica_test.go @@ -141,3 +141,128 @@ func TestInterchainAccount(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, icaAddress) } + +// TestStartOrai is a basic test to assert that spinning up a Orai network with 1 validator works properly. +func TestInterchainAccountFromGaia(t *testing.T) { + if testing.Short() { + t.Skip() + } + + t.Parallel() + + ctx := context.Background() + + numVals := 1 + numFullNodes := 1 + + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + { + Name: "orai", + ChainConfig: oraiConfig, + NumValidators: &numVals, + NumFullNodes: &numFullNodes, + }, + { + Name: "gaia", + Version: GaiaImageVersion, + ChainConfig: ibc.ChainConfig{ + GasPrices: "1uatom", + }, + NumValidators: &numVals, + NumFullNodes: &numFullNodes, + }, + }) + + // Get chains from the chain factory + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + orai, gaia := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain) + + // Create relayer factory to utilize the go-relayer + client, network := interchaintest.DockerSetup(t) + r := interchaintest.NewBuiltinRelayerFactory( + ibc.CosmosRly, + zaptest.NewLogger(t), + relayer.CustomDockerImage(IBCRelayerImage, IBCRelayerVersion, "100:1000"), + ).Build(t, client, network) + + ic := interchaintest.NewInterchain(). + AddChain(orai). + AddChain(gaia). + AddRelayer(r, "rly"). + AddLink(interchaintest.InterchainLink{ + Chain1: orai, + Chain2: gaia, + Relayer: r, + Path: pathOraiGaia, + }) + + rep := testreporter.NewNopReporter() + eRep := rep.RelayerExecReporter(t) + + err = ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + SkipPathCreation: false, + + // This can be used to write to the block database which will index all block data e.g. txs, msgs, events, etc. + // BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(), + }) + require.NoError(t, err) + + t.Cleanup(func() { + _ = ic.Close() + }) + + // Start the relayer + require.NoError(t, r.StartRelayer(ctx, eRep, pathOraiGaia)) + t.Cleanup( + func() { + err := r.StopRelayer(ctx, eRep) + if err != nil { + panic(fmt.Errorf("an error occurred while stopping the relayer: %s", err)) + } + }, + ) + + // Fund testing user + users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), genesisWalletAmount, orai, gaia) + // Get our Bech32 encoded user addresses + oraiUser, gaiaUser := users[0], users[1] + + relayerWalletOrai, found := r.GetWallet(orai.Config().ChainID) + require.True(t, found) + + err = orai.SendFunds(ctx, oraiUser.KeyName(), ibc.WalletAmount{ + Address: relayerWalletOrai.FormattedAddress(), + Amount: math.NewInt(100_000_000), + Denom: orai.Config().Denom, + }) + require.NoError(t, err) + + relayerWalletGaia, found := r.GetWallet(gaia.Config().ChainID) + require.True(t, found) + + err = gaia.SendFunds(ctx, gaiaUser.KeyName(), ibc.WalletAmount{ + Address: relayerWalletGaia.FormattedAddress(), + Amount: math.NewInt(100_000_000), + Denom: gaia.Config().Denom, + }) + require.NoError(t, err) + + // Get ibc connection + ibcConnection, err := r.GetConnections(ctx, eRep, gaia.Config().ChainID) + require.NoError(t, err) + + // register ICA + _, err = helpers.RegisterICA(t, ctx, gaia, gaiaUser.KeyName(), ibcConnection[0].ID) + require.NoError(t, err) + err = testutil.WaitForBlocks(ctx, 10, orai, gaia) + + require.NoError(t, err) + icaAddress, err := helpers.QueryInterchainAccount(t, ctx, gaia, gaiaUser.FormattedAddress(), ibcConnection[0].ID) + require.NoError(t, err) + require.NotEmpty(t, icaAddress) +} From 17e22b2b4b86407162c2be3b84a8b215105f8f38 Mon Sep 17 00:00:00 2001 From: "dang.vh" Date: Mon, 14 Jul 2025 11:39:14 +0700 Subject: [PATCH 2/4] add test send ica --- Makefile | 4 +- tests/interchaintest/helpers/ica.go | 40 +++++++++++++++- tests/interchaintest/helpers/types.go | 4 ++ tests/interchaintest/ica_test.go | 69 ++++++++++++++++++++++++++- tests/interchaintest/setup.go | 2 +- 5 files changed, 114 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d7a0632555..ed1e614dc6 100644 --- a/Makefile +++ b/Makefile @@ -163,8 +163,8 @@ ictest-basic: cd tests/interchaintest && go test -race -v -run TestStartOrai . # Executes interchain account tests via interchaintest -ictest-interchain-account: - cd tests/interchaintest && go test -race -v -run TestInterchainAccount . +ictest-interchain-account-from-orai: + cd tests/interchaintest && go test -race -v -run TestInterchainAccountFromOrai . # Executes interchain account tests via interchaintest ictest-interchain-account-from-gaia: diff --git a/tests/interchaintest/helpers/ica.go b/tests/interchaintest/helpers/ica.go index 573d857afc..f238a151b4 100644 --- a/tests/interchaintest/helpers/ica.go +++ b/tests/interchaintest/helpers/ica.go @@ -2,9 +2,13 @@ package helpers import ( "context" + "encoding/json" + "fmt" + "path" "testing" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v8/dockerutil" ) // RegisterICA will attempt to register an interchain account on the counterparty chain. @@ -24,6 +28,33 @@ func RegisterICA(t *testing.T, ) } +func ExecuteICA( + t *testing.T, + ctx context.Context, + chain *cosmos.CosmosChain, + keyName, connectionID string, + msg []byte, +) (string, error) { + tn := chain.GetNode() + + file := "msg.json" + fw := dockerutil.NewFileWriter(nil, tn.DockerClient, tn.TestName) + if err := fw.WriteFile(ctx, tn.VolumeName, file, msg); err != nil { + return "", fmt.Errorf("writing contract file to docker volume: %w", err) + } + + command := []string{ + "interchain-accounts", + "controller", + "send-tx", + connectionID, + path.Join(tn.HomeDir(), file), + "--gas", "auto", + } + + return tn.ExecTx(ctx, keyName, command...) +} + // QueryParam returns the state and details of a subspace param. func QueryInterchainAccount(t *testing.T, ctx context.Context, @@ -43,5 +74,12 @@ func QueryInterchainAccount(t *testing.T, if err != nil { return "", err } - return string(stdout), nil + + var icaAccount IcaAccount + err = json.Unmarshal(stdout, &icaAccount) + if err != nil { + return "", err + } + + return icaAccount.Address, nil } diff --git a/tests/interchaintest/helpers/types.go b/tests/interchaintest/helpers/types.go index f93ab22be2..0b87b22408 100644 --- a/tests/interchaintest/helpers/types.go +++ b/tests/interchaintest/helpers/types.go @@ -56,3 +56,7 @@ type HackatomExampleInitMsg struct { type QuerySqrtPriceResponse struct { Data string `json:"data,omitempty"` } + +type IcaAccount struct { + Address string `json:"address"` +} diff --git a/tests/interchaintest/ica_test.go b/tests/interchaintest/ica_test.go index 3c1abf4823..d31e5a7556 100644 --- a/tests/interchaintest/ica_test.go +++ b/tests/interchaintest/ica_test.go @@ -2,6 +2,7 @@ package interchaintest import ( "context" + "encoding/json" "fmt" "testing" @@ -15,10 +16,15 @@ import ( "github.com/strangelove-ventures/interchaintest/v8/testutil" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + icatypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types" + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" ) // TestStartOrai is a basic test to assert that spinning up a Orai network with 1 validator works properly. -func TestInterchainAccount(t *testing.T) { +func TestInterchainAccountFromOrai(t *testing.T) { if testing.Short() { t.Skip() } @@ -127,6 +133,31 @@ func TestInterchainAccount(t *testing.T) { }) require.NoError(t, err) + transfer := ibc.WalletAmount{ + Address: gaiaUser.FormattedAddress(), + Denom: orai.Config().Denom, + Amount: math.NewInt(1_000_000), + } + + channel, err := ibc.GetTransferChannel(ctx, r, eRep, orai.Config().ChainID, gaia.Config().ChainID) + require.NoError(t, err) + + transferTx, err := orai.SendIBCTransfer(ctx, channel.ChannelID, oraiUser.FormattedAddress(), transfer, ibc.TransferOptions{}) + require.NoError(t, err) + + // waiting for ACK -> transfer successfully + oraiHeight, err := orai.Height(ctx) + require.NoError(t, err) + _, err = testutil.PollForAck(ctx, orai, oraiHeight-5, oraiHeight+25, transferTx.Packet) + require.NoError(t, err) + + oraiDenom := transfertypes.GetPrefixedDenom(channel.Counterparty.PortID, channel.Counterparty.ChannelID, orai.Config().Denom) + ibcDenom := transfertypes.ParseDenomTrace(oraiDenom).IBCDenom() + // check balance of ica address + balance, err := gaia.BankQueryBalance(ctx, gaiaUser.FormattedAddress(), ibcDenom) + require.NoError(t, err) + require.Equal(t, math.NewInt(1_000_000), balance) + // Get ibc connection ibcConnection, err := r.GetConnections(ctx, eRep, orai.Config().ChainID) require.NoError(t, err) @@ -140,6 +171,42 @@ func TestInterchainAccount(t *testing.T) { icaAddress, err := helpers.QueryInterchainAccount(t, ctx, orai, oraiUser.FormattedAddress(), ibcConnection[0].ID) require.NoError(t, err) require.NotEmpty(t, icaAddress) + + gaia.SendFunds(ctx, gaiaUser.KeyName(), ibc.WalletAmount{ + Address: icaAddress, + Amount: math.NewInt(1_000_000), + Denom: ibcDenom, + }) + + balance, err = gaia.BankQueryBalance(ctx, icaAddress, ibcDenom) + require.NoError(t, err) + require.Equal(t, math.NewInt(1_000_000), balance) + + // send 1000 orai to the ica addre + + msg := banktypes.MsgSend{ + FromAddress: icaAddress, + ToAddress: gaiaUser.FormattedAddress(), + Amount: sdk.NewCoins(sdk.NewCoin(ibcDenom, math.NewInt(1_000_000))), + } + + msgJson, err := json.Marshal(msg) + require.NoError(t, err) + + msgICA := icatypes.InterchainAccountPacketData{ + Type: icatypes.EXECUTE_TX, + Data: msgJson, + Memo: "", + } + + msgICAJson, err := json.Marshal(msgICA) + require.NoError(t, err) + + _, err = helpers.ExecuteICA(t, ctx, orai, oraiUser.KeyName(), ibcConnection[0].ID, msgICAJson) + require.NoError(t, err) + + err = testutil.WaitForBlocks(ctx, 10, orai, gaia) + require.NoError(t, err) } // TestStartOrai is a basic test to assert that spinning up a Orai network with 1 validator works properly. diff --git a/tests/interchaintest/setup.go b/tests/interchaintest/setup.go index a653c9373a..e4b39d729d 100644 --- a/tests/interchaintest/setup.go +++ b/tests/interchaintest/setup.go @@ -31,7 +31,7 @@ const ( // Chain and relayer version inf IBCRelayerImage = "ghcr.io/cosmos/relayer" - OraidICTestRepo = "ghcr.io/oraichain/oraid-ictest" + OraidICTestRepo = "docker.io/oraichain/oraid-ictest" IBCRelayerVersion = "latest" GaiaImageVersion = "v21.0.0" OsmosisImageVersion = "v28.0.0" From 241175079e7686a78f4db6212d06e6f94d97804f Mon Sep 17 00:00:00 2001 From: "dang.vh" Date: Mon, 14 Jul 2025 13:38:14 +0700 Subject: [PATCH 3/4] add e2e test ica --- tests/interchaintest/ica_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/interchaintest/ica_test.go b/tests/interchaintest/ica_test.go index d31e5a7556..06c9e95afa 100644 --- a/tests/interchaintest/ica_test.go +++ b/tests/interchaintest/ica_test.go @@ -205,7 +205,7 @@ func TestInterchainAccountFromOrai(t *testing.T) { _, err = helpers.ExecuteICA(t, ctx, orai, oraiUser.KeyName(), ibcConnection[0].ID, msgICAJson) require.NoError(t, err) - err = testutil.WaitForBlocks(ctx, 10, orai, gaia) + err = testutil.WaitForBlocks(ctx, 20, orai, gaia) require.NoError(t, err) } From f553c0061d6ad6722b43f5f7d785b925fd8d6cea Mon Sep 17 00:00:00 2001 From: "dang.vh" Date: Mon, 14 Jul 2025 13:51:35 +0700 Subject: [PATCH 4/4] add upgrade handler --- app/upgrades.go | 2 ++ app/upgrades/v05012/upgrades.go | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 app/upgrades/v05012/upgrades.go diff --git a/app/upgrades.go b/app/upgrades.go index e1b5da7f76..c1d1cc5ef6 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -9,6 +9,7 @@ import ( v0501 "github.com/CosmWasm/wasmd/app/upgrades/v0501" v05010 "github.com/CosmWasm/wasmd/app/upgrades/v05010" v05011 "github.com/CosmWasm/wasmd/app/upgrades/v05011" + v05012 "github.com/CosmWasm/wasmd/app/upgrades/v05012" v0502 "github.com/CosmWasm/wasmd/app/upgrades/v0502" v0503 "github.com/CosmWasm/wasmd/app/upgrades/v0503" v0504 "github.com/CosmWasm/wasmd/app/upgrades/v0504" @@ -57,6 +58,7 @@ var Upgrades = []upgrades.Upgrade{ v0509.Upgrade, v05010.Upgrade, v05011.Upgrade, + v05012.Upgrade, } // RegisterUpgradeHandlers registers the chain upgrade handlers diff --git a/app/upgrades/v05012/upgrades.go b/app/upgrades/v05012/upgrades.go new file mode 100644 index 0000000000..11f917dc21 --- /dev/null +++ b/app/upgrades/v05012/upgrades.go @@ -0,0 +1,39 @@ +package v05012 + +import ( + "context" + + storetypes "cosmossdk.io/store/types" + upgradetypes "cosmossdk.io/x/upgrade/types" + + "github.com/CosmWasm/wasmd/app/upgrades" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" +) + +// UpgradeName defines the on-chain upgrade name +const UpgradeName = "v0.50.12" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateUpgradeHandler, + StoreUpgrades: storetypes.StoreUpgrades{ + Added: []string{}, + Deleted: []string{}, + }, +} + +func CreateUpgradeHandler( + mm upgrades.ModuleManager, + configurator module.Configurator, + ak *upgrades.AppKeepers, + keys map[string]*storetypes.KVStoreKey, + cdc codec.BinaryCodec, +) upgradetypes.UpgradeHandler { + return func(goCtx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + migrationRes, err := mm.RunMigrations(ctx, configurator, fromVM) + return migrationRes, err + } +}