Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/distribution commission #217

Merged
merged 5 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 103 additions & 42 deletions x/distribution/keeper/allocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@ func TestLoadRewardWeights(t *testing.T) {
func TestLoadBondedTokens(t *testing.T) {
ctx, input := createDefaultTestInput(t)

input.StakingKeeper.SetBondDenoms(ctx, []string{"foo", "bar"})

// update reward weights
// update reward weights
input.StakingKeeper.SetBondDenoms(ctx, []string{"foo", "bar", "aaa"})
setRewardWeights(t, ctx, input, []customtypes.RewardWeight{
{
Denom: "foo",
Expand All @@ -75,14 +72,20 @@ func TestLoadBondedTokens(t *testing.T) {
Denom: "bar",
Weight: math.LegacyNewDecWithPrec(6, 1),
},
{
Denom: "aaa",
Weight: math.LegacyNewDecWithPrec(1, 0),
},
})

input.VotingPowerKeeper.SetVotingPowerWeights(sdk.NewDecCoins(sdk.NewDecCoin("foo", math.NewInt(1)), sdk.NewDecCoin("bar", math.NewInt(4)), sdk.NewDecCoin("aaa", math.NewInt(10))))

valAddr1 := createValidatorWithCoin(ctx, input,
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 3_000_000), sdk.NewInt64Coin("bar", 5_000_000)), 1)
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000), sdk.NewInt64Coin("aaa", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 3_000_000), sdk.NewInt64Coin("bar", 1_000_000), sdk.NewInt64Coin("aaa", 20_000)), 1)
valAddr2 := createValidatorWithCoin(ctx, input,
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 5_000_000), sdk.NewInt64Coin("bar", 3_000_000)), 2)
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000), sdk.NewInt64Coin("aaa", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 6_000_000), sdk.NewInt64Coin("bar", 4_000_000), sdk.NewInt64Coin("aaa", 10_000)), 2)

validator1, err := input.StakingKeeper.Validator(ctx, valAddr1)
require.NoError(t, err)
Expand All @@ -100,7 +103,7 @@ func TestLoadBondedTokens(t *testing.T) {
}
abciValB := abci.Validator{
Address: valConsPk2.Address(),
Power: 100,
Power: 400,
}

votes := []abci.VoteInfo{
Expand All @@ -123,47 +126,75 @@ func TestLoadBondedTokens(t *testing.T) {
if val.ValAddr == validator1.GetOperator() {
require.Equal(t, math.NewInt(3_000_000), val.Amount)
} else {
require.Equal(t, math.NewInt(5_000_000), val.Amount)
require.Equal(t, math.NewInt(6_000_000), val.Amount)
}
}

for _, val := range bondedTokens["bar"] {
if val.ValAddr == validator2.GetOperator() {
require.Equal(t, math.NewInt(3_000_000), val.Amount)
if val.ValAddr == validator1.GetOperator() {
require.Equal(t, math.NewInt(1_000_000), val.Amount)
} else {
require.Equal(t, math.NewInt(5_000_000), val.Amount)
require.Equal(t, math.NewInt(4_000_000), val.Amount)
}
}
require.Equal(t, math.NewInt(8_000_000), bondedTokensSum["foo"])
require.Equal(t, math.NewInt(8_000_000), bondedTokensSum["bar"])

for _, val := range bondedTokens["aaa"] {
if val.ValAddr == validator1.GetOperator() {
require.Equal(t, math.NewInt(20_000), val.Amount)
} else {
require.Equal(t, math.NewInt(10_000), val.Amount)
}
}
require.Equal(t, math.NewInt(9_000_000), bondedTokensSum["foo"])
require.Equal(t, math.NewInt(5_000_000), bondedTokensSum["bar"])
require.Equal(t, math.NewInt(30_000), bondedTokensSum["aaa"])
}

func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
ctx, input := createDefaultTestInput(t)

valAddr := createValidatorWithBalance(ctx, input, 100_000_000, 1_000_000, 1)
input.StakingKeeper.SetBondDenoms(ctx, []string{"foo", "bar"})

// update reward weights
// update reward weights
setRewardWeights(t, ctx, input, []customtypes.RewardWeight{
{
Denom: "foo",
Weight: math.LegacyNewDecWithPrec(4, 1),
},
{
Denom: "bar",
Weight: math.LegacyNewDecWithPrec(6, 1),
},
})
input.VotingPowerKeeper.SetVotingPowerWeights(sdk.NewDecCoins(sdk.NewDecCoin("foo", math.NewInt(1)), sdk.NewDecCoin("bar", math.NewInt(4)), sdk.NewDecCoin("aaa", math.NewInt(10))))

valAddr := createValidatorWithCoin(ctx, input,
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 3_000_000), sdk.NewInt64Coin("bar", 5_000_000)), 1)

validator, err := input.StakingKeeper.Validator(ctx, valAddr)
require.NoError(t, err)

tokens := sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDec(10)}}
input.DistKeeper.AllocateTokensToValidatorPool(ctx, validator, bondDenom, tokens)
expected := customtypes.DecPools{{Denom: bondDenom, DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDec(5)}}}}
tokens := sdk.DecCoins{{Denom: "reward1", Amount: math.LegacyNewDec(10)}, {Denom: "reward2", Amount: math.LegacyNewDec(20)}}
input.DistKeeper.AllocateTokensToValidatorPool(ctx, validator, "bar", tokens)
expectedCommission := customtypes.DecPools{{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: "reward1", Amount: math.LegacyNewDec(1)}, {Denom: "reward2", Amount: math.LegacyNewDec(2)}}}}
expectedRewards := customtypes.DecPools{{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: "reward1", Amount: math.LegacyNewDec(9)}, {Denom: "reward2", Amount: math.LegacyNewDec(18)}}}}

// check commission
commission, err := input.DistKeeper.ValidatorAccumulatedCommissions.Get(ctx, valAddr)
require.NoError(t, err)
require.Equal(t, expected, commission.Commissions)
require.Equal(t, expectedCommission, commission.Commissions)
// check current rewards

currentRewards, err := input.DistKeeper.ValidatorCurrentRewards.Get(ctx, valAddr)
require.NoError(t, err)
require.Equal(t, expected, currentRewards.Rewards)
require.Equal(t, expectedRewards, currentRewards.Rewards)
}

func TestAllocateTokensToManyValidators(t *testing.T) {
ctx, input := createDefaultTestInput(t)
input.StakingKeeper.SetBondDenoms(ctx, []string{"foo", "bar"})
input.StakingKeeper.SetBondDenoms(ctx, []string{"foo", "bar", "aaa"})
setRewardWeights(t, ctx, input, []customtypes.RewardWeight{
{
Denom: "foo",
Expand All @@ -173,14 +204,20 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
Denom: "bar",
Weight: math.LegacyNewDecWithPrec(6, 1),
},
{
Denom: "aaa",
Weight: math.LegacyNewDecWithPrec(1, 0),
},
})

input.VotingPowerKeeper.SetVotingPowerWeights(sdk.NewDecCoins(sdk.NewDecCoin("foo", math.NewInt(1)), sdk.NewDecCoin("bar", math.NewInt(4)), sdk.NewDecCoin("aaa", math.NewInt(10))))

valAddr1 := createValidatorWithCoin(ctx, input,
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 3_000_000), sdk.NewInt64Coin("bar", 5_000_000)), 1)
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000), sdk.NewInt64Coin("aaa", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 2_000_000), sdk.NewInt64Coin("bar", 1_000_000), sdk.NewInt64Coin("aaa", 40_000)), 1)
valAddr2 := createValidatorWithCoin(ctx, input,
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 5_000_000), sdk.NewInt64Coin("bar", 3_000_000)), 2)
sdk.NewCoins(sdk.NewInt64Coin("foo", 100_000_000), sdk.NewInt64Coin("bar", 100_000_000), sdk.NewInt64Coin("aaa", 100_000_000)),
sdk.NewCoins(sdk.NewInt64Coin("foo", 2_000_000), sdk.NewInt64Coin("bar", 4_000_000), sdk.NewInt64Coin("aaa", 10_000)), 2)

validator1, err := input.StakingKeeper.Validator(ctx, valAddr1)
require.NoError(t, err)
Expand All @@ -198,7 +235,7 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
}
abciValB := abci.Validator{
Address: valConsPk2.Address(),
Power: 100,
Power: 400,
}

// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
Expand Down Expand Up @@ -247,63 +284,87 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
require.NotNil(t, feeCollector)
input.Faucet.Fund(ctx, authtypes.NewModuleAddress(authtypes.FeeCollectorName), fees...)

input.DistKeeper.AllocateTokens(ctx, 200, votes)
input.DistKeeper.AllocateTokens(ctx, 500, votes)

// 98 outstanding rewards (100 less 2 to community pool)
val1OutRewards, err = input.DistKeeper.ValidatorOutstandingRewards.Get(ctx, valAddr1)
require.NoError(t, err)
require.Equal(t,
customtypes.DecPools{
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(3675, 2)}}},
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(147, 1)}}},
// 98 * (40_000 / 50_000) * (10 / 20) = 39.2
{Denom: "aaa", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(392, 1)}}},
// 98 * (1_000_000 / 5_000_000) * (6 / 20) = 5.88
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(588, 2)}}},
// 98 * (2_000_000 / 4_000_000) * (4 / 20) = 9.8
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(98, 1)}}},
},
val1OutRewards.Rewards)
val2OutRewards, err = input.DistKeeper.ValidatorOutstandingRewards.Get(ctx, valAddr2)
require.NoError(t, err)
require.Equal(t,
customtypes.DecPools{
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(2205, 2)}}},
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(245, 1)}}},
// 98 * (10_000 / 50_000) * (10 / 20) = 9.8
{Denom: "aaa", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(98, 1)}}},
// 98 * (4_000_000 / 5_000_000) * (6 / 20) = 23.52
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(2352, 2)}}},
// 98 * (2_000_000 / 4_000_000) * (4 / 20) = 9.8
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(98, 1)}}},
},
val2OutRewards.Rewards)
// 2 community pool coins
feePool, err = input.DistKeeper.FeePool.Get(ctx)
require.NoError(t, err)
require.Equal(t, sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDec(2)}}, feePool.CommunityPool)

// 50% commission for first proposer, (0.5 * 98%) * 100 / 2 = 24.5
// 10% commission for first proposer,
val1Commission, err = input.DistKeeper.ValidatorAccumulatedCommissions.Get(ctx, valAddr1)
require.NoError(t, err)
require.Equal(t,
customtypes.DecPools{
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(18375, 3)}}},
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(735, 2)}}},
// 98 * (40_000 / 50_000) * (10 / 20) * (1 / 10) = 3.92
{Denom: "aaa", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(392, 2)}}},
// 98 * (1_000_000 / 5_000_000) * (6 / 20) * (1 / 10) = 0.588
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(588, 3)}}},
// 98 * (2_000_000 / 4_000_000) * (4 / 20) * (1 / 10) = 0.98
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(98, 2)}}},
},
val1Commission.Commissions)
val2Commission, err = input.DistKeeper.ValidatorAccumulatedCommissions.Get(ctx, valAddr2)
require.NoError(t, err)
require.Equal(t,
customtypes.DecPools{
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(11025, 3)}}},
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(1225, 2)}}},
// 98 * (10_000 / 50_000) * (10 / 20) * (1 / 10) = 0.98
{Denom: "aaa", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(98, 2)}}},
// 98 * (4_000_000 / 5_000_000) * (6 / 20) * (1 / 10) = 2.352
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(2352, 3)}}},
// 98 * (2_000_000 / 4_000_000) * (4 / 20) * (1 / 10) = 0.98
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(98, 2)}}},
},
val2Commission.Commissions)

// just staking.proportional for first proposer less commission = (0.5 * 98%) * 100 / 2 = 24.5
// just staking.proportional for first proposer less commission
val1CurRewards, err = input.DistKeeper.ValidatorCurrentRewards.Get(ctx, valAddr1)
require.NoError(t, err)
require.Equal(t,
customtypes.DecPools{
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(18375, 3)}}},
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(735, 2)}}},
// 98 * (40_000 / 50_000) * (10 / 20) * (9 / 10) = 35.28
{Denom: "aaa", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(3528, 2)}}},
// 98 * (1_000_000 / 5_000_000) * (6 / 20) * (9 / 10) = 5.292
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(5292, 3)}}},
// 98 * (2_000_000 / 4_000_000) * (4 / 20) * (9 / 10) = 8.82
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(882, 2)}}},
},
val1CurRewards.Rewards)
val2CurRewards, err = input.DistKeeper.ValidatorCurrentRewards.Get(ctx, valAddr2)
require.NoError(t, err)
require.Equal(t,
customtypes.DecPools{
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(11025, 3)}}},
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(1225, 2)}}},
// 98 * (10_000 / 50_000) * (10 / 20) * (9 / 10) = 8.82
{Denom: "aaa", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(882, 2)}}},
// 98 * (4_000_000 / 5_000_000) * (6 / 20) * (9 / 10) = 21.168
{Denom: "bar", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(21168, 3)}}},
// 98 * (2_000_000 / 4_000_000) * (4 / 20) * (9 / 10) = 8.82
{Denom: "foo", DecCoins: sdk.DecCoins{{Denom: bondDenom, Amount: math.LegacyNewDecWithPrec(882, 2)}}},
},
val2CurRewards.Rewards)
}
Expand Down
66 changes: 44 additions & 22 deletions x/distribution/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,17 @@ func (f *TestFaucet) NewFundedAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk.
}

type TestKeepers struct {
AccountKeeper authkeeper.AccountKeeper
StakingKeeper stakingkeeper.Keeper
DistKeeper distrkeeper.Keeper
BankKeeper bankkeeper.Keeper
GovKeeper govkeeper.Keeper
MoveKeeper movekeeper.Keeper
DexKeeper TestDexKeeper
EncodingConfig initiaappparams.EncodingConfig
Faucet *TestFaucet
MultiStore storetypes.CommitMultiStore
AccountKeeper authkeeper.AccountKeeper
StakingKeeper stakingkeeper.Keeper
DistKeeper distrkeeper.Keeper
BankKeeper bankkeeper.Keeper
GovKeeper govkeeper.Keeper
MoveKeeper movekeeper.Keeper
DexKeeper TestDexKeeper
VotingPowerKeeper *TestVotingPowerKeeper
EncodingConfig initiaappparams.EncodingConfig
Faucet *TestFaucet
MultiStore storetypes.CommitMultiStore
}

// createDefaultTestInput common settings for createTestInput
Expand Down Expand Up @@ -300,12 +301,14 @@ func _createTestInput(
)
require.NoError(t, bankKeeper.SetParams(ctx, banktypes.DefaultParams()))

votingPowerKeeper := NewTestVotingPowerKeeper()

stakingKeeper := stakingkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[stakingtypes.StoreKey]),
accountKeeper,
bankKeeper,
movekeeper.NewVotingPowerKeeper(moveKeeper),
votingPowerKeeper,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
vc, cc,
)
Expand Down Expand Up @@ -406,16 +409,17 @@ func _createTestInput(
cfg.SetAddressVerifier(initiaapp.VerifyAddressLen())

keepers := TestKeepers{
AccountKeeper: accountKeeper,
StakingKeeper: *stakingKeeper,
DistKeeper: *distKeeper,
MoveKeeper: *moveKeeper,
BankKeeper: bankKeeper,
GovKeeper: *govKeeper,
DexKeeper: dexKeeper,
EncodingConfig: encodingConfig,
Faucet: faucet,
MultiStore: ms,
AccountKeeper: accountKeeper,
StakingKeeper: *stakingKeeper,
DistKeeper: *distKeeper,
MoveKeeper: *moveKeeper,
BankKeeper: bankKeeper,
GovKeeper: *govKeeper,
DexKeeper: dexKeeper,
VotingPowerKeeper: votingPowerKeeper,
EncodingConfig: encodingConfig,
Faucet: faucet,
MultiStore: ms,
}
return ctx, keepers
}
Expand Down Expand Up @@ -512,7 +516,7 @@ func createValidatorWithCoin(

// newTestMsgCreateValidator test msg creator
func newTestMsgCreateValidator(address sdk.ValAddress, pubKey cryptotypes.PubKey, amt ...sdk.Coin) *stakingtypes.MsgCreateValidator {
commission := stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0))
commission := stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(1, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0))
msg, _ := stakingtypes.NewMsgCreateValidator(
address.String(), pubKey, amt,
stakingtypes.NewDescription("homeDir", "", "", "", ""), commission,
Expand Down Expand Up @@ -598,3 +602,21 @@ func (k TestDexKeeper) SwapToBase(ctx context.Context, addr sdk.AccAddress, quot
_, _, dummyAddr := keyPubAddr()
return bk.SendCoin(ctx, addr, dummyAddr, quoteCoin.Denom, quoteCoin.Amount)
}

type TestVotingPowerKeeper struct {
weights sdk.DecCoins
}

func NewTestVotingPowerKeeper() *TestVotingPowerKeeper {
return &TestVotingPowerKeeper{
weights: sdk.DecCoins{sdk.DecCoin{bondDenom, math.LegacyNewDec(1)}},
}
}

func (k *TestVotingPowerKeeper) SetVotingPowerWeights(weights sdk.DecCoins) {
k.weights = weights
}

func (k TestVotingPowerKeeper) GetVotingPowerWeights(_ context.Context, bondDenoms []string) (sdk.DecCoins, error) {
return k.weights, nil
}
Loading
Loading