github.com/Finschia/finschia-sdk@v0.48.1/x/distribution/keeper/allocation_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  	abci "github.com/tendermint/tendermint/abci/types"
     8  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
     9  
    10  	"github.com/Finschia/finschia-sdk/simapp"
    11  	sdk "github.com/Finschia/finschia-sdk/types"
    12  	"github.com/Finschia/finschia-sdk/x/auth/types"
    13  	"github.com/Finschia/finschia-sdk/x/staking/teststaking"
    14  	stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types"
    15  )
    16  
    17  func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
    18  	app := simapp.Setup(false)
    19  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
    20  
    21  	addrs := simapp.AddTestAddrs(app, ctx, 3, sdk.NewInt(1234))
    22  	valAddrs := simapp.ConvertAddrsToValAddrs(addrs)
    23  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
    24  
    25  	// create validator with 50% commission
    26  	tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
    27  	tstaking.CreateValidator(sdk.ValAddress(addrs[0]), valConsPk1, sdk.NewInt(100), true)
    28  	val := app.StakingKeeper.Validator(ctx, valAddrs[0])
    29  
    30  	// allocate tokens
    31  	tokens := sdk.DecCoins{
    32  		{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(10)},
    33  	}
    34  	app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
    35  
    36  	// check commission
    37  	expected := sdk.DecCoins{
    38  		{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(5)},
    39  	}
    40  	require.Equal(t, expected, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, val.GetOperator()).Commission)
    41  
    42  	// check current rewards
    43  	require.Equal(t, expected, app.DistrKeeper.GetValidatorCurrentRewards(ctx, val.GetOperator()).Rewards)
    44  }
    45  
    46  func TestAllocateTokensToManyValidators(t *testing.T) {
    47  	app := simapp.Setup(false)
    48  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
    49  
    50  	addrs := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1234))
    51  	valAddrs := simapp.ConvertAddrsToValAddrs(addrs)
    52  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
    53  
    54  	// create validator with 50% commission
    55  	tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
    56  	tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true)
    57  
    58  	// create second validator with 0% commission
    59  	tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0))
    60  	tstaking.CreateValidator(valAddrs[1], valConsPk2, sdk.NewInt(100), true)
    61  
    62  	abciValA := abci.Validator{
    63  		Address: valConsPk1.Address(),
    64  		Power:   100,
    65  	}
    66  	abciValB := abci.Validator{
    67  		Address: valConsPk2.Address(),
    68  		Power:   100,
    69  	}
    70  
    71  	// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
    72  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
    73  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
    74  	require.True(t, app.DistrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
    75  	require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
    76  	require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
    77  	require.True(t, app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
    78  	require.True(t, app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())
    79  
    80  	// allocate tokens as if both had voted and second was proposer
    81  	fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
    82  	feeCollector := app.AccountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
    83  	require.NotNil(t, feeCollector)
    84  
    85  	// fund fee collector
    86  	require.NoError(t, simapp.FundModuleAccount(app, ctx, feeCollector.GetName(), fees))
    87  
    88  	app.AccountKeeper.SetAccount(ctx, feeCollector)
    89  
    90  	votes := []abci.VoteInfo{
    91  		{
    92  			Validator:       abciValA,
    93  			SignedLastBlock: true,
    94  		},
    95  		{
    96  			Validator:       abciValB,
    97  			SignedLastBlock: true,
    98  		},
    99  	}
   100  	app.DistrKeeper.AllocateTokens(ctx, 200, 200, valConsAddr2, votes)
   101  
   102  	// 98 outstanding rewards (100 less 2 to community pool)
   103  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(465, 1)}}, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards)
   104  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(515, 1)}}, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards)
   105  	// 2 community pool coins
   106  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(2)}}, app.DistrKeeper.GetFeePool(ctx).CommunityPool)
   107  	// 50% commission for first proposer, (0.5 * 93%) * 100 / 2 = 23.25
   108  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2325, 2)}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
   109  	// zero commission for second proposer
   110  	require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
   111  	// just staking.proportional for first proposer less commission = (0.5 * 93%) * 100 / 2 = 23.25
   112  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2325, 2)}}, app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards)
   113  	// proposer reward + staking.proportional for second proposer = (5 % + 0.5 * (93%)) * 100 = 51.5
   114  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(515, 1)}}, app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards)
   115  }
   116  
   117  func TestAllocateTokensTruncation(t *testing.T) {
   118  	app := simapp.Setup(false)
   119  	ctx := app.BaseApp.NewContext(false, tmproto.Header{})
   120  
   121  	addrs := simapp.AddTestAddrs(app, ctx, 3, sdk.NewInt(1234))
   122  	valAddrs := simapp.ConvertAddrsToValAddrs(addrs)
   123  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   124  
   125  	// create validator with 10% commission
   126  	tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
   127  	tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(110), true)
   128  
   129  	// create second validator with 10% commission
   130  	tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
   131  	tstaking.CreateValidator(valAddrs[1], valConsPk2, sdk.NewInt(100), true)
   132  
   133  	// create third validator with 10% commission
   134  	tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
   135  	tstaking.CreateValidator(valAddrs[2], valConsPk3, sdk.NewInt(100), true)
   136  
   137  	abciValA := abci.Validator{
   138  		Address: valConsPk1.Address(),
   139  		Power:   11,
   140  	}
   141  	abciValB := abci.Validator{
   142  		Address: valConsPk2.Address(),
   143  		Power:   10,
   144  	}
   145  	abciValС := abci.Validator{
   146  		Address: valConsPk3.Address(),
   147  		Power:   10,
   148  	}
   149  
   150  	// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
   151  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
   152  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
   153  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
   154  	require.True(t, app.DistrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
   155  	require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
   156  	require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
   157  	require.True(t, app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
   158  	require.True(t, app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())
   159  
   160  	// allocate tokens as if both had voted and second was proposer
   161  	fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(634195840)))
   162  
   163  	feeCollector := app.AccountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
   164  	require.NotNil(t, feeCollector)
   165  
   166  	require.NoError(t, simapp.FundModuleAccount(app, ctx, feeCollector.GetName(), fees))
   167  
   168  	app.AccountKeeper.SetAccount(ctx, feeCollector)
   169  
   170  	votes := []abci.VoteInfo{
   171  		{
   172  			Validator:       abciValA,
   173  			SignedLastBlock: true,
   174  		},
   175  		{
   176  			Validator:       abciValB,
   177  			SignedLastBlock: true,
   178  		},
   179  		{
   180  			Validator:       abciValС,
   181  			SignedLastBlock: true,
   182  		},
   183  	}
   184  	app.DistrKeeper.AllocateTokens(ctx, 31, 31, sdk.ConsAddress(valConsPk2.Address()), votes)
   185  
   186  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsValid())
   187  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsValid())
   188  	require.True(t, app.DistrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[2]).Rewards.IsValid())
   189  }