From 7221bce78f7a29b3de6a4e2f38b9f3c44356633d Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Wed, 8 Feb 2023 11:00:59 +0100 Subject: [PATCH 1/2] Integrate Packet Forward Middleware (#3911) * added initial packet forward middleware integration * gofumpt * updated go.mod * correct value * updating to match upstream * added params * gofumpt * added PFM to upgrades * go imports * added e2e test for PFM+wasm hoks * refactor * refactored for reusability and added comments * updated to latest version that allows native json * removed unnecessary param * reordering imports after merge * added denom check * added changelog * Update tests/e2e/e2e_test.go Co-authored-by: Roman * requiring the txs to succeed * fixed e2e tests --------- Co-authored-by: Roman --- CHANGELOG.md | 1 + app/keepers/keepers.go | 45 ++++++- app/keepers/modules.go | 2 + app/upgrades/v15/constants.go | 3 +- app/upgrades/v15/upgrades.go | 2 + go.mod | 3 + go.sum | 4 + go.work.sum | 4 + tests/e2e/e2e_test.go | 222 +++++++++++++++++++++++++++++----- 9 files changed, 249 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a20a19cf3..fed951c2319 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#4107](https://github.com/osmosis-labs/osmosis/pull/4107) Add superfluid unbond partial amount * [#4207](https://github.com/osmosis-labs/osmosis/pull/4207) Add support for Async Interchain Queries * [#4248](https://github.com/osmosis-labs/osmosis/pull/4248) Add panic recovery to `MultihopEstimateInGivenExactAmountOut`, `MultihopEstimateOutGivenExactAmountIn` and `RouteExactAmountOut` + * [#3911](https://github.com/osmosis-labs/osmosis/pull/3911) Add Packet Forward Middleware ## Misc Improvements * [#4131](https://github.com/osmosis-labs/osmosis/pull/4141) Add GatherValuesFromStorePrefixWithKeyParser function to osmoutils. diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index fd73127366d..86bd2f63691 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -59,6 +59,10 @@ import ( ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" icqkeeper "github.com/strangelove-ventures/async-icq/keeper" + packetforward "github.com/strangelove-ventures/packet-forward-middleware/v4/router" + packetforwardkeeper "github.com/strangelove-ventures/packet-forward-middleware/v4/router/keeper" + packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" + // IBC Transfer: Defines the "transfer" IBC port transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" @@ -146,6 +150,7 @@ type AppKeepers struct { TransferStack *ibchooks.IBCMiddleware Ics20WasmHooks *ibchooks.WasmHooks HooksICS4Wrapper ibchooks.ICS4Middleware + PacketForwardKeeper *packetforwardkeeper.Keeper // keys to access the substores keys map[string]*sdk.KVStoreKey @@ -458,19 +463,24 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.GovKeeper = &govKeeper } -// Create the IBC Transfer Stack from bottom to top: +// WireICS20PreWasmKeeper Create the IBC Transfer Stack from bottom to top: // -// * SendPacket. Originates from the transferKeeper and and goes up the stack: +// * SendPacket. Originates from the transferKeeper and goes up the stack: // transferKeeper.SendPacket -> ibc_rate_limit.SendPacket -> ibc_hooks.SendPacket -> channel.SendPacket // * RecvPacket, message that originates from core IBC and goes down to app, the flow is the other way -// channel.RecvPacket -> ibc_hooks.OnRecvPacket -> ibc_rate_limit.OnRecvPacket -> transfer.OnRecvPacket +// channel.RecvPacket -> ibc_hooks.OnRecvPacket -> ibc_rate_limit.OnRecvPacket -> forward.OnRecvPacket -> transfer.OnRecvPacket +// +// Note that the forward middleware is only integrated on the "reveive" direction. It can be safely skipped when sending. +// Note also that the forward middleware is called "router", but we are using the name "forward" for clarity +// This may later be renamed upstream: https://github.com/strangelove-ventures/packet-forward-middleware/issues/10 // // After this, the wasm keeper is required to be set on both // appkeepers.WasmHooks AND appKeepers.RateLimitingICS4Wrapper func (appKeepers *AppKeepers) WireICS20PreWasmKeeper( appCodec codec.Codec, bApp *baseapp.BaseApp, - hooksKeeper *ibchookskeeper.Keeper) { + hooksKeeper *ibchookskeeper.Keeper, +) { // Setup the ICS4Wrapper used by the hooks middleware osmoPrefix := sdk.GetConfig().GetBech32AccountAddrPrefix() wasmHooks := ibchooks.NewWasmHooks(hooksKeeper, nil, osmoPrefix) // The contract keeper needs to be set later @@ -508,10 +518,31 @@ func (appKeepers *AppKeepers) WireICS20PreWasmKeeper( ) appKeepers.TransferKeeper = &transferKeeper appKeepers.RawIcs20TransferAppModule = transfer.NewAppModule(*appKeepers.TransferKeeper) - transferIBCModule := transfer.NewIBCModule(*appKeepers.TransferKeeper) + + // Packet Forward Middleware + // Initialize packet forward middleware router + appKeepers.PacketForwardKeeper = packetforwardkeeper.NewKeeper( + appCodec, + appKeepers.keys[packetforwardtypes.StoreKey], + appKeepers.GetSubspace(packetforwardtypes.ModuleName), + appKeepers.TransferKeeper, + appKeepers.IBCKeeper.ChannelKeeper, + appKeepers.DistrKeeper, + appKeepers.BankKeeper, + // The ICS4Wrapper is replaced by the HooksICS4Wrapper instead of the channel so that sending can be overridden by the middleware + appKeepers.HooksICS4Wrapper, + ) + packetForwardMiddleware := packetforward.NewIBCMiddleware( + transfer.NewIBCModule(*appKeepers.TransferKeeper), + appKeepers.PacketForwardKeeper, + 0, + packetforwardkeeper.DefaultForwardTransferPacketTimeoutTimestamp, + packetforwardkeeper.DefaultRefundTransferPacketTimeoutTimestamp, + ) // RateLimiting IBC Middleware - rateLimitingTransferModule := ibcratelimit.NewIBCModule(transferIBCModule, appKeepers.RateLimitingICS4Wrapper) + rateLimitingTransferModule := ibcratelimit.NewIBCModule(packetForwardMiddleware, appKeepers.RateLimitingICS4Wrapper) + // Hooks Middleware hooksTransferModule := ibchooks.NewIBCMiddleware(&rateLimitingTransferModule, &appKeepers.HooksICS4Wrapper) appKeepers.TransferStack = &hooksTransferModule @@ -587,6 +618,7 @@ func (appKeepers *AppKeepers) initParamsKeeper(appCodec codec.BinaryCodec, legac paramsKeeper.Subspace(twaptypes.ModuleName) paramsKeeper.Subspace(ibcratelimittypes.ModuleName) paramsKeeper.Subspace(icqtypes.ModuleName) + paramsKeeper.Subspace(packetforwardtypes.ModuleName).WithKeyTable(packetforwardtypes.ParamKeyTable()) return paramsKeeper } @@ -687,5 +719,6 @@ func KVStoreKeys() []string { protorevtypes.StoreKey, ibchookstypes.StoreKey, icqtypes.StoreKey, + packetforwardtypes.StoreKey, } } diff --git a/app/keepers/modules.go b/app/keepers/modules.go index 2ca8b171a15..40a83eb5322 100644 --- a/app/keepers/modules.go +++ b/app/keepers/modules.go @@ -6,6 +6,7 @@ import ( transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" ibc "github.com/cosmos/ibc-go/v4/modules/core" ibcclientclient "github.com/cosmos/ibc-go/v4/modules/core/02-client/client" + "github.com/strangelove-ventures/packet-forward-middleware/v4/router" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" @@ -101,4 +102,5 @@ var AppModuleBasics = []module.AppModuleBasic{ ica.AppModuleBasic{}, ibc_hooks.AppModuleBasic{}, ibc_rate_limit.AppModuleBasic{}, + router.AppModuleBasic{}, } diff --git a/app/upgrades/v15/constants.go b/app/upgrades/v15/constants.go index 5a41dbc8a21..7f235e2eb74 100644 --- a/app/upgrades/v15/constants.go +++ b/app/upgrades/v15/constants.go @@ -3,6 +3,7 @@ package v15 import ( store "github.com/cosmos/cosmos-sdk/store/types" icqtypes "github.com/strangelove-ventures/async-icq/types" + packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" "github.com/osmosis-labs/osmosis/v14/app/upgrades" poolmanagertypes "github.com/osmosis-labs/osmosis/v14/x/poolmanager/types" @@ -17,7 +18,7 @@ var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, CreateUpgradeHandler: CreateUpgradeHandler, StoreUpgrades: store.StoreUpgrades{ - Added: []string{poolmanagertypes.StoreKey, valsetpreftypes.StoreKey, protorevtypes.StoreKey, icqtypes.StoreKey}, + Added: []string{poolmanagertypes.StoreKey, valsetpreftypes.StoreKey, protorevtypes.StoreKey, icqtypes.StoreKey, packetforwardtypes.StoreKey}, Deleted: []string{}, }, } diff --git a/app/upgrades/v15/upgrades.go b/app/upgrades/v15/upgrades.go index 4fc25cf1c33..c23248cf54d 100644 --- a/app/upgrades/v15/upgrades.go +++ b/app/upgrades/v15/upgrades.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -27,6 +28,7 @@ func CreateUpgradeHandler( poolmanagerParams := poolmanagertypes.NewParams(keepers.GAMMKeeper.GetParams(ctx).PoolCreationFee) keepers.PoolManagerKeeper.SetParams(ctx, poolmanagerParams) + keepers.PacketForwardKeeper.SetParams(ctx, packetforwardtypes.DefaultParams()) // N.B: pool id in gamm is to be deprecated in the future // Instead,it is moved to poolmanager. diff --git a/go.mod b/go.mod index 8cc72b62a2e..d380b35d5d2 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/golangci/golangci-lint v1.51.1 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/iancoleman/orderedmap v0.2.0 github.com/mattn/go-sqlite3 v1.14.16 github.com/ory/dockertest/v3 v3.9.1 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 @@ -28,6 +29,7 @@ require ( github.com/spf13/viper v1.15.0 // Async ICQ branch: ibc-v4 github.com/strangelove-ventures/async-icq v0.0.0-20230116084035-5609e84dd443 + github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.3 github.com/stretchr/testify v1.8.1 github.com/tendermint/tendermint v0.34.24 github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b @@ -319,4 +321,5 @@ replace ( github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.24 // use grpc compatible with cosmos protobufs google.golang.org/grpc => google.golang.org/grpc v1.33.2 + ) diff --git a/go.sum b/go.sum index 95452530a54..88e4d50d469 100644 --- a/go.sum +++ b/go.sum @@ -611,6 +611,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= +github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -1061,6 +1063,8 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8 github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/strangelove-ventures/async-icq v0.0.0-20230116084035-5609e84dd443 h1:nRkSfj9IhUrGF+0MRQHs4f8mtHFPe+0li7/k3Y4k0cs= github.com/strangelove-ventures/async-icq v0.0.0-20230116084035-5609e84dd443/go.mod h1:9dxdEF3Lo8WvLYx1e2knGkz3tmiPVX0ohODzUjGl9G4= +github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.3 h1:3E7I9C+gM7n0+OkI7JmvWH5PGD6pZOIc1+mUUooh6dI= +github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.3/go.mod h1:AG8F5pdk3x1h7PlRvPoMem3623W+w8HJHrWYkVJ51kk= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= diff --git a/go.work.sum b/go.work.sum index 0ddbf38625f..d8d91b810d3 100644 --- a/go.work.sum +++ b/go.work.sum @@ -897,6 +897,8 @@ github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c/go.mod h1:fHzc09Uny github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= +github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= +github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -1282,6 +1284,8 @@ github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiu github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.3 h1:3E7I9C+gM7n0+OkI7JmvWH5PGD6pZOIc1+mUUooh6dI= +github.com/strangelove-ventures/packet-forward-middleware/v4 v4.0.3/go.mod h1:AG8F5pdk3x1h7PlRvPoMem3623W+w8HJHrWYkVJ51kk= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 9eaaa48cd96..383bfa4ff3d 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -3,6 +3,9 @@ package e2e import ( "encoding/json" "fmt" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + "github.com/iancoleman/orderedmap" + "github.com/osmosis-labs/osmosis/v14/tests/e2e/configurer/chain" "io" "os" "path/filepath" @@ -10,6 +13,8 @@ import ( "strings" "time" + packetforwardingtypes "github.com/strangelove-ventures/packet-forward-middleware/v4/router/types" + ibchookskeeper "github.com/osmosis-labs/osmosis/x/ibc-hooks/keeper" paramsutils "github.com/cosmos/cosmos-sdk/x/params/client/utils" @@ -25,6 +30,114 @@ import ( "github.com/osmosis-labs/osmosis/v14/tests/e2e/initialization" ) +// Reusable Checks + +// CheckBalance Checks the balance of an address +func (s *IntegrationTestSuite) CheckBalance(node *chain.NodeConfig, addr, denom string, amount int64) { + // check the balance of the contract + s.Require().Eventually(func() bool { + balance, err := node.QueryBalances(addr) + s.Require().NoError(err) + if len(balance) == 0 { + return false + } + // check that the amount is in one of the balances inside the balance list + for _, b := range balance { + if b.Denom == denom && b.Amount.Int64() == amount { + return true + } + } + return false + }, + 1*time.Minute, + 10*time.Millisecond, + ) +} + +func (s *IntegrationTestSuite) TestConcentratedLiquidity() { + chainA := s.configurer.GetChainConfig(0) + node, err := chainA.GetDefaultNode() + s.Require().NoError(err) + + var ( + denom0 string = "uion" + denom1 string = "uosmo" + tickSpacing uint64 = 1 + precisionFactorAtPriceOne int64 = -1 + frozenUntil int64 = time.Unix(86400, 0).Unix() + swapFee = "0.01" + ) + poolID := node.CreateConcentratedPool(initialization.ValidatorWalletName, denom0, denom1, tickSpacing, precisionFactorAtPriceOne, swapFee) + + concentratedPool, err := node.QueryConcentratedPool(poolID) + s.Require().NoError(err) + + // assert contents of the pool are valid + s.Require().Equal(concentratedPool.GetId(), poolID) + s.Require().Equal(concentratedPool.GetToken0(), denom0) + s.Require().Equal(concentratedPool.GetToken1(), denom1) + s.Require().Equal(concentratedPool.GetTickSpacing(), tickSpacing) + s.Require().Equal(concentratedPool.GetPrecisionFactorAtPriceOne(), sdk.NewInt(precisionFactorAtPriceOne)) + s.Require().Equal(concentratedPool.GetSwapFee(sdk.Context{}), sdk.MustNewDecFromStr(swapFee)) + + minTick, maxTick := cl.GetMinAndMaxTicksFromExponentAtPriceOne(sdk.NewInt(precisionFactorAtPriceOne)) + + fundTokens := []string{"1000000uosmo", "1000000uion", "1000000stake"} + // get 3 addresses to create positions + address1 := node.CreateWalletAndFund("addr1", fundTokens) + address2 := node.CreateWalletAndFund("addr2", fundTokens) + address3 := node.CreateWalletAndFund("addr3", fundTokens) + + // Create 2 positions for node1: overlap together, overlap with 2 node3 positions) + node.CreateConcentratedPosition(address1, "[-1200]", "400", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) + node.CreateConcentratedPosition(address1, "[-400]", "400", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) + + // Create 1 position for node2: does not overlap with anything, ends at maximum + node.CreateConcentratedPosition(address2, "2200", fmt.Sprintf("%d", maxTick), fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) + + // Create 2 positions for node3: overlap together, overlap with 2 node1 positions, one position starts from minimum + node.CreateConcentratedPosition(address3, "[-1600]", "[-200]", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) + node.CreateConcentratedPosition(address3, fmt.Sprintf("[%d]", minTick), "1400", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) + + // get newly created positions + positionsAddress1 := node.QueryConcentratedPositions(address1) + positionsAddress2 := node.QueryConcentratedPositions(address2) + positionsAddress3 := node.QueryConcentratedPositions(address3) + + // assert number of positions per address + s.Require().Equal(len(positionsAddress1), 2) + s.Require().Equal(len(positionsAddress2), 1) + s.Require().Equal(len(positionsAddress3), 2) + + // Assert returned positions: + validateCLPosition := func(position types.FullPositionByOwnerResult, poolId uint64, lowerTick, upperTick int64) { + s.Require().Equal(position.PoolId, poolId) + s.Require().Equal(position.LowerTick, int64(lowerTick)) + s.Require().Equal(position.UpperTick, int64(upperTick)) + } + + // assert positions for address1 + addr1position1 := positionsAddress1[0] + addr1position2 := positionsAddress1[1] + // first position first address + validateCLPosition(addr1position1, poolID, -1200, 400) + // second position second address + validateCLPosition(addr1position2, poolID, -400, 400) + + // assert positions for address2 + addr2position1 := positionsAddress2[0] + // first position second address + validateCLPosition(addr2position1, poolID, 2200, maxTick) + + // assert positions for address3 + addr3position1 := positionsAddress3[0] + addr3position2 := positionsAddress3[1] + // first position third address + validateCLPosition(addr3position1, poolID, -1600, -200) + // second position third address + validateCLPosition(addr3position2, poolID, minTick, 1400) +} + // TestGeometricTwapMigration tests that the geometric twap record // migration runs succesfully. It does so by attempting to execute // the swap on the pool created pre-upgrade. When a pool is created @@ -273,37 +386,44 @@ func (s *IntegrationTestSuite) TestLargeWasmUpload() { node.StoreWasmCode("bytecode/large.wasm", initialization.ValidatorWalletName) } -func (s *IntegrationTestSuite) TestIBCWasmHooks() { - if s.skipIBC { - s.T().Skip("Skipping IBC tests") - } - chainA := s.configurer.GetChainConfig(0) - chainB := s.configurer.GetChainConfig(1) - - nodeA, err := chainA.GetDefaultNode() - s.NoError(err) - nodeB, err := chainB.GetDefaultNode() - s.NoError(err) - - // copy the contract from x/rate-limit/testdata/ +func (s *IntegrationTestSuite) UploadAndInstantiateCounter(chain *chain.Config) string { + // copy the contract from tests/ibc-hooks/bytecode wd, err := os.Getwd() s.NoError(err) // co up two levels projectDir := filepath.Dir(filepath.Dir(wd)) err = copyFile(projectDir+"/tests/ibc-hooks/bytecode/counter.wasm", wd+"/scripts/counter.wasm") s.NoError(err) + node, err := chain.GetDefaultNode() + s.NoError(err) - nodeA.StoreWasmCode("counter.wasm", initialization.ValidatorWalletName) - chainA.LatestCodeId = int(nodeA.QueryLatestWasmCodeID()) - nodeA.InstantiateWasmContract( - strconv.Itoa(chainA.LatestCodeId), + node.StoreWasmCode("counter.wasm", initialization.ValidatorWalletName) + chain.LatestCodeId = int(node.QueryLatestWasmCodeID()) + node.InstantiateWasmContract( + strconv.Itoa(chain.LatestCodeId), `{"count": 0}`, initialization.ValidatorWalletName) - contracts, err := nodeA.QueryContractsFromId(chainA.LatestCodeId) + contracts, err := node.QueryContractsFromId(chain.LatestCodeId) s.NoError(err) s.Require().Len(contracts, 1, "Wrong number of contracts for the counter") contractAddr := contracts[0] + return contractAddr +} + +func (s *IntegrationTestSuite) TestIBCWasmHooks() { + if s.skipIBC { + s.T().Skip("Skipping IBC tests") + } + chainA := s.configurer.GetChainConfig(0) + chainB := s.configurer.GetChainConfig(1) + + nodeA, err := chainA.GetDefaultNode() + s.NoError(err) + nodeB, err := chainB.GetDefaultNode() + s.NoError(err) + + contractAddr := s.UploadAndInstantiateCounter(chainA) transferAmount := int64(10) validatorAddr := nodeB.GetWallet(initialization.ValidatorWalletName) @@ -311,23 +431,15 @@ func (s *IntegrationTestSuite) TestIBCWasmHooks() { fmt.Sprintf(`{"wasm":{"contract":"%s","msg": {"increment": {}} }}`, contractAddr)) // check the balance of the contract - s.Eventually(func() bool { - balance, err := nodeA.QueryBalances(contractAddr) - s.Require().NoError(err) - if len(balance) == 0 { - return false - } - return balance[0].Amount.Int64() == transferAmount - }, - 1*time.Minute, - 10*time.Millisecond, - ) + denomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "uosmo")) + ibcDenom := denomTrace.IBCDenom() + s.CheckBalance(nodeA, contractAddr, ibcDenom, transferAmount) // sender wasm addr senderBech32, err := ibchookskeeper.DeriveIntermediateSender("channel-0", validatorAddr, "osmo") var response map[string]interface{} - s.Eventually(func() bool { + s.Require().Eventually(func() bool { response, err = nodeA.QueryWasmSmart(contractAddr, fmt.Sprintf(`{"get_total_funds": {"addr": "%s"}}`, senderBech32)) totalFunds := response["total_funds"].([]interface{})[0] amount := totalFunds.(map[string]interface{})["amount"].(string) @@ -340,6 +452,56 @@ func (s *IntegrationTestSuite) TestIBCWasmHooks() { ) } +// TestPacketForwarding sends a packet from chainA to chainB, and forwards it +// back to chainA with a custom memo to execute the counter contract on chain A +func (s *IntegrationTestSuite) TestPacketForwarding() { + if s.skipIBC { + s.T().Skip("Skipping IBC tests") + } + chainA := s.configurer.GetChainConfig(0) + + nodeA, err := chainA.GetDefaultNode() + s.NoError(err) + + // Instantiate the counter contract on chain A + contractAddr := s.UploadAndInstantiateCounter(chainA) + + transferAmount := int64(10) + validatorAddr := nodeA.GetWallet(initialization.ValidatorWalletName) + // Specify that the counter contract should be called on chain A when the packet is received + contractCallMemo := []byte(fmt.Sprintf(`{"wasm":{"contract":"%s","msg": {"increment": {}} }}`, contractAddr)) + // Generate the forward metadata + forwardMetadata := packetforwardingtypes.ForwardMetadata{ + Receiver: contractAddr, + Port: "transfer", + Channel: "channel-0", + Next: packetforwardingtypes.NewJSONObject(false, contractCallMemo, orderedmap.OrderedMap{}), // The packet sent to chainA will have this memo + } + memoData := packetforwardingtypes.PacketMetadata{Forward: &forwardMetadata} + forwardMemo, err := json.Marshal(memoData) + s.NoError(err) + // Send the transfer from chainA to chainB. ChainB will parse the memo and forward the packet back to chainA + nodeA.SendIBCTransfer(validatorAddr, validatorAddr, fmt.Sprintf("%duosmo", transferAmount), string(forwardMemo)) + + // check the balance of the contract + s.CheckBalance(nodeA, contractAddr, "uosmo", transferAmount) + + // sender wasm addr + senderBech32, err := ibchookskeeper.DeriveIntermediateSender("channel-0", validatorAddr, "osmo") + var response map[string]interface{} + s.Require().Eventually(func() bool { + response, err = nodeA.QueryWasmSmart(contractAddr, fmt.Sprintf(`{"get_count": {"addr": "%s"}}`, senderBech32)) + if err != nil { + return false + } + count := response["count"].(float64) + return err == nil && count == 0 + }, + 15*time.Second, + 10*time.Millisecond, + ) +} + // TestAddToExistingLockPostUpgrade ensures addToExistingLock works for locks created preupgrade. func (s *IntegrationTestSuite) TestAddToExistingLockPostUpgrade() { if s.skipUpgrade { From 3b56d3012ef8b217ce57e29f9c680d08f35ff247 Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Thu, 9 Feb 2023 17:23:47 +0100 Subject: [PATCH 2/2] removed CL test --- tests/e2e/e2e_test.go | 84 ------------------------------------------- 1 file changed, 84 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 383bfa4ff3d..e79f8353175 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -54,90 +54,6 @@ func (s *IntegrationTestSuite) CheckBalance(node *chain.NodeConfig, addr, denom ) } -func (s *IntegrationTestSuite) TestConcentratedLiquidity() { - chainA := s.configurer.GetChainConfig(0) - node, err := chainA.GetDefaultNode() - s.Require().NoError(err) - - var ( - denom0 string = "uion" - denom1 string = "uosmo" - tickSpacing uint64 = 1 - precisionFactorAtPriceOne int64 = -1 - frozenUntil int64 = time.Unix(86400, 0).Unix() - swapFee = "0.01" - ) - poolID := node.CreateConcentratedPool(initialization.ValidatorWalletName, denom0, denom1, tickSpacing, precisionFactorAtPriceOne, swapFee) - - concentratedPool, err := node.QueryConcentratedPool(poolID) - s.Require().NoError(err) - - // assert contents of the pool are valid - s.Require().Equal(concentratedPool.GetId(), poolID) - s.Require().Equal(concentratedPool.GetToken0(), denom0) - s.Require().Equal(concentratedPool.GetToken1(), denom1) - s.Require().Equal(concentratedPool.GetTickSpacing(), tickSpacing) - s.Require().Equal(concentratedPool.GetPrecisionFactorAtPriceOne(), sdk.NewInt(precisionFactorAtPriceOne)) - s.Require().Equal(concentratedPool.GetSwapFee(sdk.Context{}), sdk.MustNewDecFromStr(swapFee)) - - minTick, maxTick := cl.GetMinAndMaxTicksFromExponentAtPriceOne(sdk.NewInt(precisionFactorAtPriceOne)) - - fundTokens := []string{"1000000uosmo", "1000000uion", "1000000stake"} - // get 3 addresses to create positions - address1 := node.CreateWalletAndFund("addr1", fundTokens) - address2 := node.CreateWalletAndFund("addr2", fundTokens) - address3 := node.CreateWalletAndFund("addr3", fundTokens) - - // Create 2 positions for node1: overlap together, overlap with 2 node3 positions) - node.CreateConcentratedPosition(address1, "[-1200]", "400", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) - node.CreateConcentratedPosition(address1, "[-400]", "400", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) - - // Create 1 position for node2: does not overlap with anything, ends at maximum - node.CreateConcentratedPosition(address2, "2200", fmt.Sprintf("%d", maxTick), fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) - - // Create 2 positions for node3: overlap together, overlap with 2 node1 positions, one position starts from minimum - node.CreateConcentratedPosition(address3, "[-1600]", "[-200]", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) - node.CreateConcentratedPosition(address3, fmt.Sprintf("[%d]", minTick), "1400", fmt.Sprintf("1000%s", denom0), fmt.Sprintf("1000%s", denom1), 0, 0, frozenUntil, poolID) - - // get newly created positions - positionsAddress1 := node.QueryConcentratedPositions(address1) - positionsAddress2 := node.QueryConcentratedPositions(address2) - positionsAddress3 := node.QueryConcentratedPositions(address3) - - // assert number of positions per address - s.Require().Equal(len(positionsAddress1), 2) - s.Require().Equal(len(positionsAddress2), 1) - s.Require().Equal(len(positionsAddress3), 2) - - // Assert returned positions: - validateCLPosition := func(position types.FullPositionByOwnerResult, poolId uint64, lowerTick, upperTick int64) { - s.Require().Equal(position.PoolId, poolId) - s.Require().Equal(position.LowerTick, int64(lowerTick)) - s.Require().Equal(position.UpperTick, int64(upperTick)) - } - - // assert positions for address1 - addr1position1 := positionsAddress1[0] - addr1position2 := positionsAddress1[1] - // first position first address - validateCLPosition(addr1position1, poolID, -1200, 400) - // second position second address - validateCLPosition(addr1position2, poolID, -400, 400) - - // assert positions for address2 - addr2position1 := positionsAddress2[0] - // first position second address - validateCLPosition(addr2position1, poolID, 2200, maxTick) - - // assert positions for address3 - addr3position1 := positionsAddress3[0] - addr3position2 := positionsAddress3[1] - // first position third address - validateCLPosition(addr3position1, poolID, -1600, -200) - // second position third address - validateCLPosition(addr3position2, poolID, minTick, 1400) -} - // TestGeometricTwapMigration tests that the geometric twap record // migration runs succesfully. It does so by attempting to execute // the swap on the pool created pre-upgrade. When a pool is created