Skip to content

Commit

Permalink
oracle: send probono oracle rewards to pool (#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
uhyunpark authored Jun 24, 2024
1 parent fa367b3 commit 7f65052
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 5 deletions.
13 changes: 11 additions & 2 deletions x/oracle/keeper/feeder.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ func (k Keeper) RewardBallotWinners(ctx sdk.Context, validatorClaimMap map[strin
logger.Debug("RewardBallotWinner", "rewards", rewards)

var distributedReward sdk.Coins
var probonoReward sdk.Coins

for addr, voter := range validatorClaimMap {
// skip if the validator abstained or missed the vote
Expand All @@ -311,6 +312,10 @@ func (k Keeper) RewardBallotWinners(ctx sdk.Context, validatorClaimMap map[strin
}

if !rewardCoins.IsZero() {
if receiverVal.Probono {
probonoReward = probonoReward.Add(rewardCoins...)
continue
}
k.DistributionKeeper.AllocateTokensToValidator(ctx, receiverVal, sdk.NewDecCoinsFromCoins(rewardCoins...))
distributedReward = distributedReward.Add(rewardCoins...)
} else {
Expand All @@ -322,8 +327,12 @@ func (k Keeper) RewardBallotWinners(ctx sdk.Context, validatorClaimMap map[strin
}
}

// Move distributed reward to distribution module
if err := k.BankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.distributionName, distributedReward); err != nil {
feePool := k.DistributionKeeper.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(probonoReward...)...)
k.DistributionKeeper.SetFeePool(ctx, feePool)

// Move both distributed reward and probono reward to distribution module
if err := k.BankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.distributionName, distributedReward.Add(probonoReward...)); err != nil {
return fmt.Errorf("failed to move distributed reward to distribution module: %w", err)
}

Expand Down
121 changes: 118 additions & 3 deletions x/oracle/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
Expand Down Expand Up @@ -49,9 +50,7 @@ type OracleTestSuite struct {
signer keyring.Signer
}

var (
s *OracleTestSuite
)
var s *OracleTestSuite

const (
DefaultBondAmount = 100000000000
Expand Down Expand Up @@ -449,6 +448,122 @@ func (suite *OracleTestSuite) TestKeeper_RewardBallotWinners() {
}
}

func (suite *OracleTestSuite) TestKeeper_RewardBallotWinners_WithProbono() {
tests := []struct {
name string
vcm map[string]types.Claim
totalCoin sdk.Coins
rewardMap map[string]sdk.DecCoins
probonoIndex []int
}{
{
name: "Probono validators send rewards to community pool, normal validators get rewards as usual",
vcm: map[string]types.Claim{
s.validators[0].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
s.validators[1].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
s.validators[2].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
s.validators[3].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
},
totalCoin: sdk.NewCoins(sdk.NewInt64Coin("asetl", 4000000)),
rewardMap: map[string]sdk.DecCoins{
s.validators[0].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
s.validators[1].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
s.validators[2].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
s.validators[3].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
},
probonoIndex: []int{0, 1},
},
{
name: "All probono validator, there's no normal validator",
vcm: map[string]types.Claim{
s.validators[0].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
s.validators[1].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
s.validators[2].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
s.validators[3].GetOperator().String(): {
Weight: 100,
Miss: false,
Abstain: false,
},
},
totalCoin: sdk.NewCoins(sdk.NewInt64Coin("asetl", 4000000)),
rewardMap: map[string]sdk.DecCoins{
s.validators[0].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
s.validators[1].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
s.validators[2].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
s.validators[3].GetOperator().String(): sdk.NewDecCoins(sdk.NewInt64DecCoin("asetl", 1000000)),
},
probonoIndex: []int{0, 1, 2, 3},
},
}

err := testutil.FundAccount(s.ctx, s.app.BankKeeper, s.address, sdk.NewCoins(sdk.NewInt64Coin("asetl", 10000000000)))
s.NoError(err)

for _, tt := range tests {
s.Run(tt.name, func() {
err = s.app.BankKeeper.SendCoinsFromAccountToModule(s.ctx, s.address, types.ModuleName, tt.totalCoin)
s.NoError(err)

s.app.DistrKeeper.SetFeePool(s.ctx, disttypes.InitialFeePool())
s.Equal(s.app.DistrKeeper.GetFeePoolCommunityCoins(s.ctx).AmountOf("asetl"), sdk.ZeroDec())

for _, idx := range tt.probonoIndex {
s.validators[idx].Probono = true
s.validators[idx] = stakingkeeper.TestingUpdateValidator(s.app.StakingKeeper, s.ctx, s.validators[idx], true)
}

probonoRewards := sdk.ZeroDec()

err = s.app.OracleKeeper.RewardBallotWinners(s.ctx, tt.vcm)
s.NoError(err)

for _, validator := range s.validators {
if validator.Probono {
probonoRewards = probonoRewards.Add(tt.rewardMap[validator.GetOperator().String()].AmountOf("asetl"))
validator.Probono = false
continue
}
rewards := s.app.DistrKeeper.GetValidatorCurrentRewards(s.ctx, validator.GetOperator())
s.Equal(tt.rewardMap[validator.GetOperator().String()].AmountOf("asetl"), rewards.Rewards.AmountOf("asetl"))
s.app.DistrKeeper.DeleteValidatorCurrentRewards(s.ctx, validator.GetOperator())
}

// check community pool
actualCommunityAmount := s.app.DistrKeeper.GetFeePoolCommunityCoins(s.ctx).AmountOf("asetl")
s.Equal(probonoRewards, actualCommunityAmount)
s.app.DistrKeeper.SetFeePool(s.ctx, disttypes.InitialFeePool())
})
}
}

func (suite *OracleTestSuite) TestKeeper_ClearBallots() {
tests := []struct {
name string
Expand Down
3 changes: 3 additions & 0 deletions x/oracle/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
ctypes "github.com/settlus/chain/types"
)

Expand Down Expand Up @@ -64,6 +65,8 @@ type DistributionKeeper interface {
// AllocateTokensToValidator allocate tokens to a particular validator,
// splitting according to commission.
AllocateTokensToValidator(ctx sdk.Context, val stakingtypes.ValidatorI, tokens sdk.DecCoins)
GetFeePool(ctx sdk.Context) (feePool disttypes.FeePool)
SetFeePool(ctx sdk.Context, feePool disttypes.FeePool)
}

type SettlementKeeper interface {
Expand Down

0 comments on commit 7f65052

Please sign in to comment.