diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ad5c2fe667..2539e2bb33e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#6468](https://github.com/osmosis-labs/osmosis/pull/6468) feat: remove osmo multihop discount * [#6420](https://github.com/osmosis-labs/osmosis/pull/6420) feat[CL]: Creates a governance set whitelist of addresses that can bypass the normal pool creation restrictions on concentrated liquidity pools +* [#6623](https://github.com/osmosis-labs/osmosis/pull/6420) feat: transfer cl positions to new owner * [#6632](https://github.com/osmosis-labs/osmosis/pull/6632) Taker fee bypass whitelist ### State Breaking diff --git a/go.mod b/go.mod index b7190b51c2f..1f4d1cc79cd 100644 --- a/go.mod +++ b/go.mod @@ -22,10 +22,10 @@ require ( github.com/mattn/go-sqlite3 v1.14.17 github.com/ory/dockertest/v3 v3.10.0 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 - github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231009212613-77825371576d - github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d - github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231009212613-77825371576d - github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231009212613-77825371576d + github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231011004221-fd24b80f8366 + github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366 + github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231011004221-fd24b80f8366 + github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231011004221-fd24b80f8366 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.5.1 diff --git a/go.sum b/go.sum index f03c59ae610..b0019ccae6d 100644 --- a/go.sum +++ b/go.sum @@ -960,14 +960,14 @@ github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230922030206-734f99fba785 h1: github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230922030206-734f99fba785/go.mod h1:toI9Pf+e5C4TuWAFpXfkxnkpr1RVFMK2qr7QMdkFrY8= github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:YlmchqTmlwdWSmrRmXKR+PcU96ntOd8u10vTaTZdcNY= github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI= -github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231009212613-77825371576d h1:aOymbQ0JbsFBNPbcwpVoQiN05MSW9dE1Tgr3824JAQE= -github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231009212613-77825371576d/go.mod h1:04dErgkT2m1+nMs7yZSuIRlkQRcGbuvvkokCpJFAAm8= -github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d h1:v2oZcI68YtaqkqkADipvwBrr+5skSepcljTlwH4/Gho= -github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d/go.mod h1:65FFxpq4aS72kQbjHkNYVvPvFP2mQsFDyYozZJDImW4= -github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231009212613-77825371576d h1:nkhOh+AmdvBN60Eul3adN/vXiBqtDUqMzLGQny3QFhc= -github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231009212613-77825371576d/go.mod h1:07lOzupKYfWaN/zXEtuzmpg6ZzqR0uxJStUuf0lDqb0= -github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231009212613-77825371576d h1:FgvBYm9AKJ6tPDNKrFWM6QJSNtGL77W7fzdMbP7SCnI= -github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231009212613-77825371576d/go.mod h1:nWR2rQtkk89MdvUat1CTb3mKrR40sYP/h90eCeECXn8= +github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231011004221-fd24b80f8366 h1:E/6Yk1f+8evOyi6xKHurjhPQrWKuW/KFoWJ8cfGT6I8= +github.com/osmosis-labs/osmosis/osmomath v0.0.7-0.20231011004221-fd24b80f8366/go.mod h1:YEMUPuI9gBUATC4tp2MiW0oWRlShli0K95JqgNKJh9c= +github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366 h1:EJDJ88w2Yv5LnlaJw5x53C0k/dp/fnEYOfBYOQiMsTc= +github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366/go.mod h1:Zmyx5zMUBN2KV94booSFn2v8KQcUKeCHqyWpKZ4PRMo= +github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231011004221-fd24b80f8366 h1:E6H0V3MKbSNwo1iXE9Kzatd2M02MgZpS5AiJ6CKK5us= +github.com/osmosis-labs/osmosis/x/epochs v0.0.3-0.20231011004221-fd24b80f8366/go.mod h1:vU0IHK5W38dqMeux3MkSaT3MZU6whAkx7vNuxv1IzeU= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231011004221-fd24b80f8366 h1:bK80LMyhE8sqVBhqp5tv+byHG631e4L/8QRNTPLKh50= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.9-0.20231011004221-fd24b80f8366/go.mod h1:9VUgcpBbRWkTXu4NrfNOIRtm36bRjxCTrlqTaQ8i518= github.com/osmosis-labs/wasmd v0.31.0-osmo-v16 h1:X747cZYdnqc/+RV48iPVeGprpVb/fUWSaKGsZUWrdbg= github.com/osmosis-labs/wasmd v0.31.0-osmo-v16/go.mod h1:Rf8zW/GgBQyFRRB4s62VQHWA6sTlMFSjoDQQpoq64iI= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= diff --git a/osmomath/go.sum b/osmomath/go.sum index c33ed87173d..e8cf5c06a53 100644 --- a/osmomath/go.sum +++ b/osmomath/go.sum @@ -35,6 +35,7 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cosmossdk.io/math v1.1.3-rc.1 h1:NebCNWDqb1MJRNfvxr4YY7d8FSYgkuB3L75K6xvM+Zo= +cosmossdk.io/math v1.1.3-rc.1/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -92,6 +93,7 @@ github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuA github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger/v3 v3.2103.2 h1:dpyM5eCJAtQCBcMCZcT4UBZchuTJgCywerHHgmxfxM8= github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M= github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= @@ -224,6 +226,7 @@ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -250,6 +253,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -299,6 +303,7 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -308,22 +313,27 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= @@ -334,17 +344,21 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= +github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= 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/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= @@ -357,6 +371,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= 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/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -372,6 +387,7 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= @@ -400,6 +416,7 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -410,6 +427,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= 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= @@ -482,6 +500,7 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= 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= @@ -562,6 +581,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -683,6 +703,7 @@ google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/osmoutils/compare.go b/osmoutils/compare.go index cd17e97497c..d6b01997175 100644 --- a/osmoutils/compare.go +++ b/osmoutils/compare.go @@ -1,5 +1,7 @@ package osmoutils +import "sort" + // Max returns the maximum value among the given values of any type that supports comparison. func Max(values ...interface{}) interface{} { if len(values) == 0 { @@ -57,3 +59,53 @@ func Max(values ...interface{}) interface{} { } return max } + +// DifferenceBetweenUint64Arrays takes two slices of uint64, 'a' and 'b', as input. +// It returns a new slice containing the elements that are unique to either 'a' or 'b'. +// The function uses two maps for efficient lookup of elements. +// +// Example: +// a := []uint64{1, 2, 3, 4, 5} +// b := []uint64{4, 5, 6, 7, 8} +// result := DisjointArrays(a, b) +// result will be []uint64{1, 2, 3, 6, 7, 8} +// +// Note: This function returns the difference between the two arrays in ascending order, +// and does not preserve the order of the elements in the original arrays. +func DisjointArrays(a, b []uint64) []uint64 { + if len(a) == 0 && len(b) == 0 { + return []uint64{} + } + + m1 := make(map[uint64]bool) + m2 := make(map[uint64]bool) + + for _, item := range a { + m1[item] = true + } + + for _, item := range b { + m2[item] = true + } + + var result []uint64 + for item := range m1 { + if !m2[item] { + result = append(result, item) + } + } + + for item := range m2 { + if !m1[item] { + result = append(result, item) + } + } + + if len(result) == 0 { + return []uint64{} + } + + sort.Slice(result, func(i, j int) bool { return result[i] < result[j] }) + + return result +} diff --git a/osmoutils/compare_test.go b/osmoutils/compare_test.go index 2a61b680e0b..4339a4b3c2a 100644 --- a/osmoutils/compare_test.go +++ b/osmoutils/compare_test.go @@ -1,6 +1,7 @@ package osmoutils_test import ( + "reflect" "testing" "github.com/stretchr/testify/assert" @@ -38,3 +39,95 @@ func TestMax(t *testing.T) { }) } } + +func TestDisjointArrays(t *testing.T) { + tests := []struct { + name string + a []uint64 + b []uint64 + want []uint64 + }{ + { + name: "Both arrays contain some unique elements, both sorted", + a: []uint64{1, 2, 3, 4, 5}, + b: []uint64{4, 5, 6, 7, 8}, + want: []uint64{1, 2, 3, 6, 7, 8}, + }, + { + name: "Only array 'a' contains some unique elements, both sorted", + a: []uint64{10, 20, 30, 40}, + b: []uint64{20, 30}, + want: []uint64{10, 40}, + }, + { + name: "Only array 'b' contains some unique elements, both sorted", + a: []uint64{20, 30}, + b: []uint64{10, 20, 30, 40}, + want: []uint64{10, 40}, + }, + { + name: "Both arrays contain some unique elements, both unsorted", + a: []uint64{5, 4, 3, 2, 1}, + b: []uint64{8, 7, 6, 5, 4}, + want: []uint64{1, 2, 3, 6, 7, 8}, + }, + { + name: "Both arrays contain some unique elements, a sorted, b unsorted", + a: []uint64{5, 4, 3, 2, 1}, + b: []uint64{6, 7, 8, 5, 4}, + want: []uint64{1, 2, 3, 6, 7, 8}, + }, + { + name: "Only array 'a' contains some unique elements, both unsorted", + a: []uint64{40, 30, 20, 10}, + b: []uint64{30, 20}, + want: []uint64{10, 40}, + }, + { + name: "Only array 'b' contains some unique elements, both unsorted", + a: []uint64{30, 20}, + b: []uint64{40, 30, 20, 10}, + want: []uint64{10, 40}, + }, + { + name: "Both arrays empty", + a: []uint64{}, + b: []uint64{}, + want: []uint64{}, + }, + { + name: "Array 'a' empty, unsorted", + a: []uint64{}, + b: []uint64{2, 1, 3}, + want: []uint64{1, 2, 3}, + }, + { + name: "Array 'b' empty, unsorted", + a: []uint64{2, 1, 3}, + b: []uint64{}, + want: []uint64{1, 2, 3}, + }, + { + name: "Both arrays contain completely different elements, both unsorted", + a: []uint64{2, 1, 3}, + b: []uint64{5, 4, 6}, + want: []uint64{1, 2, 3, 4, 5, 6}, + }, + { + name: "Both arrays equal, both unsorted", + a: []uint64{2, 1, 3}, + b: []uint64{2, 1, 3}, + want: []uint64{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := osmoutils.DisjointArrays(tt.a, tt.b) + + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("DifferenceBetweenUint64Arrays() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/osmoutils/go.mod b/osmoutils/go.mod index 8dde9a48ec8..d1455d0b4ca 100644 --- a/osmoutils/go.mod +++ b/osmoutils/go.mod @@ -97,7 +97,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect diff --git a/osmoutils/ibc.go b/osmoutils/ibc.go index 310059d7c56..4500a05e25e 100644 --- a/osmoutils/ibc.go +++ b/osmoutils/ibc.go @@ -3,6 +3,7 @@ package osmoutils import ( "encoding/json" "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" diff --git a/osmoutils/osmocli/cli_tester.go b/osmoutils/osmocli/cli_tester.go index 4ef6aaf9bdb..285fbf88b7a 100644 --- a/osmoutils/osmocli/cli_tester.go +++ b/osmoutils/osmocli/cli_tester.go @@ -27,6 +27,7 @@ type QueryCliTestCase[Q proto.Message] struct { } func RunTxTestCases[M sdk.Msg](t *testing.T, desc *TxCliDesc, testcases map[string]TxCliTestCase[M]) { + t.Helper() for name, tc := range testcases { t.Run(name, func(t *testing.T) { RunTxTestCase(t, desc, &tc) @@ -35,6 +36,7 @@ func RunTxTestCases[M sdk.Msg](t *testing.T, desc *TxCliDesc, testcases map[stri } func RunQueryTestCases[Q proto.Message](t *testing.T, desc *QueryDescriptor, testcases map[string]QueryCliTestCase[Q]) { + t.Helper() for name, tc := range testcases { t.Run(name, func(t *testing.T) { RunQueryTestCase(t, desc, &tc) @@ -43,6 +45,7 @@ func RunQueryTestCases[Q proto.Message](t *testing.T, desc *QueryDescriptor, tes } func RunTxTestCase[M sdk.Msg](t *testing.T, desc *TxCliDesc, tc *TxCliTestCase[M]) { + t.Helper() cmd := BuildTxCli[M](desc) err := resetCommandFlagValues(cmd) require.NoError(t, err, "error in resetCommandFlagValues") @@ -66,6 +69,7 @@ func RunTxTestCase[M sdk.Msg](t *testing.T, desc *TxCliDesc, tc *TxCliTestCase[M } func RunQueryTestCase[Q proto.Message](t *testing.T, desc *QueryDescriptor, tc *QueryCliTestCase[Q]) { + t.Helper() cmd := BuildQueryCli[Q, int](desc, nil) err := resetCommandFlagValues(cmd) require.NoError(t, err, "error in resetCommandFlagValues") @@ -85,6 +89,7 @@ func RunQueryTestCase[Q proto.Message](t *testing.T, desc *QueryDescriptor, tc * // This logic is copied from the SDK, it should've just been publicly exposed. // But instead its buried within a mega-method. func newClientContextWithFrom(t *testing.T, fs *pflag.FlagSet) client.Context { + t.Helper() clientCtx := client.Context{} from, _ := fs.GetString(flags.FlagFrom) fromAddr, fromName, _, err := client.GetFromFields(nil, from, true) diff --git a/osmoutils/osmocli/parsers.go b/osmoutils/osmocli/parsers.go index 229d450a831..dc2a467c36a 100644 --- a/osmoutils/osmocli/parsers.go +++ b/osmoutils/osmocli/parsers.go @@ -380,3 +380,15 @@ func ParseStringTo2DArray(input string) ([][]uint64, error) { return result, nil } + +// ParseUint64SliceToString converts a slice of uint64 values into a string. +// Each uint64 value in the slice is converted to a string using base 10. +// The resulting strings are then joined together with a comma separator. +// The resulting string is returned. +func ParseUint64SliceToString(values []uint64) string { + strs := make([]string, len(values)) + for i, v := range values { + strs[i] = strconv.FormatUint(v, 10) + } + return strings.Join(strs, ", ") +} diff --git a/osmoutils/osmocli/parsers_test.go b/osmoutils/osmocli/parsers_test.go index f933857341f..c10588b43b0 100644 --- a/osmoutils/osmocli/parsers_test.go +++ b/osmoutils/osmocli/parsers_test.go @@ -167,3 +167,41 @@ func TestParseFieldFromArg(t *testing.T) { }) } } + +func TestParseUint64SliceToString(t *testing.T) { + tests := []struct { + name string + input []uint64 + expected string + }{ + { + name: "Test with empty slice", + input: []uint64{}, + expected: "", + }, + { + name: "Test with single element", + input: []uint64{1}, + expected: "1", + }, + { + name: "Test with multiple elements", + input: []uint64{1, 2, 3, 4, 5}, + expected: "1, 2, 3, 4, 5", + }, + { + name: "Test with multiple elements out of order", + input: []uint64{9, 1, 2, 3, 4, 5}, + expected: "9, 1, 2, 3, 4, 5", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ParseUint64SliceToString(tt.input) + if result != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, result) + } + }) + } +} diff --git a/proto/osmosis/concentrated-liquidity/tx.proto b/proto/osmosis/concentrated-liquidity/tx.proto index 4f5f3fe880c..af8b52f7692 100644 --- a/proto/osmosis/concentrated-liquidity/tx.proto +++ b/proto/osmosis/concentrated-liquidity/tx.proto @@ -23,6 +23,10 @@ service Msg { returns (MsgCollectSpreadRewardsResponse); rpc CollectIncentives(MsgCollectIncentives) returns (MsgCollectIncentivesResponse); + // TransferPositions transfers ownership of a set of one or more positions + // from a sender to a recipient. + rpc TransferPositions(MsgTransferPositions) + returns (MsgTransferPositionsResponse); } // ===================== MsgCreatePosition @@ -221,4 +225,16 @@ message MsgFungifyChargedPositions { message MsgFungifyChargedPositionsResponse { uint64 new_position_id = 1 [ (gogoproto.moretags) = "yaml:\"new_position_id\"" ]; -} \ No newline at end of file +} + +// ===================== MsgTransferPositions +message MsgTransferPositions { + option (amino.name) = "osmosis/cl-transfer-positions"; + + repeated uint64 position_ids = 1 + [ (gogoproto.moretags) = "yaml:\"position_ids\"" ]; + string sender = 2 [ (gogoproto.moretags) = "yaml:\"sender\"" ]; + string new_owner = 3 [ (gogoproto.moretags) = "yaml:\"new_owner\"" ]; +} + +message MsgTransferPositionsResponse {} diff --git a/tests/cl-genesis-positions/go.mod b/tests/cl-genesis-positions/go.mod index 34215981408..e37651bbd72 100644 --- a/tests/cl-genesis-positions/go.mod +++ b/tests/cl-genesis-positions/go.mod @@ -106,7 +106,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect diff --git a/tests/cl-go-client/go.mod b/tests/cl-go-client/go.mod index 0331186c060..cbbc10ad691 100644 --- a/tests/cl-go-client/go.mod +++ b/tests/cl-go-client/go.mod @@ -94,7 +94,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect diff --git a/x/concentrated-liquidity/client/cli/tx.go b/x/concentrated-liquidity/client/cli/tx.go index 3e5035c207f..9425f5f0bae 100644 --- a/x/concentrated-liquidity/client/cli/tx.go +++ b/x/concentrated-liquidity/client/cli/tx.go @@ -30,6 +30,7 @@ func NewTxCmd() *cobra.Command { osmocli.AddTxCmd(txCmd, NewCollectSpreadRewardsCmd) osmocli.AddTxCmd(txCmd, NewCollectIncentivesCmd) osmocli.AddTxCmd(txCmd, NewFungifyChargedPositionsCmd) + osmocli.AddTxCmd(txCmd, NewTransferPositionsCmd) return txCmd } @@ -94,6 +95,14 @@ func NewFungifyChargedPositionsCmd() (*osmocli.TxCliDesc, *types.MsgFungifyCharg }, &types.MsgFungifyChargedPositions{} } +func NewTransferPositionsCmd() (*osmocli.TxCliDesc, *types.MsgTransferPositions) { + return &osmocli.TxCliDesc{ + Use: "transfer-positions", + Short: "transfer a list of concentrated liquidity positions to a new owner", + Example: "osmosisd tx concentratedliquidity transfer-positions 56,89,1011 osmo10fhdy8zhepstpwsr9l4a8yxuyggqmpqx4ktheq --from val --chain-id osmosis-1 -b block --keyring-backend test --fees 1000uosmo", + }, &types.MsgTransferPositions{} +} + // NewCmdCreateConcentratedLiquidityPoolsProposal implements a command handler for create concentrated liquidity pool proposal func NewCmdCreateConcentratedLiquidityPoolsProposal() *cobra.Command { cmd := &cobra.Command{ diff --git a/x/concentrated-liquidity/export_test.go b/x/concentrated-liquidity/export_test.go index 54c7b6f65c7..8387c15488c 100644 --- a/x/concentrated-liquidity/export_test.go +++ b/x/concentrated-liquidity/export_test.go @@ -328,3 +328,7 @@ func (k Keeper) SetupSwapStrategy(ctx sdk.Context, p types.ConcentratedPoolExten func MoveRewardsToNewPositionAndDeleteOldAcc(ctx sdk.Context, accum *accum.AccumulatorObject, oldPositionName, newPositionName string, growthOutside sdk.DecCoins) error { return moveRewardsToNewPositionAndDeleteOldAcc(accum, oldPositionName, newPositionName, growthOutside) } + +func (k Keeper) TransferPositions(ctx sdk.Context, positionIds []uint64, sender sdk.AccAddress, recipient sdk.AccAddress) error { + return k.transferPositions(ctx, positionIds, sender, recipient) +} diff --git a/x/concentrated-liquidity/fuzz_test.go b/x/concentrated-liquidity/fuzz_test.go index acd3d821bb4..eedfdbde54b 100644 --- a/x/concentrated-liquidity/fuzz_test.go +++ b/x/concentrated-liquidity/fuzz_test.go @@ -136,6 +136,11 @@ func (s *KeeperTestSuite) fuzzTestWithSeed(r *rand.Rand, poolId uint64, numSwaps completedPositions++ } + if r.Intn(2) == 0 { + // at some interval, transfer position to a new account + s.transferRandomPosition(r) + } + s.assertGlobalInvariants(ExpectedGlobalRewardValues{}) } } @@ -545,6 +550,42 @@ func (s *KeeperTestSuite) removeRandomPosition(r *rand.Rand) { } } +func (s *KeeperTestSuite) transferRandomPosition(r *rand.Rand) { + if len(s.positionData) == 0 { + return + } + + positionIndexToRemove := r.Intn(len(s.positionData)) + positionData := s.positionData[positionIndexToRemove] + + positionIdToTransfer := positionData.positionId + + liqToTransfer := positionData.liquidity + + originalOwner := s.TestAccs[positionData.accountIndex] + + newOwnerIndex := r.Intn(len(s.TestAccs)) + newOwner := s.TestAccs[newOwnerIndex] + + if originalOwner.Equals(newOwner) { + return + } + + fmt.Println("transferring position: ", "position id", positionIdToTransfer, "liqToTransfer", liqToTransfer, "from account: ", originalOwner.String(), "to account: ", newOwner.String()) + + err := s.App.ConcentratedLiquidityKeeper.TransferPositions(s.Ctx, []uint64{positionIdToTransfer}, originalOwner, newOwner) + s.Require().NoError(err) + + // remove position from slice + s.positionData = append(s.positionData[:positionIndexToRemove], s.positionData[positionIndexToRemove+1:]...) + + s.positionData = append(s.positionData, positionAndLiquidity{ + positionId: positionIdToTransfer, + liquidity: liqToTransfer, + accountIndex: newOwnerIndex, + }) +} + // returns multiplier of the liqudity to withdraw func (s *KeeperTestSuite) choosePartialOrFullWithdraw(r *rand.Rand) osmomath.Dec { multiplier := osmomath.OneDec() diff --git a/x/concentrated-liquidity/incentives.go b/x/concentrated-liquidity/incentives.go index 95224177152..0e1ff17daac 100644 --- a/x/concentrated-liquidity/incentives.go +++ b/x/concentrated-liquidity/incentives.go @@ -760,14 +760,18 @@ func (k Keeper) collectIncentives(ctx sdk.Context, sender sdk.AccAddress, positi } // Send the collected incentives to the position's owner from the pool's address. - if err := k.bankKeeper.SendCoins(ctx, pool.GetIncentivesAddress(), sender, collectedIncentivesForPosition); err != nil { - return sdk.Coins{}, sdk.Coins{}, err + if !collectedIncentivesForPosition.IsZero() { + if err := k.bankKeeper.SendCoins(ctx, pool.GetIncentivesAddress(), sender, collectedIncentivesForPosition); err != nil { + return sdk.Coins{}, sdk.Coins{}, err + } } // Send the forfeited incentives to the community pool from the pool's address. - err = k.communityPoolKeeper.FundCommunityPool(ctx, forfeitedIncentivesForPosition, pool.GetIncentivesAddress()) - if err != nil { - return sdk.Coins{}, sdk.Coins{}, err + if !forfeitedIncentivesForPosition.IsZero() { + err = k.communityPoolKeeper.FundCommunityPool(ctx, forfeitedIncentivesForPosition, pool.GetIncentivesAddress()) + if err != nil { + return sdk.Coins{}, sdk.Coins{}, err + } } // Emit an event indicating that incentives were collected. diff --git a/x/concentrated-liquidity/msg_server.go b/x/concentrated-liquidity/msg_server.go index 1af37cf0aba..113c8f4ba0c 100644 --- a/x/concentrated-liquidity/msg_server.go +++ b/x/concentrated-liquidity/msg_server.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/osmosis-labs/osmosis/osmomath" + "github.com/osmosis-labs/osmosis/osmoutils/osmocli" clmodel "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity/model" "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity/types" ) @@ -201,3 +202,39 @@ func (server msgServer) CollectIncentives(goCtx context.Context, msg *types.MsgC return &types.MsgCollectIncentivesResponse{CollectedIncentives: totalCollectedIncentives, ForfeitedIncentives: totalForefeitedIncentives}, nil } + +func (server msgServer) TransferPositions(goCtx context.Context, msg *types.MsgTransferPositions) (*types.MsgTransferPositionsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + newOwner, err := sdk.AccAddressFromBech32(msg.NewOwner) + if err != nil { + return nil, err + } + + err = server.keeper.transferPositions(ctx, msg.PositionIds, sender, newOwner) + if err != nil { + return nil, err + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + ), + sdk.NewEvent( + types.TypeEvtTransferPositions, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + sdk.NewAttribute(types.AttributeNewOwner, msg.NewOwner), + sdk.NewAttribute(types.AttributeInputPositionIds, osmocli.ParseUint64SliceToString(msg.PositionIds)), + ), + }) + + return &types.MsgTransferPositionsResponse{}, nil +} diff --git a/x/concentrated-liquidity/msg_server_test.go b/x/concentrated-liquidity/msg_server_test.go index 88f9c6c4ebe..512a59af72c 100644 --- a/x/concentrated-liquidity/msg_server_test.go +++ b/x/concentrated-liquidity/msg_server_test.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/osmosis-labs/osmosis/osmomath" + "github.com/osmosis-labs/osmosis/v19/app/apptesting" cl "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity" clmodel "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity/model" "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity/types" @@ -159,7 +160,7 @@ func (s *KeeperTestSuite) TestAddToPosition_Events() { }{ "happy path": { expectedAddedToPositionEvent: 1, - expectedMessageEvents: 5, + expectedMessageEvents: 4, }, "error: last position in pool": { lastPositionInPool: true, @@ -545,3 +546,142 @@ func (s *KeeperTestSuite) TestFungify_Events() { }) } } + +func (s *KeeperTestSuite) TestTransferPositions_Events() { + // expectedUptimes are used for claimable incentives tests + expectedUptimes := getExpectedUptimes() + + testcases := map[string]struct { + positionIds []uint64 + numPositionsToCreate int + shouldSetupUnownedPosition bool + hasIncentivesToClaim bool + hasSpreadRewardsToClaim bool + expectedTransferPositionsEvent int + expectedMessageEvents int + isLastPositionInPool bool + expectedError error + }{ + "single position ID": { + positionIds: []uint64{DefaultPositionId}, + numPositionsToCreate: 1, + expectedTransferPositionsEvent: 1, + expectedMessageEvents: 1, // 1 for transfer + }, + "single position ID with claimable incentives": { + positionIds: []uint64{DefaultPositionId}, + hasIncentivesToClaim: true, + numPositionsToCreate: 1, + expectedTransferPositionsEvent: 1, + expectedMessageEvents: 3, // 1 for transfer, 1 for collect incentives claim send, 1 for collect incentives forfeit send + }, + "single position ID with claimable spread rewards": { + positionIds: []uint64{DefaultPositionId}, + hasSpreadRewardsToClaim: true, + numPositionsToCreate: 1, + expectedTransferPositionsEvent: 1, + expectedMessageEvents: 2, // 1 for transfer, 1 for collect spread rewards claim send + }, + "single position ID with claimable incentives and spread rewards": { + positionIds: []uint64{DefaultPositionId}, + hasIncentivesToClaim: true, + hasSpreadRewardsToClaim: true, + numPositionsToCreate: 1, + expectedTransferPositionsEvent: 1, + expectedMessageEvents: 4, // 1 for transfer, 1 for collect incentives claim send, 1 for collect incentives forfeit send, 1 for collect spread rewards claim send + }, + "two position IDs": { + positionIds: []uint64{DefaultPositionId, DefaultPositionId + 1}, + numPositionsToCreate: 2, + expectedTransferPositionsEvent: 1, + expectedMessageEvents: 1, // 1 for transfer + }, + "three position IDs": { + positionIds: []uint64{DefaultPositionId, DefaultPositionId + 1, DefaultPositionId + 2}, + numPositionsToCreate: 3, + expectedTransferPositionsEvent: 1, + expectedMessageEvents: 1, // 1 for transfer + }, + "three position IDs with claimable incentives and spread rewards": { + positionIds: []uint64{DefaultPositionId, DefaultPositionId + 1, DefaultPositionId + 2}, + hasIncentivesToClaim: true, + hasSpreadRewardsToClaim: true, + numPositionsToCreate: 3, + expectedTransferPositionsEvent: 1, + expectedMessageEvents: 10, // 1 for transfer, 3 for collect incentives claim send, 3 for collect incentives forfeit send, 3 for collect spread rewards claim send + }, + "two position IDs, second ID does not exist": { + positionIds: []uint64{DefaultPositionId, DefaultPositionId + 1}, + numPositionsToCreate: 1, + expectedError: types.PositionIdNotFoundError{PositionId: DefaultPositionId + 1}, + }, + "three position IDs, not an owner of one of them": { + positionIds: []uint64{DefaultPositionId, DefaultPositionId + 1, DefaultPositionId + 2}, + numPositionsToCreate: 2, + shouldSetupUnownedPosition: true, + expectedError: types.NotPositionOwnerError{}, + }, + } + + for name, tc := range testcases { + s.Run(name, func() { + s.SetupTest() + + // Create a cl pool with a default position + pool := s.PrepareConcentratedPool() + for i := 0; i < tc.numPositionsToCreate; i++ { + s.SetupDefaultPosition(pool.GetId()) + } + + if tc.shouldSetupUnownedPosition { + // Position from another account. + s.SetupDefaultPositionAcc(pool.GetId(), s.TestAccs[1]) + } + + if tc.hasIncentivesToClaim { + s.fundIncentiveAddr(s.Ctx, pool.GetIncentivesAddress(), tc.positionIds) + s.addUptimeGrowthInsideRange(s.Ctx, pool.GetId(), s.TestAccs[0], apptesting.DefaultLowerTick+1, DefaultLowerTick, DefaultUpperTick, expectedUptimes.hundredTokensMultiDenom) + } + + if tc.hasSpreadRewardsToClaim { + s.fundSpreadRewardsAddr(s.Ctx, pool.GetSpreadRewardsAddress(), tc.positionIds) + s.AddToSpreadRewardAccumulator(pool.GetId(), sdk.NewDecCoin(ETH, osmomath.NewInt(10))) + } + + // Move block time forward one day to claim and forfeit part of the incentives. + s.Ctx = s.Ctx.WithBlockTime(s.Ctx.BlockTime().Add(time.Hour * 24)) + + if !tc.isLastPositionInPool { + // Setup a far out of range position that we do not touch, so when we transfer positions we do not transfer the last position in the pool. + // This is because we special case this logic in the keeper to not allow the last position in the pool to be transferred. + s.SetupPosition(pool.GetId(), s.TestAccs[2], sdk.NewCoins(DefaultCoin1), DefaultMinTick, DefaultMinTick+100, true) + } + + msgServer := cl.NewMsgServerImpl(s.App.ConcentratedLiquidityKeeper) + + // Reset event counts to 0 by creating a new manager. + s.Ctx = s.Ctx.WithEventManager(sdk.NewEventManager()) + s.Equal(0, len(s.Ctx.EventManager().Events())) + + msg := &types.MsgTransferPositions{ + PositionIds: tc.positionIds, + Sender: s.TestAccs[0].String(), + NewOwner: s.TestAccs[1].String(), + } + + // System under test + response, err := msgServer.TransferPositions(sdk.WrapSDKContext(s.Ctx), msg) + + if tc.expectedError == nil { + s.Require().NoError(err) + s.Require().NotNil(response) + s.AssertEventEmitted(s.Ctx, types.TypeEvtTransferPositions, tc.expectedTransferPositionsEvent) + s.AssertEventEmitted(s.Ctx, sdk.EventTypeMessage, tc.expectedMessageEvents) + } else { + s.Require().Error(err) + s.Require().ErrorAs(err, &tc.expectedError) + s.Require().Nil(response) + } + }) + } +} diff --git a/x/concentrated-liquidity/position.go b/x/concentrated-liquidity/position.go index 0f4844cb41a..acda80827b8 100644 --- a/x/concentrated-liquidity/position.go +++ b/x/concentrated-liquidity/position.go @@ -14,6 +14,7 @@ import ( "github.com/osmosis-labs/osmosis/osmomath" "github.com/osmosis-labs/osmosis/osmoutils" "github.com/osmosis-labs/osmosis/osmoutils/accum" + "github.com/osmosis-labs/osmosis/osmoutils/osmoassert" "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity/model" "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity/types" lockuptypes "github.com/osmosis-labs/osmosis/v19/x/lockup/types" @@ -664,3 +665,105 @@ func (k Keeper) updateFullRangeLiquidityInPool(ctx sdk.Context, poolId uint64, l osmoutils.MustSetDec(store, poolIdLiquidityKey, newTotalFullRangeLiquidity) return nil } + +// transferPositions transfers ownership of a set of positions from a sender to a recipient. +// It first checks if the provided position IDs are unique. If not, it returns a DuplicatePositionIdsError. +// For each position ID, it retrieves the corresponding position and checks if the sender is the owner of the position. +// If the sender is not the owner, it returns an error. +// It then checks if the position has an active underlying lock, and if so, returns an error. +// It then collects any outstanding incentives and rewards for the position, deletes the KVStore entries for the position, +// and restores the position under the recipient's account. +// If any of these operations fail, it returns the corresponding error. +// If all operations succeed, it returns nil. +func (k Keeper) transferPositions(ctx sdk.Context, positionIds []uint64, sender sdk.AccAddress, recipient sdk.AccAddress) error { + // Fixed gas consumption per position ID to prevent spam + ctx.GasMeter().ConsumeGas(uint64(types.BaseGasFeeForTransferPosition*len(positionIds)), "cl transfer position fee") + + // All position IDs in the array must be unique. + if !osmoassert.Uint64ArrayValuesAreUnique(positionIds) { + return types.DuplicatePositionIdsError{PositionIds: positionIds} + } + + for _, positionId := range positionIds { + position, err := k.GetPosition(ctx, positionId) + if err != nil { + return err + } + + // Check that the sender is the owner of the position. + if position.Address != sender.String() { + return types.PositionOwnerMismatchError{PositionOwner: position.Address, Sender: sender.String()} + } + + // If the position has an active underlying lock, we cannot transfer it. + positionHasActiveUnderlyingLock, lockId, err := k.positionHasActiveUnderlyingLockAndUpdate(ctx, positionId) + if err != nil { + return err + } + if positionHasActiveUnderlyingLock { + return types.LockNotMatureError{PositionId: position.PositionId, LockId: lockId} + } + + // Collect any outstanding incentives and rewards for the position. + if _, err := k.collectSpreadRewards(ctx, sender, positionId); err != nil { + return err + } + if _, _, err := k.collectIncentives(ctx, sender, positionId); err != nil { + return err + } + + // Delete the KVStore entries for the position. + err = k.deletePosition(ctx, positionId, sender, position.PoolId) + if err != nil { + return err + } + + // There exists special logic branches we take if a position is the last position in a pool and it is withdrawn. + // It makes sense to accept the small annoyance of preventing a position from being transferred if it is the last position in a pool + // instead of considering all the edge cases that would arise if we allowed it. + anyPositionsRemainingInPool, err := k.HasAnyPositionForPool(ctx, position.PoolId) + if err != nil { + return err + } + if !anyPositionsRemainingInPool { + return types.LastPositionTransferError{PositionId: positionId, PoolId: position.PoolId} + } + + // Restore the position under the recipient's account. + err = k.SetPosition(ctx, position.PoolId, recipient, position.LowerTick, position.UpperTick, position.JoinTime, position.Liquidity, position.PositionId, 0) + if err != nil { + return err + } + } + + return nil +} + +// underlyingPositionsValue calculates the value of the underlying assets in the given positions. +func (k Keeper) UnderlyingPositionsValue(ctx sdk.Context, positionIds []uint64) (sdk.Coins, error) { + underlyingAssets := sdk.Coins{} + + for _, positionId := range positionIds { + position, err := k.GetPosition(ctx, positionId) + if err != nil { + return sdk.Coins{}, err + } + + pool, err := k.GetConcentratedPoolById(ctx, position.PoolId) + if err != nil { + return sdk.Coins{}, err + } + + asset0, asset1, err := pool.CalcActualAmounts(ctx, position.LowerTick, position.UpperTick, position.Liquidity) + if err != nil { + return sdk.Coins{}, err + } + + underlyingAssets = underlyingAssets.Add( + sdk.NewCoin(pool.GetToken0(), asset0.TruncateInt()), + sdk.NewCoin(pool.GetToken1(), asset1.TruncateInt()), + ) + } + + return underlyingAssets, nil +} diff --git a/x/concentrated-liquidity/position_test.go b/x/concentrated-liquidity/position_test.go index b2149c414b5..5e49fe5a403 100644 --- a/x/concentrated-liquidity/position_test.go +++ b/x/concentrated-liquidity/position_test.go @@ -10,6 +10,7 @@ import ( "github.com/osmosis-labs/osmosis/osmomath" "github.com/osmosis-labs/osmosis/osmoutils" "github.com/osmosis-labs/osmosis/osmoutils/accum" + "github.com/osmosis-labs/osmosis/osmoutils/osmoassert" "github.com/osmosis-labs/osmosis/v19/app/apptesting" cl "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity" "github.com/osmosis-labs/osmosis/v19/x/concentrated-liquidity/math" @@ -2245,3 +2246,310 @@ func (s *KeeperTestSuite) TestNegativeTickRange_SpreadFactor() { s.clk.InitGenesis(s.Ctx, *export) } + +// TestTransferPositions validates the following: +// - Positions can be transferred from one owner to another. +// - The transfer of positions does not modify the positions that are not transferred. +// - The outstanding incentives and spread rewards go to the old owner after the transfer. +// - The new owner does not receive the outstanding incentives and spread rewards after the transfer. +// - Claiming incentives/spread rewards with the new owner returns nothing after the transfer. +// - Adding incentives/spread rewards and then claiming returns it to the new owner, and the old owner does not get anything. +// - The new owner can withdraw the positions and receive the correct amount of funds. +// The test also checks for expected errors such as: +// - Attempting to transfer a position ID that does not exist. +// - Attempting to transfer a position that the sender does not own. +// - Attempting to transfer the last position in the pool. +func (s *KeeperTestSuite) TestTransferPositions() { + // expectedUptimes are used for claimable incentives tests + expectedUptimes := getExpectedUptimes() + + errTolerance := osmomath.ErrTolerance{ + AdditiveTolerance: osmomath.NewDec(1), + // Actual amount should be less than expected, so we round down + // This is because when we withdraw the position, we always round in favor of the pool + RoundingDir: osmomath.RoundDown, + } + + oldOwner := s.TestAccs[0] + newOwner := s.TestAccs[1] + + testcases := map[string]struct { + inRangePositions []uint64 + outOfRangePositions []uint64 + positionsToTransfer []uint64 + setupUnownedPosition bool + isLastPositionInPool bool + + expectedError error + }{ + "single position ID in range": { + inRangePositions: []uint64{DefaultPositionId}, + positionsToTransfer: []uint64{DefaultPositionId}, + }, + "two position IDs, one in range, one out of range": { + inRangePositions: []uint64{DefaultPositionId}, + outOfRangePositions: []uint64{DefaultPositionId + 1}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 1}, + }, + "two position IDs in range": { + inRangePositions: []uint64{DefaultPositionId, DefaultPositionId + 1}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 1}, + }, + "three position IDs in range": { + inRangePositions: []uint64{DefaultPositionId, DefaultPositionId + 1, DefaultPositionId + 2}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 1, DefaultPositionId + 2}, + }, + "three position IDs, two in range, one out of range": { + inRangePositions: []uint64{DefaultPositionId, DefaultPositionId + 1}, + outOfRangePositions: []uint64{DefaultPositionId + 2}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 1, DefaultPositionId + 2}, + }, + "three position IDs, two in range, one out of range, only transfer the two in range": { + inRangePositions: []uint64{DefaultPositionId, DefaultPositionId + 1}, + outOfRangePositions: []uint64{DefaultPositionId + 2}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 1}, + }, + "three position IDs, one in range, two out of range, transfer one in range and one out of range": { + inRangePositions: []uint64{DefaultPositionId}, + outOfRangePositions: []uint64{DefaultPositionId + 1, DefaultPositionId + 2}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 2}, + }, + "error: two position IDs, second ID does not exist": { + inRangePositions: []uint64{DefaultPositionId, DefaultPositionId + 1}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 3}, + expectedError: types.PositionIdNotFoundError{PositionId: DefaultPositionId + 3}, + }, + "error: three position IDs, not an owner of one of them": { + inRangePositions: []uint64{DefaultPositionId, DefaultPositionId + 1}, + positionsToTransfer: []uint64{DefaultPositionId, DefaultPositionId + 1, DefaultPositionId + 2}, + setupUnownedPosition: true, + expectedError: types.PositionOwnerMismatchError{PositionOwner: newOwner.String(), Sender: oldOwner.String()}, + }, + "error: attempt to transfer last position in pool": { + inRangePositions: []uint64{DefaultPositionId}, + positionsToTransfer: []uint64{DefaultPositionId}, + isLastPositionInPool: true, + expectedError: types.LastPositionTransferError{PositionId: DefaultPositionId, PoolId: 1}, + }, + } + + for name, tc := range testcases { + s.Run(name, func() { + s.SetupTest() + pool := s.PrepareConcentratedPool() + + lastPositionId := 0 + + // Setup in range positions + for i := 0; i < len(tc.inRangePositions); i++ { + s.SetupDefaultPosition(pool.GetId()) + lastPositionId++ + } + + // Setup out of range positions + for i := 0; i < len(tc.outOfRangePositions); i++ { + // Position with out of range ticks. + s.SetupPosition(pool.GetId(), oldOwner, sdk.NewCoins(DefaultCoin1), DefaultMinTick, DefaultMinTick+100, true) + lastPositionId++ + } + + // Setup unowned position (owned by newOwner) + if tc.setupUnownedPosition { + s.SetupDefaultPositionAcc(pool.GetId(), newOwner) + lastPositionId++ + } + + // Setup a far out of range position that we do not touch, so when we transfer positions we do not transfer the last position in the pool. + // This is because we special case this logic in the keeper to not allow the last position in the pool to be transferred. + if !tc.isLastPositionInPool { + s.SetupPosition(pool.GetId(), s.TestAccs[2], sdk.NewCoins(DefaultCoin0), DefaultMaxTick-100, DefaultMaxTick, true) + } + + // For each position that is in range, add spread rewards and incentives to their respective addresses + totalSpreadRewards := s.fundSpreadRewardsAddr(s.Ctx, pool.GetSpreadRewardsAddress(), tc.inRangePositions) + totalIncentives := s.fundIncentiveAddr(s.Ctx, pool.GetIncentivesAddress(), tc.inRangePositions) + totalExpectedRewards := totalSpreadRewards.Add(totalIncentives...) + + // Add spread rewards and incentives to the pool + s.addUptimeGrowthInsideRange(s.Ctx, pool.GetId(), oldOwner, apptesting.DefaultLowerTick+1, DefaultLowerTick, DefaultUpperTick, expectedUptimes.hundredTokensMultiDenom) + s.AddToSpreadRewardAccumulator(pool.GetId(), sdk.NewDecCoin(ETH, osmomath.NewInt(10))) + + // Move block time forward. In the event we have positions in range + // this allows us to test both collected and forfeited incentives + s.Ctx = s.Ctx.WithBlockTime(s.Ctx.BlockTime().Add(time.Hour * 24)) + + initialUserPositions, err := s.App.ConcentratedLiquidityKeeper.GetUserPositions(s.Ctx, oldOwner, 1) + s.Require().NoError(err) + + // Account funds of original owner + preTransferOwnerFunds := s.App.BankKeeper.GetAllBalances(s.Ctx, oldOwner) + + // Account funds of new owner + preTransferNewOwnerFunds := s.App.BankKeeper.GetAllBalances(s.Ctx, newOwner) + + // System under test + err = s.App.ConcentratedLiquidityKeeper.TransferPositions(s.Ctx, tc.positionsToTransfer, oldOwner, newOwner) + + if tc.expectedError != nil { + s.Require().Error(err) + s.Require().ErrorIs(err, tc.expectedError) + } else { + s.Require().NoError(err) + + // Check that the positions we wanted transferred were modified appropriately + for _, positionId := range tc.positionsToTransfer { + newPosition, err := s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionId) + s.Require().NoError(err) + + oldPosition := model.Position{} + for _, initialPosition := range initialUserPositions { + if initialPosition.PositionId == newPosition.PositionId { + oldPosition = initialPosition + break + } + } + + // All position values except the owner should be the same in the new position as it was in the old one. + s.Require().Equal(oldPosition.UpperTick, newPosition.UpperTick) + s.Require().Equal(oldPosition.LowerTick, newPosition.LowerTick) + s.Require().Equal(oldPosition.PoolId, newPosition.PoolId) + s.Require().Equal(oldPosition.JoinTime, newPosition.JoinTime) + s.Require().Equal(oldPosition.Liquidity, newPosition.Liquidity) + + // The new position should have the new owner + s.Require().Equal(newOwner.String(), newPosition.Address) + } + + allPositions := append(tc.inRangePositions, tc.outOfRangePositions...) + positionsNotTransfered := osmoutils.DisjointArrays(allPositions, tc.positionsToTransfer) + + // Check that the positions not transferred were not modified + for _, positionId := range positionsNotTransfered { + oldPosition, err := s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionId) + s.Require().NoError(err) + + newPosition := model.Position{} + for _, initialPosition := range initialUserPositions { + if initialPosition.PositionId == oldPosition.PositionId { + newPosition = initialPosition + break + } + } + + // All position values should be the same in the new position as it was in the old one. + s.Require().Equal(oldPosition, newPosition) + } + + // Check that the incentives and spread rewards went to the old owner + postTransferOriginalOwnerFunds := s.App.BankKeeper.GetAllBalances(s.Ctx, oldOwner) + expectedTransferOriginalOwnerFunds := preTransferOwnerFunds.Add(totalExpectedRewards...) + s.Require().Equal(expectedTransferOriginalOwnerFunds.String(), postTransferOriginalOwnerFunds.String()) + + // Check that the new owner does not have any new funds + postTransferNewOwnerFunds := s.App.BankKeeper.GetAllBalances(s.Ctx, newOwner) + s.Require().Equal(preTransferNewOwnerFunds, postTransferNewOwnerFunds) + + // Test that claiming incentives/spread rewards with the new owner returns nothing + for _, positionId := range tc.positionsToTransfer { + fundsToClaim, fundsToForefeit, err := s.App.ConcentratedLiquidityKeeper.GetClaimableIncentives(s.Ctx, positionId) + s.Require().NoError(err) + s.Require().Equal(sdk.Coins(nil), fundsToClaim) + s.Require().Equal(sdk.Coins(nil), fundsToForefeit) + + spreadRewards, err := s.App.ConcentratedLiquidityKeeper.GetClaimableSpreadRewards(s.Ctx, positionId) + s.Require().NoError(err) + s.Require().Equal(sdk.Coins(nil), spreadRewards) + } + + // Test that adding incentives/spread rewards and then claiming returns it to the new owner, and the old owner does not get anything + totalSpreadRewards := s.fundSpreadRewardsAddr(s.Ctx, pool.GetSpreadRewardsAddress(), tc.inRangePositions) + totalIncentives := s.fundIncentiveAddr(s.Ctx, pool.GetIncentivesAddress(), tc.inRangePositions) + totalExpectedRewards := totalSpreadRewards.Add(totalIncentives...) + s.addUptimeGrowthInsideRange(s.Ctx, pool.GetId(), oldOwner, apptesting.DefaultLowerTick+1, DefaultLowerTick, DefaultUpperTick, expectedUptimes.hundredTokensMultiDenom) + s.AddToSpreadRewardAccumulator(pool.GetId(), sdk.NewDecCoin(ETH, osmomath.NewInt(10))) + for _, positionId := range tc.positionsToTransfer { + _, _, err := s.App.ConcentratedLiquidityKeeper.CollectIncentives(s.Ctx, newOwner, positionId) + s.Require().NoError(err) + _, err = s.App.ConcentratedLiquidityKeeper.CollectSpreadRewards(s.Ctx, newOwner, positionId) + s.Require().NoError(err) + } + // New owner balance check + postSecondTransferNewOwnerFunds := s.App.BankKeeper.GetAllBalances(s.Ctx, newOwner) + expectedSecondTransferNewOwnerFunds := postTransferNewOwnerFunds.Add(totalExpectedRewards...) + s.Require().Equal(expectedSecondTransferNewOwnerFunds.String(), postSecondTransferNewOwnerFunds.String()) + // Old owner balance check + postSecondTransferOriginalOwnerFunds := s.App.BankKeeper.GetAllBalances(s.Ctx, oldOwner) + s.Require().Equal(postTransferOriginalOwnerFunds, postSecondTransferOriginalOwnerFunds) + + // Test that withdrawing the positions returns the correct amount of funds to the new owner + for _, positionId := range tc.positionsToTransfer { + underlyingPositionsValue, err := s.App.ConcentratedLiquidityKeeper.UnderlyingPositionsValue(s.Ctx, []uint64{positionId}) + s.Require().NoError(err) + position, err := s.App.ConcentratedLiquidityKeeper.GetPosition(s.Ctx, positionId) + s.Require().NoError(err) + amt0, amt1, err := s.App.ConcentratedLiquidityKeeper.WithdrawPosition(s.Ctx, newOwner, positionId, position.Liquidity) + s.Require().NoError(err) + coinsWithdrawn := sdk.NewCoins(sdk.NewCoin(pool.GetToken0(), amt0), sdk.NewCoin(pool.GetToken1(), amt1)) + // Amount we withdraw is one less than actual value due to rounding in favor of pool + for i, coin := range coinsWithdrawn { + osmoassert.Equal( + s.T(), + errTolerance, + underlyingPositionsValue[i].Amount, + coin.Amount, + ) + } + } + } + }) + } +} + +// fundIncentiveAddr funds the incentive address for each position ID in the provided slice. +// It calculates the expected incentives based on uptime growth and adds these incentives to the total expected rewards. +// It also determines how much position will forfeit and funds this amount to the incentive address. +// The function returns the total expected rewards after funding all the positions. +// +// Parameters: +// - ctx: The context of the operation. +// - incentivesAddress: The address to which the incentives will be funded. +// - positionIds: A slice of position IDs for which the incentives will be funded. +// +// Returns: +// - totalExpectedRewards: The total expected rewards after funding all the positions. +func (s *KeeperTestSuite) fundIncentiveAddr(ctx sdk.Context, incentivesAddress sdk.AccAddress, positionIds []uint64) (totalExpectedRewards sdk.Coins) { + expectedUptimes := getExpectedUptimes() + for i := 0; i < len(positionIds); i++ { + coinsToFundForIncentivesToUser := expectedIncentivesFromUptimeGrowth(expectedUptimes.hundredTokensMultiDenom, DefaultLiquidityAmt, time.Hour*24, defaultMultiplier) + totalExpectedRewards = totalExpectedRewards.Add(coinsToFundForIncentivesToUser...) + s.FundAcc(incentivesAddress, coinsToFundForIncentivesToUser) + // Determine how much position will forfeit and fund + coinsToFundForForefeitToPool := expectedIncentivesFromUptimeGrowth(expectedUptimes.hundredTokensMultiDenom, DefaultLiquidityAmt, time.Hour*24*14, defaultMultiplier).Sub(expectedIncentivesFromUptimeGrowth(expectedUptimes.hundredTokensMultiDenom, DefaultLiquidityAmt, time.Hour*24, defaultMultiplier)) + s.FundAcc(incentivesAddress, coinsToFundForForefeitToPool) + } + return +} + +// fundSpreadRewardsAddr funds the spread rewards address for each position ID in the provided slice. +// It calculates the expected amount to claim based on the position's liquidity and adds these rewards to the total expected rewards. +// The function then funds the spread rewards account with the total expected rewards. +// +// Parameters: +// - ctx: The context of the operation. +// - spreadRewardsAddress: The address to which the spread rewards will be funded. +// - positionIds: A slice of position IDs for which the spread rewards will be funded. +// +// Returns: +// - totalExpectedRewards: The total expected rewards after funding all the positions. +func (s *KeeperTestSuite) fundSpreadRewardsAddr(ctx sdk.Context, spreadRewardsAddress sdk.AccAddress, positionIds []uint64) (totalExpectedRewards sdk.Coins) { + for _, positionId := range positionIds { + position, err := s.App.ConcentratedLiquidityKeeper.GetPosition(ctx, positionId) + s.Require().NoError(err) + + expectedAmountToClaim := position.Liquidity.MulInt(osmomath.NewInt(10)).TruncateInt() + totalExpectedRewards = totalExpectedRewards.Add(sdk.NewCoin(ETH, expectedAmountToClaim)) + // Fund the spread rewards account with the expected rewards and add to the pool's accum + s.FundAcc(spreadRewardsAddress, totalExpectedRewards) + } + return +} diff --git a/x/concentrated-liquidity/spread_rewards.go b/x/concentrated-liquidity/spread_rewards.go index af5e84ac1df..1541fef20ad 100644 --- a/x/concentrated-liquidity/spread_rewards.go +++ b/x/concentrated-liquidity/spread_rewards.go @@ -174,6 +174,11 @@ func (k Keeper) collectSpreadRewards(ctx sdk.Context, sender sdk.AccAddress, pos return sdk.Coins{}, err } + // Early return, emit no events if there is no spread rewards to claim. + if spreadRewardsClaimed.IsZero() { + return sdk.Coins{}, nil + } + // Send the claimed spread rewards from the pool's address to the owner's address. pool, err := k.getPoolById(ctx, position.PoolId) if err != nil { @@ -253,7 +258,7 @@ func (k Keeper) prepareClaimableSpreadRewards(ctx sdk.Context, positionId uint64 return nil, err } - // add foreited dust back to the global accumulator + // add forfeited dust back to the global accumulator if !forfeitedDust.IsZero() { // Refetch the spread reward accumulator as the number of shares has changed after claiming. spreadRewardAccumulator, err := k.GetSpreadRewardAccumulator(ctx, position.PoolId) diff --git a/x/concentrated-liquidity/spread_rewards_test.go b/x/concentrated-liquidity/spread_rewards_test.go index 37e5bd86d92..572ab624fbe 100644 --- a/x/concentrated-liquidity/spread_rewards_test.go +++ b/x/concentrated-liquidity/spread_rewards_test.go @@ -1476,7 +1476,7 @@ func (s *KeeperTestSuite) TestFunctional_SpreadRewards_LP() { collectedThree, err := s.App.ConcentratedLiquidityKeeper.CollectSpreadRewards(ctx, owner, positionDataThree.ID) s.Require().NoError(err) - s.Require().Equal(sdk.Coins(nil), collectedThree) + s.Require().Equal(sdk.Coins{}, collectedThree) } // This test validates that spread rewards are collected without issues @@ -1576,7 +1576,7 @@ func (s *KeeperTestSuite) tickStatusInvariance(ticksActivatedAfterEachSwap [][]i } } else { // If the position was not active, check that the spread rewards collected are zero - s.Require().Nil(coins) + s.Require().Equal(sdk.Coins{}, coins) } } } diff --git a/x/concentrated-liquidity/types/constants.go b/x/concentrated-liquidity/types/constants.go index d48c0ebbf40..08f38889f2b 100644 --- a/x/concentrated-liquidity/types/constants.go +++ b/x/concentrated-liquidity/types/constants.go @@ -27,6 +27,7 @@ const ( ConcentratedGasFeeForSwap = 10_000 BaseGasFeeForNewIncentive = 10_000 BaseGasFeeForInitializingTick = 10_000 + BaseGasFeeForTransferPosition = 10_000 ) var ( diff --git a/x/concentrated-liquidity/types/errors.go b/x/concentrated-liquidity/types/errors.go index fcff58c65d6..440c73beff4 100644 --- a/x/concentrated-liquidity/types/errors.go +++ b/x/concentrated-liquidity/types/errors.go @@ -896,3 +896,20 @@ type NumberOfTicksExceedsMaxError struct { func (e NumberOfTicksExceedsMaxError) Error() string { return fmt.Sprintf("number of ticks exceeds max ticks. Provided number of ticks (%d), max ticks (%d)", e.NumberOfTicks, e.MaxNumberOfTicks) } + +type DuplicatePositionIdsError struct { + PositionIds []uint64 +} + +func (e DuplicatePositionIdsError) Error() string { + return fmt.Sprintf("duplicate position ids found (%v)", e.PositionIds) +} + +type LastPositionTransferError struct { + PositionId uint64 + PoolId uint64 +} + +func (e LastPositionTransferError) Error() string { + return fmt.Sprintf("cannot transfer position %d because it is the last position in pool %d", e.PositionId, e.PoolId) +} diff --git a/x/concentrated-liquidity/types/events.go b/x/concentrated-liquidity/types/events.go index aaf8d9d0099..e24838d334f 100644 --- a/x/concentrated-liquidity/types/events.go +++ b/x/concentrated-liquidity/types/events.go @@ -12,6 +12,7 @@ const ( TypeEvtFungifyChargedPosition = "fungify_charged_position" TypeEvtMoveRewards = "move_rewards" TypeEvtCrossTick = "cross_tick" + TypeEvtTransferPositions = "transfer_positions" AttributeValueCategory = ModuleName AttributeKeyPositionId = "position_id" @@ -46,4 +47,5 @@ const ( AttributeKeyTickIndex = "tick_idx" AttributeKeySpreadRewardGrowthOppositeDirectionOfLastTraversal = "spread_reward_growth" AttributeKeyUptimeGrowthOppositeDirectionOfLastTraversal = "uptime_growth" + AttributeNewOwner = "new_owner" ) diff --git a/x/concentrated-liquidity/types/msgs.go b/x/concentrated-liquidity/types/msgs.go index 429cd028c1c..89cbd182e94 100644 --- a/x/concentrated-liquidity/types/msgs.go +++ b/x/concentrated-liquidity/types/msgs.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/osmosis-labs/osmosis/osmomath" + "github.com/osmosis-labs/osmosis/osmoutils/osmoassert" ) // constants. @@ -17,6 +18,7 @@ const ( TypeMsgCollectSpreadRewards = "collect-spread-rewards" TypeMsgCollectIncentives = "collect-incentives" TypeMsgFungifyChargedPositions = "fungify-charged-positions" + TypeMsgTransferPositions = "transfer-positions" ) var _ sdk.Msg = &MsgCreatePosition{} @@ -223,3 +225,45 @@ func (msg MsgFungifyChargedPositions) GetSigners() []sdk.AccAddress { } return []sdk.AccAddress{sender} } + +var _ sdk.Msg = &MsgTransferPositions{} + +func (msg MsgTransferPositions) Route() string { return RouterKey } +func (msg MsgTransferPositions) Type() string { return TypeMsgTransferPositions } +func (msg MsgTransferPositions) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return fmt.Errorf("Invalid sender address (%s)", err) + } + + _, err = sdk.AccAddressFromBech32(msg.NewOwner) + if err != nil { + return fmt.Errorf("Invalid new owner address (%s)", err) + } + + if msg.Sender == msg.NewOwner { + return fmt.Errorf("Sender and new owner cannot be the same (%s)", msg.Sender) + } + + if !osmoassert.Uint64ArrayValuesAreUnique(msg.PositionIds) { + return fmt.Errorf("Position IDs must be unique, got %v", msg.PositionIds) + } + + if len(msg.PositionIds) < 1 { + return fmt.Errorf("Must provide at least 1 position ID, got %d", len(msg.PositionIds)) + } + + return nil +} + +func (msg MsgTransferPositions) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg)) +} + +func (msg MsgTransferPositions) GetSigners() []sdk.AccAddress { + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{sender} +} diff --git a/x/concentrated-liquidity/types/msgs_test.go b/x/concentrated-liquidity/types/msgs_test.go index f2fe1f505c8..4797eef0dcb 100644 --- a/x/concentrated-liquidity/types/msgs_test.go +++ b/x/concentrated-liquidity/types/msgs_test.go @@ -21,13 +21,18 @@ type extMsg interface { Type() string } -var addr1 string -var invalidAddr sdk.AccAddress +var ( + addr1 string + addr2 string + invalidAddr sdk.AccAddress +) func init() { appParams.SetAddressPrefixes() pk1 := ed25519.GenPrivKey().PubKey() addr1 = sdk.AccAddress(pk1.Address()).String() + pk2 := ed25519.GenPrivKey().PubKey() + addr2 = sdk.AccAddress(pk2.Address()).String() invalidAddr = sdk.AccAddress("invalid") } @@ -364,3 +369,68 @@ func TestConcentratedLiquiditySerialization(t *testing.T) { }) } } + +func TestMsgTransferPositions(t *testing.T) { + tests := []struct { + name string + msg types.MsgTransferPositions + expectPass bool + }{ + { + name: "proper msg", + msg: types.MsgTransferPositions{ + PositionIds: []uint64{1, 2, 5, 9, 20}, + Sender: addr1, + NewOwner: addr2, + }, + expectPass: true, + }, + { + name: "position ids are not unique", + msg: types.MsgTransferPositions{ + PositionIds: []uint64{1, 2, 5, 9, 1}, + Sender: addr1, + NewOwner: addr2, + }, + expectPass: false, + }, + { + name: "no position ids", + msg: types.MsgTransferPositions{ + Sender: addr1, + NewOwner: addr2, + }, + expectPass: false, + }, + { + name: "invalid sender", + msg: types.MsgTransferPositions{ + PositionIds: []uint64{1, 2, 5, 9, 20}, + Sender: invalidAddr.String(), + NewOwner: addr2, + }, + expectPass: false, + }, + { + name: "invalid new owner", + msg: types.MsgTransferPositions{ + PositionIds: []uint64{1, 2, 5, 9, 20}, + Sender: addr1, + NewOwner: invalidAddr.String(), + }, + expectPass: false, + }, + { + name: "sender and new owner are the same", + msg: types.MsgTransferPositions{ + PositionIds: []uint64{1, 2, 5, 9, 20}, + Sender: addr1, + NewOwner: addr1, + }, + expectPass: false, + }, + } + for _, test := range tests { + runValidateBasicTest(t, test.name, &test.msg, test.expectPass, types.TypeMsgTransferPositions) + } +} diff --git a/x/concentrated-liquidity/types/tx.pb.go b/x/concentrated-liquidity/types/tx.pb.go index e15a0cef088..3be80ef5ed1 100644 --- a/x/concentrated-liquidity/types/tx.pb.go +++ b/x/concentrated-liquidity/types/tx.pb.go @@ -687,6 +687,103 @@ func (m *MsgFungifyChargedPositionsResponse) GetNewPositionId() uint64 { return 0 } +// ===================== MsgTransferPositions +type MsgTransferPositions struct { + PositionIds []uint64 `protobuf:"varint,1,rep,packed,name=position_ids,json=positionIds,proto3" json:"position_ids,omitempty" yaml:"position_ids"` + Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + NewOwner string `protobuf:"bytes,3,opt,name=new_owner,json=newOwner,proto3" json:"new_owner,omitempty" yaml:"new_owner"` +} + +func (m *MsgTransferPositions) Reset() { *m = MsgTransferPositions{} } +func (m *MsgTransferPositions) String() string { return proto.CompactTextString(m) } +func (*MsgTransferPositions) ProtoMessage() {} +func (*MsgTransferPositions) Descriptor() ([]byte, []int) { + return fileDescriptor_1f1fff802923d7db, []int{12} +} +func (m *MsgTransferPositions) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgTransferPositions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgTransferPositions.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 *MsgTransferPositions) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgTransferPositions.Merge(m, src) +} +func (m *MsgTransferPositions) XXX_Size() int { + return m.Size() +} +func (m *MsgTransferPositions) XXX_DiscardUnknown() { + xxx_messageInfo_MsgTransferPositions.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgTransferPositions proto.InternalMessageInfo + +func (m *MsgTransferPositions) GetPositionIds() []uint64 { + if m != nil { + return m.PositionIds + } + return nil +} + +func (m *MsgTransferPositions) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgTransferPositions) GetNewOwner() string { + if m != nil { + return m.NewOwner + } + return "" +} + +type MsgTransferPositionsResponse struct { +} + +func (m *MsgTransferPositionsResponse) Reset() { *m = MsgTransferPositionsResponse{} } +func (m *MsgTransferPositionsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgTransferPositionsResponse) ProtoMessage() {} +func (*MsgTransferPositionsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1f1fff802923d7db, []int{13} +} +func (m *MsgTransferPositionsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgTransferPositionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgTransferPositionsResponse.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 *MsgTransferPositionsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgTransferPositionsResponse.Merge(m, src) +} +func (m *MsgTransferPositionsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgTransferPositionsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgTransferPositionsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgTransferPositionsResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgCreatePosition)(nil), "osmosis.concentratedliquidity.v1beta1.MsgCreatePosition") proto.RegisterType((*MsgCreatePositionResponse)(nil), "osmosis.concentratedliquidity.v1beta1.MsgCreatePositionResponse") @@ -700,6 +797,8 @@ func init() { proto.RegisterType((*MsgCollectIncentivesResponse)(nil), "osmosis.concentratedliquidity.v1beta1.MsgCollectIncentivesResponse") proto.RegisterType((*MsgFungifyChargedPositions)(nil), "osmosis.concentratedliquidity.v1beta1.MsgFungifyChargedPositions") proto.RegisterType((*MsgFungifyChargedPositionsResponse)(nil), "osmosis.concentratedliquidity.v1beta1.MsgFungifyChargedPositionsResponse") + proto.RegisterType((*MsgTransferPositions)(nil), "osmosis.concentratedliquidity.v1beta1.MsgTransferPositions") + proto.RegisterType((*MsgTransferPositionsResponse)(nil), "osmosis.concentratedliquidity.v1beta1.MsgTransferPositionsResponse") } func init() { @@ -707,81 +806,85 @@ func init() { } var fileDescriptor_1f1fff802923d7db = []byte{ - // 1174 bytes of a gzipped FileDescriptorProto + // 1240 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcf, 0x6f, 0xe3, 0x44, - 0x1b, 0xee, 0x34, 0xdd, 0x54, 0x3b, 0xfd, 0xfa, 0x23, 0x6e, 0xb7, 0x4d, 0xd3, 0xfd, 0xe2, 0x32, - 0x02, 0x91, 0x05, 0x25, 0x6e, 0x16, 0x24, 0xd8, 0x20, 0xed, 0xb2, 0x29, 0x5a, 0x29, 0x2b, 0x22, - 0x56, 0xde, 0x95, 0x90, 0x10, 0x52, 0xe4, 0x78, 0xa6, 0xee, 0xa8, 0x89, 0x27, 0x78, 0x9c, 0x76, - 0xfb, 0x17, 0x20, 0x10, 0x07, 0x84, 0xc4, 0x11, 0x04, 0x37, 0xc4, 0x01, 0x21, 0x71, 0xe5, 0xc8, - 0x61, 0x0f, 0x1c, 0xf6, 0x88, 0x38, 0x18, 0xd4, 0x1e, 0x10, 0x17, 0x0e, 0xb9, 0x23, 0x21, 0x7b, - 0xec, 0xb1, 0xeb, 0xa4, 0xb4, 0x49, 0xa1, 0x07, 0x2e, 0x6d, 0x3c, 0xf3, 0xbe, 0xcf, 0x3c, 0xf3, - 0x3c, 0xef, 0xbc, 0x9e, 0x04, 0x3e, 0xcf, 0x78, 0x97, 0x71, 0xca, 0x35, 0x93, 0xd9, 0x26, 0xb1, - 0x5d, 0xc7, 0x70, 0x09, 0x2e, 0x77, 0xe8, 0x7b, 0x7d, 0x8a, 0xa9, 0x7b, 0xa8, 0xb9, 0x8f, 0x2b, - 0x3d, 0x87, 0xb9, 0x4c, 0x79, 0x2e, 0x0c, 0xac, 0x24, 0x03, 0x65, 0x5c, 0x65, 0xbf, 0xda, 0x26, - 0xae, 0x51, 0x2d, 0xac, 0x58, 0xcc, 0x62, 0x41, 0x86, 0xe6, 0x7f, 0x12, 0xc9, 0x85, 0x9c, 0xd1, - 0xa5, 0x36, 0xd3, 0x82, 0xbf, 0xe1, 0x90, 0x6a, 0x31, 0x66, 0x75, 0x88, 0x16, 0x3c, 0xb5, 0xfb, - 0x3b, 0x9a, 0x4b, 0xbb, 0x84, 0xbb, 0x46, 0xb7, 0x17, 0x06, 0x14, 0xd3, 0x01, 0xb8, 0xef, 0x18, - 0x2e, 0x65, 0x76, 0x34, 0x6f, 0x06, 0x8c, 0xb4, 0xb6, 0xc1, 0x89, 0x16, 0x2e, 0xaf, 0x99, 0x8c, - 0x86, 0xf3, 0xe8, 0xfb, 0x19, 0x98, 0x6b, 0x72, 0x6b, 0xdb, 0x21, 0x86, 0x4b, 0x1e, 0x30, 0x4e, - 0xfd, 0x5c, 0xe5, 0x45, 0x38, 0xdb, 0x63, 0xac, 0xd3, 0xa2, 0x38, 0x0f, 0x36, 0x41, 0x69, 0xa6, - 0xae, 0x0c, 0x3c, 0x75, 0xe1, 0xd0, 0xe8, 0x76, 0x6a, 0x28, 0x9c, 0x40, 0x7a, 0xd6, 0xff, 0xd4, - 0xc0, 0xca, 0x0d, 0x98, 0xe5, 0xc4, 0xc6, 0xc4, 0xc9, 0x4f, 0x6f, 0x82, 0xd2, 0xd5, 0x7a, 0x6e, - 0xe0, 0xa9, 0xf3, 0x22, 0x56, 0x8c, 0x23, 0x3d, 0x0c, 0x50, 0x5e, 0x86, 0xb0, 0xc3, 0x0e, 0x88, - 0xd3, 0x72, 0xa9, 0xb9, 0x97, 0xcf, 0x6c, 0x82, 0x52, 0xa6, 0x7e, 0x6d, 0xe0, 0xa9, 0x39, 0x11, - 0x1e, 0xcf, 0x21, 0xfd, 0x6a, 0xf0, 0xf0, 0x88, 0x9a, 0x7b, 0x7e, 0x56, 0xbf, 0xd7, 0x8b, 0xb2, - 0x66, 0xd2, 0x59, 0xf1, 0x1c, 0xd2, 0xaf, 0x06, 0x0f, 0x41, 0x96, 0x0b, 0x17, 0x5d, 0xb6, 0x47, - 0x6c, 0xde, 0xea, 0x39, 0x6c, 0x9f, 0x62, 0x82, 0xf3, 0x57, 0x36, 0x33, 0xa5, 0xb9, 0x9b, 0xeb, - 0x15, 0xa1, 0x49, 0xc5, 0xd7, 0x24, 0xb2, 0xa4, 0xb2, 0xcd, 0xa8, 0x5d, 0xdf, 0x7a, 0xe2, 0xa9, - 0x53, 0x5f, 0xff, 0xa2, 0x96, 0x2c, 0xea, 0xee, 0xf6, 0xdb, 0x15, 0x93, 0x75, 0xb5, 0x50, 0x40, - 0xf1, 0xaf, 0xcc, 0xf1, 0x9e, 0xe6, 0x1e, 0xf6, 0x08, 0x0f, 0x12, 0xb8, 0xbe, 0x20, 0xd6, 0x78, - 0x10, 0x2e, 0xa1, 0x10, 0x98, 0x0b, 0x46, 0x5a, 0x5d, 0x6a, 0xb7, 0x8c, 0x2e, 0xeb, 0xdb, 0xee, - 0x56, 0x3e, 0x1b, 0xe8, 0x72, 0xcb, 0x07, 0xff, 0xd9, 0x53, 0xaf, 0x09, 0x28, 0x8e, 0xf7, 0x2a, - 0x94, 0x69, 0x5d, 0xc3, 0xdd, 0xad, 0x34, 0x6c, 0x77, 0xe0, 0xa9, 0x79, 0xb1, 0x9f, 0xa1, 0x7c, - 0xa4, 0x8b, 0x9d, 0x34, 0xa9, 0x7d, 0x57, 0x8c, 0x8c, 0x5a, 0xa6, 0x9a, 0x9f, 0xbd, 0xd0, 0x32, - 0xd5, 0xa1, 0x65, 0xaa, 0x35, 0xf5, 0xc3, 0xdf, 0xbe, 0x7d, 0xa1, 0x20, 0x8b, 0xbf, 0x53, 0x36, - 0x83, 0x3a, 0x29, 0xf7, 0xc2, 0x42, 0x41, 0x3f, 0x64, 0xe0, 0xfa, 0x50, 0xf9, 0xe8, 0x84, 0xf7, - 0x98, 0xcd, 0x89, 0xf2, 0x0a, 0x9c, 0x8b, 0x22, 0xe3, 0x52, 0x5a, 0x1d, 0x78, 0xaa, 0x12, 0x95, - 0x92, 0x9c, 0x44, 0x3a, 0x8c, 0x9e, 0x1a, 0x58, 0x69, 0xc0, 0xd9, 0x48, 0x3b, 0x51, 0x53, 0xda, - 0x59, 0x9b, 0x0a, 0x8b, 0x53, 0x2a, 0x16, 0xe5, 0xc7, 0x50, 0xd5, 0xa0, 0xde, 0xc6, 0x85, 0xaa, - 0x4a, 0xa8, 0xaa, 0xd2, 0x81, 0x39, 0x79, 0x94, 0x5b, 0x42, 0x09, 0xbf, 0xa6, 0x7c, 0xd0, 0x3b, - 0x21, 0xe8, 0xc6, 0x30, 0xe8, 0x9b, 0xc4, 0x32, 0xcc, 0xc3, 0x37, 0x88, 0x19, 0x4b, 0x3f, 0x84, - 0x82, 0xf4, 0x25, 0x39, 0x26, 0xb4, 0xc4, 0xa9, 0xb3, 0x92, 0x9d, 0xe8, 0xac, 0xcc, 0x9e, 0xef, - 0xac, 0xa0, 0x3f, 0x33, 0x70, 0xa9, 0xc9, 0xad, 0xbb, 0x18, 0x3f, 0x62, 0xb2, 0x09, 0x4c, 0xec, - 0xde, 0x18, 0x0d, 0xe1, 0x7e, 0x6c, 0xb4, 0x70, 0x67, 0xeb, 0x2c, 0x77, 0x16, 0x93, 0xee, 0xb4, - 0x92, 0x4e, 0xdf, 0x8f, 0x9d, 0x9e, 0x99, 0x04, 0x2b, 0x69, 0xf5, 0xc8, 0x63, 0x7c, 0xe5, 0x72, - 0x8e, 0x71, 0xf6, 0xdf, 0x3f, 0xc6, 0x06, 0xc6, 0x65, 0x97, 0xc5, 0xc7, 0xf8, 0x77, 0x00, 0xf3, - 0x69, 0xff, 0xff, 0xa3, 0xa7, 0x18, 0xbd, 0x3f, 0x0d, 0x97, 0x9b, 0xdc, 0x7a, 0x9b, 0xba, 0xbb, - 0xd8, 0x31, 0x0e, 0x2e, 0xb5, 0xdc, 0x29, 0x8c, 0xcf, 0x79, 0xe8, 0x57, 0xb8, 0x9f, 0xdb, 0xe7, - 0x6b, 0x20, 0x6b, 0xe9, 0x06, 0x22, 0x40, 0x90, 0xbe, 0x28, 0x87, 0x84, 0xe9, 0xb5, 0x67, 0x7c, - 0xcf, 0xaf, 0x27, 0x3c, 0x3f, 0x08, 0x37, 0x1c, 0xbb, 0xfe, 0x1d, 0x80, 0x1b, 0x23, 0x94, 0x90, - 0xc6, 0x27, 0xfc, 0x03, 0xff, 0x9c, 0x7f, 0xd3, 0x17, 0xf4, 0xef, 0x0b, 0x00, 0xd7, 0xfc, 0x57, - 0x0e, 0xeb, 0x74, 0x88, 0xe9, 0x3e, 0xec, 0x39, 0xc4, 0xc0, 0x3a, 0x39, 0x30, 0x1c, 0xcc, 0x95, - 0x1a, 0xfc, 0x5f, 0xc2, 0x26, 0x9e, 0x07, 0x9b, 0x99, 0xd2, 0x4c, 0x7d, 0x6d, 0xe0, 0xa9, 0xcb, - 0x43, 0x26, 0x72, 0xa4, 0xcf, 0xc5, 0x2e, 0xf2, 0x31, 0x6c, 0xac, 0x15, 0x7d, 0x6d, 0xd7, 0x93, - 0xaf, 0x45, 0xd6, 0x29, 0xf3, 0x5e, 0xd9, 0x11, 0x34, 0xd0, 0x8f, 0x00, 0xaa, 0xa7, 0x50, 0x94, - 0xe2, 0x7e, 0x05, 0x60, 0xde, 0x14, 0x01, 0x04, 0xb7, 0x78, 0x10, 0xd3, 0x0a, 0x01, 0x02, 0xde, - 0x7f, 0x7b, 0x51, 0x79, 0xe8, 0xcb, 0x37, 0xf0, 0x54, 0x55, 0x10, 0x3c, 0x0d, 0x08, 0x8d, 0x75, - 0x97, 0x59, 0x95, 0x30, 0x27, 0x28, 0xa3, 0x2f, 0x01, 0x5c, 0x89, 0xb7, 0xd3, 0x08, 0x2e, 0xb6, - 0x74, 0x9f, 0x5c, 0x9a, 0xdc, 0xc8, 0x97, 0xfb, 0xff, 0x27, 0xe5, 0xf6, 0x99, 0x94, 0xa9, 0xa4, - 0x82, 0xbc, 0x69, 0x78, 0x7d, 0x14, 0x47, 0xa9, 0xf7, 0x67, 0x00, 0xae, 0xc4, 0x32, 0xc5, 0x99, - 0x67, 0x6b, 0xfd, 0x56, 0xa8, 0xf5, 0x46, 0x5a, 0xeb, 0xc4, 0xf2, 0x63, 0xe9, 0xbc, 0x2c, 0x21, - 0x12, 0x5a, 0xfa, 0xfc, 0x76, 0x98, 0xb3, 0x43, 0x68, 0x8a, 0xdf, 0xf4, 0x98, 0xfc, 0x46, 0x81, - 0x8c, 0xc9, 0x4f, 0x42, 0xc4, 0xfc, 0xd0, 0x37, 0x00, 0x16, 0x9a, 0xdc, 0xba, 0xd7, 0xb7, 0x2d, - 0xba, 0x73, 0xb8, 0xbd, 0x6b, 0x38, 0x16, 0xc1, 0x51, 0xcb, 0xb8, 0xb4, 0x52, 0xb8, 0xe1, 0x97, - 0xc2, 0xb3, 0x89, 0x52, 0xd8, 0x11, 0x7c, 0xca, 0xa6, 0x20, 0x24, 0x9b, 0x1b, 0x47, 0xbb, 0x10, - 0x9d, 0xce, 0x57, 0x96, 0x45, 0x1d, 0x2e, 0xda, 0xe4, 0xa0, 0x35, 0xdc, 0xf9, 0x0b, 0x03, 0x4f, - 0x5d, 0x15, 0x24, 0x52, 0x01, 0x48, 0x9f, 0xb7, 0x89, 0xec, 0x96, 0x0d, 0x7c, 0xf3, 0x8f, 0x2b, - 0x30, 0xd3, 0xe4, 0x96, 0xf2, 0x11, 0x80, 0x0b, 0xa9, 0x2f, 0x52, 0xaf, 0x56, 0xce, 0xf5, 0x85, - 0xb0, 0x32, 0x74, 0x87, 0x2e, 0xbc, 0x3e, 0x69, 0xa6, 0xdc, 0xda, 0x27, 0x00, 0x2e, 0x0d, 0xbd, - 0xe5, 0x6a, 0xe7, 0x87, 0x4d, 0xe7, 0x16, 0xea, 0x93, 0xe7, 0x4a, 0x52, 0x1f, 0x00, 0x38, 0x9f, - 0xba, 0x66, 0x9e, 0x1f, 0xf5, 0x44, 0x62, 0xe1, 0xce, 0x84, 0x89, 0x92, 0xcb, 0xe7, 0x00, 0xae, - 0x8c, 0x7c, 0x8d, 0xdc, 0x1e, 0x43, 0xfb, 0x11, 0xf9, 0x85, 0x7b, 0x17, 0xcb, 0x97, 0x04, 0x3f, - 0x05, 0x30, 0x37, 0xdc, 0x75, 0x5f, 0x1b, 0x1b, 0x3d, 0x4e, 0x2e, 0x6c, 0x5f, 0x20, 0x39, 0xe2, - 0x55, 0x7f, 0xf7, 0xc9, 0x51, 0x11, 0x3c, 0x3d, 0x2a, 0x82, 0x5f, 0x8f, 0x8a, 0xe0, 0xe3, 0xe3, - 0xe2, 0xd4, 0xd3, 0xe3, 0xe2, 0xd4, 0x4f, 0xc7, 0xc5, 0xa9, 0x77, 0xea, 0x89, 0x26, 0x13, 0x2e, - 0x54, 0xee, 0x18, 0x6d, 0x1e, 0x3d, 0x68, 0xfb, 0xd5, 0x5b, 0xda, 0xe3, 0x53, 0x7f, 0x46, 0xf1, - 0x9b, 0x50, 0x3b, 0x1b, 0xfc, 0x32, 0xf1, 0xd2, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x28, 0x46, - 0xa1, 0x3c, 0x75, 0x11, 0x00, 0x00, + 0x14, 0xae, 0x9b, 0x6e, 0x4a, 0xa7, 0xf4, 0x47, 0xdc, 0x6e, 0x9b, 0xa6, 0x4b, 0x5c, 0x46, 0x20, + 0xb2, 0xa0, 0xc4, 0xcd, 0x82, 0x04, 0x1b, 0xa4, 0x5d, 0x36, 0x45, 0x2b, 0x65, 0x45, 0xb4, 0x2b, + 0x6f, 0x25, 0x24, 0x84, 0x14, 0x39, 0xf6, 0xc4, 0x1d, 0x35, 0xf1, 0x04, 0xcf, 0xa4, 0xd9, 0xfe, + 0x03, 0x20, 0x10, 0x07, 0x84, 0xc4, 0x11, 0x04, 0x37, 0xc4, 0x01, 0x21, 0x71, 0xe5, 0xc8, 0x61, + 0x0f, 0x1c, 0xf6, 0xc0, 0x01, 0x71, 0x30, 0xa8, 0x3d, 0x20, 0xae, 0xb9, 0x23, 0x21, 0x7b, 0x9c, + 0xb1, 0x1b, 0xa7, 0xb4, 0x4e, 0xa1, 0x07, 0x2e, 0x6d, 0x3c, 0xf3, 0xbe, 0x37, 0xdf, 0x7c, 0xdf, + 0x7b, 0x33, 0x4e, 0xc0, 0x0b, 0x84, 0x76, 0x08, 0xc5, 0x54, 0x35, 0x88, 0x6d, 0x20, 0x9b, 0x39, + 0x3a, 0x43, 0x66, 0xb1, 0x8d, 0xdf, 0xeb, 0x61, 0x13, 0xb3, 0x43, 0x95, 0x3d, 0x2a, 0x75, 0x1d, + 0xc2, 0x88, 0xfc, 0x7c, 0x10, 0x58, 0x8a, 0x06, 0x8a, 0xb8, 0xd2, 0x41, 0xb9, 0x89, 0x98, 0x5e, + 0xce, 0xad, 0x5a, 0xc4, 0x22, 0x3e, 0x42, 0xf5, 0x3e, 0x71, 0x70, 0x2e, 0xa3, 0x77, 0xb0, 0x4d, + 0x54, 0xff, 0x6f, 0x30, 0xa4, 0x58, 0x84, 0x58, 0x6d, 0xa4, 0xfa, 0x4f, 0xcd, 0x5e, 0x4b, 0x65, + 0xb8, 0x83, 0x28, 0xd3, 0x3b, 0xdd, 0x20, 0x20, 0x3f, 0x1a, 0x60, 0xf6, 0x1c, 0x9d, 0x61, 0x62, + 0x0f, 0xe7, 0x0d, 0x9f, 0x91, 0xda, 0xd4, 0x29, 0x52, 0x83, 0xe5, 0x55, 0x83, 0xe0, 0x60, 0x1e, + 0xfe, 0x30, 0x03, 0x32, 0x75, 0x6a, 0xed, 0x38, 0x48, 0x67, 0xe8, 0x01, 0xa1, 0xd8, 0xc3, 0xca, + 0x2f, 0x81, 0xd9, 0x2e, 0x21, 0xed, 0x06, 0x36, 0xb3, 0xd2, 0x96, 0x54, 0x98, 0xa9, 0xca, 0x03, + 0x57, 0x59, 0x3c, 0xd4, 0x3b, 0xed, 0x0a, 0x0c, 0x26, 0xa0, 0x96, 0xf6, 0x3e, 0xd5, 0x4c, 0xf9, + 0x3a, 0x48, 0x53, 0x64, 0x9b, 0xc8, 0xc9, 0x4e, 0x6f, 0x49, 0x85, 0xb9, 0x6a, 0x66, 0xe0, 0x2a, + 0x0b, 0x3c, 0x96, 0x8f, 0x43, 0x2d, 0x08, 0x90, 0x5f, 0x01, 0xa0, 0x4d, 0xfa, 0xc8, 0x69, 0x30, + 0x6c, 0xec, 0x67, 0x53, 0x5b, 0x52, 0x21, 0x55, 0xbd, 0x3a, 0x70, 0x95, 0x0c, 0x0f, 0x0f, 0xe7, + 0xa0, 0x36, 0xe7, 0x3f, 0xec, 0x62, 0x63, 0xdf, 0x43, 0xf5, 0xba, 0xdd, 0x21, 0x6a, 0x66, 0x14, + 0x15, 0xce, 0x41, 0x6d, 0xce, 0x7f, 0xf0, 0x51, 0x0c, 0x2c, 0x31, 0xb2, 0x8f, 0x6c, 0xda, 0xe8, + 0x3a, 0xe4, 0x00, 0x9b, 0xc8, 0xcc, 0x5e, 0xd9, 0x4a, 0x15, 0xe6, 0x6f, 0x6c, 0x94, 0xb8, 0x26, + 0x25, 0x4f, 0x93, 0xa1, 0x25, 0xa5, 0x1d, 0x82, 0xed, 0xea, 0xf6, 0x63, 0x57, 0x99, 0xfa, 0xe6, + 0x37, 0xa5, 0x60, 0x61, 0xb6, 0xd7, 0x6b, 0x96, 0x0c, 0xd2, 0x51, 0x03, 0x01, 0xf9, 0xbf, 0x22, + 0x35, 0xf7, 0x55, 0x76, 0xd8, 0x45, 0xd4, 0x07, 0x50, 0x6d, 0x91, 0xaf, 0xf1, 0x20, 0x58, 0x42, + 0x46, 0x20, 0xe3, 0x8f, 0x34, 0x3a, 0xd8, 0x6e, 0xe8, 0x1d, 0xd2, 0xb3, 0xd9, 0x76, 0x36, 0xed, + 0xeb, 0x72, 0xd3, 0x4b, 0xfe, 0xab, 0xab, 0x5c, 0xe5, 0xa9, 0xa8, 0xb9, 0x5f, 0xc2, 0x44, 0xed, + 0xe8, 0x6c, 0xaf, 0x54, 0xb3, 0xd9, 0xc0, 0x55, 0xb2, 0x7c, 0x3f, 0x31, 0x3c, 0xd4, 0xf8, 0x4e, + 0xea, 0xd8, 0xbe, 0xc3, 0x47, 0xc6, 0x2d, 0x53, 0xce, 0xce, 0x5e, 0x68, 0x99, 0x72, 0x6c, 0x99, + 0x72, 0x45, 0xf9, 0xe8, 0x8f, 0xef, 0x5e, 0xcc, 0x89, 0xe2, 0x6f, 0x17, 0x0d, 0xbf, 0x4e, 0x8a, + 0xdd, 0xa0, 0x50, 0xe0, 0x8f, 0x29, 0xb0, 0x11, 0x2b, 0x1f, 0x0d, 0xd1, 0x2e, 0xb1, 0x29, 0x92, + 0x5f, 0x05, 0xf3, 0xc3, 0xc8, 0xb0, 0x94, 0xd6, 0x06, 0xae, 0x22, 0x0f, 0x4b, 0x49, 0x4c, 0x42, + 0x0d, 0x0c, 0x9f, 0x6a, 0xa6, 0x5c, 0x03, 0xb3, 0x43, 0xed, 0x78, 0x4d, 0xa9, 0x67, 0x6d, 0x2a, + 0x28, 0x4e, 0xa1, 0xd8, 0x10, 0x1f, 0xa6, 0x2a, 0xfb, 0xf5, 0x96, 0x34, 0x55, 0x59, 0xa4, 0x2a, + 0xcb, 0x6d, 0x90, 0x11, 0xad, 0xdc, 0xe0, 0x4a, 0x78, 0x35, 0xe5, 0x25, 0xbd, 0x1d, 0x24, 0xdd, + 0x8c, 0x27, 0x7d, 0x0b, 0x59, 0xba, 0x71, 0xf8, 0x26, 0x32, 0x42, 0xe9, 0x63, 0x59, 0xa0, 0xb6, + 0x2c, 0xc6, 0xb8, 0x96, 0xe6, 0x48, 0xaf, 0xa4, 0x27, 0xea, 0x95, 0xd9, 0xf3, 0xf5, 0x0a, 0xfc, + 0x2b, 0x05, 0x96, 0xeb, 0xd4, 0xba, 0x63, 0x9a, 0xbb, 0x44, 0x1c, 0x02, 0x13, 0xbb, 0x97, 0xe0, + 0x40, 0xb8, 0x17, 0x1a, 0xcd, 0xdd, 0xd9, 0x3e, 0xcb, 0x9d, 0xa5, 0xa8, 0x3b, 0x8d, 0xa8, 0xd3, + 0xf7, 0x42, 0xa7, 0x67, 0x26, 0xc9, 0x15, 0xb5, 0x7a, 0x6c, 0x1b, 0x5f, 0xb9, 0x9c, 0x36, 0x4e, + 0xff, 0xf7, 0x6d, 0xac, 0x9b, 0x66, 0x91, 0x91, 0xb0, 0x8d, 0xff, 0x94, 0x40, 0x76, 0xd4, 0xff, + 0xff, 0x69, 0x17, 0xc3, 0x0f, 0xa6, 0xc1, 0x4a, 0x9d, 0x5a, 0x6f, 0x63, 0xb6, 0x67, 0x3a, 0x7a, + 0xff, 0x52, 0xcb, 0x1d, 0x83, 0xb0, 0xcf, 0x03, 0xbf, 0x82, 0xfd, 0xdc, 0x3a, 0xdf, 0x01, 0xb2, + 0x3e, 0x7a, 0x80, 0xf0, 0x24, 0x50, 0x5b, 0x12, 0x43, 0xdc, 0xf4, 0xca, 0xb3, 0x9e, 0xe7, 0xd7, + 0x22, 0x9e, 0xf7, 0x83, 0x0d, 0x87, 0xae, 0x7f, 0x2f, 0x81, 0xcd, 0x31, 0x4a, 0x08, 0xe3, 0x23, + 0xfe, 0x49, 0xff, 0x9e, 0x7f, 0xd3, 0x17, 0xf4, 0xef, 0x4b, 0x09, 0xac, 0x7b, 0x57, 0x0e, 0x69, + 0xb7, 0x91, 0xc1, 0x1e, 0x76, 0x1d, 0xa4, 0x9b, 0x1a, 0xea, 0xeb, 0x8e, 0x49, 0xe5, 0x0a, 0x78, + 0x3a, 0x62, 0x13, 0xcd, 0x4a, 0x5b, 0xa9, 0xc2, 0x4c, 0x75, 0x7d, 0xe0, 0x2a, 0x2b, 0x31, 0x13, + 0x29, 0xd4, 0xe6, 0x43, 0x17, 0x69, 0x02, 0x1b, 0x2b, 0x79, 0x4f, 0xdb, 0x8d, 0xe8, 0xb5, 0x48, + 0xda, 0x45, 0xda, 0x2d, 0x3a, 0x9c, 0x06, 0xfc, 0x49, 0x02, 0xca, 0x29, 0x14, 0x85, 0xb8, 0x5f, + 0x4b, 0x20, 0x6b, 0xf0, 0x00, 0x64, 0x36, 0xa8, 0x1f, 0xd3, 0x08, 0x12, 0xf8, 0xbc, 0xff, 0xf1, + 0x45, 0xe5, 0xa1, 0x27, 0xdf, 0xc0, 0x55, 0x14, 0x4e, 0xf0, 0xb4, 0x44, 0x30, 0xd1, 0xbb, 0xcc, + 0x9a, 0x48, 0x73, 0x82, 0x32, 0xfc, 0x4a, 0x02, 0xab, 0xe1, 0x76, 0x6a, 0xfe, 0x8b, 0x2d, 0x3e, + 0x40, 0x97, 0x26, 0x37, 0xf4, 0xe4, 0x7e, 0xe6, 0xa4, 0xdc, 0x1e, 0x93, 0x22, 0x16, 0x54, 0xa0, + 0x3b, 0x0d, 0xae, 0x8d, 0xe3, 0x28, 0xf4, 0xfe, 0x5c, 0x02, 0xab, 0xa1, 0x4c, 0x21, 0xf2, 0x6c, + 0xad, 0xef, 0x07, 0x5a, 0x6f, 0x8e, 0x6a, 0x1d, 0x59, 0x3e, 0x91, 0xce, 0x2b, 0x22, 0x45, 0x44, + 0x4b, 0x8f, 0x5f, 0x8b, 0x38, 0x2d, 0x84, 0x47, 0xf8, 0x4d, 0x27, 0xe4, 0x37, 0x2e, 0x49, 0x42, + 0x7e, 0x22, 0x45, 0xc8, 0x0f, 0x7e, 0x2b, 0x81, 0x5c, 0x9d, 0x5a, 0x77, 0x7b, 0xb6, 0x85, 0x5b, + 0x87, 0x3b, 0x7b, 0xba, 0x63, 0x21, 0x73, 0x78, 0x64, 0x5c, 0x5a, 0x29, 0x5c, 0xf7, 0x4a, 0xe1, + 0xb9, 0x48, 0x29, 0xb4, 0x38, 0x9f, 0xa2, 0xc1, 0x09, 0x89, 0xc3, 0x8d, 0xc2, 0x3d, 0x00, 0x4f, + 0xe7, 0x2b, 0xca, 0xa2, 0x0a, 0x96, 0x6c, 0xd4, 0x6f, 0xc4, 0x4f, 0xfe, 0xdc, 0xc0, 0x55, 0xd6, + 0x38, 0x89, 0x91, 0x00, 0xa8, 0x2d, 0xd8, 0x48, 0x9c, 0x96, 0x35, 0x13, 0xfe, 0xcc, 0xfb, 0x63, + 0xd7, 0xd1, 0x6d, 0xda, 0x42, 0xce, 0x65, 0x8b, 0x22, 0x97, 0xc1, 0x9c, 0x47, 0x91, 0xf4, 0x6d, + 0xe4, 0x04, 0xd7, 0xc9, 0xea, 0xc0, 0x55, 0x96, 0x43, 0xf6, 0xfe, 0x14, 0xd4, 0x9e, 0xb2, 0x51, + 0xff, 0xbe, 0xf7, 0x31, 0xde, 0x52, 0x2c, 0x20, 0x1f, 0x11, 0x30, 0xef, 0x77, 0x54, 0x6c, 0x57, + 0x43, 0xe9, 0x6e, 0xbc, 0x3f, 0x0b, 0x52, 0x75, 0x6a, 0xc9, 0x1f, 0x4b, 0x60, 0x71, 0xe4, 0xfb, + 0xe3, 0x6b, 0xa5, 0x73, 0x7d, 0x0f, 0x2e, 0xc5, 0xbe, 0x3a, 0xe4, 0xde, 0x98, 0x14, 0x29, 0x1c, + 0xfd, 0x54, 0x02, 0xcb, 0xb1, 0xcb, 0xbd, 0x72, 0xfe, 0xb4, 0xa3, 0xd8, 0x5c, 0x75, 0x72, 0xac, + 0x20, 0xf5, 0xa1, 0x04, 0x16, 0x46, 0xde, 0xae, 0xcf, 0x9f, 0xf5, 0x04, 0x30, 0x77, 0x7b, 0x42, + 0xa0, 0xe0, 0xf2, 0x85, 0x04, 0x56, 0xc7, 0xde, 0x9e, 0xb7, 0x12, 0x68, 0x3f, 0x06, 0x9f, 0xbb, + 0x7b, 0x31, 0xbc, 0x20, 0xf8, 0x99, 0x04, 0x32, 0xf1, 0xcb, 0xe6, 0xf5, 0xc4, 0xd9, 0x43, 0x70, + 0x6e, 0xe7, 0x02, 0xe0, 0x13, 0xbc, 0xe2, 0x4d, 0x9e, 0x80, 0x57, 0x0c, 0x9c, 0x84, 0xd7, 0xa9, + 0x8d, 0x58, 0x7d, 0xf7, 0xf1, 0x51, 0x5e, 0x7a, 0x72, 0x94, 0x97, 0x7e, 0x3f, 0xca, 0x4b, 0x9f, + 0x1c, 0xe7, 0xa7, 0x9e, 0x1c, 0xe7, 0xa7, 0x7e, 0x39, 0xce, 0x4f, 0xbd, 0x53, 0x8d, 0x9c, 0xf9, + 0xc1, 0x42, 0xc5, 0xb6, 0xde, 0xa4, 0xc3, 0x07, 0xf5, 0xa0, 0x7c, 0x53, 0x7d, 0x74, 0xea, 0xaf, + 0x5a, 0xde, 0x9d, 0xd0, 0x4c, 0xfb, 0x3f, 0x14, 0xbd, 0xfc, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x9b, 0xb6, 0x78, 0x49, 0x04, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -806,6 +909,9 @@ type MsgClient interface { AddToPosition(ctx context.Context, in *MsgAddToPosition, opts ...grpc.CallOption) (*MsgAddToPositionResponse, error) CollectSpreadRewards(ctx context.Context, in *MsgCollectSpreadRewards, opts ...grpc.CallOption) (*MsgCollectSpreadRewardsResponse, error) CollectIncentives(ctx context.Context, in *MsgCollectIncentives, opts ...grpc.CallOption) (*MsgCollectIncentivesResponse, error) + // TransferPositions transfers ownership of a set of one or more positions + // from a sender to a recipient. + TransferPositions(ctx context.Context, in *MsgTransferPositions, opts ...grpc.CallOption) (*MsgTransferPositionsResponse, error) } type msgClient struct { @@ -861,6 +967,15 @@ func (c *msgClient) CollectIncentives(ctx context.Context, in *MsgCollectIncenti return out, nil } +func (c *msgClient) TransferPositions(ctx context.Context, in *MsgTransferPositions, opts ...grpc.CallOption) (*MsgTransferPositionsResponse, error) { + out := new(MsgTransferPositionsResponse) + err := c.cc.Invoke(ctx, "/osmosis.concentratedliquidity.v1beta1.Msg/TransferPositions", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { CreatePosition(context.Context, *MsgCreatePosition) (*MsgCreatePositionResponse, error) @@ -873,6 +988,9 @@ type MsgServer interface { AddToPosition(context.Context, *MsgAddToPosition) (*MsgAddToPositionResponse, error) CollectSpreadRewards(context.Context, *MsgCollectSpreadRewards) (*MsgCollectSpreadRewardsResponse, error) CollectIncentives(context.Context, *MsgCollectIncentives) (*MsgCollectIncentivesResponse, error) + // TransferPositions transfers ownership of a set of one or more positions + // from a sender to a recipient. + TransferPositions(context.Context, *MsgTransferPositions) (*MsgTransferPositionsResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -894,6 +1012,9 @@ func (*UnimplementedMsgServer) CollectSpreadRewards(ctx context.Context, req *Ms func (*UnimplementedMsgServer) CollectIncentives(ctx context.Context, req *MsgCollectIncentives) (*MsgCollectIncentivesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CollectIncentives not implemented") } +func (*UnimplementedMsgServer) TransferPositions(ctx context.Context, req *MsgTransferPositions) (*MsgTransferPositionsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TransferPositions not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -989,6 +1110,24 @@ func _Msg_CollectIncentives_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Msg_TransferPositions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgTransferPositions) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).TransferPositions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.concentratedliquidity.v1beta1.Msg/TransferPositions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).TransferPositions(ctx, req.(*MsgTransferPositions)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "osmosis.concentratedliquidity.v1beta1.Msg", HandlerType: (*MsgServer)(nil), @@ -1013,6 +1152,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "CollectIncentives", Handler: _Msg_CollectIncentives_Handler, }, + { + MethodName: "TransferPositions", + Handler: _Msg_TransferPositions_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "osmosis/concentrated-liquidity/tx.proto", @@ -1636,6 +1779,84 @@ func (m *MsgFungifyChargedPositionsResponse) MarshalToSizedBuffer(dAtA []byte) ( return len(dAtA) - i, nil } +func (m *MsgTransferPositions) 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 *MsgTransferPositions) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgTransferPositions) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.NewOwner) > 0 { + i -= len(m.NewOwner) + copy(dAtA[i:], m.NewOwner) + i = encodeVarintTx(dAtA, i, uint64(len(m.NewOwner))) + i-- + dAtA[i] = 0x1a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x12 + } + if len(m.PositionIds) > 0 { + dAtA8 := make([]byte, len(m.PositionIds)*10) + var j7 int + for _, num := range m.PositionIds { + for num >= 1<<7 { + dAtA8[j7] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j7++ + } + dAtA8[j7] = uint8(num) + j7++ + } + i -= j7 + copy(dAtA[i:], dAtA8[:j7]) + i = encodeVarintTx(dAtA, i, uint64(j7)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgTransferPositionsResponse) 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 *MsgTransferPositionsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgTransferPositionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -1882,6 +2103,39 @@ func (m *MsgFungifyChargedPositionsResponse) Size() (n int) { return n } +func (m *MsgTransferPositions) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.PositionIds) > 0 { + l = 0 + for _, e := range m.PositionIds { + l += sovTx(uint64(e)) + } + n += 1 + sovTx(uint64(l)) + l + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.NewOwner) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgTransferPositionsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -3710,6 +3964,246 @@ func (m *MsgFungifyChargedPositionsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgTransferPositions) 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 ErrIntOverflowTx + } + 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: MsgTransferPositions: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgTransferPositions: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.PositionIds = append(m.PositionIds, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.PositionIds) == 0 { + m.PositionIds = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.PositionIds = append(m.PositionIds, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field PositionIds", wireType) + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewOwner", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NewOwner = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgTransferPositionsResponse) 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 ErrIntOverflowTx + } + 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: MsgTransferPositionsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgTransferPositionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/epochs/go.mod b/x/epochs/go.mod index f99a56a9663..09c81ac01ec 100644 --- a/x/epochs/go.mod +++ b/x/epochs/go.mod @@ -8,7 +8,7 @@ require ( github.com/golang/protobuf v1.5.3 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d + github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366 github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 github.com/tendermint/tendermint v0.37.0-rc1 @@ -92,7 +92,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect diff --git a/x/epochs/go.sum b/x/epochs/go.sum index de2d90a20b1..5ed09206835 100644 --- a/x/epochs/go.sum +++ b/x/epochs/go.sum @@ -722,8 +722,8 @@ github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230922030206-734f99fba785 h1: github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230922030206-734f99fba785/go.mod h1:toI9Pf+e5C4TuWAFpXfkxnkpr1RVFMK2qr7QMdkFrY8= github.com/osmosis-labs/osmosis/osmomath v0.0.6 h1:WNkVmeeudAqRFk5a4CChWsdxfiY/XLClT1i845L78ss= github.com/osmosis-labs/osmosis/osmomath v0.0.6/go.mod h1:UlftwozB+QObT3o0YfkuuyL9fsVdgoWt0dm6J7MLYnU= -github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d h1:v2oZcI68YtaqkqkADipvwBrr+5skSepcljTlwH4/Gho= -github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d/go.mod h1:65FFxpq4aS72kQbjHkNYVvPvFP2mQsFDyYozZJDImW4= +github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366 h1:EJDJ88w2Yv5LnlaJw5x53C0k/dp/fnEYOfBYOQiMsTc= +github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366/go.mod h1:Zmyx5zMUBN2KV94booSFn2v8KQcUKeCHqyWpKZ4PRMo= github.com/osmosis-labs/osmosis/v19 v19.0.0 h1:gqcas/XfxtEuZXsWGTO9vNMHiY78Qs09FBQw73djIVM= github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= diff --git a/x/ibc-hooks/go.mod b/x/ibc-hooks/go.mod index c0e1fb1dda6..2c8f9bca6dc 100644 --- a/x/ibc-hooks/go.mod +++ b/x/ibc-hooks/go.mod @@ -12,7 +12,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/osmosis-labs/osmosis/osmomath v0.0.6 - github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d + github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366 github.com/spf13/cobra v1.7.0 github.com/tendermint/tendermint v0.37.0-rc1 google.golang.org/grpc v1.58.2 @@ -98,7 +98,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect diff --git a/x/ibc-hooks/go.sum b/x/ibc-hooks/go.sum index 2c7dfb98fdf..5e5022b5124 100644 --- a/x/ibc-hooks/go.sum +++ b/x/ibc-hooks/go.sum @@ -734,8 +734,8 @@ github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230922030206-734f99fba785 h1: github.com/osmosis-labs/cosmos-sdk v0.45.0-rc1.0.20230922030206-734f99fba785/go.mod h1:toI9Pf+e5C4TuWAFpXfkxnkpr1RVFMK2qr7QMdkFrY8= github.com/osmosis-labs/osmosis/osmomath v0.0.6 h1:WNkVmeeudAqRFk5a4CChWsdxfiY/XLClT1i845L78ss= github.com/osmosis-labs/osmosis/osmomath v0.0.6/go.mod h1:UlftwozB+QObT3o0YfkuuyL9fsVdgoWt0dm6J7MLYnU= -github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d h1:v2oZcI68YtaqkqkADipvwBrr+5skSepcljTlwH4/Gho= -github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231009212613-77825371576d/go.mod h1:65FFxpq4aS72kQbjHkNYVvPvFP2mQsFDyYozZJDImW4= +github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366 h1:EJDJ88w2Yv5LnlaJw5x53C0k/dp/fnEYOfBYOQiMsTc= +github.com/osmosis-labs/osmosis/osmoutils v0.0.7-0.20231011004221-fd24b80f8366/go.mod h1:Zmyx5zMUBN2KV94booSFn2v8KQcUKeCHqyWpKZ4PRMo= github.com/osmosis-labs/wasmd v0.31.0-osmo-v16 h1:X747cZYdnqc/+RV48iPVeGprpVb/fUWSaKGsZUWrdbg= github.com/osmosis-labs/wasmd v0.31.0-osmo-v16/go.mod h1:Rf8zW/GgBQyFRRB4s62VQHWA6sTlMFSjoDQQpoq64iI= github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=