Skip to content

Commit

Permalink
Bugfix/oracle rewards distribution (#573)
Browse files Browse the repository at this point in the history
* distribute non-LUNA oracle rewards

* update docker files

* remove unused param key
  • Loading branch information
yys authored Oct 9, 2021
1 parent 6e903ef commit 5bca395
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 12 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ WORKDIR /code
COPY . /code/

# See https://github.com/CosmWasm/wasmvm/releases
ADD https://github.com/CosmWasm/wasmvm/releases/download/v0.16.0/libwasmvm_muslc.a /lib/libwasmvm_muslc.a
RUN sha256sum /lib/libwasmvm_muslc.a | grep ef294a7a53c8d0aa6a8da4b10e94fb9f053f9decf160540d6c7594734bc35cd6
ADD https://github.com/CosmWasm/wasmvm/releases/download/v0.16.1/libwasmvm_muslc.a /lib/libwasmvm_muslc.a
RUN sha256sum /lib/libwasmvm_muslc.a | grep 0e62296b9f24cf3a05f8513f99cee536c7087079855ea6ffb4f89b35eccdaa66

# force it to use static lib (from above) not standard libgo_cosmwasm.so file
RUN LEDGER_ENABLED=false BUILD_TAGS=muslc make build
Expand Down
2 changes: 1 addition & 1 deletion shared.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.15-buster AS go-builder
FROM golang:1.16-buster AS go-builder

# Install minimum necessary dependencies, build Cosmos SDK, remove packages
RUN apt update
Expand Down
8 changes: 7 additions & 1 deletion x/oracle/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,13 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) {
}

// Distribute rewards to ballot winners
k.RewardBallotWinners(ctx, validatorClaimMap)
k.RewardBallotWinners(
ctx,
(int64)(params.VotePeriod),
(int64)(params.RewardDistributionWindow),
voteTargets,
validatorClaimMap,
)

// Clear the ballot
k.ClearBallots(ctx, params.VotePeriod)
Expand Down
8 changes: 7 additions & 1 deletion x/oracle/keeper/alias_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ func (k Keeper) GetOracleAccount(ctx sdk.Context) authtypes.ModuleAccountI {
}

// GetRewardPool retrieves the balance of the oracle module account
func (k Keeper) GetRewardPool(ctx sdk.Context) sdk.Coins {
func (k Keeper) GetRewardPool(ctx sdk.Context, denom string) sdk.Coin {
acc := k.accountKeeper.GetModuleAccount(ctx, types.ModuleName)
return k.bankKeeper.GetBalance(ctx, acc.GetAddress(), denom)
}

// GetRewardPool retrieves the balance of the oracle module account
func (k Keeper) GetRewardPoolLegacy(ctx sdk.Context) sdk.Coins {
acc := k.accountKeeper.GetModuleAccount(ctx, types.ModuleName)
return k.bankKeeper.GetAllBalances(ctx, acc.GetAddress())
}
4 changes: 2 additions & 2 deletions x/oracle/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ func TestRewardPool(t *testing.T) {
panic(err) // never occurs
}

KFees := input.OracleKeeper.GetRewardPool(input.Ctx)
require.Equal(t, fees, KFees)
KFees := input.OracleKeeper.GetRewardPool(input.Ctx, core.MicroSDRDenom)
require.Equal(t, fees[0], KFees)
}

func TestParams(t *testing.T) {
Expand Down
87 changes: 84 additions & 3 deletions x/oracle/keeper/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,88 @@ import (
// RewardBallotWinners implements
// at the end of every VotePeriod, we give out portion of seigniorage reward(reward-weight) to the
// oracle voters that voted faithfully.
func (k Keeper) RewardBallotWinners(ctx sdk.Context, ballotWinners map[string]types.Claim) {
func (k Keeper) RewardBallotWinners(
ctx sdk.Context,
votePeriod int64,
rewardDistributionWindow int64,
voteTargets map[string]sdk.Dec,
ballotWinners map[string]types.Claim,
) {
// softfork for reward distribution
if (ctx.ChainID() == "columbus-5" && ctx.BlockHeight() < int64(5_100_000)) ||
(ctx.ChainID() == "bombay-12" && ctx.BlockHeight() < int64(6_200_000)) {
k.RewardBallotWinnersLegacy(ctx, votePeriod, rewardDistributionWindow, ballotWinners)
return
}

rewardDenoms := make([]string, len(voteTargets)+1)
rewardDenoms[0] = core.MicroLunaDenom

i := 1
for denom := range voteTargets {
rewardDenoms[i] = denom
i++
}

// Sum weight of the claims
ballotPowerSum := int64(0)
for _, winner := range ballotWinners {
ballotPowerSum += winner.Weight
}

// Exit if the ballot is empty
if ballotPowerSum == 0 {
return
}

distributionRatio := sdk.NewDec(votePeriod).QuoInt64(rewardDistributionWindow)

var periodRewards sdk.DecCoins
for _, denom := range rewardDenoms {
rewardPool := k.GetRewardPool(ctx, denom)

// return if there's no rewards to give out
if rewardPool.IsZero() {
continue
}

periodRewards = periodRewards.Add(sdk.NewDecCoinFromDec(
denom,
sdk.NewDecFromInt(rewardPool.Amount).Mul(distributionRatio),
))
}

// Dole out rewards
var distributedReward sdk.Coins
for _, winner := range ballotWinners {
receiverVal := k.StakingKeeper.Validator(ctx, winner.Recipient)

// Reflects contribution
rewardCoins, _ := periodRewards.MulDec(sdk.NewDec(winner.Weight).QuoInt64(ballotPowerSum)).TruncateDecimal()

// In case absence of the validator, we just skip distribution
if receiverVal != nil && !rewardCoins.IsZero() {
k.distrKeeper.AllocateTokensToValidator(ctx, receiverVal, sdk.NewDecCoinsFromCoins(rewardCoins...))
distributedReward = distributedReward.Add(rewardCoins...)
}
}

// Move distributed reward to distribution module
err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.distrName, distributedReward)
if err != nil {
panic(fmt.Sprintf("[oracle] Failed to send coins to distribution module %s", err.Error()))
}

}

// RewardBallotWinnersLegacy implements
// at the end of every VotePeriod, we give out portion of seigniorage reward(reward-weight) to the
// oracle voters that voted faithfully.
func (k Keeper) RewardBallotWinnersLegacy(
ctx sdk.Context,
votePeriod int64,
rewardDistributionWindow int64,
ballotWinners map[string]types.Claim) {
// Sum weight of the claims
ballotPowerSum := int64(0)
for _, winner := range ballotWinners {
Expand All @@ -24,7 +105,7 @@ func (k Keeper) RewardBallotWinners(ctx sdk.Context, ballotWinners map[string]ty
return
}

rewardPool := k.GetRewardPool(ctx)
rewardPool := k.GetRewardPoolLegacy(ctx)

// return if there's no rewards to give out
if rewardPool.IsZero() {
Expand All @@ -33,7 +114,7 @@ func (k Keeper) RewardBallotWinners(ctx sdk.Context, ballotWinners map[string]ty

// rewardCoin = oraclePool * VotePeriod / RewardDistributionWindow
periodRewards := sdk.NewDecFromInt(rewardPool.AmountOf(core.MicroLunaDenom)).
MulInt64((int64)(k.VotePeriod(ctx))).QuoInt64((int64)(k.RewardDistributionWindow(ctx)))
MulInt64(votePeriod).QuoInt64(rewardDistributionWindow)

// Dole out rewards
var distributedReward sdk.Coins
Expand Down
14 changes: 12 additions & 2 deletions x/oracle/keeper/reward_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,32 @@ func TestRewardBallotWinners(t *testing.T) {
}

// Prepare reward pool
givingAmt := sdk.NewCoins(sdk.NewInt64Coin(core.MicroLunaDenom, 30000000))
givingAmt := sdk.NewCoins(sdk.NewInt64Coin(core.MicroLunaDenom, 30000000), sdk.NewInt64Coin(core.MicroUSDDenom, 40000000))
acc := input.AccountKeeper.GetModuleAccount(ctx, types.ModuleName)
err = FundAccount(input, acc.GetAddress(), givingAmt)
require.NoError(t, err)

voteTargets := make(map[string]sdk.Dec)
input.OracleKeeper.IterateTobinTaxes(ctx, func(denom string, tobinTax sdk.Dec) bool {
voteTargets[denom] = tobinTax
return false
})

votePeriodsPerWindow := sdk.NewDec((int64)(input.OracleKeeper.RewardDistributionWindow(input.Ctx))).
QuoInt64((int64)(input.OracleKeeper.VotePeriod(input.Ctx))).
TruncateInt64()
input.OracleKeeper.RewardBallotWinners(ctx, claims)
input.OracleKeeper.RewardBallotWinners(ctx, (int64)(input.OracleKeeper.VotePeriod(input.Ctx)), (int64)(input.OracleKeeper.RewardDistributionWindow(input.Ctx)), voteTargets, claims)
outstandingRewardsDec := input.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, addr)
outstandingRewards, _ := outstandingRewardsDec.TruncateDecimal()
require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroLunaDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).TruncateInt(),
outstandingRewards.AmountOf(core.MicroLunaDenom))
require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroUSDDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).TruncateInt(),
outstandingRewards.AmountOf(core.MicroUSDDenom))

outstandingRewardsDec1 := input.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, addr1)
outstandingRewards1, _ := outstandingRewardsDec1.TruncateDecimal()
require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroLunaDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).MulInt64(2).TruncateInt(),
outstandingRewards1.AmountOf(core.MicroLunaDenom))
require.Equal(t, sdk.NewDecFromInt(givingAmt.AmountOf(core.MicroUSDDenom)).QuoInt64(votePeriodsPerWindow).QuoInt64(3).MulInt64(2).TruncateInt(),
outstandingRewards1.AmountOf(core.MicroUSDDenom))
}

0 comments on commit 5bca395

Please sign in to comment.