Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(x/twap): geometric twap overflow tests #3732

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions x/twap/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ import (
// in logarithm and power math functions.
// See twapLog and computeGeometricTwap functions for more details.
var (
geometricTwapMathBase = sdk.NewDec(2)
// TODO: analyze choice.
geometricTwapPowPrecision = sdk.MustNewDecFromStr("0.00000001")
geometricTwapMathBase = osmomath.NewBigDec(2)
)

func newTwapRecord(k types.AmmInterface, ctx sdk.Context, poolId uint64, denom0, denom1 string) (types.TwapRecord, error) {
Expand Down Expand Up @@ -305,13 +303,11 @@ func computeGeometricTwap(startRecord types.TwapRecord, endRecord types.TwapReco
}

// twapLog returns the logarithm of the given spot price, base 2.
// TODO: basic test
func twapLog(price sdk.Dec) sdk.Dec {
return osmomath.BigDecFromSDKDec(price).LogBase2().SDKDec()
}

// twapPow exponentiates the geometricTwapMathBase to the given exponent.
// TODO: basic test and benchmark.
func twapPow(exponent sdk.Dec) sdk.Dec {
return osmomath.PowApprox(geometricTwapMathBase, exponent, geometricTwapPowPrecision)
return geometricTwapMathBase.Power(osmomath.BigDecFromSDKDec(exponent)).SDKDec()
}
23 changes: 21 additions & 2 deletions x/twap/logic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1600,13 +1600,14 @@ func (s *TestSuite) TestTwapLog() {
var expectedValue = osmomath.MustNewDecFromStr("99.525973560175362367")

result := twap.TwapLog(priceValue.SDKDec())
result_by_customBaseLog := priceValue.CustomBaseLog(osmomath.BigDecFromSDKDec(twap.GeometricTwapMathBase))
result_by_customBaseLog := priceValue.CustomBaseLog(twap.GeometricTwapMathBase)
s.Require().True(expectedValue.Sub(osmomath.BigDecFromSDKDec(result)).Abs().LTE(expectedErrTolerance))
s.Require().True(result_by_customBaseLog.Sub(osmomath.BigDecFromSDKDec(result)).Abs().LTE(expectedErrTolerance))

}

func (s *TestSuite) TestTwapPow() {
// TestTwapPow_CorrectBase tests that the right base is used for the twap power function.
func (s *TestSuite) TestTwapPow_CorrectBase() {
var expectedErrTolerance = osmomath.MustNewDecFromStr("0.00000100")
// "TwapPow(0.5) = 1.41421356"
// From: https://www.wolframalpha.com/input?i2d=true&i=power+base+2+exponent+0.5+with+9+digits
Expand All @@ -1619,6 +1620,24 @@ func (s *TestSuite) TestTwapPow() {
s.Require().True(osmomath.MustNewDecFromStr(fmt.Sprint(result_by_mathPow)).Sub(osmomath.BigDecFromSDKDec(result)).Abs().LTE(expectedErrTolerance))
}

// TestTwapPow_MaxSpotPrice_NoOverflow tests that no overflow occurs at log_2{max spot price values}.
// and that the epsilot is within the tolerated multiplicative error.
func (s *TestSuite) TestTwapLogPow_MaxSpotPrice_NoOverflow() {
errTolerance := osmomath.ErrTolerance{
MultiplicativeTolerance: sdk.OneDec().Quo(sdk.NewDec(10).Power(18)),
RoundingDir: osmomath.RoundDown,
}

oneYear := OneSec.MulInt64(60 * 60 * 24 * 365)

oneYearTimesMaxSpotPrice := oneYear.Mul(gammtypes.MaxSpotPrice)

exponentValue := twap.TwapLog(oneYearTimesMaxSpotPrice)
finalValue := twap.TwapPow(exponentValue)

s.Equal(0, errTolerance.CompareBigDec(osmomath.BigDecFromSDKDec(oneYearTimesMaxSpotPrice), osmomath.BigDecFromSDKDec(finalValue)))
}

func testCaseFromDeltas(startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeTwapTestCase {
return computeTwapTestCase{
newOneSidedRecord(baseTime, startAccum, true),
Expand Down