diff --git a/x/oracle/abci_test.go b/x/oracle/abci_test.go index 78b4fa05..10f7aea5 100644 --- a/x/oracle/abci_test.go +++ b/x/oracle/abci_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/rand" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -335,14 +336,14 @@ func TestOracleExchangeRate(t *testing.T) { input, h := setup(t) krwRandomExchangeRate := sdk.NewDecWithPrec(1000000000, int64(6)).MulInt64(core.MicroUnit) - uswRandomExchangeRate := sdk.NewDecWithPrec(1000000, int64(6)).MulInt64(core.MicroUnit) + usdRandomExchangeRate := sdk.NewDecWithPrec(1000000, int64(6)).MulInt64(core.MicroUnit) // KRW has been chosen as referenceTerra by highest voting power // Account 1, USD, KRW - makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroUSDDenom, Amount: uswRandomExchangeRate}, {Denom: core.MicroKRWDenom, Amount: krwRandomExchangeRate}}, 0) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroUSDDenom, Amount: usdRandomExchangeRate}, {Denom: core.MicroKRWDenom, Amount: krwRandomExchangeRate}}, 0) // Account 2, USD, KRW - makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroUSDDenom, Amount: uswRandomExchangeRate}, {Denom: core.MicroKRWDenom, Amount: krwRandomExchangeRate}}, 1) + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroUSDDenom, Amount: usdRandomExchangeRate}, {Denom: core.MicroKRWDenom, Amount: krwRandomExchangeRate}}, 1) // Account 3, KRW, SDR makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroKRWDenom, Amount: krwRandomExchangeRate}, {Denom: core.MicroSDRDenom, Amount: randomExchangeRate}}, 2) @@ -364,6 +365,34 @@ func TestOracleExchangeRate(t *testing.T) { require.Equal(t, expectedRewardAmt2, rewards.Rewards.AmountOf(core.MicroLunaDenom).TruncateInt()) } +func TestOracleEnsureSorted(t *testing.T) { + input, h := setup(t) + + for i := 0; i < 100; i++ { + krwExchangeRate1 := sdk.NewDecWithPrec(int64(rand.Uint64()%100000000), 6).MulInt64(core.MicroUnit) + usdExchangeRate1 := sdk.NewDecWithPrec(int64(rand.Uint64()%100000000), 6).MulInt64(core.MicroUnit) + + krwExchangeRate2 := sdk.NewDecWithPrec(int64(rand.Uint64()%100000000), 6).MulInt64(core.MicroUnit) + usdExchangeRate2 := sdk.NewDecWithPrec(int64(rand.Uint64()%100000000), 6).MulInt64(core.MicroUnit) + + krwExchangeRate3 := sdk.NewDecWithPrec(int64(rand.Uint64()%100000000), 6).MulInt64(core.MicroUnit) + usdExchangeRate3 := sdk.NewDecWithPrec(int64(rand.Uint64()%100000000), 6).MulInt64(core.MicroUnit) + + // Account 1, USD, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroUSDDenom, Amount: usdExchangeRate1}, {Denom: core.MicroKRWDenom, Amount: krwExchangeRate1}}, 0) + + // Account 2, USD, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroUSDDenom, Amount: usdExchangeRate2}, {Denom: core.MicroKRWDenom, Amount: krwExchangeRate2}}, 1) + + // Account 3, USD, KRW + makeAggregatePrevoteAndVote(t, input, h, 0, sdk.DecCoins{{Denom: core.MicroUSDDenom, Amount: krwExchangeRate3}, {Denom: core.MicroKRWDenom, Amount: usdExchangeRate3}}, 2) + + require.NotPanics(t, func() { + oracle.EndBlocker(input.Ctx.WithBlockHeight(1), input.OracleKeeper) + }) + } +} + func TestOracleExchangeRateVal5(t *testing.T) { input, h := setupVal5(t) diff --git a/x/oracle/types/ballot.go b/x/oracle/types/ballot.go index 313d3451..f65cfbb8 100644 --- a/x/oracle/types/ballot.go +++ b/x/oracle/types/ballot.go @@ -3,6 +3,7 @@ package types import ( "fmt" "math" + "sort" "strconv" sdk "github.com/cosmos/cosmos-sdk/types" @@ -60,6 +61,7 @@ func (pb ExchangeRateBallot) ToCrossRate(bases map[string]sdk.Dec) (cb ExchangeR cb = append(cb, vote) } + sort.Sort(cb) return } @@ -76,6 +78,10 @@ func (pb ExchangeRateBallot) Power() int64 { // WeightedMedian returns the median weighted by the power of the ExchangeRateVote. // CONTRACT: ballot must be sorted func (pb ExchangeRateBallot) WeightedMedian() sdk.Dec { + if !sort.IsSorted(pb) { + panic("ballot must be sorted") + } + totalPower := pb.Power() if pb.Len() > 0 { pivot := int64(0) diff --git a/x/oracle/types/ballot_test.go b/x/oracle/types/ballot_test.go index 1f2c74a0..bea8cdad 100644 --- a/x/oracle/types/ballot_test.go +++ b/x/oracle/types/ballot_test.go @@ -3,6 +3,7 @@ package types import ( "fmt" "math" + "sort" "strconv" "testing" @@ -103,6 +104,8 @@ func TestToCrossRate(t *testing.T) { } } + sort.Sort(cb) + baseMapBallot := pbBase.ToMap() require.Equal(t, cb, pbQuote.ToCrossRate(baseMapBallot)) }