diff --git a/.github/labeler.yml b/.github/labeler.yml index 901271a09ea..cfc7a7c9d0e 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -20,6 +20,8 @@ - app/wasm/**/* "C:x/claim": - x/claim/**/* +"C:x/concentrated-liquidity": + - x/concentrated-liquidity/**/* "C:x/epochs": - x/epochs/**/* "C:x/gamm": @@ -34,6 +36,8 @@ - x/pool-incentives/**/* "C:x/superfluid": - x/superfluid/**/* +"C:x/swaprouter": + - x/swaprouter/**/* "C:x/txfees": - x/txfees/**/* "C:x/tokenfactory": @@ -52,7 +56,7 @@ "C:CLI": - client/**/* - x/*/client/**/* -# Add "C:docs" label to documented related files and directories. +# Add "C:docs" label to documented related files and directories. "C:docs": - bug.md - issue.md @@ -61,4 +65,3 @@ - x/**/*.md - x/**/*/*.md - tests/**/*.md - diff --git a/.github/mergify.yml b/.github/mergify.yml index 818cb1198ad..95caf4f6041 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -38,14 +38,6 @@ pull_request_rules: backport: branches: - v4.x - - name: backport patches to v5.x branch - conditions: - - base=main - - label=A:backport/v5.x - actions: - backport: - branches: - - v5.x - name: backport patches to v6.x branch conditions: - base=main @@ -54,14 +46,6 @@ pull_request_rules: backport: branches: - v6.x - - name: backport patches to v7.x branch - conditions: - - base=main - - label=A:backport/v7.x - actions: - backport: - branches: - - v7.x - name: backport patches to v8.x branch conditions: - base=main @@ -70,14 +54,6 @@ pull_request_rules: backport: branches: - v8.x - - name: backport patches to v9.x branch - conditions: - - base=main - - label=A:backport/v9.x - actions: - backport: - branches: - - v9.x - name: backport patches to v10.x branch conditions: - base=main @@ -110,3 +86,11 @@ pull_request_rules: backport: branches: - v13.x + - name: backport patches to concentrated-liquidity-main + conditions: + - base=main + - label=A:backport/cl + actions: + backport: + branches: + - concentrated-liquidity-main diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c468161ab64..4baa5ff168e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - concentrated-liquidity-main jobs: golangci: diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go index 66a0d70fce4..70d525afa2a 100644 --- a/app/apptesting/test_suite.go +++ b/app/apptesting/test_suite.go @@ -350,6 +350,14 @@ func (s *KeeperTestHelper) BuildTx( return txBuilder.GetTx() } +// StateNotAltered validates that app state is not altered. Fails if it is. +func (s *KeeperTestHelper) StateNotAltered() { + oldState := s.App.ExportState(s.Ctx) + s.Commit() + newState := s.App.ExportState(s.Ctx) + s.Require().Equal(oldState, newState) +} + // CreateRandomAccounts is a function return a list of randomly generated AccAddresses func CreateRandomAccounts(numAccts int) []sdk.AccAddress { testAddrs := make([]sdk.AccAddress, numAccts) diff --git a/app/export.go b/app/export.go index 12be00a2431..814a332df80 100644 --- a/app/export.go +++ b/app/export.go @@ -195,3 +195,7 @@ func (app *OsmosisApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddr }, ) } + +func (app *OsmosisApp) ExportState(ctx sdk.Context) map[string]json.RawMessage { + return app.mm.ExportGenesis(ctx, app.AppCodec()) +} diff --git a/chain.schema.json b/chain.schema.json index 731bad99c6b..e367fa009d5 100644 --- a/chain.schema.json +++ b/chain.schema.json @@ -2,8 +2,10 @@ "$schema": "http://json-schema.org/draft-07/schema#", "codebase":{ "git_repo": "https://github.com/osmosis-labs/osmosis", - "recommended_version": "12.1.0", - "compatible_versions": ["12.1.0"], + "recommended_version": "12.2.0", + "compatible_versions": [ + "12.2.0" + ], "binaries": { "linux/amd64": "https://github.com/osmosis-labs/osmosis/releases/download/v12.1.0/osmosisd-12.1.0-linux-amd64?checksum=sha256:44433f93946338b8cb167d9030ebbcfe924294d95d745026ada5dbe8f50d5010", "linux/arm64": "https://github.com/osmosis-labs/osmosis/releases/download/v12.1.0/osmosisd-12.1.0-linux-arm64?checksum=sha256:ef2c3d60156be5481534ecb33f9d94d73afa38a1b016e7e1c6d3fe10e3e69b3a" @@ -12,8 +14,12 @@ "tendermint_version": "0.34", "cosmwasm_version": "0.28", "cosmwasm_enabled": true, + "ibc_go_version": "3.3.0", + "ics_enabled": [ + "ics20-1" + ], "genesis": { - "name": "v3.1.0", + "name": "v3", "genesis_url": "https://github.com/osmosis-labs/networks/raw/main/osmosis-1/genesis.json" }, "versions": [ diff --git a/go.mod b/go.mod index 0b7c21fc711..e47d61587d1 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 - github.com/golangci/golangci-lint v1.50.0 + github.com/golangci/golangci-lint v1.50.1 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/mattn/go-sqlite3 v1.14.15 @@ -24,13 +24,13 @@ require ( github.com/spf13/cobra v1.6.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.13.0 - github.com/stretchr/testify v1.8.0 - github.com/tendermint/tendermint v0.34.21 + github.com/stretchr/testify v1.8.1 + github.com/tendermint/tendermint v0.34.22 github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b go.uber.org/multierr v1.8.0 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b - google.golang.org/grpc v1.49.0 + google.golang.org/grpc v1.50.0 gopkg.in/yaml.v2 v2.4.0 mvdan.cc/gofumpt v0.4.0 ) @@ -43,7 +43,7 @@ require ( github.com/curioswitch/go-reassign v0.2.0 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/google/btree v1.0.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.2 // indirect + github.com/kkHAIKE/contextcheck v1.1.3 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/regen-network/cosmos-proto v0.3.1 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect @@ -51,8 +51,8 @@ require ( github.com/sivchari/nosnakecase v1.7.0 // indirect github.com/timonwong/loggercheck v0.9.3 // indirect github.com/zimmski/go-mutesting v0.0.0-20210610104036-6d9217011a00 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/zap v1.21.0 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/zap v1.22.0 // indirect ) require ( @@ -63,7 +63,7 @@ require ( github.com/Antonboom/errname v0.1.7 // indirect github.com/Antonboom/nilnil v0.1.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/BurntSushi/toml v1.2.0 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect github.com/CosmWasm/wasmvm v1.0.0 github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect @@ -97,7 +97,7 @@ require ( github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect github.com/cosmos/ledger-go v0.9.3 // indirect - github.com/daixiang0/gci v0.8.0 // indirect + github.com/daixiang0/gci v0.8.1 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denis-tingaikin/go-header v0.4.3 // indirect @@ -199,11 +199,11 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mbilski/exhaustivestruct v1.2.0 // indirect github.com/mgechev/revive v1.2.4 // indirect - github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect github.com/moricho/tparallel v0.2.1 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect @@ -228,14 +228,14 @@ require ( github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rs/cors v1.8.2 // indirect github.com/rs/zerolog v1.27.0 // indirect github.com/ryancurrah/gomodguard v1.2.4 // indirect github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect - github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/securego/gosec/v2 v2.13.1 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.0 // indirect @@ -247,7 +247,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.4.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca github.com/tdakkota/asciicheck v0.1.1 // indirect @@ -256,8 +256,8 @@ require ( github.com/tendermint/go-amino v0.16.0 // indirect github.com/tetafro/godot v1.4.11 // indirect github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect - github.com/tomarrell/wrapcheck/v2 v2.6.2 // indirect - github.com/tommy-muehle/go-mnd/v2 v2.5.0 // indirect + github.com/tomarrell/wrapcheck/v2 v2.7.0 // indirect + github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.0.3 // indirect github.com/ultraware/whitespace v0.0.5 // indirect github.com/uudashr/gocognit v1.0.6 // indirect @@ -272,15 +272,15 @@ require ( gitlab.com/bosi/decorder v0.2.3 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opencensus.io v0.23.0 // indirect - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect + golang.org/x/crypto v0.1.0 // indirect golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/net v0.0.0-20220726230323-06994584191e // indirect + golang.org/x/mod v0.6.0 // indirect + golang.org/x/net v0.1.0 // indirect golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect - golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect - golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.12 // indirect + golang.org/x/sys v0.1.0 // indirect + golang.org/x/term v0.1.0 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/tools v0.2.0 // indirect google.golang.org/protobuf v1.28.1 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index c878f552caa..11450d9682f 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,8 @@ github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= -github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= @@ -138,7 +138,6 @@ github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -265,8 +264,8 @@ github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDU github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/daixiang0/gci v0.8.0 h1:DzWYUm4+bc+taVUtuq1tsIMb/QFMMYgDIiykSoO98ZU= -github.com/daixiang0/gci v0.8.0/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= +github.com/daixiang0/gci v0.8.1 h1:T4xpSC+hmsi4CSyuYfIJdMZAr9o7xZmHpQVygMghGZ4= +github.com/daixiang0/gci v0.8.1/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -473,8 +472,8 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= -github.com/golangci/golangci-lint v1.50.0 h1:+Xmyt8rKLauNLp2gzcxKMN8VNGqGc5Avc2ZLTwIOpEA= -github.com/golangci/golangci-lint v1.50.0/go.mod h1:UqtDvK24R9OizqRF06foPX8opRMzQB0HQK90uI2JgKc= +github.com/golangci/golangci-lint v1.50.1 h1:C829clMcZXEORakZlwpk7M4iDw2XiwxxKaG504SZ9zY= +github.com/golangci/golangci-lint v1.50.1/go.mod h1:AQjHBopYS//oB8xs0y0M/dtxdKHkdhl0RvmjUct0/4w= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= @@ -684,8 +683,8 @@ github.com/kisielk/errcheck v1.6.2 h1:uGQ9xI8/pgc9iOoCe7kWQgRE6SBTrCGmTSf0LrEtY7 github.com/kisielk/errcheck v1.6.2/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.2 h1:BYUSG/GhMhqVz//yjl8IkBDlMEws+9DtCmkz18QO1gg= -github.com/kkHAIKE/contextcheck v1.1.2/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= +github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw= +github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= @@ -777,8 +776,9 @@ github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aks github.com/mgechev/revive v1.2.4 h1:+2Hd/S8oO2H0Ikq2+egtNwQsVhAeELHjxjIUFX5ajLI= github.com/mgechev/revive v1.2.4/go.mod h1:iAWlQishqCuj4yhV24FTnKSXGpbAA+0SckXB8GQMX/Q= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= @@ -796,8 +796,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -990,8 +990,9 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8 github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= @@ -1023,8 +1024,9 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= -github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.20.0 h1:K6CXjqqtSYSsuyRDDC7Sjn6vTMLiSJa4ZmDkiokoqtw= @@ -1102,8 +1104,9 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1112,8 +1115,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1130,8 +1134,8 @@ github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= -github.com/tendermint/tendermint v0.34.21 h1:UiGGnBFHVrZhoQVQ7EfwSOLuCtarqCSsRf8VrklqB7s= -github.com/tendermint/tendermint v0.34.21/go.mod h1:XDvfg6U7grcFTDx7VkzxnhazQ/bspGJAn4DZ6DcLLjQ= +github.com/tendermint/tendermint v0.34.22 h1:XMhtC8s8QqJO4l/dn+TkQvevTRSow3Vixjclr41o+2Q= +github.com/tendermint/tendermint v0.34.22/go.mod h1:YpP5vBEAKUT4g6oyfjKgFeZmdB/GjkJAxfF+cgmJg6Y= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b h1:Y3ZPG6gdDCAV2sdGkD759ji/09GzaNu1X3qKTmZIbTo= github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b/go.mod h1:ADqbS9NOSnBRK9R2RtYC61CdsHmVMD/yXAzcMuPexbU= @@ -1152,10 +1156,10 @@ github.com/timonwong/loggercheck v0.9.3/go.mod h1:wUqnk9yAOIKtGA39l1KLE9Iz0QiToc github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tomarrell/wrapcheck/v2 v2.6.2 h1:3dI6YNcrJTQ/CJQ6M/DUkc0gnqYSIk6o0rChn9E/D0M= -github.com/tomarrell/wrapcheck/v2 v2.6.2/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= -github.com/tommy-muehle/go-mnd/v2 v2.5.0 h1:iAj0a8e6+dXSL7Liq0aXPox36FiN1dBbjA6lt9fl65s= -github.com/tommy-muehle/go-mnd/v2 v2.5.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/tomarrell/wrapcheck/v2 v2.7.0 h1:J/F8DbSKJC83bAvC6FoZaRjZiZ/iKoueSdrEkmGeacA= +github.com/tomarrell/wrapcheck/v2 v2.7.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= +github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= +github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= @@ -1229,20 +1233,18 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= +go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1264,8 +1266,8 @@ golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1311,8 +1313,9 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1367,8 +1370,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220726230323-06994584191e h1:wOQNKh1uuDGRnmgF0jDxh7ctgGy/3P4rYWQRVJD4/Yg= -golang.org/x/net v0.0.0-20220726230323-06994584191e/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1483,13 +1486,13 @@ golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc= -golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1498,8 +1501,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1593,8 +1597,9 @@ golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlz golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/proto/osmosis/lockup/query.proto b/proto/osmosis/lockup/query.proto index 53221e05160..ef83b784414 100644 --- a/proto/osmosis/lockup/query.proto +++ b/proto/osmosis/lockup/query.proto @@ -7,6 +7,7 @@ import "google/api/annotations.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/duration.proto"; import "osmosis/lockup/lock.proto"; +import "osmosis/lockup/params.proto"; option go_package = "github.com/osmosis-labs/osmosis/v12/x/lockup/types"; @@ -118,6 +119,10 @@ service Query { option (google.api.http).get = "/osmosis/lockup/v1beta1/account_locked_longer_duration_denom/{owner}"; } + // Params returns lockup params. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/osmosis/lockup/v1beta1/params"; + } } message ModuleBalanceRequest {}; @@ -287,3 +292,8 @@ message AccountLockedLongerDurationDenomRequest { message AccountLockedLongerDurationDenomResponse { repeated PeriodLock locks = 1 [ (gogoproto.nullable) = false ]; }; + +message QueryParamsRequest {} +message QueryParamsResponse { + Params params = 1 [ (gogoproto.nullable) = false ]; +} diff --git a/scripts/generate-docs.sh b/scripts/generate-docs.sh index f1f30b2fd72..99feb6f7e8e 100755 --- a/scripts/generate-docs.sh +++ b/scripts/generate-docs.sh @@ -40,6 +40,10 @@ yarn install yarn combine yarn convert yarn build + +#Add public servers to spec file for Osmosis testnet and mainnet +yq -i '."servers"+=[{"url":"https://lcd.osmosis.zone","description":"Osmosis mainnet node"},{"url":"https://lcd-test.osmosis.zone","description":"Osmosis testnet node"}]' static/openapi/openapi.yaml + cd ../../ # clean swagger files diff --git a/x/epochs/client/cli/query_test.go b/x/epochs/client/cli/query_test.go new file mode 100644 index 00000000000..7011acbbf92 --- /dev/null +++ b/x/epochs/client/cli/query_test.go @@ -0,0 +1,73 @@ +package cli_test + +import ( + gocontext "context" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/epochs/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + // add new epoch + epoch := types.EpochInfo{ + Identifier: "weekly", + StartTime: time.Time{}, + Duration: time.Hour, + CurrentEpoch: 0, + CurrentEpochStartHeight: 0, + CurrentEpochStartTime: time.Time{}, + EpochCountingStarted: false, + } + s.App.EpochsKeeper.AddEpochInfo(s.Ctx, epoch) + + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query current epoch", + "/osmosis.epochs.v1beta1.Query/CurrentEpoch", + &types.QueryCurrentEpochRequest{Identifier: "weekly"}, + &types.QueryCurrentEpochResponse{}, + }, + { + "Query epochs info", + "/osmosis.epochs.v1beta1.Query/EpochInfos", + &types.QueryEpochsInfoRequest{}, + &types.QueryEpochsInfoResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/gamm/client/cli/query_test.go b/x/gamm/client/cli/query_test.go new file mode 100644 index 00000000000..649a849ca7f --- /dev/null +++ b/x/gamm/client/cli/query_test.go @@ -0,0 +1,102 @@ +package cli_test + +import ( + gocontext "context" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/gamm/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + // create a new pool + s.PrepareBalancerPool() + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query pools", + "/osmosis.gamm.v1beta1.Query/Pools", + &types.QueryPoolsRequest{}, + &types.QueryPoolsResponse{}, + }, + { + "Query single pool", + "/osmosis.gamm.v1beta1.Query/Pool", + &types.QueryPoolRequest{PoolId: 1}, + &types.QueryPoolsResponse{}, + }, + { + "Query num pools", + "/osmosis.gamm.v1beta1.Query/NumPools", + &types.QueryNumPoolsRequest{}, + &types.QueryNumPoolsResponse{}, + }, + { + "Query pool params", + "/osmosis.gamm.v1beta1.Query/PoolParams", + &types.QueryPoolParamsRequest{PoolId: 1}, + &types.QueryPoolParamsResponse{}, + }, + { + "Query pool type", + "/osmosis.gamm.v1beta1.Query/PoolType", + &types.QueryPoolTypeRequest{PoolId: 1}, + &types.QueryPoolTypeResponse{}, + }, + { + "Query spot price", + "/osmosis.gamm.v1beta1.Query/SpotPrice", + &types.QuerySpotPriceRequest{PoolId: 1, BaseAssetDenom: "foo", QuoteAssetDenom: "bar"}, + &types.QuerySpotPriceResponse{}, + }, + { + "Query total liquidity", + "/osmosis.gamm.v1beta1.Query/TotalLiquidity", + &types.QueryTotalLiquidityRequest{}, + &types.QueryTotalLiquidityResponse{}, + }, + { + "Query pool total liquidity", + "/osmosis.gamm.v1beta1.Query/TotalPoolLiquidity", + &types.QueryTotalPoolLiquidityRequest{PoolId: 1}, + &types.QueryTotalPoolLiquidityResponse{}, + }, + { + "Query total shares", + "/osmosis.gamm.v1beta1.Query/TotalShares", + &types.QueryTotalSharesRequest{PoolId: 1}, + &types.QueryTotalSharesResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/gamm/keeper/pool_test.go b/x/gamm/keeper/pool_test.go index 3bcd9f2a3cd..22d99dabfdb 100644 --- a/x/gamm/keeper/pool_test.go +++ b/x/gamm/keeper/pool_test.go @@ -282,7 +282,8 @@ func (suite *KeeperTestSuite) TestGetPoolAndPoke() { }, sdk.NewCoins(sdk.NewCoin(defaultAcctFunds[0].Denom, defaultAcctFunds[0].Amount.QuoRaw(2)), sdk.NewCoin(defaultAcctFunds[1].Denom, defaultAcctFunds[1].Amount.QuoRaw(2))), []uint64{1, 1}, - )}, + ), + }, } for name, tc := range tests { diff --git a/x/gamm/pool-models/stableswap/README.md b/x/gamm/pool-models/stableswap/README.md index 1f377f34bf5..30cfca5eaaa 100644 --- a/x/gamm/pool-models/stableswap/README.md +++ b/x/gamm/pool-models/stableswap/README.md @@ -146,7 +146,7 @@ def iterative_search(x_f, y_0, w, k, err_tolerance): # k_0 < k. Need to find an upperbound. Worst case assume a linear relationship, gives an upperbound # TODO: In the future, we can derive better bounds via reasoning about coefficients in the cubic # These are quite close when we are in the "stable" part of the curve though. - upperbound = ceil(y_0 * k_ratio) + upperbound = ceil(y_0 / k_ratio) elif k_ratio > 1: # need to find a lowerbound. We could use a cubic relation, but for now we just set it to 0. lowerbound = 0 diff --git a/x/gamm/pool-models/stableswap/amm.go b/x/gamm/pool-models/stableswap/amm.go index 7df0dc9e4fd..75ae8c0ef47 100644 --- a/x/gamm/pool-models/stableswap/amm.go +++ b/x/gamm/pool-models/stableswap/amm.go @@ -64,9 +64,6 @@ func cfmmConstantMulti(xReserve, yReserve, u, v osmomath.BigDec) osmomath.BigDec // and the following expression for `a` in multi-asset pools: // xyz(x^2 + y^2 + w) = (x - a)(y + b)z((x - a)^2 + (y + b)^2 + w) func solveCfmm(xReserve, yReserve osmomath.BigDec, remReserves []osmomath.BigDec, yIn osmomath.BigDec) osmomath.BigDec { - if len(remReserves) == 0 { - return solveCFMMBinarySearch(cfmmConstant)(xReserve, yReserve, yIn) - } wSumSquares := osmomath.ZeroDec() for _, assetReserve := range remReserves { wSumSquares = wSumSquares.Add(assetReserve.Mul(assetReserve)) @@ -152,6 +149,84 @@ func solveCfmmDirect(xReserve, yReserve, yIn osmomath.BigDec) osmomath.BigDec { return xOut } +// multi-asset CFMM is xyu(x^2 + y^2 + w) = k +// As described in our spec, we can ignore the u term and simply solve within the bounds of k' = k / u +// since u remains constant throughout any independent operation this solver would be used for. +// We want to solve for a given addition of `b` units of y into the pool, +// how many units `a` of x do we get out. +// Let y' = y + b +// we solve k = (x'y')(x'^2 + y^2 + w) for x', using the following equation: https://www.wolframalpha.com/input?i2d=true&i=solve+for+y%5C%2844%29+x*y*%5C%2840%29Power%5Bx%2C2%5D+%2B+Power%5By%2C2%5D+%2B+w%5C%2841%29%3Dk +// which we simplify to be the following: https://www.desmos.com/calculator/zx2qslqndl +// Then we use that to derive the change in x as x_out = x' - x +// +// Since original reserves, y' and k are known and remain constant throughout the calculation, +// deriving x' and then finding x_out is equivalent to finding x_out directly. +func solveCFMMMultiDirect(xReserve, yReserve, wSumSquares, yIn osmomath.BigDec) osmomath.BigDec { + if !xReserve.IsPositive() || !yReserve.IsPositive() || wSumSquares.IsNegative() || !yIn.IsPositive() { + panic("invalid input: reserves and input must be positive") + } else if yIn.GTE(yReserve) { + panic("cannot input more than pool reserves") + } + + // find k' using existing reserves (k' = k / v term) + k := cfmmConstantMultiNoV(xReserve, yReserve, wSumSquares) + k2 := k.Mul(k) + + // find new yReserve after join + y_new := yReserve.Add(yIn) + + // store powers to simplify calculations + y2 := y_new.Mul(y_new) + y3 := y2.Mul(y_new) + y4 := y3.Mul(y_new) + + // We then solve for new xReserve using new yReserve and old k using a solver derived from xy(x^2 + y^2 + w) = k + // Full equation: x' = (sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3) / (3 2^(1/3) y) + // - (2^(1/3) (w y + y^3))/(sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3) + // + // + // To simplify, we make the following abstractions: + // 1. sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + // 2. cube_root_term = (sqrt_term + 27 k y^2)^(1/3) + // 3. term1 = cube_root_term / (3 2^(1/3) y) + // 4. term2 = (2^(1/3) (w y + y^3)) / cube_root_term + // + // With these, the final equation becomes: x' = term1 - term2 + + // let sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + wypy3 := (wSumSquares.Mul(y_new)).Add(y3) + wypy3pow3 := wypy3.Mul(wypy3).Mul(wypy3) + + sqrt_term, err := ((k2.Mul(y4).MulInt64(729)).Add(y3.MulInt64(108).Mul(wypy3pow3))).ApproxRoot(2) + if err != nil { + panic(err) + } + + // let cube_root_term = (sqrt_term + 27 k y^2)^(1/3) + cube_root_term, err := (sqrt_term.Add(k.Mul(y2).MulInt64(27))).ApproxRoot(3) + if err != nil { + panic(err) + } + + // let term1 = cube_root_term / (3 2^(1/3) y) + term1 := cube_root_term.Quo(cubeRootTwo.MulInt64(3).Mul(y_new)) + + // let term2 = cube_root_term * (2^(1/3) (w y + y^3)) + term2 := (cubeRootTwo.Mul(wypy3)).Quo(cube_root_term) + + // finally, let x' = term1 - term2 + x_new := term1.Sub(term2) + + // find amount of x to output using initial and final xReserve values + xOut := xReserve.Sub(x_new) + + if xOut.GTE(xReserve) { + panic("invalid output: greater than full pool reserves") + } + + return xOut +} + func approxDecEqual(a, b, tol osmomath.BigDec) bool { return (a.Sub(b).Abs()).LTE(tol) } @@ -162,52 +237,31 @@ var ( ) // solveCFMMBinarySearch searches the correct dx using binary search over constant K. -// added for future extension -func solveCFMMBinarySearch(constantFunction func(osmomath.BigDec, osmomath.BigDec) osmomath.BigDec) func(osmomath.BigDec, osmomath.BigDec, osmomath.BigDec) osmomath.BigDec { - return func(xReserve, yReserve, yIn osmomath.BigDec) osmomath.BigDec { - if !xReserve.IsPositive() || !yReserve.IsPositive() { - panic("invalid input: reserves and input must be positive") - } else if yIn.Abs().GTE(yReserve) { - panic("cannot input more than pool reserves") - } - k := constantFunction(xReserve, yReserve) - yFinal := yReserve.Add(yIn) - xLowEst := osmomath.ZeroDec() - // we set upper bound at 2 * xReserve to accommodate negative yIns - xHighEst := xReserve.Mul(osmomath.NewBigDec(2)) - maxIterations := 256 - errTolerance := osmoutils.ErrTolerance{AdditiveTolerance: sdk.OneInt(), MultiplicativeTolerance: sdk.Dec{}} - - // create single-input CFMM to pass into binary search - calc_x_est := func(xEst osmomath.BigDec) (osmomath.BigDec, error) { - return constantFunction(xEst, yFinal), nil - } - - x_est, err := osmoutils.BinarySearchBigDec(calc_x_est, xLowEst, xHighEst, k, errTolerance, maxIterations) - if err != nil { - panic(err) - } - - xOut := xReserve.Sub(x_est).Abs() - if xOut.GTE(xReserve) { - panic("invalid output: greater than full pool reserves") - } - return xOut - } -} - -// solveCFMMBinarySearch searches the correct dx using binary search over constant K. -// added for future extension func solveCFMMBinarySearchMulti(xReserve, yReserve, wSumSquares, yIn osmomath.BigDec) osmomath.BigDec { - if !xReserve.IsPositive() || !yReserve.IsPositive() || wSumSquares.IsNegative() || !yIn.IsPositive() { + if !xReserve.IsPositive() || !yReserve.IsPositive() || wSumSquares.IsNegative() { panic("invalid input: reserves and input must be positive") - } else if yIn.GTE(yReserve) { + } else if yIn.Abs().GTE(yReserve) { panic("cannot input more than pool reserves") } - k := cfmmConstantMultiNoV(xReserve, yReserve, wSumSquares) yFinal := yReserve.Add(yIn) - xLowEst := osmomath.ZeroDec() - xHighEst := xReserve + xLowEst, xHighEst := xReserve, xReserve + k0 := cfmmConstantMultiNoV(xReserve, yFinal, wSumSquares) + k := cfmmConstantMultiNoV(xReserve, yReserve, wSumSquares) + kRatio := k0.Quo(k) + + if kRatio.LT(osmomath.OneDec()) { + // k_0 < k. Need to find an upperbound. Worst case assume a linear relationship, gives an upperbound + // TODO: In the future, we can derive better bounds via reasoning about coefficients in the cubic + // These are quite close when we are in the "stable" part of the curve though. + xHighEst = xReserve.Quo(kRatio).Ceil() + } else if kRatio.GT(osmomath.OneDec()) { + // need to find a lowerbound. We could use a cubic relation, but for now we just set it to 0. + xLowEst = osmomath.ZeroDec() + } else { + // k remains unchanged, so xOut = 0 + return osmomath.ZeroDec() + } + maxIterations := 256 errTolerance := osmoutils.ErrTolerance{AdditiveTolerance: sdk.OneInt(), MultiplicativeTolerance: sdk.Dec{}} @@ -296,6 +350,9 @@ func (p *Pool) calcInAmtGivenOut(tokenOut sdk.Coin, tokenInDenom string, swapFee // We are solving for the amount of token in, cfmm(x,y) = cfmm(x + x_in, y - y_out) // x = tokenInSupply, y = tokenOutSupply, yIn = -tokenOutAmount cfmmIn := solveCfmm(tokenInSupply, tokenOutSupply, remReserves, tokenOutAmount.Neg()) + // returned cfmmIn is negative, representing we need to add this many tokens to pool. + // We invert that negative here. + cfmmIn = cfmmIn.Neg() // handle swap fee inAmt := cfmmIn.QuoRoundUp(oneMinus(swapFee)) // divide by (1 - swapfee) to force a corresponding increase in input asset @@ -320,11 +377,25 @@ func (p *Pool) calcSingleAssetJoinShares(tokenIn sdk.Coin, swapFee sdk.Dec) (sdk // We can mutate pa here // TODO: some day switch this to a COW wrapped pa, for better perf func (p *Pool) joinPoolSharesInternal(ctx sdk.Context, tokensIn sdk.Coins, swapFee sdk.Dec) (numShares sdk.Int, newLiquidity sdk.Coins, err error) { - if len(tokensIn) == 1 { + if !tokensIn.DenomsSubsetOf(p.GetTotalPoolLiquidity(ctx)) { + return sdk.ZeroInt(), sdk.NewCoins(), errors.New("attempted joining pool with assets that do not exist in pool") + } + if len(tokensIn) == 1 && tokensIn[0].Amount.GT(sdk.OneInt()) { numShares, err = p.calcSingleAssetJoinShares(tokensIn[0], swapFee) + if err != nil { + return sdk.ZeroInt(), sdk.NewCoins(), err + } + newLiquidity = tokensIn + + p.updatePoolForJoin(newLiquidity, numShares) + + if err = validatePoolAssets(p.PoolLiquidity, p.ScalingFactor); err != nil { + return sdk.ZeroInt(), sdk.NewCoins(), err + } + return numShares, newLiquidity, err - } else if len(tokensIn) != p.NumAssets() || !tokensIn.DenomsSubsetOf(p.GetTotalPoolLiquidity(ctx)) { + } else if len(tokensIn) != p.NumAssets() { return sdk.ZeroInt(), sdk.NewCoins(), errors.New( "stableswap pool only supports LP'ing with one asset, or all assets in pool") } @@ -336,15 +407,11 @@ func (p *Pool) joinPoolSharesInternal(ctx sdk.Context, tokensIn sdk.Coins, swapF } p.updatePoolForJoin(tokensIn.Sub(remCoins), numShares) - for _, coin := range remCoins { - // TODO: Perhaps add a method to skip if this is too small. - newShare, err := p.calcSingleAssetJoinShares(coin, swapFee) - if err != nil { - return sdk.ZeroInt(), sdk.NewCoins(), err - } - p.updatePoolForJoin(sdk.NewCoins(coin), newShare) - numShares = numShares.Add(newShare) + tokensJoined := tokensIn.Sub(remCoins) + + if err = validatePoolAssets(p.PoolLiquidity, p.ScalingFactor); err != nil { + return sdk.ZeroInt(), sdk.NewCoins(), err } - return numShares, tokensIn, nil + return numShares, tokensJoined, nil } diff --git a/x/gamm/pool-models/stableswap/amm_bench_test.go b/x/gamm/pool-models/stableswap/amm_bench_test.go index e07cf136911..4a779a79238 100644 --- a/x/gamm/pool-models/stableswap/amm_bench_test.go +++ b/x/gamm/pool-models/stableswap/amm_bench_test.go @@ -14,12 +14,6 @@ func BenchmarkCFMM(b *testing.B) { } } -func BenchmarkBinarySearchTwoAsset(b *testing.B) { - for i := 0; i < b.N; i++ { - runCalcTwoAsset(solveCFMMBinarySearch(cfmmConstant)) - } -} - func BenchmarkBinarySearchMultiAsset(b *testing.B) { for i := 0; i < b.N; i++ { runCalcMultiAsset(solveCFMMBinarySearchMulti) diff --git a/x/gamm/pool-models/stableswap/amm_test.go b/x/gamm/pool-models/stableswap/amm_test.go index a5c1f1ec28a..3e391bea9d2 100644 --- a/x/gamm/pool-models/stableswap/amm_test.go +++ b/x/gamm/pool-models/stableswap/amm_test.go @@ -224,16 +224,38 @@ var ( yIn: osmomath.NewBigDec(1), expectPanic: false, }, - /* TODO: increase BigDec precision (36 -> 72) to be able to accommodate this - "even 4-asset large pool, small input": { + "even 4-asset large pool (100M each), small input": { xReserve: osmomath.NewBigDec(100000000), yReserve: osmomath.NewBigDec(100000000), // represents a 4-asset pool with 100M in each reserve remReserves: []osmomath.BigDec{osmomath.NewBigDec(100000000), osmomath.NewBigDec(100000000)}, - yIn: osmomath.NewBigDec(100), + yIn: osmomath.NewBigDec(100), + expectPanic: false, + }, + "even 4-asset pool (10B each post-scaled), small input": { + xReserve: osmomath.NewBigDec(10000000000), + yReserve: osmomath.NewBigDec(10000000000), + // represents a 4-asset pool with 10B in each reserve + remReserves: []osmomath.BigDec{osmomath.NewBigDec(10000000000), osmomath.NewBigDec(10000000000)}, + yIn: osmomath.NewBigDec(100000000), + expectPanic: false, + }, + "even 10-asset pool (10B each post-scaled), small input": { + xReserve: osmomath.NewBigDec(10_000_000_000), + yReserve: osmomath.NewBigDec(10_000_000_000), + // represents a 10-asset pool with 10B in each reserve + remReserves: []osmomath.BigDec{osmomath.NewBigDec(10_000_000_000), osmomath.NewBigDec(10_000_000_000), osmomath.NewBigDec(10_000_000_000), osmomath.NewBigDec(10_000_000_000), osmomath.NewBigDec(10_000_000_000), osmomath.NewBigDec(10_000_000_000), osmomath.NewBigDec(10_000_000_000), osmomath.NewBigDec(10_000_000_000)}, + yIn: osmomath.NewBigDec(100), + expectPanic: false, + }, + "even 10-asset pool (100B each post-scaled), large input": { + xReserve: osmomath.NewBigDec(100_000_000_000), + yReserve: osmomath.NewBigDec(100_000_000_000), + // represents a 10-asset pool with 100B in each reserve + remReserves: []osmomath.BigDec{osmomath.NewBigDec(100_000_000_000), osmomath.NewBigDec(100_000_000_000), osmomath.NewBigDec(100_000_000_000), osmomath.NewBigDec(100_000_000_000), osmomath.NewBigDec(100_000_000_000), osmomath.NewBigDec(100_000_000_000), osmomath.NewBigDec(100_000_000_000), osmomath.NewBigDec(100_000_000_000)}, + yIn: osmomath.NewBigDec(10_000_000_000), expectPanic: false, }, - */ // uneven pools "uneven 3-asset pool, even swap assets as pool minority": { @@ -406,7 +428,7 @@ func TestCFMMInvariantTwoAssets(t *testing.T) { } } -func TestCFMMInvariantTwoAssetsBinarySearch(t *testing.T) { +func TestCFMMInvariantTwoAssetsDirect(t *testing.T) { kErrTolerance := osmomath.OneDec() tests := twoAssetCFMMTestCases @@ -415,9 +437,9 @@ func TestCFMMInvariantTwoAssetsBinarySearch(t *testing.T) { t.Run(name, func(t *testing.T) { // system under test sut := func() { - // using two-asset binary search cfmm solver + // using two-asset cfmm k0 := cfmmConstant(test.xReserve, test.yReserve) - xOut := solveCFMMBinarySearch(cfmmConstant)(test.xReserve, test.yReserve, test.yIn) + xOut := solveCfmmDirect(test.xReserve, test.yReserve, test.yIn) k1 := cfmmConstant(test.xReserve.Sub(xOut), test.yReserve.Add(test.yIn)) osmomath.DecApproxEq(t, k0, k1, kErrTolerance) @@ -428,21 +450,23 @@ func TestCFMMInvariantTwoAssetsBinarySearch(t *testing.T) { } } -func TestCFMMInvariantTwoAssetsDirect(t *testing.T) { +func TestCFMMInvariantMultiAssets(t *testing.T) { kErrTolerance := osmomath.OneDec() - tests := twoAssetCFMMTestCases + tests := multiAssetCFMMTestCases for name, test := range tests { t.Run(name, func(t *testing.T) { // system under test sut := func() { - // using two-asset cfmm - k0 := cfmmConstant(test.xReserve, test.yReserve) - xOut := solveCfmmDirect(test.xReserve, test.yReserve, test.yIn) + uReserve := calcUReserve(test.remReserves) + wSumSquares := calcWSumSquares(test.remReserves) - k1 := cfmmConstant(test.xReserve.Sub(xOut), test.yReserve.Add(test.yIn)) - osmomath.DecApproxEq(t, k0, k1, kErrTolerance) + // using multi-asset cfmm + k2 := cfmmConstantMulti(test.xReserve, test.yReserve, uReserve, wSumSquares) + xOut2 := solveCfmm(test.xReserve, test.yReserve, test.remReserves, test.yIn) + k3 := cfmmConstantMulti(test.xReserve.Sub(xOut2), test.yReserve.Add(test.yIn), uReserve, wSumSquares) + osmomath.DecApproxEq(t, k2, k3, kErrTolerance) } osmoassert.ConditionalPanic(t, test.expectPanic, sut) @@ -450,7 +474,7 @@ func TestCFMMInvariantTwoAssetsDirect(t *testing.T) { } } -func TestCFMMInvariantMultiAssets(t *testing.T) { +func TestCFMMInvariantMultiAssetsDirect(t *testing.T) { kErrTolerance := osmomath.OneDec() tests := multiAssetCFMMTestCases @@ -459,13 +483,12 @@ func TestCFMMInvariantMultiAssets(t *testing.T) { t.Run(name, func(t *testing.T) { // system under test sut := func() { - uReserve := calcUReserve(test.remReserves) wSumSquares := calcWSumSquares(test.remReserves) // using multi-asset cfmm - k2 := cfmmConstantMulti(test.xReserve, test.yReserve, uReserve, wSumSquares) - xOut2 := solveCfmm(test.xReserve, test.yReserve, test.remReserves, test.yIn) - k3 := cfmmConstantMulti(test.xReserve.Sub(xOut2), test.yReserve.Add(test.yIn), uReserve, wSumSquares) + k2 := cfmmConstantMultiNoV(test.xReserve, test.yReserve, wSumSquares) + xOut2 := solveCFMMMultiDirect(test.xReserve, test.yReserve, wSumSquares, test.yIn) + k3 := cfmmConstantMultiNoV(test.xReserve.Sub(xOut2), test.yReserve.Add(test.yIn), wSumSquares) osmomath.DecApproxEq(t, k2, k3, kErrTolerance) } @@ -505,41 +528,153 @@ func (suite *StableSwapTestSuite) Test_StableSwap_CalculateAmountOutAndIn_Invers denomIn string initialPoolIn int64 + + poolLiquidity sdk.Coins + scalingFactors []uint64 } // For every test case in testcases, apply a swap fee in swapFeeCases. - testcases := []testcase{ - { + testcases := map[string]testcase{ + // two-asset pools + "even pool": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000_000_000)), + ), + scalingFactors: []uint64{1, 1}, + }, + "uneven pool (2:1)": { + denomIn: "ion", denomOut: "uosmo", - initialPoolOut: 1_000_000_000, initialCalcOut: 100, - denomIn: "ion", - initialPoolIn: 1_000_000_000, + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(500_000)), + ), + scalingFactors: []uint64{1, 1}, }, - { + "uneven pool (1_000_000:1)": { + denomIn: "ion", denomOut: "uosmo", - initialPoolOut: 500_000, initialCalcOut: 100, - denomIn: "ion", - initialPoolIn: 1_000_000, + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000)), + ), + scalingFactors: []uint64{1, 1}, }, - { + "uneven pool (1:1_000_000)": { + denomIn: "ion", denomOut: "uosmo", - initialPoolOut: 1_000, initialCalcOut: 100, - denomIn: "ion", - initialPoolIn: 1_000_000_000, + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000_000_000)), + ), + scalingFactors: []uint64{1, 1}, }, - { + "even pool, uneven scaling factors": { + denomIn: "ion", denomOut: "uosmo", - initialPoolOut: 1_000_000_000, initialCalcOut: 100, - denomIn: "ion", - initialPoolIn: 1_000, + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000_000_000)), + ), + scalingFactors: []uint64{1, 8}, + }, + "uneven pool, uneven scaling factors": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(500_000)), + ), + scalingFactors: []uint64{1, 9}, + }, + + // multi asset pools + "even multi-asset pool": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000_000)), + sdk.NewCoin("foo", sdk.NewInt(1_000_000)), + ), + scalingFactors: []uint64{1, 1, 1}, + }, + "uneven multi-asset pool (2:1:2)": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(500_000)), + sdk.NewCoin("foo", sdk.NewInt(1_000_000)), + ), + scalingFactors: []uint64{1, 1, 1}, + }, + "uneven multi-asset pool (1_000_000:1:1_000_000)": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000)), + sdk.NewCoin("foo", sdk.NewInt(1_000_000)), + ), + scalingFactors: []uint64{1, 1, 1}, + }, + "uneven multi-asset pool (1:1_000_000:1_000_000)": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000_000)), + sdk.NewCoin("foo", sdk.NewInt(1_000_000)), + ), + scalingFactors: []uint64{1, 1, 1}, + }, + "even multi-asset pool, uneven scaling factors": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(1_000_000)), + sdk.NewCoin("foo", sdk.NewInt(1_000_000)), + ), + scalingFactors: []uint64{5, 3, 9}, + }, + "uneven multi-asset pool (2:1:2), uneven scaling factors": { + denomIn: "ion", + denomOut: "uosmo", + initialCalcOut: 100, + + poolLiquidity: sdk.NewCoins( + sdk.NewCoin("ion", sdk.NewInt(1_000_000)), + sdk.NewCoin("uosmo", sdk.NewInt(500_000)), + sdk.NewCoin("foo", sdk.NewInt(1_000_000)), + ), + scalingFactors: []uint64{100, 76, 33}, }, } @@ -559,9 +694,8 @@ func (suite *StableSwapTestSuite) Test_StableSwap_CalculateAmountOutAndIn_Invers suite.Run(getTestCaseName(tc, swapFee), func() { ctx := suite.CreateTestContext() - poolLiquidityIn := sdk.NewInt64Coin(tc.denomOut, tc.initialPoolOut) - poolLiquidityOut := sdk.NewInt64Coin(tc.denomIn, tc.initialPoolIn) - poolLiquidity := sdk.NewCoins(poolLiquidityIn, poolLiquidityOut) + poolLiquidityIn := sdk.NewInt64Coin(tc.denomIn, tc.initialPoolIn) + poolLiquidityOut := sdk.NewInt64Coin(tc.denomOut, tc.initialPoolOut) swapFeeDec, err := sdk.NewDecFromStr(swapFee) suite.Require().NoError(err) @@ -570,7 +704,7 @@ func (suite *StableSwapTestSuite) Test_StableSwap_CalculateAmountOutAndIn_Invers suite.Require().NoError(err) // TODO: add scaling factors into inverse relationship tests - pool := createTestPool(suite.T(), poolLiquidity, swapFeeDec, exitFeeDec, []uint64{1, 1}) + pool := createTestPool(suite.T(), tc.poolLiquidity, swapFeeDec, exitFeeDec, tc.scalingFactors) suite.Require().NotNil(pool) test_helpers.TestCalculateAmountOutAndIn_InverseRelationship(suite.T(), ctx, pool, poolLiquidityIn.Denom, poolLiquidityOut.Denom, tc.initialCalcOut, swapFeeDec) }) @@ -677,8 +811,6 @@ func TestCalcSingleAssetJoinShares(t *testing.T) { swapFee: sdk.MustNewDecFromStr("0.03"), expectedOut: sdk.NewInt(100 - 3), }, - - // TODO: increase BigDec precision further to be able to accommodate 5-asset pool tests } for name, tc := range tests { @@ -702,3 +834,117 @@ func TestCalcSingleAssetJoinShares(t *testing.T) { }) } } + +func TestJoinPoolSharesInternal(t *testing.T) { + tenPercentOfTwoPoolRaw := int64(1000000000 / 10) + tenPercentOfTwoPoolCoins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(int64(1000000000/10))), sdk.NewCoin("bar", sdk.NewInt(int64(1000000000/10)))) + twoAssetPlusTenPercent := twoEvenStablePoolAssets.Add(tenPercentOfTwoPoolCoins...) + type testcase struct { + tokensIn sdk.Coins + poolAssets sdk.Coins + scalingFactors []uint64 + swapFee sdk.Dec + expNumShare sdk.Int + expTokensJoined sdk.Coins + expPoolAssets sdk.Coins + expectPass bool + } + + tests := map[string]testcase{ + "even two asset pool, same tokenIn ratio": { + tokensIn: tenPercentOfTwoPoolCoins, + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: tenPercentOfTwoPoolCoins, + expPoolAssets: twoAssetPlusTenPercent, + expectPass: true, + }, + "even two asset pool, different tokenIn ratio with pool": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPoolRaw)), sdk.NewCoin("bar", sdk.NewInt(10+tenPercentOfTwoPoolRaw))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPoolRaw)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPoolRaw))), + expPoolAssets: twoAssetPlusTenPercent, + expectPass: true, + }, + "all-asset pool join attempt exceeds max scaled asset amount": { + tokensIn: sdk.NewCoins( + sdk.NewInt64Coin("foo", 1), + sdk.NewInt64Coin("bar", 1), + ), + poolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expNumShare: sdk.ZeroInt(), + expTokensJoined: sdk.Coins{}, + expPoolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + expectPass: false, + }, + "single-asset pool join exceeds hits max scaled asset amount": { + tokensIn: sdk.NewCoins( + sdk.NewInt64Coin("foo", 1), + ), + poolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expNumShare: sdk.ZeroInt(), + expTokensJoined: sdk.Coins{}, + expPoolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + expectPass: false, + }, + "all-asset pool join attempt exactly hits max scaled asset amount": { + tokensIn: sdk.NewCoins( + sdk.NewInt64Coin("foo", 1), + sdk.NewInt64Coin("bar", 1), + ), + poolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 9_999_999_999), + sdk.NewInt64Coin("bar", 9_999_999_999), + ), + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expNumShare: sdk.NewInt(10000000000), + expTokensJoined: sdk.NewCoins( + sdk.NewInt64Coin("foo", 1), + sdk.NewInt64Coin("bar", 1), + ), + expPoolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + expectPass: true, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + ctx := sdk.Context{} + p := poolStructFromAssets(tc.poolAssets, tc.scalingFactors) + + shares, joinedLiquidity, err := p.joinPoolSharesInternal(ctx, tc.tokensIn, tc.swapFee) + + if tc.expectPass { + require.Equal(t, tc.expNumShare, shares) + require.Equal(t, tc.expTokensJoined, joinedLiquidity) + require.Equal(t, tc.expPoolAssets, p.PoolLiquidity) + } + osmoassert.ConditionalError(t, !tc.expectPass, err) + }) + } +} diff --git a/x/gamm/pool-models/stableswap/msgs.go b/x/gamm/pool-models/stableswap/msgs.go index d2d45101188..16953bbaf56 100644 --- a/x/gamm/pool-models/stableswap/msgs.go +++ b/x/gamm/pool-models/stableswap/msgs.go @@ -46,13 +46,6 @@ func (msg MsgCreateStableswapPool) ValidateBasic() error { return err } - // validation for pool initial liquidity - if len(msg.InitialPoolLiquidity) < 2 { - return types.ErrTooFewPoolAssets - } else if len(msg.InitialPoolLiquidity) > 8 { - return types.ErrTooManyPoolAssets - } - // validation for scaling factors // The message's scaling factors must be empty or a valid set of scaling factors if len(msg.ScalingFactors) != 0 { @@ -61,6 +54,12 @@ func (msg MsgCreateStableswapPool) ValidateBasic() error { } } + // validation for pool initial liquidity + // The message's pool liquidity must have between 2 and 8 assets with at most 10B post-scaled units in each + if err = validatePoolAssets(msg.InitialPoolLiquidity, msg.ScalingFactors); err != nil { + return err + } + // validation for scaling factor owner if err = validateScalingFactorController(msg.ScalingFactorController); err != nil { return err diff --git a/x/gamm/pool-models/stableswap/msgs_test.go b/x/gamm/pool-models/stableswap/msgs_test.go index aa3fcbd8e93..727e4dc3fa1 100644 --- a/x/gamm/pool-models/stableswap/msgs_test.go +++ b/x/gamm/pool-models/stableswap/msgs_test.go @@ -209,6 +209,60 @@ func TestMsgCreateStableswapPool(t *testing.T) { }), expectPass: true, }, + { + name: "max asset amounts", + msg: createMsg(func(msg stableswap.MsgCreateStableswapPool) stableswap.MsgCreateStableswapPool { + msg.InitialPoolLiquidity = sdk.Coins{ + sdk.NewCoin("osmo", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("atom", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("usdt", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("usdc", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("juno", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("akt", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("regen", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("band", sdk.NewInt(10_000_000_000)), + } + msg.ScalingFactors = []uint64{1, 1, 1, 1, 1, 1, 1, 1} + return msg + }), + expectPass: true, + }, + { + name: "greater than max post-scaled amount with regular scaling factors", + msg: createMsg(func(msg stableswap.MsgCreateStableswapPool) stableswap.MsgCreateStableswapPool { + msg.InitialPoolLiquidity = sdk.Coins{ + sdk.NewCoin("osmo", sdk.NewInt(1+10_000_000_000)), + sdk.NewCoin("atom", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("usdt", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("usdc", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("juno", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("akt", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("regen", sdk.NewInt(10_000_000_000)), + sdk.NewCoin("band", sdk.NewInt(10_000_000_000)), + } + msg.ScalingFactors = []uint64{1, 1, 1, 1, 1, 1, 1, 1} + return msg + }), + expectPass: false, + }, + { + name: "100B token 8-asset pool using large scaling factors", + msg: createMsg(func(msg stableswap.MsgCreateStableswapPool) stableswap.MsgCreateStableswapPool { + msg.InitialPoolLiquidity = sdk.Coins{ + sdk.NewCoin("osmo", sdk.NewInt(100_000_000_000_000_000)), + sdk.NewCoin("atom", sdk.NewInt(100_000_000_000_000_000)), + sdk.NewCoin("usdt", sdk.NewInt(100_000_000_000_000_000)), + sdk.NewCoin("usdc", sdk.NewInt(100_000_000_000_000_000)), + sdk.NewCoin("juno", sdk.NewInt(100_000_000_000_000_000)), + sdk.NewCoin("akt", sdk.NewInt(100_000_000_000_000_000)), + sdk.NewCoin("regen", sdk.NewInt(100_000_000_000_000_000)), + sdk.NewCoin("band", sdk.NewInt(100_000_000_000_000_000)), + } + msg.ScalingFactors = []uint64{10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000} + return msg + }), + expectPass: true, + }, } for _, test := range tests { diff --git a/x/gamm/pool-models/stableswap/pool.go b/x/gamm/pool-models/stableswap/pool.go index 728bc15ac5a..db995e3333c 100644 --- a/x/gamm/pool-models/stableswap/pool.go +++ b/x/gamm/pool-models/stableswap/pool.go @@ -39,6 +39,10 @@ func NewStableswapPool(poolId uint64, return Pool{}, err } + if err := validatePoolAssets(initialLiquidity, scalingFactors); err != nil { + return Pool{}, err + } + pool := Pool{ Address: types.NewPoolAddress(poolId).String(), Id: poolId, @@ -232,6 +236,10 @@ func (p Pool) CalcOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coins, tokenOutDeno } func (p *Pool) SwapOutAmtGivenIn(ctx sdk.Context, tokenIn sdk.Coins, tokenOutDenom string, swapFee sdk.Dec) (tokenOut sdk.Coin, err error) { + if err = validatePoolAssets(p.PoolLiquidity.Add(tokenIn...), p.ScalingFactor); err != nil { + return sdk.Coin{}, err + } + tokenOut, err = p.CalcOutAmtGivenIn(ctx, tokenIn, tokenOutDenom, swapFee) if err != nil { return sdk.Coin{}, err @@ -268,6 +276,10 @@ func (p *Pool) SwapInAmtGivenOut(ctx sdk.Context, tokenOut sdk.Coins, tokenInDen return sdk.Coin{}, err } + if err = validatePoolAssets(p.PoolLiquidity.Add(tokenIn), p.ScalingFactor); err != nil { + return sdk.Coin{}, err + } + p.updatePoolLiquidityForSwap(sdk.NewCoins(tokenIn), tokenOut) return tokenIn, nil @@ -288,19 +300,48 @@ func (p *Pool) CalcJoinPoolShares(ctx sdk.Context, tokensIn sdk.Coins, swapFee s return pCopy.joinPoolSharesInternal(ctx, tokensIn, swapFee) } -// TODO: implement this -func (p *Pool) CalcJoinPoolNoSwapShares(ctx sdk.Context, tokensIn sdk.Coins, swapFee sdk.Dec) (numShares sdk.Int, newLiquidity sdk.Coins, err error) { - return sdk.ZeroInt(), nil, err +// CalcJoinPoolNoSwapShares calculates the number of shares created to execute an all-asset pool join with the provided amount of `tokensIn`. +// The input tokens must contain the same tokens as in the pool. +// +// Returns the number of shares created, the amount of coins actually joined into the pool as not all may tokens may be joinable. +// If an all-asset join is not possible, returns an error. +func (p Pool) CalcJoinPoolNoSwapShares(ctx sdk.Context, tokensIn sdk.Coins, swapFee sdk.Dec) (numShares sdk.Int, tokensJoined sdk.Coins, err error) { + // ensure that there aren't too many or too few assets in `tokensIn` + if tokensIn.Len() != p.NumAssets() || !tokensIn.DenomsSubsetOf(p.GetTotalPoolLiquidity(ctx)) { + return sdk.ZeroInt(), sdk.NewCoins(), errors.New("no-swap joins require LP'ing with all assets in pool") + } + + // execute a no-swap join with as many tokens as possible given a perfect ratio: + // * numShares is how many shares are perfectly matched. + // * remainingTokensIn is how many coins we have left to join that have not already been used. + numShares, remainingTokensIn, err := cfmm_common.MaximalExactRatioJoin(&p, ctx, tokensIn) + if err != nil { + return sdk.ZeroInt(), sdk.NewCoins(), err + } + + // ensure that no more tokens have been joined than is possible with the given `tokensIn` + tokensJoined = tokensIn.Sub(remainingTokensIn) + if tokensJoined.IsAnyGT(tokensIn) { + return sdk.ZeroInt(), sdk.NewCoins(), errors.New("an error has occurred, more coins joined than token In") + } + + return numShares, tokensJoined, nil } -func (p *Pool) JoinPool(ctx sdk.Context, tokensIn sdk.Coins, swapFee sdk.Dec) (numShares sdk.Int, err error) { - numShares, _, err = p.joinPoolSharesInternal(ctx, tokensIn, swapFee) +func (p *Pool) JoinPool(ctx sdk.Context, tokensIn sdk.Coins, swapFee sdk.Dec) (sdk.Int, error) { + numShares, _, err := p.joinPoolSharesInternal(ctx, tokensIn, swapFee) return numShares, err } -// TODO: implement this -func (p *Pool) JoinPoolNoSwap(ctx sdk.Context, tokensIn sdk.Coins, swapFee sdk.Dec) (numShares sdk.Int, err error) { - return sdk.ZeroInt(), err +func (p *Pool) JoinPoolNoSwap(ctx sdk.Context, tokensIn sdk.Coins, swapFee sdk.Dec) (sdk.Int, error) { + newShares, tokensJoined, err := p.CalcJoinPoolNoSwapShares(ctx, tokensIn, swapFee) + if err != nil { + return sdk.Int{}, err + } + + // update pool with the calculated share and liquidity needed to join pool + p.updatePoolForJoin(tokensJoined, newShares) + return newShares, nil } func (p *Pool) ExitPool(ctx sdk.Context, exitingShares sdk.Int, exitFee sdk.Dec) (exitingCoins sdk.Coins, err error) { @@ -331,6 +372,10 @@ func (p *Pool) SetStableSwapScalingFactors(ctx sdk.Context, scalingFactors []uin return err } + if err := validatePoolAssets(p.PoolLiquidity, scalingFactors); err != nil { + return err + } + p.ScalingFactor = scalingFactors return nil } @@ -356,3 +401,19 @@ func validateScalingFactors(scalingFactors []uint64, numAssets int) error { return nil } + +func validatePoolAssets(initialAssets sdk.Coins, scalingFactors []uint64) error { + if len(initialAssets) < types.MinPoolAssets { + return types.ErrTooFewPoolAssets + } else if len(initialAssets) > types.MaxPoolAssets { + return types.ErrTooManyPoolAssets + } + + for i, asset := range initialAssets { + if asset.Amount.Quo(sdk.NewInt(int64(scalingFactors[i]))).GT(sdk.NewInt(types.StableswapMaxScaledAmtPerAsset)) { + return types.ErrHitMaxScaledAssets + } + } + + return nil +} diff --git a/x/gamm/pool-models/stableswap/pool_test.go b/x/gamm/pool-models/stableswap/pool_test.go index 1f48ca8534d..c408b9b180d 100644 --- a/x/gamm/pool-models/stableswap/pool_test.go +++ b/x/gamm/pool-models/stableswap/pool_test.go @@ -10,6 +10,7 @@ import ( "github.com/osmosis-labs/osmosis/v12/app/apptesting/osmoassert" "github.com/osmosis-labs/osmosis/v12/osmomath" + "github.com/osmosis-labs/osmosis/v12/x/gamm/pool-models/internal/cfmm_common" "github.com/osmosis-labs/osmosis/v12/x/gamm/types" ) @@ -505,3 +506,460 @@ func TestScaleCoin(t *testing.T) { }) } } + +func TestCalcJoinPoolNoSwapShares(t *testing.T) { + tenPercentOfTwoPool := int64(1000000000 / 10) + tenPercentOfThreePool := int64(1000000 / 10) + tests := map[string]struct { + tokensIn sdk.Coins + poolAssets sdk.Coins + scalingFactors []uint64 + expNumShare sdk.Int + expTokensJoined sdk.Coins + expPoolAssets sdk.Coins + expectPass bool + }{ + "even two asset pool, same tokenIn ratio": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool))), + expPoolAssets: twoEvenStablePoolAssets, + expectPass: true, + }, + "even two asset pool, different tokenIn ratio with pool": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool+1))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool))), + expPoolAssets: twoEvenStablePoolAssets, + expectPass: true, + }, + "uneven two asset pool, same tokenIn ratio": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(2*tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool))), + poolAssets: twoUnevenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(2*tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool))), + expPoolAssets: twoUnevenStablePoolAssets, + expectPass: true, + }, + "uneven two asset pool, different tokenIn ratio with pool": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(2*tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool+1))), + poolAssets: twoUnevenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(2*tenPercentOfTwoPool)), sdk.NewCoin("bar", sdk.NewInt(tenPercentOfTwoPool))), + expPoolAssets: twoUnevenStablePoolAssets, + expectPass: true, + }, + "even three asset pool, same tokenIn ratio": { + tokensIn: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(tenPercentOfThreePool))), + poolAssets: threeEvenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(tenPercentOfThreePool))), + expPoolAssets: threeEvenStablePoolAssets, + expectPass: true, + }, + "even three asset pool, different tokenIn ratio with pool": { + tokensIn: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(tenPercentOfThreePool+1))), + poolAssets: threeEvenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(tenPercentOfThreePool))), + expPoolAssets: threeEvenStablePoolAssets, + expectPass: true, + }, + "uneven three asset pool, same tokenIn ratio": { + tokensIn: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(2*tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(3*tenPercentOfThreePool))), + poolAssets: threeUnevenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(2*tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(3*tenPercentOfThreePool))), + expPoolAssets: threeUnevenStablePoolAssets, + expectPass: true, + }, + "uneven three asset pool, different tokenIn ratio with pool": { + tokensIn: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(2*tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(3*tenPercentOfThreePool+1))), + poolAssets: threeUnevenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(2*tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(3*tenPercentOfThreePool))), + expPoolAssets: threeUnevenStablePoolAssets, + expectPass: true, + }, + "uneven three asset pool, uneven scaling factors": { + tokensIn: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(2*tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(3*tenPercentOfThreePool))), + poolAssets: threeUnevenStablePoolAssets, + scalingFactors: []uint64{5, 9, 175}, + expNumShare: sdk.NewIntFromUint64(10000000000000000000), + expTokensJoined: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(2*tenPercentOfThreePool)), sdk.NewCoin("asset/c", sdk.NewInt(3*tenPercentOfThreePool))), + expPoolAssets: threeUnevenStablePoolAssets, + expectPass: true, + }, + + // error catching + "even two asset pool, no-swap join attempt with one asset": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPool))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(0), + expTokensJoined: sdk.Coins{}, + expPoolAssets: twoEvenStablePoolAssets, + expectPass: false, + }, + "even two asset pool, no-swap join attempt with one valid and one invalid asset": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPool)), sdk.NewCoin("baz", sdk.NewInt(tenPercentOfTwoPool))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(0), + expTokensJoined: sdk.Coins{}, + expPoolAssets: twoEvenStablePoolAssets, + expectPass: false, + }, + "even two asset pool, no-swap join attempt with two invalid assets": { + tokensIn: sdk.NewCoins(sdk.NewCoin("baz", sdk.NewInt(tenPercentOfTwoPool)), sdk.NewCoin("qux", sdk.NewInt(tenPercentOfTwoPool))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(0), + expTokensJoined: sdk.Coins{}, + expPoolAssets: twoEvenStablePoolAssets, + expectPass: false, + }, + "even three asset pool, no-swap join attempt with an invalid asset": { + tokensIn: sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("asset/b", sdk.NewInt(tenPercentOfThreePool)), sdk.NewCoin("qux", sdk.NewInt(tenPercentOfThreePool))), + poolAssets: threeEvenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + expNumShare: sdk.NewIntFromUint64(0), + expTokensJoined: sdk.Coins{}, + expPoolAssets: threeEvenStablePoolAssets, + expectPass: false, + }, + "single asset pool, no-swap join attempt with one asset": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(sdk.MaxSortableDec.TruncateInt64()))), + poolAssets: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1))), + scalingFactors: []uint64{1}, + expNumShare: sdk.NewIntFromUint64(0), + expTokensJoined: sdk.Coins{}, + expPoolAssets: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1))), + expectPass: false, + }, + "attempt joining pool with no assets in it": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1))), + poolAssets: sdk.Coins{}, + scalingFactors: []uint64{}, + expNumShare: sdk.NewIntFromUint64(0), + expTokensJoined: sdk.Coins{}, + expPoolAssets: sdk.Coins{}, + expectPass: false, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + ctx := sdk.Context{} + pool := poolStructFromAssets(test.poolAssets, test.scalingFactors) + numShare, tokensJoined, err := pool.CalcJoinPoolNoSwapShares(ctx, test.tokensIn, pool.GetSwapFee(ctx)) + + if test.expectPass { + require.NoError(t, err) + require.Equal(t, test.expPoolAssets, pool.GetTotalPoolLiquidity(ctx)) + require.Equal(t, test.expNumShare, numShare) + require.Equal(t, test.expTokensJoined, tokensJoined) + } else { + require.Error(t, err) + require.Equal(t, test.expPoolAssets, pool.GetTotalPoolLiquidity(ctx)) + require.Equal(t, test.expNumShare, numShare) + require.Equal(t, test.expTokensJoined, tokensJoined) + } + }) + } +} + +func TestSwapOutAmtGivenIn(t *testing.T) { + tests := map[string]struct { + poolAssets sdk.Coins + scalingFactors []uint64 + tokenIn sdk.Coins + expectedTokenOut sdk.Coin + expectedPoolLiquidity sdk.Coins + swapFee sdk.Dec + expError bool + }{ + "even pool basic trade": { + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + tokenIn: sdk.NewCoins(sdk.NewInt64Coin("foo", 100)), + // we expect at least a 1 token difference since output is truncated + expectedTokenOut: sdk.NewInt64Coin("bar", 99), + expectedPoolLiquidity: twoEvenStablePoolAssets.Add(sdk.NewInt64Coin("foo", 100)).Sub(sdk.NewCoins(sdk.NewInt64Coin("bar", 99))), + swapFee: sdk.ZeroDec(), + expError: false, + }, + "trade hits max pool capacity for asset": { + poolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 9_999_999_998), + sdk.NewInt64Coin("bar", 9_999_999_999), + ), + scalingFactors: defaultTwoAssetScalingFactors, + tokenIn: sdk.NewCoins(sdk.NewInt64Coin("foo", 1)), + expectedTokenOut: sdk.NewInt64Coin("bar", 1), + expectedPoolLiquidity: sdk.NewCoins( + sdk.NewInt64Coin("foo", 9_999_999_999), + sdk.NewInt64Coin("bar", 9_999_999_998), + ), + swapFee: sdk.ZeroDec(), + expError: false, + }, + "trade exceeds max pool capacity for asset": { + poolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + scalingFactors: defaultTwoAssetScalingFactors, + tokenIn: sdk.NewCoins(sdk.NewInt64Coin("foo", 1)), + expectedTokenOut: sdk.Coin{}, + expectedPoolLiquidity: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + swapFee: sdk.ZeroDec(), + expError: true, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + ctx := sdk.Context{} + p := poolStructFromAssets(tc.poolAssets, tc.scalingFactors) + + tokenOut, err := p.SwapOutAmtGivenIn(ctx, tc.tokenIn, tc.expectedTokenOut.Denom, tc.swapFee) + if !tc.expError { + require.Equal(t, tc.expectedTokenOut, tokenOut) + require.Equal(t, tc.expectedPoolLiquidity, p.PoolLiquidity) + } + osmoassert.ConditionalError(t, tc.expError, err) + }) + } +} + +func TestSwapInAmtGivenOut(t *testing.T) { + tests := map[string]struct { + poolAssets sdk.Coins + scalingFactors []uint64 + tokenOut sdk.Coins + expectedTokenIn sdk.Coin + expectedPoolLiquidity sdk.Coins + swapFee sdk.Dec + expError bool + }{ + "even pool basic trade": { + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + tokenOut: sdk.NewCoins(sdk.NewInt64Coin("bar", 99)), + // we expect at least a 1 token difference from our true expected output since it is truncated + expectedTokenIn: sdk.NewInt64Coin("foo", 99), + expectedPoolLiquidity: twoEvenStablePoolAssets.Add(sdk.NewInt64Coin("foo", 99)).Sub(sdk.NewCoins(sdk.NewInt64Coin("bar", 99))), + swapFee: sdk.ZeroDec(), + expError: false, + }, + "trade hits max pool capacity for asset": { + poolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 9_999_999_998), + sdk.NewInt64Coin("bar", 9_999_999_999), + ), + scalingFactors: defaultTwoAssetScalingFactors, + tokenOut: sdk.NewCoins(sdk.NewInt64Coin("bar", 1)), + expectedTokenIn: sdk.NewInt64Coin("foo", 1), + expectedPoolLiquidity: sdk.NewCoins( + sdk.NewInt64Coin("foo", 9_999_999_999), + sdk.NewInt64Coin("bar", 9_999_999_998), + ), + swapFee: sdk.ZeroDec(), + expError: false, + }, + "trade exceeds max pool capacity for asset": { + poolAssets: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + scalingFactors: defaultTwoAssetScalingFactors, + tokenOut: sdk.NewCoins(sdk.NewInt64Coin("bar", 1)), + expectedTokenIn: sdk.Coin{}, + expectedPoolLiquidity: sdk.NewCoins( + sdk.NewInt64Coin("foo", 10_000_000_000), + sdk.NewInt64Coin("bar", 10_000_000_000), + ), + swapFee: sdk.ZeroDec(), + expError: true, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + ctx := sdk.Context{} + p := poolStructFromAssets(tc.poolAssets, tc.scalingFactors) + + tokenIn, err := p.SwapInAmtGivenOut(ctx, tc.tokenOut, tc.expectedTokenIn.Denom, tc.swapFee) + if !tc.expError { + require.Equal(t, tc.expectedTokenIn, tokenIn) + require.Equal(t, tc.expectedPoolLiquidity, p.PoolLiquidity) + } + osmoassert.ConditionalError(t, tc.expError, err) + }) + } +} + +func TestInverseJoinPoolExitPool(t *testing.T) { + hundredFoo := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100))) + thousandAssetA := sdk.NewCoins(sdk.NewCoin("asset/a", sdk.NewInt(1000))) + tenPercentOfTwoPoolRaw := int64(1000000000 / 10) + tenPercentOfTwoPoolCoins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(int64(1000000000/10))), sdk.NewCoin("bar", sdk.NewInt(int64(1000000000/10)))) + type testcase struct { + tokensIn sdk.Coins + poolAssets sdk.Coins + unevenJoinedTokens sdk.Coins + scalingFactors []uint64 + swapFee sdk.Dec + expectPass bool + } + + tests := map[string]testcase{ + "[single asset join] even two asset pool, no swap fee": { + tokensIn: hundredFoo, + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expectPass: true, + }, + "[single asset join] uneven two asset pool, no swap fee": { + tokensIn: hundredFoo, + poolAssets: twoUnevenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expectPass: true, + }, + "[single asset join] even 3-asset pool, no swap fee": { + tokensIn: thousandAssetA, + poolAssets: threeEvenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expectPass: true, + }, + "[single asset join] uneven 3-asset pool, no swap fee": { + tokensIn: thousandAssetA, + poolAssets: threeUnevenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expectPass: true, + }, + "[single asset join] even two asset pool, default swap fee": { + tokensIn: hundredFoo, + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: defaultSwapFee, + expectPass: true, + }, + "[single asset join] uneven two asset pool, default swap fee": { + tokensIn: hundredFoo, + poolAssets: twoUnevenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: defaultSwapFee, + expectPass: true, + }, + "[single asset join] even 3-asset pool, default swap fee": { + tokensIn: thousandAssetA, + poolAssets: threeEvenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + swapFee: defaultSwapFee, + expectPass: true, + }, + "[single asset join] uneven 3-asset pool, default swap fee": { + tokensIn: thousandAssetA, + poolAssets: threeUnevenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + swapFee: defaultSwapFee, + expectPass: true, + }, + "[single asset join] even 3-asset pool, 0.03 swap fee": { + tokensIn: thousandAssetA, + poolAssets: threeEvenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + swapFee: sdk.MustNewDecFromStr("0.03"), + expectPass: true, + }, + "[single asset join] uneven 3-asset pool, 0.03 swap fee": { + tokensIn: thousandAssetA, + poolAssets: threeUnevenStablePoolAssets, + scalingFactors: defaultThreeAssetScalingFactors, + swapFee: sdk.MustNewDecFromStr("0.03"), + expectPass: true, + }, + + "[all asset join] even two asset pool, same tokenIn ratio": { + tokensIn: tenPercentOfTwoPoolCoins, + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expectPass: true, + }, + "[all asset join] even two asset pool, different tokenIn ratio with pool": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPoolRaw)), sdk.NewCoin("bar", sdk.NewInt(10+tenPercentOfTwoPoolRaw))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expectPass: true, + }, + "[all asset join] even two asset pool, different tokenIn ratio with pool, nonzero swap fee": { + tokensIn: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(tenPercentOfTwoPoolRaw)), sdk.NewCoin("bar", sdk.NewInt(10+tenPercentOfTwoPoolRaw))), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: defaultSwapFee, + expectPass: true, + }, + "[all asset join] even two asset pool, no tokens in": { + tokensIn: sdk.NewCoins(), + poolAssets: twoEvenStablePoolAssets, + scalingFactors: defaultTwoAssetScalingFactors, + swapFee: sdk.ZeroDec(), + expectPass: true, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + ctx := sdk.Context{} + p := poolStructFromAssets(tc.poolAssets, tc.scalingFactors) + + // we join then exit the pool + shares, err := p.JoinPool(ctx, tc.tokensIn, tc.swapFee) + tokenOut, err := p.ExitPool(ctx, shares, defaultExitFee) + + // if single asset join, we swap output tokens to input denom to test the full inverse relationship + if len(tc.tokensIn) == 1 { + tokenOutAmt, err := cfmm_common.SwapAllCoinsToSingleAsset(&p, ctx, tokenOut, tc.tokensIn[0].Denom) + require.NoError(t, err) + tokenOut = sdk.NewCoins(sdk.NewCoin(tc.tokensIn[0].Denom, tokenOutAmt)) + } + + // if single asset join, we expect output token swapped into the input denom to be input minus swap fee + var expectedTokenOut sdk.Coins + if len(tc.tokensIn) == 1 { + expectedAmt := (tc.tokensIn[0].Amount.ToDec().Mul(sdk.OneDec().Sub(tc.swapFee))).TruncateInt() + expectedTokenOut = sdk.NewCoins(sdk.NewCoin(tc.tokensIn[0].Denom, expectedAmt)) + } else { + expectedTokenOut = tc.tokensIn + } + + if tc.expectPass { + finalPoolLiquidity := p.GetTotalPoolLiquidity(ctx) + require.True(t, tokenOut.IsAllLTE(expectedTokenOut)) + require.True(t, finalPoolLiquidity.IsAllGTE(tc.poolAssets)) + } + osmoassert.ConditionalError(t, !tc.expectPass, err) + }) + } +} diff --git a/x/gamm/types/constants.go b/x/gamm/types/constants.go index 76ad1efec91..4152661d7a8 100644 --- a/x/gamm/types/constants.go +++ b/x/gamm/types/constants.go @@ -13,6 +13,8 @@ const ( // i.e. SigFigExponent = 8 is 10^8 which is 100000000. This gives 8 significant figures. SigFigsExponent = 8 BalancerGasFeeForSwap = 10_000 + + StableswapMaxScaledAmtPerAsset = 10_000_000_000 ) var ( diff --git a/x/gamm/types/errors.go b/x/gamm/types/errors.go index e6e8e559652..8a1ca1df76d 100644 --- a/x/gamm/types/errors.go +++ b/x/gamm/types/errors.go @@ -20,7 +20,7 @@ var ( ErrPoolAlreadyExist = sdkerrors.Register(ModuleName, 2, "pool already exist") ErrPoolLocked = sdkerrors.Register(ModuleName, 3, "pool is locked") ErrTooFewPoolAssets = sdkerrors.Register(ModuleName, 4, "pool should have at least 2 assets, as they must be swapping between at least two assets") - ErrTooManyPoolAssets = sdkerrors.Register(ModuleName, 5, "pool has too many assets (currently capped at 8 assets per balancer pool and 2 per stableswap)") + ErrTooManyPoolAssets = sdkerrors.Register(ModuleName, 5, "pool has too many assets (currently capped at 8 assets per pool)") ErrLimitMaxAmount = sdkerrors.Register(ModuleName, 6, "calculated amount is larger than max amount") ErrLimitMinAmount = sdkerrors.Register(ModuleName, 7, "calculated amount is lesser than min amount") ErrInvalidMathApprox = sdkerrors.Register(ModuleName, 8, "invalid calculated result") @@ -51,4 +51,5 @@ var ( ErrInvalidStableswapScalingFactors = sdkerrors.Register(ModuleName, 62, "length between liquidity and scaling factors mismatch") ErrNotScalingFactorGovernor = sdkerrors.Register(ModuleName, 63, "not scaling factor governor") ErrInvalidScalingFactors = sdkerrors.Register(ModuleName, 64, "invalid scaling factor") + ErrHitMaxScaledAssets = sdkerrors.Register(ModuleName, 65, "post-scaled pool assets can not exceed 10B") ) diff --git a/x/incentives/client/cli/query_test.go b/x/incentives/client/cli/query_test.go new file mode 100644 index 00000000000..a8806954497 --- /dev/null +++ b/x/incentives/client/cli/query_test.go @@ -0,0 +1,110 @@ +package cli_test + +import ( + gocontext "context" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/incentives/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + // create a pool + s.PrepareBalancerPool() + // set up lock with id = 1 + s.LockTokens(s.TestAccs[0], sdk.Coins{sdk.NewCoin("gamm/pool/1", sdk.NewInt(1000000))}, time.Hour*24) + + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query active gauges", + "/osmosis.incentives.Query/ActiveGauges", + &types.ActiveGaugesRequest{}, + &types.ActiveGaugesResponse{}, + }, + { + "Query active gauges per denom", + "/osmosis.incentives.Query/ActiveGaugesPerDenom", + &types.ActiveGaugesPerDenomRequest{Denom: "stake"}, + &types.ActiveGaugesPerDenomResponse{}, + }, + { + "Query gauge by id", + "/osmosis.incentives.Query/GaugeByID", + &types.GaugeByIDRequest{Id: 1}, + &types.GaugeByIDResponse{}, + }, + { + "Query all gauges", + "/osmosis.incentives.Query/Gauges", + &types.GaugesRequest{}, + &types.GaugesResponse{}, + }, + { + "Query lockable durations", + "/osmosis.incentives.Query/LockableDurations", + &types.QueryLockableDurationsRequest{}, + &types.QueryLockableDurationsResponse{}, + }, + { + "Query module to distibute coins", + "/osmosis.incentives.Query/ModuleToDistributeCoins", + &types.ModuleToDistributeCoinsRequest{}, + &types.ModuleToDistributeCoinsResponse{}, + }, + { + "Query reward estimate", + "/osmosis.incentives.Query/RewardsEst", + &types.RewardsEstRequest{Owner: s.TestAccs[0].String()}, + &types.RewardsEstResponse{}, + }, + { + "Query upcoming gauges", + "/osmosis.incentives.Query/UpcomingGauges", + &types.UpcomingGaugesRequest{}, + &types.UpcomingGaugesResponse{}, + }, + { + "Query upcoming gauges", + "/osmosis.incentives.Query/UpcomingGaugesPerDenom", + &types.UpcomingGaugesPerDenomRequest{Denom: "stake"}, + &types.UpcomingGaugesPerDenomResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/incentives/keeper/distribute.go b/x/incentives/keeper/distribute.go index 90f3780e6fc..e3a4d06cf01 100644 --- a/x/incentives/keeper/distribute.go +++ b/x/incentives/keeper/distribute.go @@ -386,7 +386,7 @@ func (k Keeper) checkFinishDistribution(ctx sdk.Context, gauges []types.Gauge) { // GetModuleToDistributeCoins returns sum of coins yet to be distributed for all of the module. func (k Keeper) GetModuleToDistributeCoins(ctx sdk.Context) sdk.Coins { activeGaugesDistr := k.getToDistributeCoinsFromIterator(ctx, k.ActiveGaugesIterator(ctx)) - upcomingGaugesDistr := k.getToDistributeCoinsFromIterator(ctx, k.UpcomingGaugesIteratorAfterTime(ctx, ctx.BlockTime())) + upcomingGaugesDistr := k.getToDistributeCoinsFromIterator(ctx, k.UpcomingGaugesIterator(ctx)) return activeGaugesDistr.Add(upcomingGaugesDistr...) } diff --git a/x/lockup/client/cli/cli_test.go b/x/lockup/client/cli/cli_test.go index eb3f0427d7e..2108a98a3d1 100644 --- a/x/lockup/client/cli/cli_test.go +++ b/x/lockup/client/cli/cli_test.go @@ -735,6 +735,38 @@ func (s IntegrationTestSuite) TestCmdAccountLockedLongerDurationDenom() { } } +// TestGetCmdParams tests module params CLI query commands +func (s IntegrationTestSuite) TestGetCmdParams() { + val := s.network.Validators[0] + + testCases := []struct { + name string + args []string + }{ + { + "query module params", + []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdParams() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + s.Require().NoError(err) + + var result types.QueryParamsResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) + }) + } +} + func TestIntegrationTestSuite(t *testing.T) { suite.Run(t, new(IntegrationTestSuite)) } diff --git a/x/lockup/client/cli/query.go b/x/lockup/client/cli/query.go index 6977e0625b3..634e41a6826 100644 --- a/x/lockup/client/cli/query.go +++ b/x/lockup/client/cli/query.go @@ -48,6 +48,7 @@ func GetQueryCmd() *cobra.Command { GetCmdOutputLocksJson(), GetCmdSyntheticLockupsByLockupID(), GetCmdAccountLockedDuration(), + GetCmdParams(), ) return cmd @@ -799,3 +800,39 @@ $ %s query lockup output-all-locks return cmd } + +// GetCmdParams returns module params. +func GetCmdParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Short: "Query module params", + Long: strings.TrimSpace( + fmt.Sprintf(`Query module params. + +Example: +$ %s query lockup params +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/lockup/client/cli/query_test.go b/x/lockup/client/cli/query_test.go new file mode 100644 index 00000000000..9532c5137d3 --- /dev/null +++ b/x/lockup/client/cli/query_test.go @@ -0,0 +1,152 @@ +package cli_test + +import ( + gocontext "context" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/lockup/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + // create a pool + s.PrepareBalancerPool() + // set up lock with id = 1 + s.LockTokens(s.TestAccs[0], sdk.Coins{sdk.NewCoin("gamm/pool/1", sdk.NewInt(1000000))}, time.Hour*24) + + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query account locked coins", + "/osmosis.lockup.Query/AccountLockedCoins", + &types.AccountLockedCoinsRequest{Owner: s.TestAccs[0].String()}, + &types.AccountLockedCoinsResponse{}, + }, + { + "Query account locked by duration", + "/osmosis.lockup.Query/AccountLockedDuration", + &types.AccountLockedDurationRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour * 24}, + &types.AccountLockedDurationResponse{}, + }, + { + "Query account locked longer than given duration", + "/osmosis.lockup.Query/AccountLockedLongerDuration", + &types.AccountLockedLongerDurationRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour}, + &types.AccountLockedLongerDurationResponse{}, + }, + { + "Query account locked by denom that longer than given duration", + "/osmosis.lockup.Query/AccountLockedLongerDurationDenom", + &types.AccountLockedLongerDurationDenomRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour, Denom: "gamm/pool/1"}, + &types.AccountLockedLongerDurationDenomResponse{}, + }, + { + "Query account locked longer than given duration not unlocking", + "/osmosis.lockup.Query/AccountLockedLongerDurationNotUnlockingOnly", + &types.AccountLockedLongerDurationNotUnlockingOnlyRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour}, + &types.AccountLockedLongerDurationNotUnlockingOnlyResponse{}, + }, + { + "Query account locked in past time", + "/osmosis.lockup.Query/AccountLockedPastTime", + &types.AccountLockedPastTimeRequest{Owner: s.TestAccs[0].String()}, + &types.AccountLockedPastTimeResponse{}, + }, + { + "Query account locked in past time by denom", + "/osmosis.lockup.Query/AccountLockedPastTimeDenom", + &types.AccountLockedPastTimeDenomRequest{Owner: s.TestAccs[0].String(), Denom: "gamm/pool/1"}, + &types.AccountLockedPastTimeDenomResponse{}, + }, + { + " Query account locked in past time that not unlocking", + "/osmosis.lockup.Query/AccountLockedPastTimeNotUnlockingOnly", + &types.AccountLockedPastTimeNotUnlockingOnlyRequest{Owner: s.TestAccs[0].String()}, + &types.AccountLockedPastTimeNotUnlockingOnlyResponse{}, + }, + { + "Query account unlockable coins", + "/osmosis.lockup.Query/AccountUnlockableCoins", + &types.AccountUnlockableCoinsRequest{Owner: s.TestAccs[0].String()}, + &types.AccountUnlockableCoinsResponse{}, + }, + { + "Query account unlocked before given time", + "/osmosis.lockup.Query/AccountUnlockedBeforeTime", + &types.AccountUnlockedBeforeTimeRequest{Owner: s.TestAccs[0].String()}, + &types.AccountUnlockedBeforeTimeResponse{}, + }, + { + "Query account unlocking coins", + "/osmosis.lockup.Query/AccountUnlockingCoins", + &types.AccountUnlockingCoinsRequest{Owner: s.TestAccs[0].String()}, + &types.AccountUnlockingCoinsResponse{}, + }, + { + "Query lock by id", + "/osmosis.lockup.Query/LockedByID", + &types.LockedRequest{LockId: 1}, + &types.LockedResponse{}, + }, + { + "Query lock by denom", + "/osmosis.lockup.Query/LockedDenom", + &types.LockedDenomRequest{Duration: time.Hour * 24, Denom: "gamm/pool/1"}, + &types.LockedDenomResponse{}, + }, + { + "Query module balances", + "/osmosis.lockup.Query/ModuleBalance", + &types.ModuleBalanceRequest{}, + &types.ModuleBalanceResponse{}, + }, + { + "Query module locked amount", + "/osmosis.lockup.Query/ModuleLockedAmount", + &types.ModuleLockedAmountRequest{}, + &types.ModuleLockedAmountResponse{}, + }, + { + "Query synthetic lock by id", + "/osmosis.lockup.Query/SyntheticLockupsByLockupID", + &types.SyntheticLockupsByLockupIDRequest{LockId: 1}, + &types.SyntheticLockupsByLockupIDResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/lockup/keeper/genesis.go b/x/lockup/keeper/genesis.go index 13deb6cb77c..da14e318c48 100644 --- a/x/lockup/keeper/genesis.go +++ b/x/lockup/keeper/genesis.go @@ -9,6 +9,7 @@ import ( // InitGenesis initializes the capability module's state from a provided genesis // state. func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { + k.SetParams(ctx, types.DefaultParams()) k.SetLastLockID(ctx, genState.LastLockId) if err := k.InitializeAllLocks(ctx, genState.Locks); err != nil { return diff --git a/x/lockup/keeper/grpc_query.go b/x/lockup/keeper/grpc_query.go index 08e251b64d8..af1ce919517 100644 --- a/x/lockup/keeper/grpc_query.go +++ b/x/lockup/keeper/grpc_query.go @@ -285,3 +285,9 @@ func (q Querier) LockedDenom(goCtx context.Context, req *types.LockedDenomReques ctx := sdk.UnwrapSDKContext(goCtx) return &types.LockedDenomResponse{Amount: q.Keeper.GetLockedDenom(ctx, req.Denom, req.Duration)}, nil } + +// Params returns module params +func (q Querier) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + return &types.QueryParamsResponse{Params: q.Keeper.GetParams(ctx)}, nil +} diff --git a/x/lockup/keeper/grpc_query_test.go b/x/lockup/keeper/grpc_query_test.go index 6de4b1e0059..91556ee29b9 100644 --- a/x/lockup/keeper/grpc_query_test.go +++ b/x/lockup/keeper/grpc_query_test.go @@ -513,3 +513,18 @@ func (suite *KeeperTestSuite) TestLockedDenom() { testTotalLockedDuration("2h", 0) testTotalLockedDuration("1h", 10) } + +func (suite *KeeperTestSuite) TestParams() { + suite.SetupTest() + + // Query default params + res, err := suite.querier.Params(sdk.WrapSDKContext(suite.Ctx), &types.QueryParamsRequest{}) + suite.Require().NoError(err) + suite.Require().Equal([]string(nil), res.Params.ForceUnlockAllowedAddresses) + + // Set new params & query + suite.App.LockupKeeper.SetParams(suite.Ctx, types.NewParams([]string{suite.TestAccs[0].String()})) + res, err = suite.querier.Params(sdk.WrapSDKContext(suite.Ctx), &types.QueryParamsRequest{}) + suite.Require().NoError(err) + suite.Require().Equal([]string{suite.TestAccs[0].String()}, res.Params.ForceUnlockAllowedAddresses) +} diff --git a/x/lockup/types/query.pb.go b/x/lockup/types/query.pb.go index 14c0be97d39..1aca6de8f7a 100644 --- a/x/lockup/types/query.pb.go +++ b/x/lockup/types/query.pb.go @@ -1528,6 +1528,86 @@ func (m *AccountLockedLongerDurationDenomResponse) GetLocks() []PeriodLock { return nil } +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_e906fda01cffd91a, []int{32} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +type QueryParamsResponse struct { + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_e906fda01cffd91a, []int{33} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + func init() { proto.RegisterType((*ModuleBalanceRequest)(nil), "osmosis.lockup.ModuleBalanceRequest") proto.RegisterType((*ModuleBalanceResponse)(nil), "osmosis.lockup.ModuleBalanceResponse") @@ -1561,102 +1641,108 @@ func init() { proto.RegisterType((*AccountLockedLongerDurationNotUnlockingOnlyResponse)(nil), "osmosis.lockup.AccountLockedLongerDurationNotUnlockingOnlyResponse") proto.RegisterType((*AccountLockedLongerDurationDenomRequest)(nil), "osmosis.lockup.AccountLockedLongerDurationDenomRequest") proto.RegisterType((*AccountLockedLongerDurationDenomResponse)(nil), "osmosis.lockup.AccountLockedLongerDurationDenomResponse") + proto.RegisterType((*QueryParamsRequest)(nil), "osmosis.lockup.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "osmosis.lockup.QueryParamsResponse") } func init() { proto.RegisterFile("osmosis/lockup/query.proto", fileDescriptor_e906fda01cffd91a) } var fileDescriptor_e906fda01cffd91a = []byte{ - // 1426 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xce, 0xb4, 0x4d, 0xa1, 0xaf, 0xf4, 0x87, 0x86, 0xb6, 0x24, 0xdb, 0xd6, 0x4e, 0xb7, 0x6d, - 0x30, 0x10, 0xef, 0x36, 0x6e, 0x95, 0x96, 0x2a, 0x6d, 0x52, 0xc7, 0x04, 0x05, 0x19, 0x68, 0xdd, - 0x42, 0xc5, 0x2f, 0x59, 0x6b, 0x7b, 0xeb, 0xae, 0x62, 0xef, 0xb8, 0xde, 0x75, 0xc1, 0x54, 0xa5, - 0xa2, 0xe5, 0xc8, 0xa1, 0x88, 0x0b, 0xe2, 0x80, 0x80, 0x1b, 0x1c, 0x10, 0x17, 0x0e, 0x15, 0x77, - 0x54, 0x81, 0x84, 0x2a, 0x71, 0x41, 0x1c, 0x52, 0x94, 0xf0, 0x17, 0xe4, 0xc4, 0x11, 0xed, 0xcc, - 0xec, 0xc6, 0xbb, 0xde, 0x5d, 0xef, 0xda, 0x24, 0xca, 0xc9, 0x3f, 0xe6, 0xcd, 0x7b, 0xdf, 0xf7, - 0xcd, 0xdb, 0x99, 0xf9, 0x16, 0x04, 0x62, 0xd4, 0x89, 0xa1, 0x19, 0x72, 0x8d, 0x94, 0x17, 0x5b, - 0x0d, 0xf9, 0x46, 0x4b, 0x6d, 0xb6, 0xa5, 0x46, 0x93, 0x98, 0x04, 0xef, 0xe6, 0x63, 0x12, 0x1b, - 0x13, 0xf6, 0x55, 0x49, 0x95, 0xd0, 0x21, 0xd9, 0xfa, 0xc6, 0xa2, 0x84, 0x44, 0x99, 0x86, 0xc9, - 0x25, 0xc5, 0x50, 0xe5, 0x9b, 0x93, 0x25, 0xd5, 0x54, 0x26, 0xe5, 0x32, 0xd1, 0x74, 0x3e, 0x7e, - 0xa8, 0x4a, 0x48, 0xb5, 0xa6, 0xca, 0x4a, 0x43, 0x93, 0x15, 0x5d, 0x27, 0xa6, 0x62, 0x6a, 0x44, - 0x37, 0xf8, 0x68, 0x92, 0x8f, 0xd2, 0x5f, 0xa5, 0xd6, 0x35, 0xd9, 0xd4, 0xea, 0xaa, 0x61, 0x2a, - 0xf5, 0x86, 0x9d, 0xde, 0x1b, 0x50, 0x69, 0x35, 0x69, 0x06, 0x3e, 0x3e, 0xea, 0x21, 0x60, 0x7d, - 0xb0, 0x21, 0xf1, 0x00, 0xec, 0x7b, 0x95, 0x54, 0x5a, 0x35, 0x35, 0xab, 0xd4, 0x14, 0xbd, 0xac, - 0x16, 0xd4, 0x1b, 0x2d, 0xd5, 0x30, 0xc5, 0x0f, 0x61, 0xbf, 0xe7, 0x7f, 0xa3, 0x41, 0x74, 0x43, - 0xc5, 0x0a, 0x0c, 0x5b, 0xc0, 0x8d, 0x11, 0x34, 0xb6, 0x35, 0xb5, 0x33, 0x33, 0x2a, 0x31, 0x6a, - 0x92, 0x45, 0x4d, 0xe2, 0xd4, 0xa4, 0x39, 0xa2, 0xe9, 0xd9, 0x13, 0x0f, 0x97, 0x92, 0x43, 0xdf, - 0x3f, 0x4e, 0xa6, 0xaa, 0x9a, 0x79, 0xbd, 0x55, 0x92, 0xca, 0xa4, 0x2e, 0x73, 0x1d, 0xd8, 0x47, - 0xda, 0xa8, 0x2c, 0xca, 0x66, 0xbb, 0xa1, 0x1a, 0x74, 0x82, 0x51, 0x60, 0x99, 0xc5, 0x83, 0x30, - 0xca, 0x6a, 0xe7, 0x49, 0x79, 0x51, 0xad, 0x5c, 0xa8, 0x93, 0x96, 0x6e, 0xda, 0xc0, 0xee, 0x80, - 0xe0, 0x37, 0xb8, 0x71, 0xe8, 0x5e, 0x86, 0xc3, 0x17, 0xca, 0x65, 0xab, 0xea, 0x1b, 0xba, 0x25, - 0xa4, 0x52, 0xaa, 0xa9, 0x2c, 0x80, 0x21, 0xc4, 0xe3, 0x30, 0x4c, 0xde, 0xd7, 0xd5, 0xe6, 0x08, - 0x1a, 0x43, 0xa9, 0x1d, 0xd9, 0xbd, 0xab, 0x4b, 0xc9, 0xa7, 0xda, 0x4a, 0xbd, 0x76, 0x56, 0xa4, - 0x7f, 0x8b, 0x05, 0x36, 0x2c, 0xde, 0x43, 0x90, 0x08, 0xca, 0xb4, 0x71, 0x74, 0xe6, 0xe1, 0x90, - 0x0b, 0x84, 0xa6, 0x57, 0xfb, 0x62, 0x73, 0x17, 0x79, 0x74, 0x59, 0x4b, 0xb4, 0x71, 0x64, 0xe6, - 0x60, 0x94, 0x63, 0x60, 0xdd, 0xd1, 0x17, 0x93, 0x3b, 0x20, 0xf8, 0x25, 0xd9, 0x38, 0x16, 0x5f, - 0x21, 0x67, 0x4d, 0x18, 0x82, 0x8b, 0x8a, 0x61, 0x5e, 0xd1, 0xea, 0x6a, 0x4c, 0x26, 0xf8, 0x4d, - 0xd8, 0xe1, 0x6c, 0x15, 0x23, 0x5b, 0xc6, 0x50, 0x6a, 0x67, 0x46, 0x90, 0xd8, 0x5e, 0x21, 0xd9, - 0x7b, 0x85, 0x74, 0xc5, 0x8e, 0xc8, 0x1e, 0xb2, 0x00, 0xaf, 0x2e, 0x25, 0xf7, 0xb2, 0x5c, 0xce, - 0x54, 0xf1, 0xfe, 0xe3, 0x24, 0x2a, 0xac, 0xa5, 0x12, 0xaf, 0x3a, 0x4b, 0xed, 0xc5, 0xc7, 0x45, - 0x9a, 0x82, 0x61, 0xab, 0x05, 0x6c, 0x91, 0x04, 0xc9, 0xbd, 0x4b, 0x4a, 0x17, 0xd5, 0xa6, 0x46, - 0x2a, 0xd6, 0xe4, 0xec, 0x36, 0xab, 0x68, 0x81, 0x85, 0x8b, 0x3f, 0x20, 0x98, 0xf0, 0xcd, 0xfc, - 0x1a, 0x59, 0xeb, 0xaa, 0xd7, 0xf5, 0x5a, 0x7b, 0xb3, 0x28, 0x51, 0x85, 0x74, 0x44, 0xbc, 0x03, - 0x2a, 0xf3, 0x2d, 0x82, 0x31, 0xd7, 0xe3, 0xa5, 0x56, 0xb2, 0xea, 0x35, 0xd2, 0x54, 0x37, 0x53, - 0x5f, 0xbc, 0x03, 0x47, 0x42, 0x30, 0x0e, 0xa8, 0xc0, 0x03, 0xe4, 0x64, 0x77, 0x6b, 0x9d, 0x53, - 0x75, 0x52, 0xdf, 0x24, 0x12, 0xe0, 0x7d, 0x30, 0x5c, 0xb1, 0xf0, 0x8c, 0x6c, 0xb5, 0xea, 0x17, - 0xd8, 0x0f, 0xf1, 0x5d, 0x10, 0xc3, 0xa0, 0x0f, 0xa8, 0xcc, 0x47, 0x80, 0x59, 0x5a, 0x97, 0x12, - 0x0e, 0x12, 0xd4, 0x81, 0x04, 0x17, 0xe0, 0x49, 0xfb, 0x72, 0xc0, 0x69, 0x8f, 0x76, 0xd1, 0xce, - 0xf1, 0x80, 0xec, 0x41, 0xce, 0x7a, 0x0f, 0x63, 0x6d, 0x4f, 0x14, 0xbf, 0xb0, 0x48, 0x3b, 0x79, - 0x44, 0x1d, 0x9e, 0x76, 0xd5, 0xe7, 0x74, 0xae, 0xc2, 0x76, 0x85, 0x9e, 0xce, 0x7c, 0x2d, 0x66, - 0xac, 0x6c, 0x7f, 0x2d, 0x25, 0xc7, 0x23, 0xec, 0x87, 0x0b, 0xba, 0xb9, 0xba, 0x94, 0xdc, 0xc5, - 0xea, 0xb2, 0x2c, 0x62, 0x81, 0xa7, 0x13, 0x53, 0xb0, 0x8b, 0xd5, 0xb3, 0xa9, 0x3e, 0x03, 0x4f, - 0x58, 0x4a, 0x14, 0xb5, 0x0a, 0x2d, 0xb5, 0xad, 0xb0, 0xdd, 0xfa, 0xb9, 0x50, 0x11, 0x67, 0x61, - 0xb7, 0x1d, 0xc9, 0x41, 0x49, 0xb0, 0xcd, 0x1a, 0xa3, 0x71, 0xa1, 0x12, 0x17, 0x68, 0x9c, 0x38, - 0x0d, 0x47, 0x2e, 0xb7, 0x75, 0xf3, 0xba, 0x6a, 0x6a, 0xe5, 0x3c, 0x8d, 0x31, 0xb2, 0x6d, 0xf6, - 0x65, 0x21, 0xd7, 0xb3, 0x7e, 0x13, 0xc4, 0xb0, 0xd9, 0x1c, 0x53, 0x1e, 0xf6, 0x18, 0x76, 0x54, - 0xb1, 0xb3, 0x03, 0x0e, 0x7b, 0xe1, 0xb9, 0x92, 0xf1, 0x26, 0xd8, 0x6d, 0x74, 0xfe, 0x69, 0x88, - 0x5f, 0x23, 0x4f, 0xb3, 0xe5, 0x89, 0x5e, 0x55, 0x9b, 0xf6, 0xa2, 0xc6, 0x7d, 0x50, 0xd6, 0xa3, - 0x61, 0xde, 0x83, 0xa3, 0xa1, 0x08, 0x07, 0x7c, 0x1e, 0xbe, 0xf4, 0x9e, 0x9f, 0x9b, 0x89, 0xbb, - 0xf7, 0xec, 0xfc, 0xdf, 0x58, 0xff, 0x88, 0x20, 0x13, 0xa2, 0xea, 0xa0, 0x27, 0xe8, 0x7a, 0x68, - 0x51, 0x87, 0x93, 0xb1, 0x10, 0x0f, 0xa8, 0xd0, 0xcf, 0x08, 0x9e, 0x0d, 0xa9, 0xd7, 0xd7, 0x39, - 0xb2, 0x0e, 0xb2, 0x04, 0x9c, 0x21, 0x25, 0x48, 0xf5, 0x06, 0x3f, 0x98, 0x42, 0x99, 0x8f, 0x47, - 0x60, 0xf8, 0x92, 0xe5, 0x6e, 0xf1, 0xa7, 0x08, 0x76, 0xb9, 0x0c, 0x20, 0x3e, 0xe6, 0x4d, 0xe2, - 0xe7, 0x1b, 0x85, 0xe3, 0x3d, 0xa2, 0x18, 0x40, 0x51, 0xba, 0xfb, 0xc7, 0x3f, 0x9f, 0x6f, 0x49, - 0xe1, 0x71, 0xd9, 0x63, 0x4d, 0x6d, 0x73, 0x5c, 0xa7, 0xd3, 0x8a, 0x25, 0x5e, 0xfc, 0x1b, 0x04, - 0xb8, 0xdb, 0xf6, 0xe1, 0xe7, 0xfc, 0xab, 0xf9, 0xf8, 0x46, 0xe1, 0xf9, 0x28, 0xa1, 0x1c, 0xdd, - 0x29, 0x8a, 0x4e, 0xc2, 0x13, 0x3d, 0xd0, 0xb1, 0x3b, 0x4e, 0x91, 0x1d, 0x4b, 0xf8, 0x01, 0x82, - 0x03, 0xfe, 0x7e, 0x0e, 0xa7, 0xbd, 0xc5, 0x43, 0x1d, 0xa4, 0x20, 0x45, 0x0d, 0xe7, 0x78, 0x67, - 0x29, 0xde, 0xb3, 0xf8, 0x4c, 0x10, 0x5e, 0x85, 0xcd, 0x2f, 0xb6, 0x9c, 0x04, 0x45, 0x6a, 0x35, - 0xe4, 0x5b, 0xb4, 0x8b, 0x6f, 0xe3, 0x9f, 0x10, 0xec, 0xf7, 0x75, 0x6f, 0x78, 0x22, 0x14, 0x8b, - 0xc7, 0x2d, 0x0a, 0xe9, 0x88, 0xd1, 0x1c, 0xf8, 0x0c, 0x05, 0xfe, 0x22, 0x3e, 0x1d, 0x0d, 0xb8, - 0xa6, 0x57, 0x3d, 0xb8, 0xbf, 0x43, 0x80, 0xbb, 0xcd, 0x5a, 0x77, 0x5f, 0x04, 0xba, 0xc2, 0xee, - 0xbe, 0x08, 0xf6, 0x7e, 0xe2, 0x34, 0x85, 0x3b, 0x85, 0x4f, 0xf5, 0x82, 0xcb, 0x1b, 0x23, 0x50, - 0x63, 0xf7, 0x2d, 0x30, 0x50, 0x63, 0x5f, 0xf7, 0x17, 0xa8, 0xb1, 0xbf, 0x17, 0x8b, 0xae, 0x31, - 0x07, 0xdd, 0x50, 0x0c, 0xd3, 0xba, 0xcf, 0x3a, 0xb8, 0xff, 0x45, 0x70, 0x3c, 0x92, 0xc9, 0xc1, - 0xd3, 0x91, 0x90, 0x05, 0x9c, 0x44, 0xc2, 0xb9, 0x3e, 0x67, 0x73, 0x9e, 0x05, 0xca, 0x33, 0x8f, - 0x5f, 0x89, 0xc9, 0xb3, 0xa8, 0x93, 0xce, 0xfe, 0x22, 0x7a, 0xad, 0xed, 0x50, 0xff, 0x05, 0x39, - 0x2f, 0x14, 0xba, 0x1d, 0x0d, 0x3e, 0x11, 0xda, 0xec, 0x3e, 0x06, 0x4d, 0x98, 0x8c, 0x31, 0x83, - 0xd3, 0xca, 0x51, 0x5a, 0xe7, 0xf1, 0x74, 0xb4, 0x47, 0x44, 0xad, 0x14, 0x4b, 0x34, 0x49, 0xd1, - 0xb5, 0x86, 0xbf, 0x22, 0xcf, 0x4b, 0x0d, 0x97, 0x03, 0xc1, 0x93, 0x91, 0xa4, 0xef, 0x3c, 0x20, - 0x85, 0x4c, 0x9c, 0x29, 0x9c, 0xcb, 0x4b, 0x94, 0xcb, 0x0c, 0x3e, 0x17, 0x77, 0x89, 0xe8, 0x09, - 0xe8, 0x90, 0xf9, 0x04, 0xc1, 0xce, 0x0e, 0xc3, 0x81, 0x45, 0x2f, 0x94, 0x6e, 0x37, 0x24, 0x1c, - 0x0d, 0x8d, 0xe1, 0xf8, 0x26, 0x28, 0xbe, 0x71, 0x7c, 0x2c, 0x08, 0x1f, 0xc7, 0xc5, 0xac, 0xd4, - 0x3d, 0x04, 0xc0, 0xb2, 0x64, 0xdb, 0x0b, 0x39, 0x7c, 0xd8, 0xbf, 0x82, 0x0d, 0x20, 0x11, 0x34, - 0xcc, 0x6b, 0x4f, 0xd1, 0xda, 0x27, 0xb0, 0xd4, 0xa3, 0x76, 0xa9, 0x5d, 0xd4, 0x2a, 0xf2, 0x2d, - 0xee, 0x37, 0x6e, 0xe3, 0xdf, 0x10, 0x08, 0xc1, 0x1e, 0xa3, 0x7b, 0x65, 0x7b, 0xba, 0x99, 0xee, - 0x95, 0xed, 0x6d, 0x61, 0xc4, 0x79, 0x8a, 0x7e, 0x16, 0x9f, 0x0f, 0x42, 0xef, 0x36, 0x38, 0xad, - 0x86, 0x61, 0x11, 0xe1, 0x24, 0x3a, 0xd8, 0xfc, 0x8e, 0xe0, 0x60, 0xc8, 0x2d, 0x07, 0x87, 0x77, - 0x9d, 0xaf, 0xd3, 0x11, 0x4e, 0xc6, 0x9a, 0x13, 0x95, 0x90, 0xa7, 0x55, 0x6b, 0x34, 0x4d, 0xd1, - 0xbe, 0xc3, 0x05, 0x6f, 0xfa, 0x0e, 0x95, 0xf0, 0x4d, 0xdf, 0x4b, 0x22, 0x1d, 0x31, 0xba, 0xcf, - 0x4d, 0xbf, 0x0b, 0xf7, 0x67, 0x5b, 0xe0, 0x85, 0x18, 0x77, 0x73, 0x9c, 0x8d, 0x21, 0x72, 0xd0, - 0x01, 0x30, 0x37, 0x50, 0x0e, 0xce, 0xfc, 0x2d, 0xca, 0xfc, 0x32, 0xbe, 0xd4, 0xdf, 0xc2, 0x85, - 0x9d, 0x06, 0x2b, 0x6b, 0xef, 0xe0, 0x02, 0xaf, 0xe0, 0xf8, 0x74, 0x0c, 0x12, 0xae, 0x1d, 0xea, - 0x4c, 0xfc, 0x89, 0x9c, 0x72, 0x9e, 0x52, 0x9e, 0xc7, 0xb9, 0x3e, 0x29, 0xbb, 0x76, 0xd7, 0x6c, - 0xfe, 0xe1, 0x72, 0x02, 0x3d, 0x5a, 0x4e, 0xa0, 0xbf, 0x97, 0x13, 0xe8, 0xfe, 0x4a, 0x62, 0xe8, - 0xd1, 0x4a, 0x62, 0xe8, 0xcf, 0x95, 0xc4, 0xd0, 0xdb, 0x99, 0x8e, 0x17, 0x37, 0xbc, 0x52, 0xba, - 0xa6, 0x94, 0x0c, 0xa7, 0xec, 0xcd, 0xc9, 0x8c, 0xfc, 0x81, 0x5d, 0x9c, 0xbe, 0xc8, 0x29, 0x6d, - 0xa7, 0x2e, 0xe8, 0xe4, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xbc, 0x1f, 0x4f, 0x44, 0x1b, - 0x00, 0x00, + // 1492 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xcd, 0x8f, 0x14, 0x45, + 0x14, 0xdf, 0x02, 0x76, 0x95, 0x87, 0x7c, 0xa4, 0x58, 0x70, 0xb7, 0x17, 0x66, 0x96, 0x02, 0xd6, + 0x51, 0x77, 0xbb, 0xd9, 0x81, 0x00, 0x92, 0xe5, 0x6b, 0x58, 0x31, 0xab, 0xa3, 0xc2, 0x80, 0x12, + 0xbf, 0x32, 0xe9, 0x99, 0x69, 0x86, 0x0e, 0x33, 0x5d, 0xc3, 0x74, 0x0f, 0x3a, 0x12, 0x24, 0x01, + 0x8f, 0x1e, 0x30, 0x5e, 0x8c, 0x07, 0xa3, 0xde, 0xf4, 0x60, 0xbc, 0x78, 0x20, 0xde, 0x0d, 0xd1, + 0xc4, 0x90, 0x78, 0x31, 0x1e, 0x16, 0xc3, 0xfa, 0x17, 0x70, 0xf2, 0xe0, 0xc1, 0x74, 0x55, 0x75, + 0xef, 0xf4, 0xe7, 0xf4, 0xcc, 0xb8, 0x9b, 0x3d, 0xed, 0x4e, 0xbf, 0x57, 0xef, 0xfd, 0x7e, 0xaf, + 0x5e, 0xbf, 0xaa, 0x5f, 0x83, 0x44, 0xcd, 0x3a, 0x35, 0x75, 0x53, 0xa9, 0xd1, 0xf2, 0xd5, 0x56, + 0x43, 0xb9, 0xd6, 0xd2, 0x9a, 0x6d, 0xb9, 0xd1, 0xa4, 0x16, 0xc5, 0x5b, 0x84, 0x4d, 0xe6, 0x36, + 0x69, 0xb4, 0x4a, 0xab, 0x94, 0x99, 0x14, 0xfb, 0x3f, 0xee, 0x25, 0xa5, 0xca, 0xcc, 0x4d, 0x29, + 0xa9, 0xa6, 0xa6, 0x5c, 0x9f, 0x2d, 0x69, 0x96, 0x3a, 0xab, 0x94, 0xa9, 0x6e, 0x08, 0xfb, 0xae, + 0x2a, 0xa5, 0xd5, 0x9a, 0xa6, 0xa8, 0x0d, 0x5d, 0x51, 0x0d, 0x83, 0x5a, 0xaa, 0xa5, 0x53, 0xc3, + 0x14, 0xd6, 0xb4, 0xb0, 0xb2, 0x5f, 0xa5, 0xd6, 0x65, 0xc5, 0xd2, 0xeb, 0x9a, 0x69, 0xa9, 0xf5, + 0x86, 0x13, 0xde, 0xef, 0x50, 0x69, 0x35, 0x59, 0x04, 0x61, 0x1f, 0xf7, 0x11, 0xb0, 0xff, 0x08, + 0xd3, 0x84, 0xcf, 0xd4, 0x50, 0x9b, 0x6a, 0x5d, 0x24, 0x26, 0x3b, 0x61, 0xf4, 0x55, 0x5a, 0x69, + 0xd5, 0xb4, 0x9c, 0x5a, 0x53, 0x8d, 0xb2, 0x56, 0xd0, 0xae, 0xb5, 0x34, 0xd3, 0x22, 0x1f, 0xc2, + 0x0e, 0xdf, 0x73, 0xb3, 0x41, 0x0d, 0x53, 0xc3, 0x2a, 0x0c, 0xdb, 0xac, 0xcc, 0x31, 0x34, 0xb9, + 0x3e, 0xb3, 0x29, 0x3b, 0x2e, 0x73, 0xde, 0xb2, 0xcd, 0x5b, 0x16, 0xbc, 0xe5, 0x33, 0x54, 0x37, + 0x72, 0x07, 0xee, 0x2f, 0xa6, 0x87, 0xbe, 0x7b, 0x98, 0xce, 0x54, 0x75, 0xeb, 0x4a, 0xab, 0x24, + 0x97, 0x69, 0x5d, 0x11, 0x45, 0xe2, 0x7f, 0x66, 0xcc, 0xca, 0x55, 0xc5, 0x6a, 0x37, 0x34, 0x93, + 0x2d, 0x30, 0x0b, 0x3c, 0x32, 0x99, 0x80, 0x71, 0x9e, 0x3b, 0x4f, 0xcb, 0x57, 0xb5, 0xca, 0xe9, + 0x3a, 0x6d, 0x19, 0x96, 0x03, 0xec, 0x16, 0x48, 0x61, 0xc6, 0xd5, 0x43, 0xf7, 0x12, 0xec, 0x3e, + 0x5d, 0x2e, 0xdb, 0x59, 0xdf, 0x30, 0xec, 0x8a, 0xaa, 0xa5, 0x9a, 0xc6, 0x1d, 0x38, 0x42, 0x3c, + 0x05, 0xc3, 0xf4, 0x7d, 0x43, 0x6b, 0x8e, 0xa1, 0x49, 0x94, 0xd9, 0x98, 0xdb, 0xf6, 0x78, 0x31, + 0xfd, 0x54, 0x5b, 0xad, 0xd7, 0x8e, 0x11, 0xf6, 0x98, 0x14, 0xb8, 0x99, 0xdc, 0x41, 0x90, 0x8a, + 0x8a, 0xb4, 0x7a, 0x74, 0xce, 0xc2, 0x2e, 0x0f, 0x08, 0xdd, 0xa8, 0xf6, 0xc5, 0xe6, 0x36, 0xf2, + 0xd5, 0x65, 0x39, 0xd0, 0xea, 0x91, 0x39, 0x03, 0xe3, 0x02, 0x03, 0xef, 0x8e, 0xbe, 0x98, 0xdc, + 0x02, 0x29, 0x2c, 0xc8, 0xea, 0xb1, 0xf8, 0x12, 0xb9, 0x7b, 0xc2, 0x11, 0x9c, 0x53, 0x4d, 0xeb, + 0xa2, 0x5e, 0xd7, 0x7a, 0x64, 0x82, 0xdf, 0x84, 0x8d, 0xee, 0x1c, 0x19, 0x5b, 0x37, 0x89, 0x32, + 0x9b, 0xb2, 0x92, 0xcc, 0x07, 0x89, 0xec, 0x0c, 0x12, 0xf9, 0xa2, 0xe3, 0x91, 0xdb, 0x65, 0x03, + 0x7e, 0xbc, 0x98, 0xde, 0xc6, 0x63, 0xb9, 0x4b, 0xc9, 0xdd, 0x87, 0x69, 0x54, 0x58, 0x0e, 0x45, + 0x2e, 0xb9, 0x5b, 0xed, 0xc7, 0x27, 0x8a, 0x74, 0x18, 0x86, 0xed, 0x16, 0x70, 0x8a, 0x24, 0xc9, + 0xde, 0x11, 0x2a, 0x9f, 0xd3, 0x9a, 0x3a, 0xad, 0xd8, 0x8b, 0x73, 0x1b, 0xec, 0xa4, 0x05, 0xee, + 0x4e, 0xbe, 0x47, 0x30, 0x1d, 0x1a, 0xf9, 0x35, 0xba, 0xdc, 0x55, 0xaf, 0x1b, 0xb5, 0xf6, 0x5a, + 0xa9, 0x44, 0x15, 0x66, 0x12, 0xe2, 0x1d, 0xb0, 0x32, 0xdf, 0x20, 0x98, 0xf4, 0xbc, 0x5e, 0x5a, + 0x25, 0xa7, 0x5d, 0xa6, 0x4d, 0x6d, 0x2d, 0xf5, 0xc5, 0x3b, 0xb0, 0x27, 0x06, 0xe3, 0x80, 0x15, + 0xb8, 0x87, 0xdc, 0xe8, 0xde, 0x5a, 0xcf, 0x6b, 0x06, 0xad, 0xaf, 0x91, 0x12, 0xe0, 0x51, 0x18, + 0xae, 0xd8, 0x78, 0xc6, 0xd6, 0xdb, 0xf9, 0x0b, 0xfc, 0x07, 0x79, 0x17, 0x48, 0x1c, 0xf4, 0x01, + 0x2b, 0xf3, 0x11, 0x60, 0x1e, 0xd6, 0x53, 0x09, 0x17, 0x09, 0xea, 0x40, 0x82, 0x0b, 0xf0, 0xa4, + 0x73, 0x73, 0x10, 0xb4, 0xc7, 0x03, 0xb4, 0xe7, 0x85, 0x43, 0x6e, 0x42, 0xb0, 0xde, 0xca, 0x59, + 0x3b, 0x0b, 0xc9, 0xe7, 0x36, 0x69, 0x37, 0x0e, 0x31, 0x60, 0xbb, 0x27, 0xbf, 0xa0, 0x73, 0x09, + 0x46, 0x54, 0x76, 0x3a, 0x8b, 0xbd, 0x38, 0x69, 0x47, 0xfb, 0x73, 0x31, 0x3d, 0x95, 0x60, 0x1e, + 0x2e, 0x18, 0xd6, 0xe3, 0xc5, 0xf4, 0x66, 0x9e, 0x97, 0x47, 0x21, 0x05, 0x11, 0x8e, 0x64, 0x60, + 0x33, 0xcf, 0xe7, 0x50, 0x7d, 0x1a, 0x9e, 0xb0, 0x2b, 0x51, 0xd4, 0x2b, 0x2c, 0xd5, 0x86, 0xc2, + 0x88, 0xfd, 0x73, 0xa1, 0x42, 0x4e, 0xc1, 0x16, 0xc7, 0x53, 0x80, 0x92, 0x61, 0x83, 0x6d, 0x63, + 0x7e, 0xb1, 0x25, 0x2e, 0x30, 0x3f, 0x32, 0x07, 0x7b, 0x2e, 0xb4, 0x0d, 0xeb, 0x8a, 0x66, 0xe9, + 0xe5, 0x3c, 0xf3, 0x31, 0x73, 0x6d, 0xfe, 0xcf, 0xc2, 0x7c, 0xd7, 0xfc, 0x4d, 0x20, 0x71, 0xab, + 0x05, 0xa6, 0x3c, 0x6c, 0x35, 0x1d, 0xaf, 0x62, 0x67, 0x07, 0xec, 0xf6, 0xc3, 0xf3, 0x04, 0x13, + 0x4d, 0xb0, 0xc5, 0xec, 0x7c, 0x68, 0x92, 0xaf, 0x90, 0xaf, 0xd9, 0xf2, 0xd4, 0xa8, 0x6a, 0x4d, + 0x67, 0x53, 0x7b, 0x7d, 0x51, 0x56, 0xa2, 0x61, 0xde, 0x83, 0xbd, 0xb1, 0x08, 0x07, 0x7c, 0x1f, + 0xbe, 0xf0, 0x9f, 0x9f, 0x6b, 0x89, 0xbb, 0xff, 0xec, 0xfc, 0xdf, 0x58, 0xff, 0x80, 0x20, 0x1b, + 0x53, 0xd5, 0x41, 0x4f, 0xd0, 0x95, 0xa8, 0x45, 0x1d, 0x0e, 0xf6, 0x84, 0x78, 0xc0, 0x0a, 0xfd, + 0x84, 0xe0, 0x99, 0x98, 0x7c, 0x7d, 0x9d, 0x23, 0x2b, 0x50, 0x96, 0x88, 0x33, 0xa4, 0x04, 0x99, + 0xee, 0xe0, 0x07, 0xac, 0xd0, 0x28, 0xe0, 0xf3, 0xb6, 0xf2, 0x3d, 0xc7, 0x24, 0xa2, 0x23, 0xb9, + 0x5e, 0x81, 0xed, 0x9e, 0xa7, 0x22, 0xc9, 0x21, 0x18, 0xe1, 0x52, 0x52, 0x0c, 0xd3, 0x9d, 0x81, + 0x2c, 0xcc, 0x2a, 0x32, 0x08, 0xdf, 0xec, 0xbf, 0x63, 0x30, 0xcc, 0xa2, 0xe1, 0x4f, 0x10, 0x6c, + 0xf6, 0x68, 0x4c, 0xbc, 0xcf, 0x1f, 0x21, 0x4c, 0x9a, 0x4a, 0xfb, 0xbb, 0x78, 0x71, 0x78, 0x44, + 0xbe, 0xfd, 0xfb, 0xdf, 0x9f, 0xad, 0xcb, 0xe0, 0x29, 0xc5, 0xa7, 0x7f, 0x1d, 0x71, 0x5e, 0x67, + 0xcb, 0x8a, 0x25, 0x91, 0xfc, 0x6b, 0x04, 0x38, 0xa8, 0x2c, 0xf1, 0xb3, 0xe1, 0xd9, 0x42, 0xa4, + 0xa9, 0xf4, 0x5c, 0x12, 0x57, 0x81, 0xee, 0x10, 0x43, 0x27, 0xe3, 0xe9, 0x2e, 0xe8, 0xf8, 0x35, + 0xaa, 0xc8, 0x4f, 0x3e, 0x7c, 0x0f, 0xc1, 0xce, 0x70, 0xc9, 0x88, 0x67, 0xfc, 0xc9, 0x63, 0x45, + 0xaa, 0x24, 0x27, 0x75, 0x17, 0x78, 0x4f, 0x31, 0xbc, 0xc7, 0xf0, 0xd1, 0x28, 0xbc, 0x2a, 0x5f, + 0x5f, 0x6c, 0xb9, 0x01, 0x8a, 0x4c, 0xcd, 0x28, 0x37, 0xd8, 0x8b, 0x72, 0x13, 0xff, 0x88, 0x60, + 0x47, 0xa8, 0x40, 0xc4, 0xd3, 0xb1, 0x58, 0x7c, 0x82, 0x54, 0x9a, 0x49, 0xe8, 0x2d, 0x80, 0x9f, + 0x64, 0xc0, 0x5f, 0xc0, 0x47, 0x92, 0x01, 0xd7, 0x8d, 0xaa, 0x0f, 0xf7, 0xb7, 0x08, 0x70, 0x50, + 0x0f, 0x06, 0xfb, 0x22, 0x52, 0x78, 0x06, 0xfb, 0x22, 0x5a, 0x5e, 0x92, 0x39, 0x06, 0xf7, 0x30, + 0x3e, 0xd4, 0x0d, 0xae, 0x68, 0x8c, 0xc8, 0x1a, 0x7b, 0x2f, 0x9a, 0x91, 0x35, 0x0e, 0x15, 0x98, + 0x91, 0x35, 0x0e, 0x97, 0x7b, 0xc9, 0x6b, 0x2c, 0x40, 0x37, 0x54, 0xd3, 0xb2, 0xaf, 0xcc, 0x2e, + 0xee, 0x7f, 0x10, 0xec, 0x4f, 0xa4, 0xa3, 0xf0, 0x5c, 0x22, 0x64, 0x11, 0x87, 0x9d, 0x74, 0xbc, + 0xcf, 0xd5, 0x82, 0x67, 0x81, 0xf1, 0xcc, 0xe3, 0x97, 0x7b, 0xe4, 0x59, 0x34, 0x68, 0x67, 0x7f, + 0x51, 0xa3, 0xd6, 0x76, 0xa9, 0xff, 0x8c, 0xdc, 0x6f, 0x16, 0x41, 0xd1, 0x84, 0x0f, 0xc4, 0x36, + 0x7b, 0x88, 0x06, 0x94, 0x66, 0x7b, 0x58, 0x21, 0x68, 0xcd, 0x33, 0x5a, 0x27, 0xf0, 0x5c, 0xb2, + 0x57, 0x44, 0xab, 0x14, 0x4b, 0x2c, 0x48, 0xd1, 0xb3, 0x87, 0xbf, 0x20, 0xdf, 0x77, 0x13, 0x8f, + 0xc8, 0xc1, 0xb3, 0x89, 0x4a, 0xdf, 0x79, 0x06, 0x4b, 0xd9, 0x5e, 0x96, 0x08, 0x2e, 0x2f, 0x32, + 0x2e, 0x27, 0xf1, 0xf1, 0x5e, 0xb7, 0x88, 0x1d, 0xb2, 0x2e, 0x99, 0x8f, 0x11, 0x6c, 0xea, 0xd0, + 0x34, 0x98, 0xf8, 0xa1, 0x04, 0x05, 0x97, 0xb4, 0x37, 0xd6, 0x47, 0xe0, 0x9b, 0x66, 0xf8, 0xa6, + 0xf0, 0xbe, 0x28, 0x7c, 0x02, 0x17, 0x57, 0x6b, 0x77, 0x10, 0x00, 0x8f, 0x92, 0x6b, 0x2f, 0xcc, + 0xe3, 0xdd, 0xe1, 0x19, 0x1c, 0x00, 0xa9, 0x28, 0xb3, 0xc8, 0x7d, 0x98, 0xe5, 0x3e, 0x80, 0xe5, + 0x2e, 0xb9, 0x4b, 0xed, 0xa2, 0x5e, 0x51, 0x6e, 0x08, 0x49, 0x73, 0x13, 0xff, 0x8a, 0x40, 0x8a, + 0x96, 0x31, 0xc1, 0x9d, 0xed, 0x2a, 0x98, 0x82, 0x3b, 0xdb, 0x5d, 0x25, 0x91, 0xb3, 0x0c, 0xfd, + 0x29, 0x7c, 0x22, 0x0a, 0xbd, 0x57, 0x43, 0xb5, 0x1a, 0xa6, 0x4d, 0x44, 0x90, 0xe8, 0x60, 0xf3, + 0x1b, 0x82, 0x89, 0x98, 0x8b, 0x14, 0x8e, 0xef, 0xba, 0x50, 0x31, 0x25, 0x1d, 0xec, 0x69, 0x4d, + 0x52, 0x42, 0xbe, 0x56, 0xad, 0xb1, 0x30, 0x45, 0xe7, 0x9a, 0x18, 0x3d, 0xf4, 0x5d, 0x2a, 0xf1, + 0x43, 0xdf, 0x4f, 0x62, 0x26, 0xa1, 0x77, 0x9f, 0x43, 0x3f, 0x80, 0xfb, 0xd3, 0x75, 0xf0, 0x7c, + 0x0f, 0xd7, 0x7f, 0x9c, 0xeb, 0xa1, 0xc8, 0x51, 0x07, 0xc0, 0x99, 0x81, 0x62, 0x08, 0xe6, 0x6f, + 0x31, 0xe6, 0x17, 0xf0, 0xf9, 0xfe, 0x36, 0x2e, 0xee, 0x34, 0x58, 0x5a, 0xfe, 0xcc, 0x17, 0x79, + 0xcb, 0xc7, 0x47, 0x7a, 0x20, 0xe1, 0x99, 0x50, 0x47, 0x7b, 0x5f, 0x28, 0x28, 0xe7, 0x19, 0xe5, + 0xb3, 0x78, 0xbe, 0x4f, 0xca, 0xde, 0xe9, 0xda, 0x86, 0x11, 0xae, 0x0d, 0x82, 0x73, 0x35, 0x28, + 0x3f, 0x82, 0x73, 0x35, 0x44, 0x8c, 0x90, 0x29, 0x06, 0x70, 0x12, 0xa7, 0xa2, 0x00, 0x72, 0xf9, + 0x91, 0xcb, 0xdf, 0x7f, 0x94, 0x42, 0x0f, 0x1e, 0xa5, 0xd0, 0x5f, 0x8f, 0x52, 0xe8, 0xee, 0x52, + 0x6a, 0xe8, 0xc1, 0x52, 0x6a, 0xe8, 0x8f, 0xa5, 0xd4, 0xd0, 0xdb, 0xd9, 0x8e, 0xcf, 0x52, 0x22, + 0xc6, 0x4c, 0x4d, 0x2d, 0x99, 0x6e, 0xc0, 0xeb, 0xb3, 0x59, 0xe5, 0x03, 0x27, 0x2c, 0xfb, 0x4c, + 0x55, 0x1a, 0x61, 0x1a, 0xef, 0xe0, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x35, 0x14, 0x89, 0xb7, + 0x3f, 0x1c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1705,6 +1791,8 @@ type QueryClient interface { AccountLockedLongerDurationNotUnlockingOnly(ctx context.Context, in *AccountLockedLongerDurationNotUnlockingOnlyRequest, opts ...grpc.CallOption) (*AccountLockedLongerDurationNotUnlockingOnlyResponse, error) // Returns account's locked records for a denom with longer duration AccountLockedLongerDurationDenom(ctx context.Context, in *AccountLockedLongerDurationDenomRequest, opts ...grpc.CallOption) (*AccountLockedLongerDurationDenomResponse, error) + // Params returns lockup params. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) } type queryClient struct { @@ -1859,6 +1947,15 @@ func (c *queryClient) AccountLockedLongerDurationDenom(ctx context.Context, in * return out, nil } +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/osmosis.lockup.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Return full balance of the module @@ -1895,6 +1992,8 @@ type QueryServer interface { AccountLockedLongerDurationNotUnlockingOnly(context.Context, *AccountLockedLongerDurationNotUnlockingOnlyRequest) (*AccountLockedLongerDurationNotUnlockingOnlyResponse, error) // Returns account's locked records for a denom with longer duration AccountLockedLongerDurationDenom(context.Context, *AccountLockedLongerDurationDenomRequest) (*AccountLockedLongerDurationDenomResponse, error) + // Params returns lockup params. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1949,6 +2048,9 @@ func (*UnimplementedQueryServer) AccountLockedLongerDurationNotUnlockingOnly(ctx func (*UnimplementedQueryServer) AccountLockedLongerDurationDenom(ctx context.Context, req *AccountLockedLongerDurationDenomRequest) (*AccountLockedLongerDurationDenomResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AccountLockedLongerDurationDenom not implemented") } +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -2242,6 +2344,24 @@ func _Query_AccountLockedLongerDurationDenom_Handler(srv interface{}, ctx contex return interceptor(ctx, in, info, handler) } +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.lockup.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "osmosis.lockup.Query", HandlerType: (*QueryServer)(nil), @@ -2310,6 +2430,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "AccountLockedLongerDurationDenom", Handler: _Query_AccountLockedLongerDurationDenom_Handler, }, + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "osmosis/lockup/query.proto", @@ -3449,6 +3573,62 @@ func (m *AccountLockedLongerDurationDenomResponse) MarshalToSizedBuffer(dAtA []b return len(dAtA) - i, nil } +func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -3918,6 +4098,26 @@ func (m *AccountLockedLongerDurationDenomResponse) Size() (n int) { return n } +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -6853,6 +7053,139 @@ func (m *AccountLockedLongerDurationDenomResponse) Unmarshal(dAtA []byte) error } return nil } +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/lockup/types/query.pb.gw.go b/x/lockup/types/query.pb.gw.go index ec04d9c76a9..ae8adba4b0e 100644 --- a/x/lockup/types/query.pb.gw.go +++ b/x/lockup/types/query.pb.gw.go @@ -951,6 +951,24 @@ func local_request_Query_AccountLockedLongerDurationDenom_0(ctx context.Context, } +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1325,6 +1343,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1686,6 +1727,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1721,6 +1782,8 @@ var ( pattern_Query_AccountLockedLongerDurationNotUnlockingOnly_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"osmosis", "lockup", "v1beta1", "account_locked_longer_duration_not_unlocking_only", "owner"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_AccountLockedLongerDurationDenom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"osmosis", "lockup", "v1beta1", "account_locked_longer_duration_denom", "owner"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "lockup", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -1755,4 +1818,6 @@ var ( forward_Query_AccountLockedLongerDurationNotUnlockingOnly_0 = runtime.ForwardResponseMessage forward_Query_AccountLockedLongerDurationDenom_0 = runtime.ForwardResponseMessage + + forward_Query_Params_0 = runtime.ForwardResponseMessage ) diff --git a/x/mint/client/cli/query_test.go b/x/mint/client/cli/query_test.go new file mode 100644 index 00000000000..84ba9dc6605 --- /dev/null +++ b/x/mint/client/cli/query_test.go @@ -0,0 +1,60 @@ +package cli_test + +import ( + gocontext "context" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/mint/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query epoch provisions", + "/osmosis.mint.v1beta1.Query/EpochProvisions", + &types.QueryEpochProvisionsRequest{}, + &types.QueryEpochProvisionsResponse{}, + }, + { + "Query params", + "/osmosis.mint.v1beta1.Query/Params", + &types.QueryParamsRequest{}, + &types.QueryParamsResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/pool-incentives/client/cli/query_test.go b/x/pool-incentives/client/cli/query_test.go new file mode 100644 index 00000000000..565e3a7d31d --- /dev/null +++ b/x/pool-incentives/client/cli/query_test.go @@ -0,0 +1,86 @@ +package cli_test + +import ( + gocontext "context" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/pool-incentives/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + // set up pool + s.PrepareBalancerPool() + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query distribution info", + "/osmosis.poolincentives.v1beta1.Query/DistrInfo", + &types.QueryDistrInfoRequest{}, + &types.QueryDistrInfoResponse{}, + }, + { + "Query external incentive gauges", + "/osmosis.poolincentives.v1beta1.Query/ExternalIncentiveGauges", + &types.QueryExternalIncentiveGaugesRequest{}, + &types.QueryExternalIncentiveGaugesResponse{}, + }, + { + "Query all gauge ids", + "/osmosis.poolincentives.v1beta1.Query/GaugeIds", + &types.QueryGaugeIdsRequest{PoolId: 1}, + &types.QueryGaugeIdsResponse{}, + }, + { + "Query all incentivized pools", + "/osmosis.poolincentives.v1beta1.Query/IncentivizedPools", + &types.QueryIncentivizedPoolsRequest{}, + &types.QueryIncentivizedPoolsResponse{}, + }, + { + "Query lockable durations", + "/osmosis.poolincentives.v1beta1.Query/LockableDurations", + &types.QueryLockableDurationsRequest{}, + &types.QueryLockableDurationsResponse{}, + }, + { + "Query params", + "/osmosis.poolincentives.v1beta1.Query/Params", + &types.QueryParamsRequest{}, + &types.QueryParamsResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/superfluid/client/cli/query_test.go b/x/superfluid/client/cli/query_test.go new file mode 100644 index 00000000000..a6f760cc521 --- /dev/null +++ b/x/superfluid/client/cli/query_test.go @@ -0,0 +1,156 @@ +package cli_test + +import ( + gocontext "context" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/superfluid/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient + val sdk.ValAddress +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + // set up durations + s.App.IncentivesKeeper.SetLockableDurations(s.Ctx, []time.Duration{ + time.Hour * 24 * 14, + time.Hour, + time.Hour * 3, + time.Hour * 7, + time.Hour * 24 * 21, + }) + // set up pool + s.SetupGammPoolsWithBondDenomMultiplier([]sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + // set up lock with id = 1 + s.LockTokens(s.TestAccs[0], sdk.Coins{sdk.NewCoin("gamm/pool/1", sdk.NewInt(1000000))}, time.Hour*24*21) + // set up validator + s.val = s.SetupValidator(stakingtypes.Bonded) + // set up sfs asset + err := s.App.SuperfluidKeeper.AddNewSuperfluidAsset(s.Ctx, types.SuperfluidAsset{ + Denom: "gamm/pool/1", + AssetType: types.SuperfluidAssetTypeLPShare, + }) + s.Require().NoError(err) + // set up sfs delegation + err = s.App.SuperfluidKeeper.SuperfluidDelegate(s.Ctx, s.TestAccs[0].String(), 1, s.val.String()) + s.Require().NoError(err) + + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + s.SetupSuite() + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query all superfluild assets", + "/osmosis.superfluid.Query/AllAssets", + &types.AllAssetsRequest{}, + &types.AllAssetsResponse{}, + }, + { + "Query all intermediary accounts", + "/osmosis.superfluid.Query/AllIntermediaryAccounts", + &types.AllIntermediaryAccountsRequest{}, + &types.AllIntermediaryAccountsResponse{}, + }, + { + "Query osmo equivalent multiplier of an asset", + "/osmosis.superfluid.Query/AssetMultiplier", + &types.AssetMultiplierRequest{Denom: "gamm/pool/1"}, + &types.AssetMultiplierResponse{}, + }, + { + "Query asset type", + "/osmosis.superfluid.Query/AssetType", + &types.AssetTypeRequest{Denom: "gamm/pool/1"}, + &types.AssetTypeResponse{}, + }, + { + "Query connected intermediary account", + "/osmosis.superfluid.Query/ConnectedIntermediaryAccount", + &types.ConnectedIntermediaryAccountRequest{LockId: 1}, + &types.ConnectedIntermediaryAccountResponse{}, + }, + { + "Query estimate sfs delegated amount by validator & denom", + "/osmosis.superfluid.Query/EstimateSuperfluidDelegatedAmountByValidatorDenom", + &types.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1"}, + &types.EstimateSuperfluidDelegatedAmountByValidatorDenomResponse{}, + }, + { + "Query params", + "/osmosis.superfluid.Query/Params", + &types.QueryParamsRequest{}, + &types.QueryParamsResponse{}, + }, + { + "Query sfs delegation amount", + "/osmosis.superfluid.Query/SuperfluidDelegationAmount", + &types.SuperfluidDelegationAmountRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1", DelegatorAddress: s.TestAccs[0].String()}, + &types.SuperfluidDelegationAmountResponse{}, + }, + { + "Query sfs delegation by delegator", + "/osmosis.superfluid.Query/SuperfluidDelegationsByDelegator", + &types.SuperfluidDelegationsByDelegatorRequest{DelegatorAddress: s.TestAccs[0].String()}, + &types.SuperfluidDelegationsByDelegatorResponse{}, + }, + { + "Query sfs delegation by validator & denom", + "/osmosis.superfluid.Query/SuperfluidDelegationsByValidatorDenom", + &types.SuperfluidDelegationsByValidatorDenomRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1"}, + &types.SuperfluidDelegationsByValidatorDenomResponse{}, + }, + { + "Query sfs undelegation by delegator", + "/osmosis.superfluid.Query/SuperfluidUndelegationsByDelegator", + &types.SuperfluidUndelegationsByDelegatorRequest{DelegatorAddress: s.TestAccs[0].String(), Denom: "gamm/pool/1"}, + &types.SuperfluidUndelegationsByDelegatorResponse{}, + }, + { + "Query total sfs delegation by delegator", + "/osmosis.superfluid.Query/TotalDelegationByDelegator", + &types.QueryTotalDelegationByDelegatorRequest{DelegatorAddress: s.TestAccs[0].String()}, + &types.QueryTotalDelegationByDelegatorResponse{}, + }, + { + "Query total sfs delegations", + "/osmosis.superfluid.Query/TotalSuperfluidDelegations", + &types.TotalSuperfluidDelegationsRequest{}, + &types.TotalSuperfluidDelegationsResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/tokenfactory/client/cli/query_test.go b/x/tokenfactory/client/cli/query_test.go new file mode 100644 index 00000000000..ea756feb9e9 --- /dev/null +++ b/x/tokenfactory/client/cli/query_test.go @@ -0,0 +1,75 @@ +package cli_test + +import ( + gocontext "context" + "testing" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/tokenfactory/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + // fund acc + fundAccsAmount := sdk.NewCoins(sdk.NewCoin(types.DefaultParams().DenomCreationFee[0].Denom, types.DefaultParams().DenomCreationFee[0].Amount.MulRaw(100)), sdk.NewCoin(apptesting.SecondaryDenom, apptesting.SecondaryAmount)) + s.FundAcc(s.TestAccs[0], fundAccsAmount) + // create new token + _, err := s.App.TokenFactoryKeeper.CreateDenom(s.Ctx, s.TestAccs[0].String(), "tokenfactory") + s.Require().NoError(err) + + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query denom authority metadata", + "/osmosis.tokenfactory.v1beta1.Query/DenomAuthorityMetadata", + &types.QueryDenomAuthorityMetadataRequest{Denom: "tokenfactory"}, + &types.QueryDenomAuthorityMetadataResponse{}, + }, + { + "Query denoms by creator", + "/osmosis.tokenfactory.v1beta1.Query/DenomsFromCreator", + &types.QueryDenomsFromCreatorRequest{Creator: s.TestAccs[0].String()}, + &types.QueryDenomsFromCreatorResponse{}, + }, + { + "Query params", + "/osmosis.tokenfactory.v1beta1.Query/Params", + &types.QueryParamsRequest{}, + &types.QueryParamsResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +} diff --git a/x/twap/export_test.go b/x/twap/export_test.go index f4cf043f7ca..462808753ea 100644 --- a/x/twap/export_test.go +++ b/x/twap/export_test.go @@ -93,3 +93,7 @@ func (k *Keeper) GetAmmInterface() types.AmmInterface { func (k *Keeper) SetAmmInterface(ammInterface types.AmmInterface) { k.ammkeeper = ammInterface } + +func (k *Keeper) AfterCreatePool(ctx sdk.Context, poolId uint64) error { + return k.afterCreatePool(ctx, poolId) +} diff --git a/x/twap/logic_test.go b/x/twap/logic_test.go index a5e3beecce4..8d629c99589 100644 --- a/x/twap/logic_test.go +++ b/x/twap/logic_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/osmosis-labs/osmosis/v12/app/apptesting/osmoassert" + "github.com/osmosis-labs/osmosis/v12/osmoutils" gammtypes "github.com/osmosis-labs/osmosis/v12/x/gamm/types" "github.com/osmosis-labs/osmosis/v12/x/twap" "github.com/osmosis-labs/osmosis/v12/x/twap/types" @@ -1275,3 +1276,93 @@ func (s *TestSuite) TestUpdateRecords() { }) } } + +func (s *TestSuite) TestAfterCreatePool() { + tests := map[string]struct { + poolId uint64 + poolCoins sdk.Coins + // if this field is set true, we swap in the same block with pool creation + runSwap bool + expectedErr bool + }{ + "Pool not existing": { + poolId: 2, + expectedErr: true, + }, + "Default Pool, no swap on pool creation block": { + poolId: 1, + poolCoins: defaultTwoAssetCoins, + runSwap: false, + }, + "Default Pool, swap on pool creation block": { + poolId: 1, + poolCoins: defaultTwoAssetCoins, + runSwap: true, + }, + "Multi assets pool, no swap on pool creation block": { + poolId: 1, + poolCoins: defaultThreeAssetCoins, + runSwap: false, + }, + "Multi assets pool, swap on pool creation block": { + poolId: 1, + poolCoins: defaultThreeAssetCoins, + runSwap: true, + }, + } + + for name, tc := range tests { + s.Run(name, func() { + s.SetupTest() + var poolId uint64 + + // set up pool with input coins + if tc.poolCoins != nil { + poolId = s.PrepareBalancerPoolWithCoins(tc.poolCoins...) + if tc.runSwap { + s.RunBasicSwap(poolId) + } + } + + err := s.twapkeeper.AfterCreatePool(s.Ctx, tc.poolId) + if tc.expectedErr { + s.Require().Error(err) + return + } + s.Require().Equal(tc.poolId, poolId) + s.Require().NoError(err) + + denoms := osmoutils.CoinsDenoms(tc.poolCoins) + denomPairs0, denomPairs1 := types.GetAllUniqueDenomPairs(denoms) + expectedRecords := []types.TwapRecord{} + for i := 0; i < len(denomPairs0); i++ { + expectedRecord, err := twap.NewTwapRecord(s.App.GAMMKeeper, s.Ctx, poolId, denomPairs0[i], denomPairs1[i]) + s.Require().NoError(err) + expectedRecords = append(expectedRecords, expectedRecord) + } + + // consistency check that the number of records is exactly equal to the number of denompairs + allRecords, err := s.twapkeeper.GetAllMostRecentRecordsForPool(s.Ctx, poolId) + s.Require().NoError(err) + s.Require().Equal(len(denomPairs0), len(allRecords)) + s.Require().Equal(len(expectedRecords), len(allRecords)) + + // check on the correctness of all individual twap records + for i := 0; i < len(denomPairs0); i++ { + actualRecord, err := s.twapkeeper.GetMostRecentRecordStoreRepresentation(s.Ctx, poolId, denomPairs0[i], denomPairs1[i]) + s.Require().NoError(err) + s.Require().Equal(expectedRecords[i], actualRecord) + actualRecord, err = s.twapkeeper.GetRecordAtOrBeforeTime(s.Ctx, poolId, s.Ctx.BlockTime(), denomPairs0[i], denomPairs1[i]) + s.Require().NoError(err) + s.Require().Equal(expectedRecords[i], actualRecord) + } + + // test that after creating a pool + // has triggered `trackChangedPool`, + // and that we have the state of price impacted pools. + changedPools := s.twapkeeper.GetChangedPools(s.Ctx) + s.Require().Equal(1, len(changedPools)) + s.Require().Equal(tc.poolId, changedPools[0]) + }) + } +} diff --git a/x/txfees/client/cli/query_test.go b/x/txfees/client/cli/query_test.go new file mode 100644 index 00000000000..7575d3eb902 --- /dev/null +++ b/x/txfees/client/cli/query_test.go @@ -0,0 +1,92 @@ +package cli_test + +import ( + gocontext "context" + "testing" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/v12/app/apptesting" + "github.com/osmosis-labs/osmosis/v12/x/txfees/types" +) + +type QueryTestSuite struct { + apptesting.KeeperTestHelper + queryClient types.QueryClient +} + +func (s *QueryTestSuite) SetupSuite() { + s.Setup() + s.queryClient = types.NewQueryClient(s.QueryHelper) + + // set up pool + poolAssets := []sdk.Coin{ + sdk.NewInt64Coin("uosmo", 1000000), + sdk.NewInt64Coin("stake", 120000000), + } + s.PrepareBalancerPoolWithCoins(poolAssets...) + + // set up fee token + upgradeProp := types.NewUpdateFeeTokenProposal( + "Test Proposal", + "test", + types.FeeToken{ + Denom: "uosmo", + PoolID: 1, + }, + ) + err := s.App.TxFeesKeeper.HandleUpdateFeeTokenProposal(s.Ctx, &upgradeProp) + s.Require().NoError(err) + + s.Commit() +} + +func (s *QueryTestSuite) TestQueriesNeverAlterState() { + testCases := []struct { + name string + query string + input interface{} + output interface{} + }{ + { + "Query base denom", + "/osmosis.txfees.v1beta1.Query/BaseDenom", + &types.QueryBaseDenomRequest{}, + &types.QueryBaseDenomResponse{}, + }, + { + "Query poolID by denom", + "/osmosis.txfees.v1beta1.Query/DenomPoolId", + &types.QueryDenomPoolIdRequest{Denom: "uosmo"}, + &types.QueryDenomPoolIdResponse{}, + }, + { + "Query spot price by denom", + "/osmosis.txfees.v1beta1.Query/DenomSpotPrice", + &types.QueryDenomSpotPriceRequest{Denom: "uosmo"}, + &types.QueryDenomSpotPriceResponse{}, + }, + { + "Query fee tokens", + "/osmosis.txfees.v1beta1.Query/FeeTokens", + &types.QueryFeeTokensRequest{}, + &types.QueryFeeTokensResponse{}, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + s.SetupSuite() + err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) + s.Require().NoError(err) + s.StateNotAltered() + }) + } +} + +func TestQueryTestSuite(t *testing.T) { + suite.Run(t, new(QueryTestSuite)) +}