Skip to content

Commit

Permalink
feat(x/twap): use exp2 in twapPow; add overflow test
Browse files Browse the repository at this point in the history
  • Loading branch information
p0mvn committed Dec 21, 2022
1 parent d1349db commit 654b2a5
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 17 deletions.
2 changes: 0 additions & 2 deletions x/twap/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ type (
GeometricTwapStrategy = geometric
)

var GeometricTwapMathBase = geometricTwapMathBase

func (k Keeper) StoreNewRecord(ctx sdk.Context, record types.TwapRecord) {
k.storeNewRecord(ctx, record)
}
Expand Down
13 changes: 1 addition & 12 deletions x/twap/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ import (
"github.com/osmosis-labs/osmosis/v13/x/twap/types"
)

// geometricTwapMathBase is the base used for geometric twap calculation
// 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")
)

func newTwapRecord(k types.AmmInterface, ctx sdk.Context, poolId uint64, denom0, denom1 string) (types.TwapRecord, error) {
denom0, denom1, err := types.LexicographicalOrderDenoms(denom0, denom1)
if err != nil {
Expand Down Expand Up @@ -268,13 +259,11 @@ func computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quote
}

// 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 osmomath.Exp2(osmomath.BigDecFromSDKDec(exponent)).SDKDec()
}
7 changes: 4 additions & 3 deletions x/twap/logic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1327,20 +1327,21 @@ 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(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
exponentValue := osmomath.MustNewDecFromStr("0.5")
expectedValue := osmomath.MustNewDecFromStr("1.41421356")

result := twap.TwapPow(exponentValue.SDKDec())
result_by_mathPow := math.Pow(twap.GeometricTwapMathBase.MustFloat64(), exponentValue.SDKDec().MustFloat64())
result_by_mathPow := math.Pow(geometricTwapMathBase.MustFloat64(), exponentValue.SDKDec().MustFloat64())
s.Require().True(expectedValue.Sub(osmomath.BigDecFromSDKDec(result)).Abs().LTE(expectedErrTolerance))
s.Require().True(osmomath.MustNewDecFromStr(fmt.Sprint(result_by_mathPow)).Sub(osmomath.BigDecFromSDKDec(result)).Abs().LTE(expectedErrTolerance))
}
Expand Down
26 changes: 26 additions & 0 deletions x/twap/strategy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/osmosis-labs/osmosis/v13/app/apptesting/osmoassert"
"github.com/osmosis-labs/osmosis/v13/osmomath"
gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types"
"github.com/osmosis-labs/osmosis/v13/x/twap"
"github.com/osmosis-labs/osmosis/v13/x/twap/types"
)
Expand All @@ -21,6 +22,13 @@ type computeTwapTestCase struct {
expPanic bool
}

// geometricTwapMathBase is the base used for geometric twap calculation
// in logarithm and power math functions.
// See twapLog and computeGeometricTwap functions for more details.
var (
geometricTwapMathBase = osmomath.NewBigDec(2)
)

// TestComputeArithmeticTwap tests computeTwap on various inputs.
// The test vectors are structured by setting up different start and records,
// based on time interval, and their accumulator values.
Expand Down Expand Up @@ -300,3 +308,21 @@ func (s *TestSuite) TestComputeGeometricStrategyTwap_ThreeAsset() {
})
}
}

// 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)))
}

0 comments on commit 654b2a5

Please sign in to comment.