diff --git a/CHANGELOG.md b/CHANGELOG.md index e198e4f1946..9117acf1414 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### State Compatible +<<<<<<< HEAD +======= +* [#8006](https://github.com/osmosis-labs/osmosis/pull/8006), [#8014](https://github.com/osmosis-labs/osmosis/pull/8014) Speedup many BigDec operations + +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) ## v24.0.1 * [#7994](https://github.com/osmosis-labs/osmosis/pull/7994) Async pruning for IAVL v1 diff --git a/go.mod b/go.mod index ac15cc9f6df..1b4550c1eb9 100644 --- a/go.mod +++ b/go.mod @@ -27,11 +27,19 @@ 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 +<<<<<<< HEAD github.com/osmosis-labs/osmosis/osmomath v0.0.10-0.20240409161506-a48ca4af185c github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c github.com/osmosis-labs/osmosis/x/epochs v0.0.6-0.20240409161506-a48ca4af185c github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.11-0.20240409161506-a48ca4af185c github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240328223248-ae061110b150 +======= + github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 + github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 + github.com/osmosis-labs/osmosis/x/epochs v0.0.8-0.20240411125512-cb0fada2dee8 + github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.14-0.20240411125512-cb0fada2dee8 + github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240404053421-41aab009fb04 +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.6.0 diff --git a/go.sum b/go.sum index fa0ac37e249..7440e0c0b63 100644 --- a/go.sum +++ b/go.sum @@ -1510,6 +1510,7 @@ github.com/osmosis-labs/cosmos-sdk v0.47.5-v23-osmo-9-iavl-v1 h1:cJfWAQHK2Em6cE5 github.com/osmosis-labs/cosmos-sdk v0.47.5-v23-osmo-9-iavl-v1/go.mod h1:O4R0cSw6y7aGLpDCd9epgX+1nsRQMpmexmI03j/sQYI= 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= +<<<<<<< HEAD github.com/osmosis-labs/ibc-go/v7 v7.3.3 h1:aSqu18eqAR9tMjIrqYSy5GezIBPvZbvOEyZeM/5VgEo= github.com/osmosis-labs/ibc-go/v7 v7.3.3/go.mod h1:IMeOXb7gwpZ+/nOG5BuUkdW4weM1ezvN4PQPws4uzOI= github.com/osmosis-labs/osmosis/osmomath v0.0.10-0.20240409161506-a48ca4af185c h1:9uBBhQT17o2fF+pKPWrSGAqG2aXjm4SR9fjMxuxuqbk= @@ -1522,6 +1523,18 @@ github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.11-0.20240409161506-a48ca4af185 github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.11-0.20240409161506-a48ca4af185c/go.mod h1:9C+lwGSUB+MpivIIu7iS2PoJK6aJZuaf+KXOX2fQ4Kg= github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240328223248-ae061110b150 h1:z490JBjgVkvreJNeFE9es16rhc0rurM2GRhwqW0wEoY= github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240328223248-ae061110b150/go.mod h1:H6XfDqE0PiUoIXaTTVipupfbrpz7Cu95jYbu2yYo6Tg= +======= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 h1:p1jOOamB3IHz5qXeN50KJLEQmNx3PSz5wunNtUrSb4g= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:OQj1UyxCyuunzCPuYtbRGTvaL62OIznjQpXqdFDINbs= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 h1:3BlWDp7ivc+gyjdIPxkcvcDBsATq8s+ZEUD1AxFuDzo= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:n41vW6Nr5BmO7jCrdEONyOrJ3PACRcOt/KvhVTrEfjo= +github.com/osmosis-labs/osmosis/x/epochs v0.0.8-0.20240411125512-cb0fada2dee8 h1:/q88xaj3yRcGpFBHnsw/FetvA3f6qa8sKSPx7L12uKw= +github.com/osmosis-labs/osmosis/x/epochs v0.0.8-0.20240411125512-cb0fada2dee8/go.mod h1:9eNG5sUawozrcuYUGhSQlsynneDXXfg7yzy7FnGa1sY= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.14-0.20240411125512-cb0fada2dee8 h1:m3zpevamz76sscGFDpc4LzMGE18GCAm0oAZyYtcxok8= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.14-0.20240411125512-cb0fada2dee8/go.mod h1:P6eRZizImh4d4nAW9iHYWFcXUJ+SQlRYqXXktlu9tuo= +github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240404053421-41aab009fb04 h1:mvkk1A/jIe+lsFFpRNfyd9UfvhagATdpnjy8K7kANeo= +github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240404053421-41aab009fb04/go.mod h1:mYYf7pYb7sGJ9zYIOw2aYlIl5cgKT0K93rZx4LvDAuA= +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/osmosis-labs/wasmd v0.45.0-osmo h1:NIp7pvJV5HuBN1HwPgEmXKQM2TjVIVdJErIHnB9IMO8= github.com/osmosis-labs/wasmd v0.45.0-osmo/go.mod h1:J6eRvwii5T1WxhetZkBg1kOJS3GTn1Bw2OLyZBb8EVU= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= diff --git a/osmomath/decimal.go b/osmomath/decimal.go index 0030f8e0b57..1a77d6b5540 100644 --- a/osmomath/decimal.go +++ b/osmomath/decimal.go @@ -41,11 +41,24 @@ var ( squaredPrecisionReuse = new(big.Int).Mul(precisionReuse, precisionReuse) precisionReuseSDK = new(big.Int).Exp(big.NewInt(10), big.NewInt(DecPrecision), nil) bigDecDecPrecisionFactorDiff = new(big.Int).Exp(big.NewInt(10), big.NewInt(BigDecPrecision-DecPrecision), nil) +<<<<<<< HEAD fivePrecision = new(big.Int).Quo(precisionReuse, big.NewInt(2)) precisionMultipliers []*big.Int zeroInt = big.NewInt(0) oneInt = big.NewInt(1) tenInt = big.NewInt(10) +======= + + tenTimesPrecision = new(big.Int).Exp(big.NewInt(10), big.NewInt(BigDecPrecision+1), nil) + fivePrecision = new(big.Int).Quo(defaultBigDecPrecisionReuse, big.NewInt(2)) + fivePrecisionSDKDec = new(big.Int).Quo(precisionReuseSDKDec, big.NewInt(2)) + + precisionMultipliers []*big.Int + zeroInt = big.NewInt(0) + oneInt = big.NewInt(1) + fiveInt = big.NewInt(5) + tenInt = big.NewInt(10) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) // log_2(e) // From: https://www.wolframalpha.com/input?i=log_2%28e%29+with+37+digits @@ -167,6 +180,11 @@ func NewBigDecFromIntWithPrec(i BigInt, prec int64) BigDec { } } +func NewBigDecFromDecMulDec(a, b Dec) BigDec { + newBi := new(big.Int).Mul(a.BigIntMut(), b.BigIntMut()) + return BigDec{newBi} +} + // create a decimal from an input decimal string. // valid must come in the form: // @@ -288,20 +306,29 @@ func (d BigDec) Add(d2 BigDec) BigDec { func (d BigDec) AddMut(d2 BigDec) BigDec { d.i.Add(d.i, d2.i) - if d.i.BitLen() > maxDecBitLen { - panic("Int overflow") - } + assertMaxBitLen(d.i) return d } // subtraction func (d BigDec) Sub(d2 BigDec) BigDec { +<<<<<<< HEAD res := new(big.Int).Sub(d.i, d2.i) if res.BitLen() > maxDecBitLen { panic("Int overflow") } +======= + copy := d.Clone() + copy.SubMut(d2) + return copy +} + +func (d BigDec) SubMut(d2 BigDec) BigDec { + res := d.i.Sub(d.i, d2.i) + assertMaxBitLen(res) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) return BigDec{res} } @@ -332,12 +359,11 @@ func (d BigDec) MulMut(d2 BigDec) BigDec { d.i.Mul(d.i, d2.i) d.i = chopPrecisionAndRound(d.i) - if d.i.BitLen() > maxDecBitLen { - panic("Int overflow") - } + assertMaxBitLen(d.i) return BigDec{d.i} } +<<<<<<< HEAD // multiplication truncate func (d BigDec) MulTruncate(d2 BigDec) BigDec { mul := new(big.Int).Mul(d.i, d2.i) @@ -346,27 +372,61 @@ func (d BigDec) MulTruncate(d2 BigDec) BigDec { if chopped.BitLen() > maxDecBitLen { panic("Int overflow") } +======= +func (d BigDec) MulDec(d2 Dec) BigDec { + copy := d.Clone() + copy.MulDecMut(d2) + return copy +} + +func (d BigDec) MulDecMut(d2 Dec) BigDec { + d.i.Mul(d.i, d2.BigIntMut()) + d.i = chopPrecisionAndRoundSdkDec(d.i) + + assertMaxBitLen(d.i) + return BigDec{d.i} +} + +// multiplication truncate +func (d BigDec) MulTruncate(d2 BigDec) BigDec { + mul := new(big.Int).Mul(d.i, d2.i) + chopped := chopPrecisionAndTruncateMut(mul, defaultBigDecPrecisionReuse) + assertMaxBitLen(chopped) + return BigDec{chopped} +} + +func (d BigDec) MulTruncateDec(d2 Dec) BigDec { + mul := new(big.Int).Mul(d.i, d2.BigIntMut()) + chopped := chopPrecisionAndTruncateMut(mul, precisionReuseSDKDec) + assertMaxBitLen(chopped) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) return BigDec{chopped} } // multiplication round up func (d BigDec) MulRoundUp(d2 BigDec) BigDec { mul := new(big.Int).Mul(d.i, d2.i) +<<<<<<< HEAD chopped := chopPrecisionAndRoundUpBigDec(mul) +======= + chopped := chopPrecisionAndRoundUpMut(mul, defaultBigDecPrecisionReuse) + assertMaxBitLen(chopped) + return BigDec{chopped} +} +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) - if chopped.BitLen() > maxDecBitLen { - panic("Int overflow") - } +// multiplication round up by Dec +func (d BigDec) MulRoundUpDec(d2 Dec) BigDec { + mul := new(big.Int).Mul(d.i, d2.BigIntMut()) + chopped := chopPrecisionAndRoundUpMut(mul, precisionReuseSDKDec) + assertMaxBitLen(chopped) return BigDec{chopped} } // multiplication func (d BigDec) MulInt(i BigInt) BigDec { mul := new(big.Int).Mul(d.i, i.i) - - if mul.BitLen() > maxDecBitLen { - panic("Int overflow") - } + assertMaxBitLen(mul) return BigDec{mul} } @@ -374,10 +434,7 @@ func (d BigDec) MulInt(i BigInt) BigDec { func (d BigDec) MulInt64(i int64) BigDec { bi := big.NewInt(i) mul := bi.Mul(d.i, bi) - - if mul.BitLen() > maxDecBitLen { - panic("Int overflow") - } + assertMaxBitLen(mul) return BigDec{mul} } @@ -391,32 +448,38 @@ func (d BigDec) Quo(d2 BigDec) BigDec { // mutative quotient func (d BigDec) QuoMut(d2 BigDec) BigDec { // multiply precision twice +<<<<<<< HEAD d.i.Mul(d.i, precisionReuse) d.i.Mul(d.i, precisionReuse) +======= + // TODO: Use lower overhead thing here + d.i.Mul(d.i, squaredPrecisionReuse) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) d.i.Quo(d.i, d2.i) chopPrecisionAndRound(d.i) - if d.i.BitLen() > maxDecBitLen { - panic("Int overflow") - } + assertMaxBitLen(d.i) return d } func (d BigDec) QuoRaw(d2 int64) BigDec { // multiply precision, so we can chop it later +<<<<<<< HEAD mul := new(big.Int).Mul(d.i, precisionReuse) +======= + // TODO: There is certainly more efficient ways to do this, come back later + mul := new(big.Int).Mul(d.i, defaultBigDecPrecisionReuse) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) quo := mul.Quo(mul, big.NewInt(d2)) chopped := chopPrecisionAndRound(quo) - - if chopped.BitLen() > maxDecBitLen { - panic("Int overflow") - } + assertMaxBitLen(chopped) return BigDec{chopped} } // quotient truncate func (d BigDec) QuoTruncate(d2 BigDec) BigDec { +<<<<<<< HEAD // multiply precision twice mul := new(big.Int).Mul(d.i, precisionReuse) mul.Mul(mul, precisionReuse) @@ -428,6 +491,12 @@ func (d BigDec) QuoTruncate(d2 BigDec) BigDec { panic("Int overflow") } return BigDec{chopped} +======= + mul := new(big.Int).Mul(d.i, defaultBigDecPrecisionReuse) + quo := mul.Quo(mul, d2.i) + assertMaxBitLen(quo) + return BigDec{quo} +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) } // quotient truncate (mutative) @@ -435,16 +504,40 @@ func (d BigDec) QuoTruncateMut(d2 BigDec) BigDec { // multiply precision twice d.i.Mul(d.i, squaredPrecisionReuse) d.i.Quo(d.i, d2.i) +<<<<<<< HEAD chopPrecisionAndTruncateMut(d.i) if d.i.BitLen() > maxDecBitLen { panic("Int overflow") } +======= + assertMaxBitLen(d.i) + return d +} + +// quotient truncate +func (d BigDec) QuoTruncateDec(d2 Dec) BigDec { + // multiply Dec Precision + mul := new(big.Int).Mul(d.i, precisionReuseSDKDec) + quo := mul.Quo(mul, d2.BigIntMut()) + assertMaxBitLen(quo) + return BigDec{quo} +} + +// quotient truncate (mutative) +func (d BigDec) QuoTruncateDecMut(d2 Dec) BigDec { + // multiply Dec Precision + d.i.Mul(d.i, precisionReuseSDKDec) + d.i.Quo(d.i, d2.BigIntMut()) + + assertMaxBitLen(d.i) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) return d } // quotient, round up func (d BigDec) QuoRoundUp(d2 BigDec) BigDec { +<<<<<<< HEAD // multiply precision twice mul := new(big.Int).Mul(d.i, precisionReuse) mul.Mul(mul, precisionReuse) @@ -454,21 +547,53 @@ func (d BigDec) QuoRoundUp(d2 BigDec) BigDec { if chopped.BitLen() > maxDecBitLen { panic("Int overflow") +======= + mul := new(big.Int).Mul(d.i, defaultBigDecPrecisionReuse) + + chopped, rem := mul.QuoRem(mul, d2.i, new(big.Int)) + if rem.Sign() > 0 { + chopped.Add(chopped, oneInt) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) } + + assertMaxBitLen(chopped) + return BigDec{chopped} +} + +// quotient, round up +func (d BigDec) QuoByDecRoundUp(d2 Dec) BigDec { + mul := new(big.Int).Mul(d.i, precisionReuseSDKDec) + + chopped, rem := mul.QuoRem(mul, d2.BigIntMut(), new(big.Int)) + if rem.Sign() > 0 { + chopped.Add(chopped, oneInt) + } + + assertMaxBitLen(chopped) return BigDec{chopped} } // quotient, round up (mutative) func (d BigDec) QuoRoundUpMut(d2 BigDec) BigDec { - // multiply precision twice - d.i.Mul(d.i, squaredPrecisionReuse) - d.i.Quo(d.i, d2.i) + d.i.Mul(d.i, defaultBigDecPrecisionReuse) + _, rem := d.i.QuoRem(d.i, d2.i, new(big.Int)) +<<<<<<< HEAD chopPrecisionAndRoundUpMut(d.i, precisionReuse) +======= + d.i = incBasedOnRem(rem, d.i) + assertMaxBitLen(d.i) + return BigDec{d.i} +} +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) - if d.i.BitLen() > maxDecBitLen { - panic("Int overflow") - } +// quotient, round up to next integer (mutative) +func (d BigDec) QuoRoundUpNextIntMut(d2 BigDec) BigDec { + _, rem := d.i.QuoRem(d.i, d2.i, new(big.Int)) + + d.i = incBasedOnRem(rem, d.i) + d.i.Mul(d.i, defaultBigDecPrecisionReuse) + assertMaxBitLen(d.i) return BigDec{d.i} } @@ -532,6 +657,12 @@ func (d BigDec) ApproxRoot(root uint64) (guess BigDec, err error) { return guess, nil } +func assertMaxBitLen(i *big.Int) { + if i.BitLen() > maxDecBitLen { + panic("Int overflow") + } +} + // ApproxSqrt is a wrapper around ApproxRoot for the common special case // of finding the square root of a number. It returns -(sqrt(abs(d)) if input is negative. func (d BigDec) ApproxSqrt() (BigDec, error) { @@ -781,6 +912,13 @@ func chopPrecisionAndRoundUpDec(d *big.Int) *big.Int { return chopPrecisionAndRoundUpMut(copy, precisionReuseSDK) } +func incBasedOnRem(rem *big.Int, d *big.Int) *big.Int { + if rem.Sign() == 0 { + return d + } + return d.Add(d, oneInt) +} + // chopPrecisionAndRoundUp removes a Precision amount of rightmost digits and rounds up. // Mutates input d. // Mutations occur: @@ -799,12 +937,7 @@ func chopPrecisionAndRoundUpMut(d *big.Int, precisionReuse *big.Int) *big.Int { // get the truncated quotient and remainder _, rem := d.QuoRem(d, precisionReuse, big.NewInt(0)) - - if rem.Sign() == 0 { // remainder is zero - return d - } - - return d.Add(d, oneInt) + return incBasedOnRem(rem, d) } func chopPrecisionAndRoundNonMutative(d *big.Int) *big.Int { @@ -1163,6 +1296,11 @@ func (d BigDec) PowerInteger(power uint64) BigDec { func (d BigDec) PowerIntegerMut(power uint64) BigDec { if power == 0 { return OneBigDec() + } else if power == 1 { + return d + } else if power == 2 { + // save a oneBigDec allocation + return d.MulMut(d) } tmp := OneBigDec() diff --git a/osmomath/decimal_test.go b/osmomath/decimal_test.go index 0afb3d45a02..2226bd04585 100644 --- a/osmomath/decimal_test.go +++ b/osmomath/decimal_test.go @@ -178,6 +178,75 @@ func (s *decimalTestSuite) TestNewDecFromStr() { } } +var interestingDecNumbers = []string{ + "123456789012345678901234567890123456789012345678901234567890.123456789012345678901234567890123456", + "111111111111111111111111111111111111111111111111111111111111.111111111111111111111111111111111111", + "999999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999", + "3141592653589793238462643383279502884197169399375105820974944.592307816406286208998628034825342117", // Approximation of Pi, extended + "1618033988749894848204586834365638117720309179805762862135448.622705260462818902449707207204189391", // Approximation of Phi, extended + "2718281828459045235360287471352662497757247093699959574966967.627724076630353547594571382178525166", // Approximation of e, extended + "101010101010101010101010101010101010101010101010101010101010.101010101010101010101010101010101010", // Binary pattern extended + "1234567899876543210123456789987654321012345678998765432101234.567899876543210123456789987654321012", // Ascending and descending pattern extended + "1123581321345589144233377610987159725844181676510946173113801.986211915342546982272763642843251547", // Inspired by Fibonacci sequence, creatively adjusted + "1428571428571428571428571428571428571428571428571428571428571.428571428571428571428571428571428571", // Repeating decimal for 1/7 extended +} + +var interestingDecNumbersBigDec = []osmomath.BigDec{} +var interestingDecNumbersDec = []osmomath.Dec{} + +func init() { + for _, str := range interestingDecNumbers { + d, err := osmomath.NewBigDecFromStr(str) + if err != nil { + panic(fmt.Sprintf("error parsing decimal string %v: %v", str, err)) + } + interestingDecNumbersBigDec = append(interestingDecNumbersBigDec, d) + interestingDecNumbersDec = append(interestingDecNumbersDec, d.Dec()) + } +} + +func (s *decimalTestSuite) TestNewBigDecFromDecMulDec() { + type testcase struct { + s1, s2 osmomath.Dec + } + tests := []testcase{} + for _, d1 := range interestingDecNumbersDec { + for _, d2 := range interestingDecNumbersDec { + tests = append(tests, testcase{d1, d2}) + } + } + s.Require().True(len(tests) > 20, "no tests to run") + for _, tc := range tests { + s.Run(fmt.Sprintf("d1=%v, d2=%v", tc.s1, tc.s2), func() { + s1D := osmomath.BigDecFromDec(tc.s1) + s2D := osmomath.BigDecFromDec(tc.s2) + expected := s1D.MulMut(s2D) + actual := osmomath.NewBigDecFromDecMulDec(tc.s1, tc.s2) + s.Require().True(expected.Equal(actual), "expected %v, got %v", expected, actual) + }) + } +} + +func (s *decimalTestSuite) TestQuoRoundUpNextIntMut() { + type testcase struct { + s1, s2 osmomath.BigDec + } + tests := []testcase{} + for _, d1 := range interestingDecNumbersBigDec { + for _, d2 := range interestingDecNumbersBigDec { + tests = append(tests, testcase{d1, d2}) + } + } + s.Require().True(len(tests) > 20, "no tests to run") + for _, tc := range tests { + s.Run(fmt.Sprintf("d1=%v, d2=%v", tc.s1, tc.s2), func() { + expected := tc.s1.QuoRoundUp(tc.s2).CeilMut() + actual := tc.s1.QuoRoundUpNextIntMut(tc.s2) + s.Require().True(expected.Equal(actual), "expected %v, got %v", expected, actual) + }) + } +} + func (s *decimalTestSuite) TestDecString() { tests := []struct { d osmomath.BigDec @@ -466,6 +535,11 @@ func (s *decimalTestSuite) TestArithmetic() { s.Require().True(tc.expQuoRoundUp.Equal(resQuoRoundUp), "exp %v, res %v, tc %d", tc.expQuoRoundUp.String(), resQuoRoundUp.String(), tcIndex) + resQuoRoundUpDec := tc.d1.QuoByDecRoundUp(tc.d2.Dec()) + expResQuoRoundUpDec := tc.d1.QuoRoundUp(osmomath.BigDecFromDec(tc.d2.Dec())) + s.Require().True(expResQuoRoundUpDec.Equal(resQuoRoundUpDec), "exp %v, res %v, tc %d", + expResQuoRoundUpDec.String(), resQuoRoundUpDec.String(), tcIndex) + resQuoTruncate := tc.d1.QuoTruncate(tc.d2) s.Require().True(tc.expQuoTruncate.Equal(resQuoTruncate), "exp %v, res %v, tc %d", tc.expQuoTruncate.String(), resQuoTruncate.String(), tcIndex) diff --git a/osmomath/go.mod b/osmomath/go.mod index b302091a9a7..6e47640fc56 100644 --- a/osmomath/go.mod +++ b/osmomath/go.mod @@ -5,8 +5,13 @@ go 1.21 require ( cosmossdk.io/math v1.3.0 github.com/cosmos/cosmos-sdk v0.47.8 +<<<<<<< HEAD github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c github.com/stretchr/testify v1.8.4 +======= + github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 + github.com/stretchr/testify v1.9.0 +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) gopkg.in/yaml.v2 v2.4.0 ) diff --git a/osmomath/go.sum b/osmomath/go.sum index 6bed22e85ae..b08bcc5ebd0 100644 --- a/osmomath/go.sum +++ b/osmomath/go.sum @@ -261,10 +261,17 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +<<<<<<< HEAD github.com/osmosis-labs/cosmos-sdk v0.47.5-v23-osmo-9-iavl-v1 h1:cJfWAQHK2Em6cE5w3Uev3AysCvjenchKBuliiXjxcxg= github.com/osmosis-labs/cosmos-sdk v0.47.5-v23-osmo-9-iavl-v1/go.mod h1:O4R0cSw6y7aGLpDCd9epgX+1nsRQMpmexmI03j/sQYI= github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c h1:o9rUAOO3ccXRc/BVzU0E43EfK1WKLonaexNBVmSUgbo= github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c/go.mod h1:rIKIgsXj7bXTO604WSbjF2PB7WaVmoe+xhWgDfnwXIo= +======= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5 h1:fnt89Cw+55vbnIEGkpCmj0cx/EaEnwHfYi4JN3rKkLU= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5/go.mod h1:eSRUVYwL3eG1jnh01CnBbHiqOM3xJO49p5rTOrSFX1k= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 h1:3BlWDp7ivc+gyjdIPxkcvcDBsATq8s+ZEUD1AxFuDzo= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:n41vW6Nr5BmO7jCrdEONyOrJ3PACRcOt/KvhVTrEfjo= +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) 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= diff --git a/osmoutils/go.mod b/osmoutils/go.mod index 81e812494d4..8355f464e9c 100644 --- a/osmoutils/go.mod +++ b/osmoutils/go.mod @@ -11,9 +11,15 @@ require ( github.com/cosmos/cosmos-sdk v0.47.8 github.com/cosmos/gogoproto v1.4.11 github.com/cosmos/iavl v1.1.2-0.20240405173644-e52f7630d3b7 +<<<<<<< HEAD github.com/cosmos/ibc-go/v7 v7.3.2 github.com/osmosis-labs/osmosis/osmomath v0.0.10-0.20240409161506-a48ca4af185c github.com/osmosis-labs/osmosis/v23 v23.0.4-0.20240320225031-1dc6c4fe00b8 +======= + github.com/cosmos/ibc-go/v7 v7.4.0 + github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 + github.com/osmosis-labs/osmosis/v24 v24.0.0-rc0 +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 @@ -122,7 +128,14 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/onsi/gomega v1.28.1 // indirect +<<<<<<< HEAD github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240328223248-ae061110b150 // indirect +======= + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/osmosis-labs/osmosis/x/epochs v0.0.8-0.20240411125512-cb0fada2dee8 // indirect + github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.14-0.20240411125512-cb0fada2dee8 // indirect + github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240404053421-41aab009fb04 // indirect +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/osmoutils/go.sum b/osmoutils/go.sum index ae84c3726ff..e2c3a8101a5 100644 --- a/osmoutils/go.sum +++ b/osmoutils/go.sum @@ -1266,6 +1266,7 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +<<<<<<< HEAD github.com/osmosis-labs/cometbft v0.37.4-v23-osmo-3 h1:HJItohXCYHMTd1x938+zpxswkzdKFikHPz9xkHFtpBk= github.com/osmosis-labs/cometbft v0.37.4-v23-osmo-3/go.mod h1:Cmg5Hp4sNpapm7j+x0xRyt2g0juQfmB752ous+pA0G8= github.com/osmosis-labs/cosmos-sdk v0.47.5-v23-osmo-9-iavl-v1 h1:cJfWAQHK2Em6cE5w3Uev3AysCvjenchKBuliiXjxcxg= @@ -1280,6 +1281,22 @@ github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.10 h1:s4Y1ZeOmQ+iTgODCbnuge0mcB github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.10/go.mod h1:G3FNk7hOfmKKHP5aaDShRi93i3c7s6jok+gPS7It9rI= github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240328223248-ae061110b150 h1:z490JBjgVkvreJNeFE9es16rhc0rurM2GRhwqW0wEoY= github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240328223248-ae061110b150/go.mod h1:H6XfDqE0PiUoIXaTTVipupfbrpz7Cu95jYbu2yYo6Tg= +======= +github.com/osmosis-labs/cometbft v0.37.4-v24-osmo-2 h1:3k4I3zCxdNP+mjhR7AtKr1PPuGR58CcVTMZN0aV/iL4= +github.com/osmosis-labs/cometbft v0.37.4-v24-osmo-2/go.mod h1:fE+yBeExsJHA35plOZ7FmC/JejO5UdEHNcwO3dj2wc8= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5 h1:fnt89Cw+55vbnIEGkpCmj0cx/EaEnwHfYi4JN3rKkLU= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5/go.mod h1:eSRUVYwL3eG1jnh01CnBbHiqOM3xJO49p5rTOrSFX1k= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 h1:p1jOOamB3IHz5qXeN50KJLEQmNx3PSz5wunNtUrSb4g= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:OQj1UyxCyuunzCPuYtbRGTvaL62OIznjQpXqdFDINbs= +github.com/osmosis-labs/osmosis/v24 v24.0.0-rc0 h1:wAcm5rvcAMwSPFWgzUr/lR7U+e+4PvZ8fkehhpwiJho= +github.com/osmosis-labs/osmosis/v24 v24.0.0-rc0/go.mod h1:5QdPU/ttG3dPeg1EtX/LVT7yuxdz3E+BXnEqxwgh+ec= +github.com/osmosis-labs/osmosis/x/epochs v0.0.8-0.20240411125512-cb0fada2dee8 h1:/q88xaj3yRcGpFBHnsw/FetvA3f6qa8sKSPx7L12uKw= +github.com/osmosis-labs/osmosis/x/epochs v0.0.8-0.20240411125512-cb0fada2dee8/go.mod h1:9eNG5sUawozrcuYUGhSQlsynneDXXfg7yzy7FnGa1sY= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.14-0.20240411125512-cb0fada2dee8 h1:m3zpevamz76sscGFDpc4LzMGE18GCAm0oAZyYtcxok8= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.14-0.20240411125512-cb0fada2dee8/go.mod h1:P6eRZizImh4d4nAW9iHYWFcXUJ+SQlRYqXXktlu9tuo= +github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240404053421-41aab009fb04 h1:mvkk1A/jIe+lsFFpRNfyd9UfvhagATdpnjy8K7kANeo= +github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240404053421-41aab009fb04/go.mod h1:mYYf7pYb7sGJ9zYIOw2aYlIl5cgKT0K93rZx4LvDAuA= +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/osmosis-labs/wasmd v0.45.0-osmo h1:NIp7pvJV5HuBN1HwPgEmXKQM2TjVIVdJErIHnB9IMO8= github.com/osmosis-labs/wasmd v0.45.0-osmo/go.mod h1:J6eRvwii5T1WxhetZkBg1kOJS3GTn1Bw2OLyZBb8EVU= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= diff --git a/x/concentrated-liquidity/incentives_test.go b/x/concentrated-liquidity/incentives_test.go index 5105c5e92c3..aad96c98f82 100644 --- a/x/concentrated-liquidity/incentives_test.go +++ b/x/concentrated-liquidity/incentives_test.go @@ -3647,8 +3647,8 @@ func (s *KeeperTestSuite) TestIncentiveTruncation() { desiredCurrentSqrtPrice, err := math.TickToSqrtPrice(desiredCurrentTick) s.Require().NoError(err) - amount0 := math.CalcAmount0Delta(desiredLiquidity, desiredCurrentSqrtPrice, types.MaxSqrtPriceBigDec, true).Dec().TruncateInt() - amount1 := math.CalcAmount1Delta(desiredLiquidity, types.MinSqrtPriceBigDec, desiredCurrentSqrtPrice, true).Dec().TruncateInt() + amount0 := math.CalcAmount0Delta(desiredLiquidity.Dec(), desiredCurrentSqrtPrice, types.MaxSqrtPriceBigDec, true).Dec().TruncateInt() + amount1 := math.CalcAmount1Delta(desiredLiquidity.Dec(), types.MinSqrtPriceBigDec, desiredCurrentSqrtPrice, true).Dec().TruncateInt() lpCoins := sdk.NewCoins(sdk.NewCoin(ETH, amount0), sdk.NewCoin(USDC, amount1)) s.FundAcc(s.TestAccs[0], lpCoins) diff --git a/x/concentrated-liquidity/math/math.go b/x/concentrated-liquidity/math/math.go index fe459160c37..8a01010bc35 100644 --- a/x/concentrated-liquidity/math/math.go +++ b/x/concentrated-liquidity/math/math.go @@ -57,7 +57,7 @@ func Liquidity1(amount osmomath.Int, sqrtPriceA, sqrtPriceB osmomath.BigDec) osm // sqrtPriceA is the smaller of sqrtpCur and the nextPrice // sqrtPriceB is the larger of sqrtpCur and the nextPrice // CalcAmount0Delta = (liquidity * (sqrtPriceB - sqrtPriceA)) / (sqrtPriceB * sqrtPriceA) -func CalcAmount0Delta(liq, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool) osmomath.BigDec { +func CalcAmount0Delta(liq osmomath.Dec, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool) osmomath.BigDec { if sqrtPriceA.GT(sqrtPriceB) { sqrtPriceA, sqrtPriceB = sqrtPriceB, sqrtPriceA } @@ -79,8 +79,9 @@ func CalcAmount0Delta(liq, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool) // The denominator is truncated to get a higher final amount. // Note that the order of divisions is important here. First, we divide by a larger number (sqrtPriceB) and then by a smaller number (sqrtPriceA). // This leads to a smaller error amplification. This only matters in cases where at least one of the sqrt prices is below 1. - // TODO (perf): QuoRoundUpMut with no reallocation. - return liq.MulRoundUp(diff).QuoRoundUpMut(sqrtPriceB).QuoRoundUpMut(sqrtPriceA).CeilMut() + // TODO (perf): Don't truncate after liq.MulRoundUp(diff), we actually scale by that in the next Quo. ALT: Switch liq to Dec + // TODO (perf): QuoRoundUpMut with no reallocation for internal scratch var. + return diff.MulRoundUpDec(liq).QuoRoundUpMut(sqrtPriceB).QuoRoundUpNextIntMut(sqrtPriceA) } // These are truncated at precision end to round in favor of the pool when: // - calculating amount out during swap @@ -88,19 +89,24 @@ func CalcAmount0Delta(liq, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool) // Each intermediary step is truncated at precision end to get a smaller final amount. // Note that the order of divisions is important here. First, we divide by a larger number (sqrtPriceB) and then by a smaller number (sqrtPriceA). // This leads to a smaller error amplification. - return liq.MulTruncate(diff).QuoTruncateMut(sqrtPriceB).QuoTruncateMut(sqrtPriceA) + return diff.MulTruncateDec(liq).QuoTruncateMut(sqrtPriceB).QuoTruncateMut(sqrtPriceA) } // CalcAmount1Delta takes the asset with the smaller liquidity in the pool as well as the sqrtpCur and the nextPrice and calculates the amount of asset 1 // sqrtPriceA is the smaller of sqrtpCur and the nextPrice // sqrtPriceB is the larger of sqrtpCur and the nextPrice // CalcAmount1Delta = liq * (sqrtPriceB - sqrtPriceA) +<<<<<<< HEAD func CalcAmount1Delta(liq, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool) osmomath.BigDec { // make sqrtPriceA the smaller value amongst sqrtPriceA and sqrtPriceB if sqrtPriceA.GT(sqrtPriceB) { sqrtPriceA, sqrtPriceB = sqrtPriceB, sqrtPriceA } diff := sqrtPriceB.Sub(sqrtPriceA) +======= +func CalcAmount1Delta(liq osmomath.Dec, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool) osmomath.BigDec { + diff := sqrtPriceB.Sub(sqrtPriceA).AbsMut() +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) // if calculating for amountIn, we round up // if calculating for amountOut, we don't round at all // this is to prevent removing more from the pool than expected due to rounding @@ -114,13 +120,14 @@ func CalcAmount1Delta(liq, sqrtPriceA, sqrtPriceB osmomath.BigDec, roundUp bool) // Examples include: // - calculating amountIn during swap // - adding liquidity (request user to provide more tokens in in favor of the pool) - return liq.Mul(diff).CeilMut() + // TODO: Make a MulDecCeilMut to save more internal ops + return diff.MulDecMut(liq).CeilMut() } // This is truncated at precision end to round in favor of the pool when: // - calculating amount out during swap // - withdrawing liquidity // The denominator is rounded up to get a higher final amount. - return liq.MulTruncate(diff) + return diff.MulTruncateDec(liq) } // GetNextSqrtPriceFromAmount0InRoundingUp utilizes sqrtPriceCurrent, liquidity, and amount of denom0 that still needs @@ -147,13 +154,13 @@ func GetNextSqrtPriceFromAmount0InRoundingUp(sqrtPriceCurrent, liquidity, amount // When we swap for token one in given token zero out, the price is increasing and we need to move the price up enough // so that we get the desired output amount out. Therefore, we round up. // sqrt_next = liq * sqrt_cur / (liq - token_out * sqrt_cur) -func GetNextSqrtPriceFromAmount0OutRoundingUp(sqrtPriceCurrent, liquidity, amountZeroRemainingOut osmomath.BigDec) (sqrtPriceNext osmomath.BigDec) { +func GetNextSqrtPriceFromAmount0OutRoundingUp(sqrtPriceCurrent, liquidity osmomath.BigDec, amountZeroRemainingOut osmomath.Dec) (sqrtPriceNext osmomath.BigDec) { if amountZeroRemainingOut.IsZero() { return sqrtPriceCurrent } // mul round up to make the final denominator smaller and final result larger - product := amountZeroRemainingOut.MulRoundUp(sqrtPriceCurrent) + product := sqrtPriceCurrent.MulRoundUpDec(amountZeroRemainingOut) denominator := liquidity.Sub(product) // mul round up numerator to make the final result larger // quo round up to make the final result larger @@ -165,8 +172,8 @@ func GetNextSqrtPriceFromAmount0OutRoundingUp(sqrtPriceCurrent, liquidity, amoun // When we swap for token zero out given token one in, the price is increasing and we need to move the sqrt price (increase it) less to // avoid overpaying out of the pool. Therefore, we round down. // sqrt_next = sqrt_cur + token_in / liq -func GetNextSqrtPriceFromAmount1InRoundingDown(sqrtPriceCurrent, liquidity, amountOneRemainingIn osmomath.BigDec) (sqrtPriceNext osmomath.BigDec) { - return sqrtPriceCurrent.Add(amountOneRemainingIn.QuoTruncate(liquidity)) +func GetNextSqrtPriceFromAmount1InRoundingDown(sqrtPriceCurrent osmomath.BigDec, liquidity osmomath.Dec, amountOneRemainingIn osmomath.BigDec) (sqrtPriceNext osmomath.BigDec) { + return amountOneRemainingIn.QuoTruncateDec(liquidity).AddMut(sqrtPriceCurrent) } // GetNextSqrtPriceFromAmount1OutRoundingDown utilizes the current sqrtPriceCurrent, liquidity, and amount of denom1 that still needs @@ -174,8 +181,8 @@ func GetNextSqrtPriceFromAmount1InRoundingDown(sqrtPriceCurrent, liquidity, amou // When we swap for token zero in given token one out, the price is decrearing and we need to move the price down enough // so that we get the desired output amount out. // sqrt_next = sqrt_cur - token_out / liq -func GetNextSqrtPriceFromAmount1OutRoundingDown(sqrtPriceCurrent, liquidity, amountOneRemainingOut osmomath.BigDec) (sqrtPriceNext osmomath.BigDec) { - return sqrtPriceCurrent.Sub(amountOneRemainingOut.QuoRoundUp(liquidity)) +func GetNextSqrtPriceFromAmount1OutRoundingDown(sqrtPriceCurrent osmomath.BigDec, liquidity osmomath.Dec, amountOneRemainingOut osmomath.BigDec) (sqrtPriceNext osmomath.BigDec) { + return sqrtPriceCurrent.Sub(amountOneRemainingOut.QuoByDecRoundUp(liquidity)) } // GetLiquidityFromAmounts takes the current sqrtPrice and the sqrtPrice for the upper and lower ticks as well as the amounts of asset0 and asset1 diff --git a/x/concentrated-liquidity/math/math_test.go b/x/concentrated-liquidity/math/math_test.go index e801a633352..296c014d3ad 100644 --- a/x/concentrated-liquidity/math/math_test.go +++ b/x/concentrated-liquidity/math/math_test.go @@ -124,7 +124,7 @@ func TestLiquidity0(t *testing.T) { // calcAmount0Delta = (liquidity * (sqrtPriceB - sqrtPriceA)) / (sqrtPriceB * sqrtPriceA) func TestCalcAmount0Delta(t *testing.T) { testCases := map[string]struct { - liquidity osmomath.BigDec + liquidity osmomath.Dec sqrtPA osmomath.BigDec sqrtPB osmomath.BigDec isWithTolerance bool @@ -132,16 +132,16 @@ func TestCalcAmount0Delta(t *testing.T) { amount0Expected osmomath.BigDec }{ "happy path": { - liquidity: osmomath.MustNewBigDecFromStr("1517882343.751510418088349649"), // we use the smaller liquidity between liq0 and liq1 - sqrtPA: sqrt5000BigDec, // 5000 - sqrtPB: sqrt5500BigDec, // 5500 + liquidity: osmomath.MustNewDecFromStr("1517882343.751510418088349649"), // we use the smaller liquidity between liq0 and liq1 + sqrtPA: sqrt5000BigDec, // 5000 + sqrtPB: sqrt5500BigDec, // 5500 roundUp: false, // calculated with x/concentrated-liquidity/python/clmath.py round_decimal(amount0, 36, ROUND_FLOOR) amount0Expected: osmomath.MustNewBigDecFromStr("998976.618347426388356629926969277767437533"), // truncated at precision end. isWithTolerance: false, }, "happy path, sqrtPriceA greater than sqrtPrice B": { // commute prior vector - liquidity: osmomath.MustNewBigDecFromStr("1517882343.751510418088349649"), + liquidity: osmomath.MustNewDecFromStr("1517882343.751510418088349649"), sqrtPA: sqrt5500BigDec, sqrtPB: sqrt5000BigDec, roundUp: false, @@ -160,7 +160,7 @@ func TestCalcAmount0Delta(t *testing.T) { // min_sqrt_p = Decimal("0.000000152731791058") // liq = Decimal("931361973132462178951297") // liq * (max_sqrt_p - min_sqrt_p) / (max_sqrt_p * min_sqrt_p) - liquidity: osmomath.MustNewBigDecFromStr("931361973132462178951297"), + liquidity: osmomath.MustNewDecFromStr("931361973132462178951297"), // price: 0.000000000000023327 sqrtPA: osmomath.MustNewBigDecFromStr("0.000000152731791058"), // price: 952361284325389721913 @@ -181,7 +181,7 @@ func TestCalcAmount0Delta(t *testing.T) { // min_sqrt_p = Decimal("0.000000152731791058") // liq = Decimal("931361973132462178951297") // liq * (max_sqrt_p - min_sqrt_p) / (max_sqrt_p * min_sqrt_p) - liquidity: osmomath.MustNewBigDecFromStr("931361973132462178951297"), + liquidity: osmomath.MustNewDecFromStr("931361973132462178951297"), // price: 0.000000000000023327 sqrtPA: osmomath.MustNewBigDecFromStr("0.000000152731791058"), // price: 952361284325389721913 @@ -200,7 +200,7 @@ func TestCalcAmount0Delta(t *testing.T) { // min_sqrt_p = Decimal("0.000000000000001409841835100661211756") // liq = Decimal("5000252259822539816806336.971796256914465071095518135400579243") // liq * (max_sqrt_p - min_sqrt_p) / (max_sqrt_p * min_sqrt_p) - liquidity: osmomath.MustNewBigDecFromStr("5000252259822539816806336.971796256914465071095518135400579243"), + liquidity: osmomath.MustNewDecFromStr("5000252259822539816806336.971796256914465071"), sqrtPA: osmomath.MustNewBigDecFromStr("0.00000099994999874993749609347654199"), sqrtPB: osmomath.MustNewBigDecFromStr("0.000000000000001409841835100661211756"), roundUp: true, @@ -216,7 +216,7 @@ func TestCalcAmount0Delta(t *testing.T) { // min_sqrt_p = Decimal("0.000000000000001409841835100661211756") // liq = Decimal("5000252259822539816806336.971796256914465071095518135400579243") // liq * (max_sqrt_p - min_sqrt_p) / (max_sqrt_p * min_sqrt_p) - liquidity: osmomath.MustNewBigDecFromStr("5000252259822539816806336.971796256914465071095518135400579243"), + liquidity: osmomath.MustNewDecFromStr("5000252259822539816806336.971796256914465071"), sqrtPA: osmomath.MustNewBigDecFromStr("0.00000099994999874993749609347654199"), sqrtPB: osmomath.MustNewBigDecFromStr("0.000000000000001409841835100661211756"), roundUp: false, @@ -224,14 +224,14 @@ func TestCalcAmount0Delta(t *testing.T) { amount0Expected: osmomath.MustNewBigDecFromStr("3546676037185128488234786333758360815266.999539026068480181194797910898392880"), }, "low price range": { - liquidity: smallLiquidity, + liquidity: smallLiquidity.Dec(), sqrtPA: sqrtANearMin, sqrtPB: sqrtBNearMin, roundUp: false, // from clmath decimal import * // from math import * // calc_amount_zero_delta(liq, sqrtPriceA, sqrtPriceB, False) - amount0Expected: osmomath.MustNewBigDecFromStr("12399.405290456300691064448232516066947340"), + amount0Expected: osmomath.MustNewBigDecFromStr("12399.403617882634341191547243098659145924"), }, } @@ -267,7 +267,7 @@ func TestCalcAmount0Delta(t *testing.T) { // calcAmount1Delta = liq * (sqrtPriceB - sqrtPriceA) func TestCalcAmount1Delta(t *testing.T) { testCases := map[string]struct { - liquidity osmomath.BigDec + liquidity osmomath.Dec sqrtPA osmomath.BigDec sqrtPB osmomath.BigDec exactEqual bool @@ -275,9 +275,9 @@ func TestCalcAmount1Delta(t *testing.T) { amount1Expected osmomath.BigDec }{ "round down": { - liquidity: osmomath.MustNewBigDecFromStr("1517882343.751510418088349649"), // we use the smaller liquidity between liq0 and liq1 - sqrtPA: sqrt5000BigDec, // 5000 - sqrtPB: sqrt4545BigDec, // 4545 + liquidity: osmomath.MustNewDecFromStr("1517882343.751510418088349649"), // we use the smaller liquidity between liq0 and liq1 + sqrtPA: sqrt5000BigDec, // 5000 + sqrtPB: sqrt4545BigDec, // 4545 roundUp: false, // calculated with x/concentrated-liquidity/python/clmath.py amount1Expected: osmomath.MustNewBigDecFromStr("4999999999.999999999999999999696837821702147054"), @@ -292,7 +292,7 @@ func TestCalcAmount1Delta(t *testing.T) { // min_sqrt_p = Decimal("0.000000152731791058") // liq = Decimal("931361973132462178951297") // liq * (max_sqrt_p - min_sqrt_p) - liquidity: osmomath.MustNewBigDecFromStr("931361973132462178951297"), + liquidity: osmomath.MustNewDecFromStr("931361973132462178951297"), // price: 0.000000000000023327 sqrtPA: osmomath.MustNewBigDecFromStr("0.000000152731791058"), // price: 952361284325389721913 @@ -311,7 +311,7 @@ func TestCalcAmount1Delta(t *testing.T) { // min_sqrt_p = Decimal("0.000000152731791058") // liq = Decimal("931361973132462178951297") // liq * (max_sqrt_p - min_sqrt_p) - liquidity: osmomath.MustNewBigDecFromStr("931361973132462178951297"), + liquidity: osmomath.MustNewDecFromStr("931361973132462178951297"), // price: 0.000000000000023327 sqrtPA: osmomath.MustNewBigDecFromStr("0.000000152731791058"), // price: 952361284325389721913 @@ -320,24 +320,24 @@ func TestCalcAmount1Delta(t *testing.T) { amount1Expected: osmomath.MustNewBigDecFromStr("28742157707995443393876876754535992.801567623738751734").Ceil(), // round up at precision end. }, "low price range (no round up)": { - liquidity: smallLiquidity, + liquidity: smallLiquidity.Dec(), sqrtPA: sqrtANearMin, sqrtPB: sqrtBNearMin, roundUp: false, // from clmath decimal import * // from math import * // calc_amount_one_delta(liq, sqrtPriceA, sqrtPriceB, False) - amount1Expected: osmomath.MustNewBigDecFromStr("0.000000000000000000000000000103787162"), + amount1Expected: osmomath.MustNewBigDecFromStr("0.000000000000000000000000000103787148"), }, "low price range (with round up)": { - liquidity: smallLiquidity, + liquidity: smallLiquidity.Dec(), sqrtPA: sqrtANearMin, sqrtPB: sqrtBNearMin, roundUp: true, // from clmath decimal import * // calc_amount_one_delta(liq, sqrtPriceA, sqrtPriceB, False) - // Actual result: 0.000000000000000000000000000103787163 - amount1Expected: osmomath.MustNewBigDecFromStr("0.000000000000000000000000000103787163").Ceil(), + // Actual result: 0.000000000000000000000000000103787149 + amount1Expected: osmomath.MustNewBigDecFromStr("0.000000000000000000000000000103787149").Ceil(), }, } @@ -472,6 +472,20 @@ type sqrtRoundingTestCase struct { expected osmomath.BigDec } +type sqrtRoundingDecTestCase struct { + sqrtPriceCurrent osmomath.BigDec + liquidity osmomath.Dec + amountRemaining osmomath.BigDec + expected osmomath.BigDec +} + +type sqrtRoundingAmtDecTestCase struct { + sqrtPriceCurrent osmomath.BigDec + liquidity osmomath.BigDec + amountRemaining osmomath.Dec + expected osmomath.BigDec +} + func runSqrtRoundingTestCase( t *testing.T, name string, @@ -487,6 +501,36 @@ func runSqrtRoundingTestCase( } } +func runSqrtRoundingDecTestCase( + t *testing.T, + name string, + fn func(osmomath.BigDec, osmomath.Dec, osmomath.BigDec) osmomath.BigDec, + cases map[string]sqrtRoundingDecTestCase, +) { + for name, tc := range cases { + tc := tc + t.Run(name, func(t *testing.T) { + sqrtPriceNext := fn(tc.sqrtPriceCurrent, tc.liquidity, tc.amountRemaining) + require.Equal(t, tc.expected.String(), sqrtPriceNext.String()) + }) + } +} + +func runSqrtRoundingAmtDecTestCase( + t *testing.T, + name string, + fn func(osmomath.BigDec, osmomath.BigDec, osmomath.Dec) osmomath.BigDec, + cases map[string]sqrtRoundingAmtDecTestCase, +) { + for name, tc := range cases { + tc := tc + t.Run(name, func(t *testing.T) { + sqrtPriceNext := fn(tc.sqrtPriceCurrent, tc.liquidity, tc.amountRemaining) + require.Equal(t, tc.expected.String(), sqrtPriceNext.String()) + }) + } +} + // Estimates are computed with x/concentrated-liquidity/python/clmath.py func TestGetNextSqrtPriceFromAmount0InRoundingUp(t *testing.T) { tests := map[string]sqrtRoundingTestCase{ @@ -525,88 +569,88 @@ func TestGetNextSqrtPriceFromAmount0InRoundingUp(t *testing.T) { // Estimates are computed with x/concentrated-liquidity/python/clmath.py func TestGetNextSqrtPriceFromAmount0OutRoundingUp(t *testing.T) { - tests := map[string]sqrtRoundingTestCase{ + tests := map[string]sqrtRoundingAmtDecTestCase{ "rounded up at precision end": { sqrtPriceCurrent: sqrt5000BigDec, liquidity: osmomath.MustNewBigDecFromStr("3035764687.503020836176699298"), - amountRemaining: osmomath.MustNewBigDecFromStr("8398"), + amountRemaining: osmomath.MustNewDecFromStr("8398"), // get_next_sqrt_price_from_amount0_out_round_up(liquidity,sqrtPriceCurrent ,amountRemaining) expected: osmomath.MustNewBigDecFromStr("70.724512595179305565323229510645063950"), }, "no round up due zeroes at precision end": { sqrtPriceCurrent: osmomath.MustNewBigDecFromStr("2"), liquidity: osmomath.MustNewBigDecFromStr("10"), - amountRemaining: osmomath.MustNewBigDecFromStr("1"), + amountRemaining: osmomath.MustNewDecFromStr("1"), // liq * sqrt_cur / (liq + token_out * sqrt_cur) = 2.5 expected: osmomath.MustNewBigDecFromStr("2.5"), }, "low price range": { liquidity: smallLiquidity, sqrtPriceCurrent: sqrtANearMin, - amountRemaining: smallValue, + amountRemaining: smallValue.Dec(), // from clmath decimal import * // get_next_sqrt_price_from_amount0_out_round_up(liq, sqrtPriceA, amountRemaining) expected: osmomath.MustNewBigDecFromStr("0.000000000000000023829902587267894423"), }, } - runSqrtRoundingTestCase(t, "TestGetNextSqrtPriceFromAmount0OutRoundingUp", math.GetNextSqrtPriceFromAmount0OutRoundingUp, tests) + runSqrtRoundingAmtDecTestCase(t, "TestGetNextSqrtPriceFromAmount0OutRoundingUp", math.GetNextSqrtPriceFromAmount0OutRoundingUp, tests) } // Estimates are computed with x/concentrated-liquidity/python/clmath.py func TestGetNextSqrtPriceFromAmount1InRoundingDown(t *testing.T) { - tests := map[string]sqrtRoundingTestCase{ + tests := map[string]sqrtRoundingDecTestCase{ "rounded down at precision end": { sqrtPriceCurrent: sqrt5000BigDec, - liquidity: osmomath.MustNewBigDecFromStr("3035764687.503020836176699298"), + liquidity: osmomath.MustNewDecFromStr("3035764687.503020836176699298"), amountRemaining: osmomath.MustNewBigDecFromStr("8398"), expected: osmomath.MustNewBigDecFromStr("70.710680885008822823343339270800000167"), }, "no round up due zeroes at precision end": { sqrtPriceCurrent: osmomath.MustNewBigDecFromStr("2.5"), - liquidity: osmomath.MustNewBigDecFromStr("1"), + liquidity: osmomath.OneDec(), amountRemaining: osmomath.MustNewBigDecFromStr("10"), // sqrt_next = sqrt_cur + token_in / liq expected: osmomath.MustNewBigDecFromStr("12.5"), }, "happy path": { - liquidity: osmomath.MustNewBigDecFromStr("1519437308.014768571721000000"), // liquidity1 calculated above - sqrtPriceCurrent: sqrt5000BigDec, // 5000000000 + liquidity: osmomath.MustNewDecFromStr("1519437308.014768571721000000"), // liquidity1 calculated above + sqrtPriceCurrent: sqrt5000BigDec, // 5000000000 amountRemaining: osmomath.NewBigDec(42000000), // sqrt_next = sqrt_cur + token_in / liq // calculated with x/concentrated-liquidity/python/clmath.py round_decimal(sqrt_next, 36, ROUND_FLOOR) expected: osmomath.MustNewBigDecFromStr("70.738319930382329008049494613660784220"), }, "low price range": { - liquidity: smallLiquidity, + liquidity: smallLiquidity.Dec(), sqrtPriceCurrent: sqrtANearMin, amountRemaining: smallValue, // from clmath decimal import * // get_next_sqrt_price_from_amount1_in_round_down(liq, sqrtPriceA, amountRemaining) - expected: osmomath.MustNewBigDecFromStr("31964936923603.477920799226065501544948016880497639"), + expected: osmomath.MustNewBigDecFromStr("31964941472737.900293161392817774305123129525585219"), }, } - runSqrtRoundingTestCase(t, "TestGetNextSqrtPriceFromAmount1InRoundingDown", math.GetNextSqrtPriceFromAmount1InRoundingDown, tests) + runSqrtRoundingDecTestCase(t, "TestGetNextSqrtPriceFromAmount1InRoundingDown", math.GetNextSqrtPriceFromAmount1InRoundingDown, tests) } func TestGetNextSqrtPriceFromAmount1OutRoundingDown(t *testing.T) { - tests := map[string]sqrtRoundingTestCase{ + tests := map[string]sqrtRoundingDecTestCase{ "rounded down at precision end": { sqrtPriceCurrent: sqrt5000BigDec, - liquidity: osmomath.MustNewBigDecFromStr("3035764687.503020836176699298"), + liquidity: osmomath.MustNewDecFromStr("3035764687.503020836176699298"), amountRemaining: osmomath.MustNewBigDecFromStr("8398"), // round_osmo_prec_down(sqrtPriceCurrent - round_osmo_prec_up(tokenOut / liquidity)) expected: osmomath.MustNewBigDecFromStr("70.710675352300682056656660729199999832"), }, "no round up due zeroes at precision end": { sqrtPriceCurrent: osmomath.MustNewBigDecFromStr("12.5"), - liquidity: osmomath.MustNewBigDecFromStr("1"), + liquidity: osmomath.MustNewDecFromStr("1"), amountRemaining: osmomath.MustNewBigDecFromStr("10"), // round_osmo_prec_down(sqrtPriceCurrent - round_osmo_prec_up(tokenOut / liquidity)) expected: osmomath.MustNewBigDecFromStr("2.5"), }, "low price range": { - liquidity: smallLiquidity, + liquidity: smallLiquidity.Dec(), sqrtPriceCurrent: sqrtANearMin, amountRemaining: smallValue, // from clmath decimal import * @@ -614,8 +658,8 @@ func TestGetNextSqrtPriceFromAmount1OutRoundingDown(t *testing.T) { // While a negative sqrt price value is invalid and should be caught by the caller, // we mostly focus on testing rounding behavior and math correctness at low spot prices. // For the purposes of our test, this result is acceptable. - expected: osmomath.MustNewBigDecFromStr("-31964936923603.477920799226065453921424417717867010"), + expected: osmomath.MustNewBigDecFromStr("-31964941472737.900293161392817726681599530362954590"), }, } - runSqrtRoundingTestCase(t, "TestGetNextSqrtPriceFromAmount1OutRoundingDown", math.GetNextSqrtPriceFromAmount1OutRoundingDown, tests) + runSqrtRoundingDecTestCase(t, "TestGetNextSqrtPriceFromAmount1OutRoundingDown", math.GetNextSqrtPriceFromAmount1OutRoundingDown, tests) } diff --git a/x/concentrated-liquidity/model/pool.go b/x/concentrated-liquidity/model/pool.go index 648bd8a2ec9..495ead6b51e 100644 --- a/x/concentrated-liquidity/model/pool.go +++ b/x/concentrated-liquidity/model/pool.go @@ -125,7 +125,7 @@ func (p Pool) SpotPrice(ctx sdk.Context, quoteAssetDenom string, baseAssetDenom if baseAssetDenom == p.Token0 { return osmomath.BigDecFromDecMut(priceSquared.Dec()), nil } - return osmomath.BigDecFromDecMut(osmomath.OneBigDec().Quo(priceSquared).Dec()), nil + return osmomath.BigDecFromDecMut(osmomath.OneBigDec().QuoMut(priceSquared).Dec()), nil } // GetToken0 returns the token0 of the pool @@ -246,9 +246,8 @@ func (p Pool) CalcActualAmounts(ctx sdk.Context, lowerTick, upperTick int64, liq roundUp := liquidityDelta.IsPositive() var ( - liquidityDeltaBigDec = osmomath.BigDecFromDec(liquidityDelta) - actualAmountDenom0 osmomath.BigDec - actualAmountDenom1 osmomath.BigDec + actualAmountDenom0 osmomath.BigDec + actualAmountDenom1 osmomath.BigDec ) if p.IsCurrentTickInRange(lowerTick, upperTick) { @@ -256,18 +255,18 @@ func (p Pool) CalcActualAmounts(ctx sdk.Context, lowerTick, upperTick int64, liq // if this is the case, we attempt to provide liquidity evenly between asset0 and asset1 // we also update the pool liquidity since the virtual liquidity is modified by this position's creation currentSqrtPrice := p.CurrentSqrtPrice - actualAmountDenom0 = math.CalcAmount0Delta(liquidityDeltaBigDec, currentSqrtPrice, sqrtPriceUpperTick, roundUp) - actualAmountDenom1 = math.CalcAmount1Delta(liquidityDeltaBigDec, currentSqrtPrice, sqrtPriceLowerTick, roundUp) + actualAmountDenom0 = math.CalcAmount0Delta(liquidityDelta, currentSqrtPrice, sqrtPriceUpperTick, roundUp) + actualAmountDenom1 = math.CalcAmount1Delta(liquidityDelta, currentSqrtPrice, sqrtPriceLowerTick, roundUp) } else if p.CurrentTick < lowerTick { // outcome two: position is below current price // this means position is solely made up of asset0 actualAmountDenom1 = osmomath.ZeroBigDec() - actualAmountDenom0 = math.CalcAmount0Delta(liquidityDeltaBigDec, sqrtPriceLowerTick, sqrtPriceUpperTick, roundUp) + actualAmountDenom0 = math.CalcAmount0Delta(liquidityDelta, sqrtPriceLowerTick, sqrtPriceUpperTick, roundUp) } else { // outcome three: position is above current price // this means position is solely made up of asset1 actualAmountDenom0 = osmomath.ZeroBigDec() - actualAmountDenom1 = math.CalcAmount1Delta(liquidityDeltaBigDec, sqrtPriceLowerTick, sqrtPriceUpperTick, roundUp) + actualAmountDenom1 = math.CalcAmount1Delta(liquidityDelta, sqrtPriceLowerTick, sqrtPriceUpperTick, roundUp) } if roundUp { diff --git a/x/concentrated-liquidity/model/pool_test.go b/x/concentrated-liquidity/model/pool_test.go index 380a6153b76..d4f7b1a765b 100644 --- a/x/concentrated-liquidity/model/pool_test.go +++ b/x/concentrated-liquidity/model/pool_test.go @@ -574,8 +574,7 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { return sqrtPrice } - defaultLiquidityDelta = osmomath.NewDec(1000) - defaultLiquidityDeltaBigDec = osmomath.NewBigDec(1000) + defaultLiquidityDelta = osmomath.NewDec(1000) lowerTick = int64(-99) lowerSqrtPriceBigDec = tickToSqrtPrice(lowerTick) @@ -605,8 +604,8 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { liquidityDelta: defaultLiquidityDelta, shouldTestRoundingInvariant: true, - expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDeltaBigDec, midSqrtPriceBigDec, upperSqrtPriceBigDec, true).Dec(), - expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDeltaBigDec, midSqrtPriceBigDec, lowerSqrtPriceBigDec, true).Dec(), + expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDelta, midSqrtPriceBigDec, upperSqrtPriceBigDec, true).Dec(), + expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDelta, midSqrtPriceBigDec, lowerSqrtPriceBigDec, true).Dec(), }, "current in range, negative liquidity": { currentTick: midtick, @@ -614,8 +613,8 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { upperTick: uppertick, liquidityDelta: defaultLiquidityDelta.Neg(), - expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDeltaBigDec.Neg(), midSqrtPriceBigDec, upperSqrtPriceBigDec, false).Dec(), - expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDeltaBigDec.Neg(), midSqrtPriceBigDec, lowerSqrtPriceBigDec, false).Dec(), + expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDelta.Neg(), midSqrtPriceBigDec, upperSqrtPriceBigDec, false).Dec(), + expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDelta.Neg(), midSqrtPriceBigDec, lowerSqrtPriceBigDec, false).Dec(), }, "current below range, positive liquidity": { currentTick: lowerTick, @@ -623,7 +622,7 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { upperTick: uppertick, liquidityDelta: defaultLiquidityDelta, - expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDeltaBigDec, midSqrtPriceBigDec, upperSqrtPriceBigDec, true).Dec(), + expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDelta, midSqrtPriceBigDec, upperSqrtPriceBigDec, true).Dec(), expectedAmount1: osmomath.ZeroDec(), }, "current below range, negative liquidity": { @@ -632,7 +631,7 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { upperTick: uppertick, liquidityDelta: defaultLiquidityDelta.Neg(), - expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDeltaBigDec.Neg(), midSqrtPriceBigDec, upperSqrtPriceBigDec, false).Dec(), + expectedAmount0: clmath.CalcAmount0Delta(defaultLiquidityDelta.Neg(), midSqrtPriceBigDec, upperSqrtPriceBigDec, false).Dec(), expectedAmount1: osmomath.ZeroDec(), }, "current above range, positive liquidity": { @@ -642,7 +641,7 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { liquidityDelta: defaultLiquidityDelta, expectedAmount0: osmomath.ZeroDec(), - expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDeltaBigDec, lowerSqrtPriceBigDec, midSqrtPriceBigDec, true).Dec(), + expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDelta, lowerSqrtPriceBigDec, midSqrtPriceBigDec, true).Dec(), }, "current above range, negative liquidity": { currentTick: uppertick, @@ -651,7 +650,7 @@ func (suite *ConcentratedPoolTestSuite) TestCalcActualAmounts() { liquidityDelta: defaultLiquidityDelta.Neg(), expectedAmount0: osmomath.ZeroDec(), - expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDeltaBigDec.Neg(), lowerSqrtPriceBigDec, midSqrtPriceBigDec, false).Dec(), + expectedAmount1: clmath.CalcAmount1Delta(defaultLiquidityDelta.Neg(), lowerSqrtPriceBigDec, midSqrtPriceBigDec, false).Dec(), }, // errors diff --git a/x/concentrated-liquidity/position_test.go b/x/concentrated-liquidity/position_test.go index fd91500e0ee..7af4232a8f7 100644 --- a/x/concentrated-liquidity/position_test.go +++ b/x/concentrated-liquidity/position_test.go @@ -2036,7 +2036,7 @@ func (s *KeeperTestSuite) TestNegativeTickRange_SpreadFactor() { s.Require().True(toTick < pool.GetCurrentTick()) - amountZeroIn := math.CalcAmount0Delta(osmomath.BigDecFromDec(pool.GetLiquidity()), pool.GetCurrentSqrtPrice(), s.tickToSqrtPrice(toTick), true) + amountZeroIn := math.CalcAmount0Delta(pool.GetLiquidity(), pool.GetCurrentSqrtPrice(), s.tickToSqrtPrice(toTick), true) coinZeroIn := sdk.NewCoin(denom0, amountZeroIn.Dec().TruncateInt()) return coinZeroIn @@ -2052,7 +2052,7 @@ func (s *KeeperTestSuite) TestNegativeTickRange_SpreadFactor() { s.Require().True(toTick > pool.GetCurrentTick()) - amountOneIn := math.CalcAmount1Delta(osmomath.BigDecFromDec(pool.GetLiquidity()), pool.GetCurrentSqrtPrice(), s.tickToSqrtPrice(toTick), true) + amountOneIn := math.CalcAmount1Delta(pool.GetLiquidity(), pool.GetCurrentSqrtPrice(), s.tickToSqrtPrice(toTick), true) coinOneIn := sdk.NewCoin(denom1, amountOneIn.Dec().TruncateInt()) return coinOneIn diff --git a/x/concentrated-liquidity/swaps_tick_cross_test.go b/x/concentrated-liquidity/swaps_tick_cross_test.go index 341d1a0816c..8ee029cf178 100644 --- a/x/concentrated-liquidity/swaps_tick_cross_test.go +++ b/x/concentrated-liquidity/swaps_tick_cross_test.go @@ -293,7 +293,7 @@ func (s *KeeperTestSuite) computeSwapAmounts(poolId uint64, curSqrtPrice osmomat var isWithinDesiredBucketAfterSwap bool if isZeroForOne { // Round up so that we cross the tick by default. - curAmountIn := math.CalcAmount0Delta(osmomath.BigDecFromDec(currentLiquidity), curSqrtPrice, nextInitTickSqrtPrice, true).DecRoundUp() + curAmountIn := math.CalcAmount0Delta(currentLiquidity, curSqrtPrice, nextInitTickSqrtPrice, true).DecRoundUp() amountIn = amountIn.Add(curAmountIn) @@ -316,12 +316,12 @@ func (s *KeeperTestSuite) computeSwapAmounts(poolId uint64, curSqrtPrice osmomat nextInitTickSqrtPrice := s.tickToSqrtPrice(liquidityNetAmounts[i+1].TickIndex) // We discount by half so that we do no cross any tick and remain in the same bucket. - curAmountIn := math.CalcAmount0Delta(osmomath.BigDecFromDec(currentLiquidity), curSqrtPrice, nextInitTickSqrtPrice, true).QuoInt64(2).DecRoundUp() + curAmountIn := math.CalcAmount0Delta(currentLiquidity, curSqrtPrice, nextInitTickSqrtPrice, true).QuoInt64(2).DecRoundUp() amountIn = amountIn.Add(curAmountIn) } } else { // Round up so that we cross the tick by default. - curAmountIn := math.CalcAmount1Delta(osmomath.BigDecFromDec(currentLiquidity), curSqrtPrice, nextInitTickSqrtPrice, true).Dec() + curAmountIn := math.CalcAmount1Delta(currentLiquidity, curSqrtPrice, nextInitTickSqrtPrice, true).Dec() amountIn = amountIn.Add(curAmountIn) // The tick should be crossed if currentTick <= expectedTickToSwapTo, unless the intention @@ -346,7 +346,7 @@ func (s *KeeperTestSuite) computeSwapAmounts(poolId uint64, curSqrtPrice osmomat return amountIn, currentLiquidity, curSqrtPrice } -func (s *KeeperTestSuite) computeSwapAmountsInGivenOut(poolId uint64, curSqrtPrice osmomath.BigDec, expectedTickToSwapTo int64, isZeroForOne bool, shouldStayWithinTheSameBucket bool) (osmomath.Dec, osmomath.BigDec, osmomath.BigDec) { +func (s *KeeperTestSuite) computeSwapAmountsInGivenOut(poolId uint64, curSqrtPrice osmomath.BigDec, expectedTickToSwapTo int64, isZeroForOne bool, shouldStayWithinTheSameBucket bool) (osmomath.Dec, osmomath.Dec, osmomath.BigDec) { pool, err := s.App.ConcentratedLiquidityKeeper.GetPoolById(s.Ctx, poolId) s.Require().NoError(err) @@ -368,7 +368,7 @@ func (s *KeeperTestSuite) computeSwapAmountsInGivenOut(poolId uint64, curSqrtPri } // Start from current pool liquidity and zero amount in. - currentLiquidity := osmomath.BigDecFromDec(pool.GetLiquidity()) + currentLiquidity := pool.GetLiquidity() amountOut := osmomath.ZeroDec() for i, liquidityNetEntry := range liquidityNetAmounts { @@ -391,7 +391,7 @@ func (s *KeeperTestSuite) computeSwapAmountsInGivenOut(poolId uint64, curSqrtPri if shouldCrossTick { // Runs regular tick crossing logic. curSqrtPrice = s.tickToSqrtPrice(nextInitializedTick) - currentLiquidity = currentLiquidity.Sub(osmomath.BigDecFromDec(liquidityNetEntry.LiquidityNet)) + currentLiquidity = currentLiquidity.Sub(liquidityNetEntry.LiquidityNet) currentTick = nextInitializedTick - 1 } @@ -418,7 +418,7 @@ func (s *KeeperTestSuite) computeSwapAmountsInGivenOut(poolId uint64, curSqrtPri if shouldCrossTick { // Runs regular tick crossing logic. curSqrtPrice = s.tickToSqrtPrice(nextInitializedTick) - currentLiquidity = currentLiquidity.Add(osmomath.BigDecFromDec(liquidityNetEntry.LiquidityNet)) + currentLiquidity = currentLiquidity.Add(liquidityNetEntry.LiquidityNet) currentTick = nextInitializedTick } @@ -643,7 +643,7 @@ func (s *KeeperTestSuite) TestSwapOutGivenIn_Tick_Initialization_And_Crossing() if tickToSwapTo < nr1Position.lowerTick { sqrtPriceLowerTickOne := s.tickToSqrtPrice(nr1Position.lowerTick) - amountZeroIn = math.CalcAmount0Delta(osmomath.BigDecFromDec(liquidity), sqrtPriceLowerTickOne, sqrtPriceStart, true).Dec() + amountZeroIn = math.CalcAmount0Delta(liquidity, sqrtPriceLowerTickOne, sqrtPriceStart, true).Dec() sqrtPriceStart = sqrtPriceLowerTickOne @@ -652,7 +652,7 @@ func (s *KeeperTestSuite) TestSwapOutGivenIn_Tick_Initialization_And_Crossing() // This is the total amount necessary to cross the lower tick of narrow position. // Note it is rounded up to ensure that the tick is crossed. - amountZeroIn = math.CalcAmount0Delta(osmomath.BigDecFromDec(liquidity), sqrtPriceTarget, sqrtPriceStart, true).DecRoundUp().Add(amountZeroIn) + amountZeroIn = math.CalcAmount0Delta(liquidity, sqrtPriceTarget, sqrtPriceStart, true).DecRoundUp().Add(amountZeroIn) tokenZeroIn := sdk.NewCoin(pool.GetToken0(), amountZeroIn.Ceil().TruncateInt()) @@ -734,7 +734,7 @@ func (s *KeeperTestSuite) TestSwapOutGivenIn_Tick_Initialization_And_Crossing() if tickToSwapTo >= nr1Position.upperTick { sqrtPriceUpperOne := s.tickToSqrtPrice(nr1Position.upperTick) - amountOneIn = math.CalcAmount1Delta(osmomath.BigDecFromDec(liquidity), sqrtPriceUpperOne, sqrtPriceStart, true).DecRoundUp() + amountOneIn = math.CalcAmount1Delta(liquidity, sqrtPriceUpperOne, sqrtPriceStart, true).DecRoundUp() sqrtPriceStart = sqrtPriceUpperOne @@ -743,7 +743,7 @@ func (s *KeeperTestSuite) TestSwapOutGivenIn_Tick_Initialization_And_Crossing() // This is the total amount necessary to cross the lower tick of narrow position. // Note it is rounded up to ensure that the tick is crossed. - amountOneIn = math.CalcAmount1Delta(osmomath.BigDecFromDec(liquidity), sqrtPriceTarget, sqrtPriceStart, true).DecRoundUp().Add(amountOneIn) + amountOneIn = math.CalcAmount1Delta(liquidity, sqrtPriceTarget, sqrtPriceStart, true).DecRoundUp().Add(amountOneIn) tokenOneIn := sdk.NewCoin(pool.GetToken1(), amountOneIn.Ceil().TruncateInt()) @@ -1201,6 +1201,7 @@ func (s *KeeperTestSuite) TestSwaps_Contiguous_Initialized_TickSpacingOne() { // estimateAmountInFromRounding is a helper to estimate the impact of amountOut rounding on the amountIn and next sqrt price. // This is necessary for correct amount in estimation to pre-fund the swapper account to. It is also required for updating // the "current sqrt price" for the next swap in the sequence as defined by our test configuration. + // TODO: Change type arg of liq estimateAmountInFromRounding := func(isZeroForOne bool, nextSqrtPrice osmomath.BigDec, liq osmomath.BigDec, amountOutDifference osmomath.BigDec) (osmomath.Dec, osmomath.BigDec) { if !liq.IsPositive() { return osmomath.ZeroDec(), nextSqrtPrice @@ -1210,17 +1211,17 @@ func (s *KeeperTestSuite) TestSwaps_Contiguous_Initialized_TickSpacingOne() { // Round down since we want to overestimate the change in sqrt price stemming from the amount out going right-to-left // from the current sqrt price. This overestimated value is then used to calculate amount in charged on the user. // Since amount in is overestimated, this done in favor of the pool. - updatedNextCurSqrtPrice := math.GetNextSqrtPriceFromAmount1OutRoundingDown(nextSqrtPrice, liq, amountOutDifference) + updatedNextCurSqrtPrice := math.GetNextSqrtPriceFromAmount1OutRoundingDown(nextSqrtPrice, liq.Dec(), amountOutDifference) // Round up since we want to overestimate the amount in in favor of the pool. - return math.CalcAmount0Delta(liq, updatedNextCurSqrtPrice, nextSqrtPrice, true).DecRoundUp(), updatedNextCurSqrtPrice + return math.CalcAmount0Delta(liq.Dec(), updatedNextCurSqrtPrice, nextSqrtPrice, true).DecRoundUp(), updatedNextCurSqrtPrice } // Round up since we want to overestimate the change in sqrt price stemming from the amount out going left-to-right // from the current sqrt price. This overestimated value is then used to calculate amount in charged on the user. // Since amount in is overestimated, this is done in favor of the pool. - updatedNextCurSqrtPrice := math.GetNextSqrtPriceFromAmount0OutRoundingUp(nextSqrtPrice, liq, amountOutDifference) + updatedNextCurSqrtPrice := math.GetNextSqrtPriceFromAmount0OutRoundingUp(nextSqrtPrice, liq, amountOutDifference.Dec()) // Round up since we want to overestimate the amount in in favor of the pool. - return math.CalcAmount1Delta(liq, updatedNextCurSqrtPrice, nextSqrtPrice, true).DecRoundUp(), updatedNextCurSqrtPrice + return math.CalcAmount1Delta(liq.Dec(), updatedNextCurSqrtPrice, nextSqrtPrice, true).DecRoundUp(), updatedNextCurSqrtPrice } for name, tc := range testcases { @@ -1277,7 +1278,8 @@ func (s *KeeperTestSuite) TestSwaps_Contiguous_Initialized_TickSpacingOne() { // properly estimating the next swap. This also allows us to precisely calculate by how many tokens in we need // to pre-fund the swapper account. amountOutDifference := amountOutRoundedUp.ToLegacyDec().Sub(amountOut) - amountInFromRounding, updatedNextCurSqrtPrice := estimateAmountInFromRounding(isZeroForOne, nextSqrtPrice, expectedLiquidity, osmomath.BigDecFromDec(amountOutDifference)) + liqBigDec := osmomath.BigDecFromDec(expectedLiquidity) // TODO: Delete + amountInFromRounding, updatedNextCurSqrtPrice := estimateAmountInFromRounding(isZeroForOne, nextSqrtPrice, liqBigDec, osmomath.BigDecFromDec(amountOutDifference)) amountInToPreFund := amountIn.Add(amountInFromRounding) // Perform the swap in the desired direction. @@ -1293,7 +1295,7 @@ func (s *KeeperTestSuite) TestSwaps_Contiguous_Initialized_TickSpacingOne() { // Validate that current tick and current liquidity are as expected. s.assertPoolTickEquals(poolId, expectedSwapEndTick) - s.assertPoolLiquidityEquals(poolId, expectedLiquidity.Dec()) + s.assertPoolLiquidityEquals(poolId, expectedLiquidity) // Update the current sqrt price and tick for next swap. curSqrtPrice = updatedNextCurSqrtPrice diff --git a/x/concentrated-liquidity/swapstrategy/one_for_zero.go b/x/concentrated-liquidity/swapstrategy/one_for_zero.go index 12f22dbef93..5523b8f1e71 100644 --- a/x/concentrated-liquidity/swapstrategy/one_for_zero.go +++ b/x/concentrated-liquidity/swapstrategy/one_for_zero.go @@ -60,14 +60,22 @@ func (s oneForZeroStrategy) GetSqrtTargetPrice(nextTickSqrtPrice osmomath.BigDec // OneForZero details: // - oneForZeroStrategy assumes moving to the right of the current square root price. func (s oneForZeroStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent, sqrtPriceTarget osmomath.BigDec, liquidity, amountOneInRemaining osmomath.Dec) (osmomath.BigDec, osmomath.Dec, osmomath.Dec, osmomath.Dec) { +<<<<<<< HEAD liquidityBigDec := osmomath.BigDecFromDec(liquidity) amountOneInRemainingBigDec := osmomath.BigDecFromDec(amountOneInRemaining) +======= +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) // Estimate the amount of token one needed until the target sqrt price is reached. - amountOneIn := math.CalcAmount1Delta(liquidityBigDec, sqrtPriceTarget, sqrtPriceCurrent, true) + amountOneIn := math.CalcAmount1Delta(liquidity, sqrtPriceTarget, sqrtPriceCurrent, true) // Calculate sqrtPriceNext on the amount of token remaining after spread reward. +<<<<<<< HEAD amountOneInRemainingLessSpreadReward := amountOneInRemainingBigDec.MulTruncate(oneBigDec.Sub(osmomath.BigDecFromDec(s.spreadFactor))) +======= + oneMinusTakerFee := oneDec.Sub(s.spreadFactor) + amountOneInRemainingLessSpreadReward := osmomath.NewBigDecFromDecMulDec(amountOneInRemaining, oneMinusTakerFee) +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) var sqrtPriceNext osmomath.BigDec // If have more of the amount remaining after spread reward than estimated until target, @@ -76,7 +84,7 @@ func (s oneForZeroStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent, sqrtPriceNext = sqrtPriceTarget } else { // Otherwise, compute the next sqrt price based on the amount remaining after spread reward. - sqrtPriceNext = math.GetNextSqrtPriceFromAmount1InRoundingDown(sqrtPriceCurrent, liquidityBigDec, amountOneInRemainingLessSpreadReward) + sqrtPriceNext = math.GetNextSqrtPriceFromAmount1InRoundingDown(sqrtPriceCurrent, liquidity, amountOneInRemainingLessSpreadReward) } hasReachedTarget := sqrtPriceTarget.Equal(sqrtPriceNext) @@ -85,11 +93,11 @@ func (s oneForZeroStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent, // to complete the swap step. This implies that some of the amount remaining after spread reward is left over after the // current swap step. if !hasReachedTarget { - amountOneIn = math.CalcAmount1Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, true) // N.B.: if this is false, causes infinite loop + amountOneIn = math.CalcAmount1Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, true) // N.B.: if this is false, causes infinite loop } // Calculate the amount of the other token given the sqrt price range. - amountZeroOut := math.CalcAmount0Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, false) + amountZeroOut := math.CalcAmount0Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, false) // Round up to charge user more in pool's favor. amountInDecFinal := amountOneIn.DecRoundUp() @@ -128,7 +136,7 @@ func (s oneForZeroStrategy) ComputeSwapWithinBucketInGivenOut(sqrtPriceCurrent, // Estimate the amount of token zero needed until the target sqrt price is reached. // N.B.: contrary to out given in, we do not round up because we do not want to exceed the initial amount out at the end. - amountZeroOut := math.CalcAmount0Delta(liquidityBigDec, sqrtPriceTarget, sqrtPriceCurrent, false) + amountZeroOut := math.CalcAmount0Delta(liquidity, sqrtPriceTarget, sqrtPriceCurrent, false) // Calculate sqrtPriceNext on the amount of token remaining. Note that the // spread reward is not charged as amountRemaining is amountOut, and we only charge spread reward on @@ -140,7 +148,7 @@ func (s oneForZeroStrategy) ComputeSwapWithinBucketInGivenOut(sqrtPriceCurrent, sqrtPriceNext = sqrtPriceTarget } else { // Otherwise, compute the next sqrt price based on the amount remaining after spread reward. - sqrtPriceNext = math.GetNextSqrtPriceFromAmount0OutRoundingUp(sqrtPriceCurrent, liquidityBigDec, amountZeroRemainingOutBigDec) + sqrtPriceNext = math.GetNextSqrtPriceFromAmount0OutRoundingUp(sqrtPriceCurrent, liquidityBigDec, amountZeroRemainingOut) } hasReachedTarget := sqrtPriceTarget.Equal(sqrtPriceNext) @@ -150,11 +158,11 @@ func (s oneForZeroStrategy) ComputeSwapWithinBucketInGivenOut(sqrtPriceCurrent, // current swap step. if !hasReachedTarget { // N.B.: contrary to out given in, we do not round up because we do not want to exceed the initial amount out at the end. - amountZeroOut = math.CalcAmount0Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, false) + amountZeroOut = math.CalcAmount0Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, false) } // Calculate the amount of the other token given the sqrt price range. - amountOneIn := math.CalcAmount1Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, true) + amountOneIn := math.CalcAmount1Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, true) // Round up to charge user more in pool's favor. amountOneInFinal := amountOneIn.DecRoundUp() diff --git a/x/concentrated-liquidity/swapstrategy/spread_rewards.go b/x/concentrated-liquidity/swapstrategy/spread_rewards.go index a99e31d894a..47d8b3b54ba 100644 --- a/x/concentrated-liquidity/swapstrategy/spread_rewards.go +++ b/x/concentrated-liquidity/swapstrategy/spread_rewards.go @@ -23,17 +23,14 @@ import ( // If spread factor is negative, it panics. // If spread factor is 0, returns 0. Otherwise, computes and returns the spread factor charge per step. func computeSpreadRewardChargePerSwapStepOutGivenIn(hasReachedTarget bool, amountIn, amountSpecifiedRemaining, spreadFactor osmomath.Dec) osmomath.Dec { - spreadRewardChargeTotal := osmomath.ZeroDec() - - if spreadFactor.IsNegative() { + if spreadFactor.IsZero() { + return osmomath.ZeroDec() + } else if spreadFactor.IsNegative() { // This should never happen but is added as a defense-in-depth measure. panic(fmt.Errorf("spread factor must be non-negative, was (%s)", spreadFactor)) } - if spreadFactor.IsZero() { - return spreadRewardChargeTotal - } - + var spreadRewardChargeTotal osmomath.Dec if hasReachedTarget { // This branch implies two options: // 1) either sqrtPriceNextTick is reached @@ -61,6 +58,7 @@ func computeSpreadRewardChargePerSwapStepOutGivenIn(hasReachedTarget bool, amoun // Computes amountIn * spreadFactor / (1 - spreadFactor) where math operations round up // at precision end. This is necessary to ensure that the spread factor charge is always // rounded in favor of the pool. +// TODO: Change this fn to take in 1 - spreadFactor as it should already have been computed. func computeSpreadRewardChargeFromAmountIn(amountIn osmomath.Dec, spreadFactor osmomath.Dec) osmomath.Dec { return amountIn.MulRoundUp(spreadFactor).QuoRoundupMut(osmomath.OneDec().SubMut(spreadFactor)) } diff --git a/x/concentrated-liquidity/swapstrategy/swap_strategy.go b/x/concentrated-liquidity/swapstrategy/swap_strategy.go index bbd46ede75c..195bd894ac9 100644 --- a/x/concentrated-liquidity/swapstrategy/swap_strategy.go +++ b/x/concentrated-liquidity/swapstrategy/swap_strategy.go @@ -90,7 +90,7 @@ type SwapStrategy interface { } var ( - oneBigDec = osmomath.OneBigDec() + oneDec = osmomath.OneDec() ) // New returns a swap strategy based on the provided zeroForOne parameter diff --git a/x/concentrated-liquidity/swapstrategy/zero_for_one.go b/x/concentrated-liquidity/swapstrategy/zero_for_one.go index 1e5c84dd275..ced97ce9056 100644 --- a/x/concentrated-liquidity/swapstrategy/zero_for_one.go +++ b/x/concentrated-liquidity/swapstrategy/zero_for_one.go @@ -61,13 +61,13 @@ func (s zeroForOneStrategy) GetSqrtTargetPrice(nextTickSqrtPrice osmomath.BigDec // - zeroForOneStrategy assumes moving to the left of the current square root price. func (s zeroForOneStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent, sqrtPriceTarget osmomath.BigDec, liquidity, amountZeroInRemaining osmomath.Dec) (osmomath.BigDec, osmomath.Dec, osmomath.Dec, osmomath.Dec) { liquidityBigDec := osmomath.BigDecFromDec(liquidity) - amountZeroInRemainingBigDec := osmomath.BigDecFromDec(amountZeroInRemaining) // Estimate the amount of token zero needed until the target sqrt price is reached. - amountZeroIn := math.CalcAmount0Delta(liquidityBigDec, sqrtPriceTarget, sqrtPriceCurrent, true) // N.B.: if this is false, causes infinite loop + amountZeroIn := math.CalcAmount0Delta(liquidity, sqrtPriceTarget, sqrtPriceCurrent, true) // N.B.: if this is false, causes infinite loop // Calculate sqrtPriceNext on the amount of token remaining after spread reward. - amountZeroInRemainingLessSpreadReward := amountZeroInRemainingBigDec.Mul(oneBigDec.Sub(osmomath.BigDecFromDec(s.spreadFactor))) + oneMinusTakerFee := oneDec.Sub(s.spreadFactor) + amountZeroInRemainingLessSpreadReward := osmomath.NewBigDecFromDecMulDec(amountZeroInRemaining, oneMinusTakerFee) var sqrtPriceNext osmomath.BigDec // If have more of the amount remaining after spread reward than estimated until target, @@ -85,11 +85,11 @@ func (s zeroForOneStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent, // to complete the swap step. This implies that some of the amount remaining after spread reward is left over after the // current swap step. if !hasReachedTarget { - amountZeroIn = math.CalcAmount0Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, true) // N.B.: if this is false, causes infinite loop + amountZeroIn = math.CalcAmount0Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, true) // N.B.: if this is false, causes infinite loop } // Calculate the amount of the other token given the sqrt price range. - amountOneOut := math.CalcAmount1Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, false) + amountOneOut := math.CalcAmount1Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, false) // Round up to charge user more in pool's favor. amountZeroInFinal := amountZeroIn.DecRoundUp() @@ -123,11 +123,10 @@ func (s zeroForOneStrategy) ComputeSwapWithinBucketOutGivenIn(sqrtPriceCurrent, // ZeroForOne details: // - zeroForOneStrategy assumes moving to the left of the current square root price. func (s zeroForOneStrategy) ComputeSwapWithinBucketInGivenOut(sqrtPriceCurrent, sqrtPriceTarget osmomath.BigDec, liquidity, amountOneRemainingOut osmomath.Dec) (osmomath.BigDec, osmomath.Dec, osmomath.Dec, osmomath.Dec) { - liquidityBigDec := osmomath.BigDecFromDec(liquidity) amountOneRemainingOutBigDec := osmomath.BigDecFromDec(amountOneRemainingOut) // Estimate the amount of token one needed until the target sqrt price is reached. - amountOneOut := math.CalcAmount1Delta(liquidityBigDec, sqrtPriceTarget, sqrtPriceCurrent, false) + amountOneOut := math.CalcAmount1Delta(liquidity, sqrtPriceTarget, sqrtPriceCurrent, false) // Calculate sqrtPriceNext on the amount of token remaining. Note that the // spread reward is not charged as amountRemaining is amountOut, and we only charge spread reward on @@ -139,7 +138,7 @@ func (s zeroForOneStrategy) ComputeSwapWithinBucketInGivenOut(sqrtPriceCurrent, sqrtPriceNext = sqrtPriceTarget } else { // Otherwise, compute the next sqrt price based on the amount remaining after spread reward. - sqrtPriceNext = math.GetNextSqrtPriceFromAmount1OutRoundingDown(sqrtPriceCurrent, liquidityBigDec, amountOneRemainingOutBigDec) + sqrtPriceNext = math.GetNextSqrtPriceFromAmount1OutRoundingDown(sqrtPriceCurrent, liquidity, amountOneRemainingOutBigDec) } hasReachedTarget := sqrtPriceTarget.Equal(sqrtPriceNext) @@ -148,11 +147,11 @@ func (s zeroForOneStrategy) ComputeSwapWithinBucketInGivenOut(sqrtPriceCurrent, // to complete the swap step. This implies that some of the amount remaining after spread reward is left over after the // current swap step. if !hasReachedTarget { - amountOneOut = math.CalcAmount1Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, false) + amountOneOut = math.CalcAmount1Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, false) } // Calculate the amount of the other token given the sqrt price range. - amountZeroIn := math.CalcAmount0Delta(liquidityBigDec, sqrtPriceNext, sqrtPriceCurrent, true) + amountZeroIn := math.CalcAmount0Delta(liquidity, sqrtPriceNext, sqrtPriceCurrent, true) // Round up to charge user more in pool's favor. amountZeroInFinal := amountZeroIn.DecRoundUp() diff --git a/x/epochs/go.mod b/x/epochs/go.mod index 1a90e6b9e5b..0053cdffd81 100644 --- a/x/epochs/go.mod +++ b/x/epochs/go.mod @@ -9,8 +9,12 @@ require ( github.com/cosmos/gogoproto v1.4.11 github.com/golang/protobuf v1.5.3 github.com/grpc-ecosystem/grpc-gateway v1.16.0 +<<<<<<< HEAD github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c github.com/osmosis-labs/osmosis/v23 v23.0.8 +======= + github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 @@ -145,10 +149,15 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mtibben/percent v0.2.1 // indirect +<<<<<<< HEAD github.com/opencontainers/go-digest v1.0.0 // indirect github.com/osmosis-labs/osmosis/osmomath v0.0.10-0.20240409161506-a48ca4af185c // indirect github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.11-0.20240409161506-a48ca4af185c // indirect github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240208035010-35d5b08f4975 // indirect +======= + github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae // indirect + github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 // indirect +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/x/epochs/go.sum b/x/epochs/go.sum index 3adcf79b326..e0496526a1b 100644 --- a/x/epochs/go.sum +++ b/x/epochs/go.sum @@ -1251,6 +1251,7 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +<<<<<<< HEAD github.com/osmosis-labs/cometbft v0.37.4-v23-osmo-3 h1:HJItohXCYHMTd1x938+zpxswkzdKFikHPz9xkHFtpBk= github.com/osmosis-labs/cometbft v0.37.4-v23-osmo-3/go.mod h1:Cmg5Hp4sNpapm7j+x0xRyt2g0juQfmB752ous+pA0G8= github.com/osmosis-labs/cosmos-sdk v0.47.5-v23-osmo-9-iavl-v1 h1:cJfWAQHK2Em6cE5w3Uev3AysCvjenchKBuliiXjxcxg= @@ -1267,6 +1268,16 @@ github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240208035010-35d5b08f4975 h1:3XxO github.com/osmosis-labs/sqs/sqsdomain v0.0.0-20240208035010-35d5b08f4975/go.mod h1:xwisuj2W2+dwsjNodLTFxLyvUb6u+0kj2kBQbGXJPuQ= github.com/osmosis-labs/wasmd v0.45.0-osmo h1:NIp7pvJV5HuBN1HwPgEmXKQM2TjVIVdJErIHnB9IMO8= github.com/osmosis-labs/wasmd v0.45.0-osmo/go.mod h1:J6eRvwii5T1WxhetZkBg1kOJS3GTn1Bw2OLyZBb8EVU= +======= +github.com/osmosis-labs/cometbft v0.37.4-v24-osmo-2 h1:3k4I3zCxdNP+mjhR7AtKr1PPuGR58CcVTMZN0aV/iL4= +github.com/osmosis-labs/cometbft v0.37.4-v24-osmo-2/go.mod h1:fE+yBeExsJHA35plOZ7FmC/JejO5UdEHNcwO3dj2wc8= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5 h1:fnt89Cw+55vbnIEGkpCmj0cx/EaEnwHfYi4JN3rKkLU= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5/go.mod h1:eSRUVYwL3eG1jnh01CnBbHiqOM3xJO49p5rTOrSFX1k= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 h1:p1jOOamB3IHz5qXeN50KJLEQmNx3PSz5wunNtUrSb4g= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:OQj1UyxCyuunzCPuYtbRGTvaL62OIznjQpXqdFDINbs= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 h1:3BlWDp7ivc+gyjdIPxkcvcDBsATq8s+ZEUD1AxFuDzo= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:n41vW6Nr5BmO7jCrdEONyOrJ3PACRcOt/KvhVTrEfjo= +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= diff --git a/x/ibc-hooks/go.mod b/x/ibc-hooks/go.mod index 742429c3f41..127512a5e10 100644 --- a/x/ibc-hooks/go.mod +++ b/x/ibc-hooks/go.mod @@ -11,8 +11,13 @@ require ( github.com/cosmos/gogoproto v1.4.11 github.com/cosmos/ibc-go/v7 v7.3.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 +<<<<<<< HEAD github.com/osmosis-labs/osmosis/osmomath v0.0.10-0.20240409161506-a48ca4af185c github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c +======= + github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 + github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/spf13/cobra v1.8.0 google.golang.org/grpc v1.61.1 google.golang.org/protobuf v1.32.0 diff --git a/x/ibc-hooks/go.sum b/x/ibc-hooks/go.sum index db6a7824b1a..20e2d98891f 100644 --- a/x/ibc-hooks/go.sum +++ b/x/ibc-hooks/go.sum @@ -1237,6 +1237,7 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +<<<<<<< HEAD github.com/osmosis-labs/cometbft v0.37.4-v23-osmo-3 h1:HJItohXCYHMTd1x938+zpxswkzdKFikHPz9xkHFtpBk= github.com/osmosis-labs/cometbft v0.37.4-v23-osmo-3/go.mod h1:Cmg5Hp4sNpapm7j+x0xRyt2g0juQfmB752ous+pA0G8= github.com/osmosis-labs/cosmos-sdk v0.47.5-v23-osmo-9-iavl-v1 h1:cJfWAQHK2Em6cE5w3Uev3AysCvjenchKBuliiXjxcxg= @@ -1245,6 +1246,16 @@ github.com/osmosis-labs/osmosis/osmomath v0.0.10-0.20240409161506-a48ca4af185c h github.com/osmosis-labs/osmosis/osmomath v0.0.10-0.20240409161506-a48ca4af185c/go.mod h1:odGDOV3P5HeMPaA892k0V9iBykR1SfUp7nlkzn0e2lM= github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c h1:o9rUAOO3ccXRc/BVzU0E43EfK1WKLonaexNBVmSUgbo= github.com/osmosis-labs/osmosis/osmoutils v0.0.10-0.20240409161506-a48ca4af185c/go.mod h1:rIKIgsXj7bXTO604WSbjF2PB7WaVmoe+xhWgDfnwXIo= +======= +github.com/osmosis-labs/cometbft v0.37.4-v24-osmo-2 h1:3k4I3zCxdNP+mjhR7AtKr1PPuGR58CcVTMZN0aV/iL4= +github.com/osmosis-labs/cometbft v0.37.4-v24-osmo-2/go.mod h1:fE+yBeExsJHA35plOZ7FmC/JejO5UdEHNcwO3dj2wc8= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5 h1:fnt89Cw+55vbnIEGkpCmj0cx/EaEnwHfYi4JN3rKkLU= +github.com/osmosis-labs/cosmos-sdk v0.47.5-v24-osmo-5/go.mod h1:eSRUVYwL3eG1jnh01CnBbHiqOM3xJO49p5rTOrSFX1k= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8 h1:p1jOOamB3IHz5qXeN50KJLEQmNx3PSz5wunNtUrSb4g= +github.com/osmosis-labs/osmosis/osmomath v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:OQj1UyxCyuunzCPuYtbRGTvaL62OIznjQpXqdFDINbs= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8 h1:3BlWDp7ivc+gyjdIPxkcvcDBsATq8s+ZEUD1AxFuDzo= +github.com/osmosis-labs/osmosis/osmoutils v0.0.12-0.20240411125512-cb0fada2dee8/go.mod h1:n41vW6Nr5BmO7jCrdEONyOrJ3PACRcOt/KvhVTrEfjo= +>>>>>>> 7b599d55 (Speedup quo round up, start CL speedup integration (#8014)) github.com/osmosis-labs/wasmd v0.45.0-osmo h1:NIp7pvJV5HuBN1HwPgEmXKQM2TjVIVdJErIHnB9IMO8= github.com/osmosis-labs/wasmd v0.45.0-osmo/go.mod h1:J6eRvwii5T1WxhetZkBg1kOJS3GTn1Bw2OLyZBb8EVU= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=