diff --git a/.golangci.yml b/.golangci.yml index 27fdada5b66..ba9195a2e10 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -43,13 +43,6 @@ linters: issues: exclude-rules: - - path: x/gamm/pool-models/stableswap - linters: - # Stableswap is in development. - # We should re-enable deadcode and unused linting - # across its files, once stableswap is fully complete. - - unused - - deadcode - linters: - staticcheck text: "SA1024: cutset contains duplicate characters" # proved to not provide much value, only false positives. diff --git a/CHANGELOG.md b/CHANGELOG.md index 9701ee798ef..284b55b0128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Misc Improvements + * [#5105](https://github.com/osmosis-labs/osmosis/pull/5105) Lint stableswap in the same manner as all of Osmosis * [#5065](https://github.com/osmosis-labs/osmosis/pull/5065) Use cosmossdk.io/errors * [#4549](https://github.com/osmosis-labs/osmosis/pull/4549) Add single pool price estimate queries * [#4767](https://github.com/osmosis-labs/osmosis/pull/4767) Disable create pool with non-zero exit fee diff --git a/go.sum b/go.sum index 0ba829ecdea..7c3e0395fd2 100644 --- a/go.sum +++ b/go.sum @@ -938,8 +938,6 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch 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.3-dev.0.20230503232557-ba905586c111 h1:1ahWbf9iF9sxDOjxrHWFaBGLE0nWFdpiX1pqObUaJO8= github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230503232557-ba905586c111/go.mod h1:a7lhiXRpn8QJ21OhFpaEnUNErTSIafaYpp02q6uI/Dk= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504184701-a406002c7632 h1:IWZLnQlhnkirvlT/yMivfoB6EgWzkA8mLk0BAXAyfNg= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504184701-a406002c7632/go.mod h1:hk/o9/kmTSZmZqwXcSrPuwj/gpRMCqbE/d3vj6teL2A= github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504190933-b174397f0bc5 h1:fBzTtgZHxvZkpwlg6YtAsNaexEHYaFZDXsYfPQWu9GE= github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504190933-b174397f0bc5/go.mod h1:hk/o9/kmTSZmZqwXcSrPuwj/gpRMCqbE/d3vj6teL2A= github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo= diff --git a/tests/cl-go-client/go.mod b/tests/cl-go-client/go.mod index 42d73de674c..d7214d96065 100644 --- a/tests/cl-go-client/go.mod +++ b/tests/cl-go-client/go.mod @@ -45,12 +45,10 @@ require ( github.com/felixge/httpsnoop v1.0.2 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect - github.com/gin-gonic/gin v1.8.1 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-playground/validator/v10 v10.11.1 // indirect - github.com/goccy/go-json v0.10.2 // indirect + github.com/go-playground/locales v0.14.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/gateway v1.1.0 // indirect github.com/gogo/protobuf v1.3.3 // indirect @@ -88,8 +86,8 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/nxadm/tail v1.4.8 // indirect - github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230425121701-4d427b673864 // indirect - github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230502182115-74bd398c7d6d // indirect + github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230503232557-ba905586c111 // indirect + github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504190933-b174397f0bc5 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -118,6 +116,7 @@ require ( github.com/tendermint/go-amino v0.16.0 // indirect github.com/tendermint/tendermint v0.34.26 // indirect github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b // indirect + github.com/ugorji/go/codec v1.2.7 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect diff --git a/tests/cl-go-client/go.sum b/tests/cl-go-client/go.sum index 79711e8f8b7..47ed5e7eac8 100644 --- a/tests/cl-go-client/go.sum +++ b/tests/cl-go-client/go.sum @@ -287,7 +287,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= -github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= @@ -315,10 +314,8 @@ github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= -github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -330,7 +327,6 @@ github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -561,7 +557,6 @@ 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= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -573,7 +568,6 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= @@ -691,11 +685,8 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434 h1:RetElHdhDl6f00Tjj7ii2r+HX2aa/u+dhgwQb5hKv8Y= github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20230326212251-7a2cf2993434/go.mod h1:ss3tUfPTwaa6NsoPZrCR7xOqLqCK0LwoNbc2Q8Zs5/Y= -github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230425121701-4d427b673864 h1:UhkJ67kx4NP7FEEQ+ybpDLIiS0Rl8vX8G55FKZux98I= -github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230425121701-4d427b673864/go.mod h1:Hu4OHAvKtnCaqA4GlodNf89JZ+2TFtH7IDNxNi6Vue8= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230411200859-ae3065d0ca05 h1:fqVGxZPgUWuYWxVcMxHz5vrDV/aoxGJ7Kt0J4Vu/bsY= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230411200859-ae3065d0ca05/go.mod h1:zyBrzl2rsZWGbOU+/1hzA+xoQlCshzZuHe/5mzdb/zo= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230502182115-74bd398c7d6d/go.mod h1:QeqmptMwAREnUtUTL6KbPRY+zjejIZrj3rRz4RScfyM= +github.com/osmosis-labs/osmosis/osmomath v0.0.3-dev.0.20230503232557-ba905586c111 h1:1ahWbf9iF9sxDOjxrHWFaBGLE0nWFdpiX1pqObUaJO8= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230504190933-b174397f0bc5 h1:fBzTtgZHxvZkpwlg6YtAsNaexEHYaFZDXsYfPQWu9GE= github.com/osmosis-labs/osmosis/x/epochs v0.0.0-20230328024000-175ec88e4304 h1:RIrWLzIiZN5Xd2JOfSOtGZaf6V3qEQYg6EaDTAkMnCo= github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230331072320-5d6f6cfa2627 h1:A0SwZgp4bmJFbivYJc8mmVhMjrr3EdUZluBYFke11+w= github.com/osmosis-labs/wasmd v0.31.0-osmo-v16 h1:X747cZYdnqc/+RV48iPVeGprpVb/fUWSaKGsZUWrdbg= @@ -720,7 +711,6 @@ github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -780,8 +770,6 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= @@ -885,7 +873,6 @@ github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+l github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= @@ -957,7 +944,6 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1052,7 +1038,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1147,7 +1132,6 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/x/gamm/pool-models/stableswap/amm.go b/x/gamm/pool-models/stableswap/amm.go index 964affb7d87..1805d858443 100644 --- a/x/gamm/pool-models/stableswap/amm.go +++ b/x/gamm/pool-models/stableswap/amm.go @@ -10,27 +10,6 @@ import ( types "github.com/osmosis-labs/osmosis/v15/x/gamm/types" ) -var ( - cubeRootTwo, _ = osmomath.NewBigDec(2).ApproxRoot(3) - threeRootTwo, _ = osmomath.NewBigDec(3).ApproxRoot(2) - cubeRootThree, _ = osmomath.NewBigDec(3).ApproxRoot(3) - threeCubeRootTwo = cubeRootTwo.MulInt64(3) - cubeRootSixSquared, _ = (osmomath.NewBigDec(6).MulInt64(6)).ApproxRoot(3) - twoCubeRootThree = cubeRootThree.MulInt64(2) - twentySevenRootTwo, _ = osmomath.NewBigDec(27).ApproxRoot(2) -) - -// solidly CFMM is xy(x^2 + y^2) = k -func cfmmConstant(xReserve, yReserve osmomath.BigDec) osmomath.BigDec { - if !xReserve.IsPositive() || !yReserve.IsPositive() { - panic("invalid input: reserves must be positive") - } - xy := xReserve.Mul(yReserve) - x2 := xReserve.Mul(xReserve) - y2 := yReserve.Mul(yReserve) - return xy.Mul(x2.Add(y2)) -} - // Simplified multi-asset CFMM is xy(x^2 + y^2 + w) = k, // where w is the sum of the squares of the // reserve assets (e.g. w = m^2 + n^2). @@ -53,17 +32,6 @@ func cfmmConstantMultiNoVY(xReserve, yReserve, wSumSquares osmomath.BigDec) osmo return xReserve.Mul(x2.Add(y2).Add(wSumSquares)) } -// full multi-asset CFMM is xyu(x^2 + y^2 + w) = k, -// where u is the product of asset reserves (e.g. u = m * n) -// and w is the sum of the squares of their squares (e.g. w = m^2 + n^2). -// When u = 1 and w = 0, this is equivalent to solidly's CFMM -func cfmmConstantMulti(xReserve, yReserve, u, v osmomath.BigDec) osmomath.BigDec { - if !u.IsPositive() { - panic("invalid input: reserves must be positive") - } - return cfmmConstantMultiNoV(xReserve, yReserve, v).Mul(u) -} - // Solidly's CFMM is xy(x^2 + y^2) = k, and our multi-asset CFMM is xyz(x^2 + y^2 + w) = k // So we want to solve for a given addition of `b` units of y into the pool, // how many units `a` of x do we get out. @@ -78,171 +46,6 @@ func solveCfmm(xReserve, yReserve osmomath.BigDec, remReserves []osmomath.BigDec return solveCFMMBinarySearchMulti(xReserve, yReserve, wSumSquares, yIn) } -// solidly CFMM is xy(x^2 + y^2) = k -// So we want to solve for a given addition of `b` units of y into the pool, -// how many units `a` of x do we get out. -// Let y' = y + b -// we solve k = (x'y')(x'^2 + y^2) for x', using the following equation: https://www.wolframalpha.com/input?i2d=true&i=solve+for+y%5C%2844%29+x*y*%5C%2840%29Power%5Bx%2C2%5D%2BPower%5By%2C2%5D%5C%2841%29%3Dk -// which we simplify to be the following: https://www.desmos.com/calculator/bx5m5wpind -// Then we use that to derive the change in x as x_out = x' - x -// -// Since original reserves, y' and k are known and remain constant throughout the calculation, -// deriving x' and then finding x_out is equivalent to finding x_out directly. -func solveCfmmDirect(xReserve, yReserve, yIn osmomath.BigDec) osmomath.BigDec { - if !xReserve.IsPositive() || !yReserve.IsPositive() || !yIn.IsPositive() { - panic("invalid input: reserves and input must be positive") - } - - if yIn.GT(yReserve) { - panic("invalid input: cannot trade greater than reserve amount into CFMM") - } - - // find k using existing reserves - k := cfmmConstant(xReserve, yReserve) - - // find new yReserve after join - y_new := yReserve.Add(yIn) - - // store powers to simplify calculations - y2 := y_new.Mul(y_new) - y3 := y2.Mul(y_new) - y4 := y3.Mul(y_new) - - // We then solve for new xReserve using new yReserve and old k using a solver derived from xy(x^2 + y^2) = k - // Full equation: x' = [((2^(1/3)) * ([y^2 * 9k) * ((sqrt(1 + ((2 / sqrt(27)) * (y^4 / k))^2)) + 1)]^(1/3)) / y') - // - (2 * (3^(1/3)) * y^3 / ([y^2 * 9k) * ((sqrt(1 + ((2 / sqrt(27)) * (y^4 / k))^2)) + 1)]^(1/3))) - // ] / (6^(2/3)) - // - // To simplify, we make the following abstractions: - // 1. scaled_y4_quo_k = (2 / sqrt(27)) * (y^4 / k) - // 2. sqrt_term = sqrt(1 + scaled_y4_quo_k2) - // 3. common_factor = [y^2 * 9k) * (sqrt_term + 1)]^(1/3) - // 4. term1 = (2^(1/3)) * common_factor / y' - // 5. term2 = 2 * (3^(1/3)) * y^3 / common_factor - // - // With these, the final equation becomes: x' = (term1 - term2) / (6^(2/3)) - - // let scaled_y4_quo_k = (2 / sqrt(27)) * (y^4 / k) - scaled_y4_quo_k := (y4.Quo(k)).Mul(osmomath.NewBigDec(2).Quo(twentySevenRootTwo)) - scaled_y4_quo_k2 := scaled_y4_quo_k.Mul(scaled_y4_quo_k) - - // let sqrt_term = sqrt(1 + scaled_y4_quo_k2) - sqrt_term, err := (osmomath.OneDec().Add(scaled_y4_quo_k2)).ApproxRoot(2) - if err != nil { - panic(err) - } - - // let common_factor = [y^2 * 9k) * (sqrt_term + 1)]^(1/3) - common_factor, err := (y2.MulInt64(9).Mul(k).Mul((sqrt_term.Add(osmomath.OneDec())))).ApproxRoot(3) - if err != nil { - panic(err) - } - - // term1 = (2^(1/3)) * common_factor / y' - term1 := cubeRootTwo.Mul(common_factor).Quo(y_new) - // term2 = 2 * (3^(1/3)) * y^3 / common_factor - term2 := twoCubeRootThree.Mul(y3).Quo(common_factor) - - // finally, x' = (term1 - term2) / (6^(2/3)) - x_new := (term1.Sub(term2)).Quo(cubeRootSixSquared) - - // find amount of x to output using initial and final xReserve values - xOut := xReserve.Sub(x_new) - - if xOut.GTE(xReserve) { - panic("invalid output: greater than full pool reserves") - } - - return xOut -} - -// multi-asset CFMM is xyu(x^2 + y^2 + w) = k -// As described in our spec, we can ignore the u term and simply solve within the bounds of k' = k / u -// since u remains constant throughout any independent operation this solver would be used for. -// We want to solve for a given addition of `b` units of y into the pool, -// how many units `a` of x do we get out. -// Let y' = y + b -// we solve k = (x'y')(x'^2 + y^2 + w) for x', using the following equation: https://www.wolframalpha.com/input?i2d=true&i=solve+for+y%5C%2844%29+x*y*%5C%2840%29Power%5Bx%2C2%5D+%2B+Power%5By%2C2%5D+%2B+w%5C%2841%29%3Dk -// which we simplify to be the following: https://www.desmos.com/calculator/zx2qslqndl -// Then we use that to derive the change in x as x_out = x' - x -// -// Since original reserves, y' and k are known and remain constant throughout the calculation, -// deriving x' and then finding x_out is equivalent to finding x_out directly. -func solveCFMMMultiDirect(xReserve, yReserve, wSumSquares, yIn osmomath.BigDec) osmomath.BigDec { - if !xReserve.IsPositive() || !yReserve.IsPositive() || wSumSquares.IsNegative() || !yIn.IsPositive() { - panic("invalid input: reserves and input must be positive") - } else if yIn.GTE(yReserve) { - panic("cannot input more than pool reserves") - } - - // find k' using existing reserves (k' = k / v term) - k := cfmmConstantMultiNoV(xReserve, yReserve, wSumSquares) - k2 := k.Mul(k) - - // find new yReserve after join - y_new := yReserve.Add(yIn) - - // store powers to simplify calculations - y2 := y_new.Mul(y_new) - y3 := y2.Mul(y_new) - y4 := y3.Mul(y_new) - - // We then solve for new xReserve using new yReserve and old k using a solver derived from xy(x^2 + y^2 + w) = k - // Full equation: x' = (sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3) / (3 2^(1/3) y) - // - (2^(1/3) (w y + y^3))/(sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3) - // - // - // To simplify, we make the following abstractions: - // 1. sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) - // 2. cube_root_term = (sqrt_term + 27 k y^2)^(1/3) - // 3. term1 = cube_root_term / (3 2^(1/3) y) - // 4. term2 = (2^(1/3) (w y + y^3)) / cube_root_term - // - // With these, the final equation becomes: x' = term1 - term2 - - // let sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) - wypy3 := (wSumSquares.Mul(y_new)).Add(y3) - wypy3pow3 := wypy3.Mul(wypy3).Mul(wypy3) - - sqrt_term, err := ((k2.Mul(y4).MulInt64(729)).Add(y3.MulInt64(108).Mul(wypy3pow3))).ApproxRoot(2) - if err != nil { - panic(err) - } - - // let cube_root_term = (sqrt_term + 27 k y^2)^(1/3) - cube_root_term, err := (sqrt_term.Add(k.Mul(y2).MulInt64(27))).ApproxRoot(3) - if err != nil { - panic(err) - } - - // let term1 = cube_root_term / (3 2^(1/3) y) - term1 := cube_root_term.Quo(cubeRootTwo.MulInt64(3).Mul(y_new)) - - // let term2 = cube_root_term * (2^(1/3) (w y + y^3)) - term2 := (cubeRootTwo.Mul(wypy3)).Quo(cube_root_term) - - // finally, let x' = term1 - term2 - x_new := term1.Sub(term2) - - // find amount of x to output using initial and final xReserve values - xOut := xReserve.Sub(x_new) - - if xOut.GTE(xReserve) { - panic("invalid output: greater than full pool reserves") - } - - return xOut -} - -func approxDecEqual(a, b, tol osmomath.BigDec) bool { - return (a.Sub(b).Abs()).LTE(tol) -} - -var ( - twodec = osmomath.MustNewDecFromStr("2.0") - k_threshold = osmomath.NewDecWithPrec(1, 1) // Correct within a factor of 1 * 10^{-1} -) - // $$k_{target} = \frac{x_0 y_0 (x_0^2 + y_0^2 + w)}{y_f} - (x_0 (y_f^2 + w) + x_0^3)$$ func targetKCalculator(x0, y0, w, yf osmomath.BigDec) osmomath.BigDec { // cfmmNoV(x0, y0, w) = x_0 y_0 (x_0^2 + y_0^2 + w) diff --git a/x/gamm/pool-models/stableswap/amm_test.go b/x/gamm/pool-models/stableswap/amm_test.go index f63e1cd3c95..98245da170b 100644 --- a/x/gamm/pool-models/stableswap/amm_test.go +++ b/x/gamm/pool-models/stableswap/amm_test.go @@ -18,6 +18,16 @@ import ( types "github.com/osmosis-labs/osmosis/v15/x/gamm/types" ) +var ( + cubeRootTwo, _ = osmomath.NewBigDec(2).ApproxRoot(3) + threeRootTwo, _ = osmomath.NewBigDec(3).ApproxRoot(2) + cubeRootThree, _ = osmomath.NewBigDec(3).ApproxRoot(3) + threeCubeRootTwo = cubeRootTwo.MulInt64(3) + cubeRootSixSquared, _ = (osmomath.NewBigDec(6).MulInt64(6)).ApproxRoot(3) + twoCubeRootThree = cubeRootThree.MulInt64(2) + twentySevenRootTwo, _ = osmomath.NewBigDec(27).ApproxRoot(2) +) + // CFMMTestCase defines a testcase for stableswap pools type CFMMTestCase struct { xReserve osmomath.BigDec @@ -453,6 +463,95 @@ func TestCFMMInvariantTwoAssetsDirect(t *testing.T) { } } +// solidly CFMM is xy(x^2 + y^2) = k +// So we want to solve for a given addition of `b` units of y into the pool, +// how many units `a` of x do we get out. +// Let y' = y + b +// we solve k = (x'y')(x'^2 + y^2) for x', using the following equation: https://www.wolframalpha.com/input?i2d=true&i=solve+for+y%5C%2844%29+x*y*%5C%2840%29Power%5Bx%2C2%5D%2BPower%5By%2C2%5D%5C%2841%29%3Dk +// which we simplify to be the following: https://www.desmos.com/calculator/bx5m5wpind +// Then we use that to derive the change in x as x_out = x' - x +// +// Since original reserves, y' and k are known and remain constant throughout the calculation, +// deriving x' and then finding x_out is equivalent to finding x_out directly. +func solveCfmmDirect(xReserve, yReserve, yIn osmomath.BigDec) osmomath.BigDec { + if !xReserve.IsPositive() || !yReserve.IsPositive() || !yIn.IsPositive() { + panic("invalid input: reserves and input must be positive") + } + + if yIn.GT(yReserve) { + panic("invalid input: cannot trade greater than reserve amount into CFMM") + } + + // find k using existing reserves + k := cfmmConstant(xReserve, yReserve) + + // find new yReserve after join + y_new := yReserve.Add(yIn) + + // store powers to simplify calculations + y2 := y_new.Mul(y_new) + y3 := y2.Mul(y_new) + y4 := y3.Mul(y_new) + + // We then solve for new xReserve using new yReserve and old k using a solver derived from xy(x^2 + y^2) = k + // Full equation: x' = [((2^(1/3)) * ([y^2 * 9k) * ((sqrt(1 + ((2 / sqrt(27)) * (y^4 / k))^2)) + 1)]^(1/3)) / y') + // - (2 * (3^(1/3)) * y^3 / ([y^2 * 9k) * ((sqrt(1 + ((2 / sqrt(27)) * (y^4 / k))^2)) + 1)]^(1/3))) + // ] / (6^(2/3)) + // + // To simplify, we make the following abstractions: + // 1. scaled_y4_quo_k = (2 / sqrt(27)) * (y^4 / k) + // 2. sqrt_term = sqrt(1 + scaled_y4_quo_k2) + // 3. common_factor = [y^2 * 9k) * (sqrt_term + 1)]^(1/3) + // 4. term1 = (2^(1/3)) * common_factor / y' + // 5. term2 = 2 * (3^(1/3)) * y^3 / common_factor + // + // With these, the final equation becomes: x' = (term1 - term2) / (6^(2/3)) + + // let scaled_y4_quo_k = (2 / sqrt(27)) * (y^4 / k) + scaled_y4_quo_k := (y4.Quo(k)).Mul(osmomath.NewBigDec(2).Quo(twentySevenRootTwo)) + scaled_y4_quo_k2 := scaled_y4_quo_k.Mul(scaled_y4_quo_k) + + // let sqrt_term = sqrt(1 + scaled_y4_quo_k2) + sqrt_term, err := (osmomath.OneDec().Add(scaled_y4_quo_k2)).ApproxRoot(2) + if err != nil { + panic(err) + } + + // let common_factor = [y^2 * 9k) * (sqrt_term + 1)]^(1/3) + common_factor, err := (y2.MulInt64(9).Mul(k).Mul((sqrt_term.Add(osmomath.OneDec())))).ApproxRoot(3) + if err != nil { + panic(err) + } + + // term1 = (2^(1/3)) * common_factor / y' + term1 := cubeRootTwo.Mul(common_factor).Quo(y_new) + // term2 = 2 * (3^(1/3)) * y^3 / common_factor + term2 := twoCubeRootThree.Mul(y3).Quo(common_factor) + + // finally, x' = (term1 - term2) / (6^(2/3)) + x_new := (term1.Sub(term2)).Quo(cubeRootSixSquared) + + // find amount of x to output using initial and final xReserve values + xOut := xReserve.Sub(x_new) + + if xOut.GTE(xReserve) { + panic("invalid output: greater than full pool reserves") + } + + return xOut +} + +// solidly CFMM is xy(x^2 + y^2) = k +func cfmmConstant(xReserve, yReserve osmomath.BigDec) osmomath.BigDec { + if !xReserve.IsPositive() || !yReserve.IsPositive() { + panic("invalid input: reserves must be positive") + } + xy := xReserve.Mul(yReserve) + x2 := xReserve.Mul(xReserve) + y2 := yReserve.Mul(yReserve) + return xy.Mul(x2.Add(y2)) +} + func TestCFMMInvariantMultiAssets(t *testing.T) { kErrTolerance := osmomath.OneDec() @@ -477,6 +576,17 @@ func TestCFMMInvariantMultiAssets(t *testing.T) { } } +// full multi-asset CFMM is xyu(x^2 + y^2 + w) = k, +// where u is the product of asset reserves (e.g. u = m * n) +// and w is the sum of the squares of their squares (e.g. w = m^2 + n^2). +// When u = 1 and w = 0, this is equivalent to solidly's CFMM +func cfmmConstantMulti(xReserve, yReserve, u, v osmomath.BigDec) osmomath.BigDec { + if !u.IsPositive() { + panic("invalid input: reserves must be positive") + } + return cfmmConstantMultiNoV(xReserve, yReserve, v).Mul(u) +} + func TestCFMMInvariantMultiAssetsDirect(t *testing.T) { kErrTolerance := osmomath.OneDec() @@ -500,6 +610,84 @@ func TestCFMMInvariantMultiAssetsDirect(t *testing.T) { } } +// multi-asset CFMM is xyu(x^2 + y^2 + w) = k +// As described in our spec, we can ignore the u term and simply solve within the bounds of k' = k / u +// since u remains constant throughout any independent operation this solver would be used for. +// We want to solve for a given addition of `b` units of y into the pool, +// how many units `a` of x do we get out. +// Let y' = y + b +// we solve k = (x'y')(x'^2 + y^2 + w) for x', using the following equation: https://www.wolframalpha.com/input?i2d=true&i=solve+for+y%5C%2844%29+x*y*%5C%2840%29Power%5Bx%2C2%5D+%2B+Power%5By%2C2%5D+%2B+w%5C%2841%29%3Dk +// which we simplify to be the following: https://www.desmos.com/calculator/zx2qslqndl +// Then we use that to derive the change in x as x_out = x' - x +// +// Since original reserves, y' and k are known and remain constant throughout the calculation, +// deriving x' and then finding x_out is equivalent to finding x_out directly. +func solveCFMMMultiDirect(xReserve, yReserve, wSumSquares, yIn osmomath.BigDec) osmomath.BigDec { + if !xReserve.IsPositive() || !yReserve.IsPositive() || wSumSquares.IsNegative() || !yIn.IsPositive() { + panic("invalid input: reserves and input must be positive") + } else if yIn.GTE(yReserve) { + panic("cannot input more than pool reserves") + } + + // find k' using existing reserves (k' = k / v term) + k := cfmmConstantMultiNoV(xReserve, yReserve, wSumSquares) + k2 := k.Mul(k) + + // find new yReserve after join + y_new := yReserve.Add(yIn) + + // store powers to simplify calculations + y2 := y_new.Mul(y_new) + y3 := y2.Mul(y_new) + y4 := y3.Mul(y_new) + + // We then solve for new xReserve using new yReserve and old k using a solver derived from xy(x^2 + y^2 + w) = k + // Full equation: x' = (sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3) / (3 2^(1/3) y) + // - (2^(1/3) (w y + y^3))/(sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + 27 k y^2)^(1/3) + // + // + // To simplify, we make the following abstractions: + // 1. sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + // 2. cube_root_term = (sqrt_term + 27 k y^2)^(1/3) + // 3. term1 = cube_root_term / (3 2^(1/3) y) + // 4. term2 = (2^(1/3) (w y + y^3)) / cube_root_term + // + // With these, the final equation becomes: x' = term1 - term2 + + // let sqrt_term = sqrt(729 k^2 y^4 + 108 y^3 (w y + y^3)^3) + wypy3 := (wSumSquares.Mul(y_new)).Add(y3) + wypy3pow3 := wypy3.Mul(wypy3).Mul(wypy3) + + sqrt_term, err := ((k2.Mul(y4).MulInt64(729)).Add(y3.MulInt64(108).Mul(wypy3pow3))).ApproxRoot(2) + if err != nil { + panic(err) + } + + // let cube_root_term = (sqrt_term + 27 k y^2)^(1/3) + cube_root_term, err := (sqrt_term.Add(k.Mul(y2).MulInt64(27))).ApproxRoot(3) + if err != nil { + panic(err) + } + + // let term1 = cube_root_term / (3 2^(1/3) y) + term1 := cube_root_term.Quo(cubeRootTwo.MulInt64(3).Mul(y_new)) + + // let term2 = cube_root_term * (2^(1/3) (w y + y^3)) + term2 := (cubeRootTwo.Mul(wypy3)).Quo(cube_root_term) + + // finally, let x' = term1 - term2 + x_new := term1.Sub(term2) + + // find amount of x to output using initial and final xReserve values + xOut := xReserve.Sub(x_new) + + if xOut.GTE(xReserve) { + panic("invalid output: greater than full pool reserves") + } + + return xOut +} + func TestCFMMInvariantMultiAssetsBinarySearch(t *testing.T) { kErrTolerance := osmomath.OneDec() @@ -726,7 +914,8 @@ func (suite *StableSwapTestSuite) Test_StableSwap_CalculateAmountOutAndIn_Invers pool := createTestPool(suite.T(), tc.poolLiquidity, swapFeeDec, exitFeeDec, tc.scalingFactors) suite.Require().NotNil(pool) errTolerance := osmomath.ErrTolerance{ - AdditiveTolerance: sdk.Dec{}, MultiplicativeTolerance: sdk.NewDecWithPrec(1, 12)} + AdditiveTolerance: sdk.Dec{}, MultiplicativeTolerance: sdk.NewDecWithPrec(1, 12), + } test_helpers.TestCalculateAmountOutAndIn_InverseRelationship(suite.T(), ctx, pool, tc.denomIn, tc.denomOut, tc.initialCalcOut, swapFeeDec, errTolerance) }) }