Skip to content

Commit

Permalink
Fix spotprice sigfig rounding for small spot prices (backport #1699) (#…
Browse files Browse the repository at this point in the history
…1703)

* Fix spotprice sigfig rounding for small spot prices (#1699)

* Fix spotprice sigfig rounding for small spot prices

* Changelog

* Fix off by one in precision

* Address PR comment

(cherry picked from commit c211999)

# Conflicts:
#	CHANGELOG.md

* Update CHANGELOG.md

Co-authored-by: Dev Ojha <[email protected]>
  • Loading branch information
mergify[bot] and ValarDragon authored Jun 7, 2022
1 parent ddd75fe commit 7327a04
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 4 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
## v9.0.1

### Breaking Changes

* [#1699](https://github.com/osmosis-labs/osmosis/pull/1699) Fixes bug in sig fig rounding on spot price queries for small values

* [#1312] Stableswap: Createpool logic
* [#1230] Stableswap CFMM equations
Expand Down
2 changes: 1 addition & 1 deletion app/apptesting/gamm.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (suite *KeeperTestHelper) PrepareBalancerPool() uint64 {
spotPrice, err = suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx, poolId, "baz", "foo")
suite.NoError(err)
s := sdk.NewDec(1).Quo(sdk.NewDec(3))
sp := s.Mul(gammtypes.SigFigs).RoundInt().ToDec().Quo(gammtypes.SigFigs)
sp := s.MulInt(gammtypes.SigFigs).RoundInt().ToDec().QuoInt(gammtypes.SigFigs)
suite.Equal(sp.String(), spotPrice.String())

return poolId
Expand Down
24 changes: 24 additions & 0 deletions osmomath/sigfig_round.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package osmomath

import sdk "github.com/cosmos/cosmos-sdk/types"

var pointOne = sdk.OneDec().QuoInt64(10)

func SigFigRound(d sdk.Dec, tenToSigFig sdk.Int) sdk.Dec {
// for d > .1, we do round(d * 10^sigfig) / 10^sigfig
// for k, where 10^k*d > .1 && 10^{k-1}*d < .1, we do:
// (round(10^k * d * 10^sigfig) / (10^sigfig * 10^k)
// take note of floor div, vs normal div
k := uint64(0)
dTimesK := d
for ; dTimesK.LT(pointOne); k += 1 {
dTimesK.MulInt64Mut(10)
}
// d * 10^k * 10^sigfig
dkSigFig := dTimesK.MulInt(tenToSigFig)
numerator := dkSigFig.RoundInt().ToDec()

tenToK := sdk.NewInt(10).ToDec().Power(k)
denominator := tenToSigFig.Mul(tenToK.TruncateInt())
return numerator.QuoInt(denominator)
}
3 changes: 2 additions & 1 deletion x/gamm/pool-models/balancer/amm.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ func (p Pool) SpotPrice(ctx sdk.Context, baseAsset, quoteAsset string) (sdk.Dec,
invWeightRatio := quote.Weight.ToDec().Quo(base.Weight.ToDec())
supplyRatio := base.Token.Amount.ToDec().Quo(quote.Token.Amount.ToDec())
fullRatio := supplyRatio.Mul(invWeightRatio)
ratio := (fullRatio.Mul(types.SigFigs).RoundInt()).ToDec().Quo(types.SigFigs)
// we want to round this to `SigFigs` of precision
ratio := osmomath.SigFigRound(fullRatio, types.SigFigs)
return ratio, nil
}

Expand Down
14 changes: 14 additions & 0 deletions x/gamm/pool-models/balancer/amm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ func (suite *KeeperTestSuite) TestBalancerSpotPrice() {
expectError: false,
expectedOutput: sdk.MustNewDecFromStr("1.913043480000000000"), // ans is 1.913043478260869565, rounded is 1.91304348
},
{
name: "check number of sig figs",
baseDenomPoolInput: sdk.NewInt64Coin(baseDenom, 100),
quoteDenomPoolInput: sdk.NewInt64Coin(quoteDenom, 300),
expectError: false,
expectedOutput: sdk.MustNewDecFromStr("0.333333330000000000"),
},
{
name: "check number of sig figs high sizes",
baseDenomPoolInput: sdk.NewInt64Coin(baseDenom, 343569192534),
quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.MustNewDecFromStr("186633424395479094888742").TruncateInt()),
expectError: false,
expectedOutput: sdk.MustNewDecFromStr("0.000000000001840877"),
},
}

for _, tc := range tests {
Expand Down
2 changes: 1 addition & 1 deletion x/gamm/types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ var (
InitPoolSharesSupply = OneShare.MulRaw(100)

// SigFigs is the amount of significant figures used to calculate SpotPrice
SigFigs = sdk.NewDec(10).Power(SigFigsExponent)
SigFigs = sdk.NewDec(10).Power(SigFigsExponent).TruncateInt()
)

0 comments on commit 7327a04

Please sign in to comment.