bugfix form TestWithdrawDelegationRewardTwoDelegatorsUneven

This commit is contained in:
rigelrozanski 2018-10-12 05:37:30 -04:00
parent f3c0496c99
commit a60b91b7b2
3 changed files with 121 additions and 7 deletions

View File

@ -32,14 +32,12 @@ func (k Keeper) AllocateFees(ctx sdk.Context) {
proposerMultiplier := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul(
sumPowerPrecommitValidators).Quo(bondedTokens))
proposerReward := feesCollectedDec.MulDec(proposerMultiplier)
fmt.Printf("debug proposerReward: %v\n", proposerReward[0].Amount.String())
// apply commission
commission := proposerReward.MulDec(proposerValidator.GetCommission())
remaining := proposerReward.MulDec(sdk.OneDec().Sub(proposerValidator.GetCommission()))
proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission)
proposerDist.Pool = proposerDist.Pool.Plus(remaining)
fmt.Printf("debug proposerDist.Pool: %v\n", proposerDist.Pool[0].Amount.String())
// allocate community funding
communityTax := k.GetCommunityTax(ctx)
@ -50,7 +48,6 @@ func (k Keeper) AllocateFees(ctx sdk.Context) {
// set the global pool within the distribution module
poolReceived := feesCollectedDec.MulDec(sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax))
feePool.Pool = feePool.Pool.Plus(poolReceived)
fmt.Printf("debug poolReceived: %v\n", poolReceived[0].Amount.String())
k.SetValidatorDistInfo(ctx, proposerDist)
k.SetFeePool(ctx, feePool)

View File

@ -79,6 +79,7 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccA
k.SetFeePool(ctx, feePool)
k.SetValidatorDistInfo(ctx, valInfo)
k.SetDelegationDistInfo(ctx, delInfo)
withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr)
_, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal())
if err != nil {

View File

@ -42,8 +42,8 @@ func TestWithdrawDelegationRewardBasic(t *testing.T) {
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
expRes := sdk.NewDec(90).Add(sdk.NewDec(100).Quo(sdk.NewDec(2))) // 90 + 100 tokens * 10/20
require.True(sdk.DecEq(t, expRes, sdk.NewDecFromInt(amt)))
expRes := sdk.NewDec(90).Add(sdk.NewDec(100).Quo(sdk.NewDec(2))).TruncateInt() // 90 + 100 tokens * 10/20
require.True(sdk.IntEq(t, expRes, amt))
}
func TestWithdrawDelegationRewardWithCommission(t *testing.T) {
@ -81,12 +81,128 @@ func TestWithdrawDelegationRewardWithCommission(t *testing.T) {
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
expRes := sdk.NewDec(90).Add(sdk.NewDec(90).Quo(sdk.NewDec(2))) // 90 + 100*90% tokens * 10/20
require.True(sdk.DecEq(t, expRes, sdk.NewDecFromInt(amt)))
expRes := sdk.NewDec(90).Add(sdk.NewDec(90).Quo(sdk.NewDec(2))).TruncateInt() // 90 + 100*90% tokens * 10/20
require.True(sdk.IntEq(t, expRes, amt))
}
func TestWithdrawDelegationRewardTwoDelegators(t *testing.T) {
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
stakeHandler := stake.NewHandler(sk)
denom := sk.GetParams(ctx).BondDenom
//first make a validator with 10% commission
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
valOpAddr1, valConsPk1, 10, sdk.NewDecWithPrec(1, 1))
got := stakeHandler(ctx, msgCreateValidator)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
// delegate
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
got = stakeHandler(ctx, msgDelegate)
require.True(t, got.IsOK())
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
require.Equal(t, int64(90), amt.Int64())
msgDelegate = stake.NewTestMsgDelegate(delAddr2, valOpAddr1, 20)
got = stakeHandler(ctx, msgDelegate)
require.True(t, got.IsOK())
amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom)
require.Equal(t, int64(80), amt.Int64())
totalPower := int64(40)
totalPowerDec := sdk.NewDec(totalPower)
// allocate 100 denom of fees
feeInputs := sdk.NewInt(100)
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
keeper.SetProposerConsAddr(ctx, valConsAddr1)
keeper.SetSumPrecommitPower(ctx, totalPowerDec)
keeper.AllocateFees(ctx)
// delegator 1 withdraw delegation
ctx = ctx.WithBlockHeight(1)
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
expRes := sdk.NewDec(90).Add(sdk.NewDec(90).Quo(sdk.NewDec(4))).TruncateInt() // 90 + 100*90% tokens * 10/40
require.True(sdk.IntEq(t, expRes, amt))
}
// this test demonstrates how two delegators with the same power can end up
// with different rewards in the end
func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) {
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
stakeHandler := stake.NewHandler(sk)
denom := sk.GetParams(ctx).BondDenom
//first make a validator with no commission
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
valOpAddr1, valConsPk1, 10, sdk.ZeroDec())
got := stakeHandler(ctx, msgCreateValidator)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
// delegate
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
got = stakeHandler(ctx, msgDelegate)
require.True(t, got.IsOK())
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
require.Equal(t, int64(90), amt.Int64())
msgDelegate = stake.NewTestMsgDelegate(delAddr2, valOpAddr1, 10)
got = stakeHandler(ctx, msgDelegate)
require.True(t, got.IsOK())
amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom)
require.Equal(t, int64(90), amt.Int64())
totalPower := int64(30)
totalPowerDec := sdk.NewDec(totalPower)
// allocate 100 denom of fees
feeInputs := sdk.NewInt(90)
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
keeper.SetProposerConsAddr(ctx, valConsAddr1)
keeper.SetSumPrecommitPower(ctx, totalPowerDec)
keeper.AllocateFees(ctx)
ctx = ctx.WithBlockHeight(1)
// delegator 1 withdraw delegation early, delegator 2 just keeps it's accum
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
expRes1 := sdk.NewDec(90).Add(sdk.NewDec(90).Quo(sdk.NewDec(3))).TruncateInt() // 90 + 100 * 10/30
require.True(sdk.IntEq(t, expRes1, amt))
// allocate 200 denom of fees
feeInputs = sdk.NewInt(180)
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
keeper.SetProposerConsAddr(ctx, valConsAddr1)
keeper.SetSumPrecommitPower(ctx, totalPowerDec)
keeper.AllocateFees(ctx)
ctx = ctx.WithBlockHeight(2)
// delegator 2 now withdraws everything it's entitled to
keeper.WithdrawDelegationReward(ctx, delAddr2, valOpAddr1)
amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom)
// existingTokens + (100+200 * (10/(20+30))
withdrawnFromVal := sdk.NewDec(60 + 180).Mul(sdk.NewDec(2)).Quo(sdk.NewDec(5))
expRes2 := sdk.NewDec(90).Add(withdrawnFromVal).TruncateInt()
require.True(sdk.IntEq(t, expRes2, amt))
// finally delegator 1 withdraws the remainder of its reward
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
remainingInVal := sdk.NewDec(60 + 180).Sub(withdrawnFromVal)
expRes3 := sdk.NewDecFromInt(expRes1).Add(remainingInVal.Mul(sdk.NewDec(1)).Quo(sdk.NewDec(3))).TruncateInt()
require.True(sdk.IntEq(t, expRes3, amt))
// verify the final withdraw amounts are different
require.True(t, expRes2.GT(expRes3))
}
func TestWithdrawDelegationRewardsAll(t *testing.T) {