Update reward vesting length calculation (#624)

* use remaining length when sending coins to vesting account

* query claims that have corresponding claim periods

* cleanup comments

* remove debugging statements

* fix bug with inserting period in middle of vesting schedule

* apply review suggestion
This commit is contained in:
Kevin Davis 2020-08-26 20:34:55 -04:00 committed by GitHub
parent fca16da84a
commit c0006ca8eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 297 additions and 140 deletions

View File

@ -1,6 +1,8 @@
package keeper package keeper
import ( import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
@ -34,6 +36,7 @@ func (k Keeper) PayoutClaim(ctx sdk.Context, addr sdk.AccAddress, collateralType
types.EventTypeClaim, types.EventTypeClaim,
sdk.NewAttribute(types.AttributeKeyClaimedBy, addr.String()), sdk.NewAttribute(types.AttributeKeyClaimedBy, addr.String()),
sdk.NewAttribute(types.AttributeKeyClaimAmount, claim.Reward.String()), sdk.NewAttribute(types.AttributeKeyClaimAmount, claim.Reward.String()),
sdk.NewAttribute(types.AttributeKeyClaimPeriod, fmt.Sprintf("%d", claim.ClaimPeriodID)),
), ),
) )
return nil return nil
@ -141,16 +144,22 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
// Add the new vesting coins to OriginalVesting // Add the new vesting coins to OriginalVesting
vacc.OriginalVesting = vacc.OriginalVesting.Add(amt...) vacc.OriginalVesting = vacc.OriginalVesting.Add(amt...)
// update vesting periods // update vesting periods
// EndTime = 100
// BlockTime = 110
// length == 6
if vacc.EndTime < ctx.BlockTime().Unix() { if vacc.EndTime < ctx.BlockTime().Unix() {
// edge case one - the vesting account's end time is in the past (ie, all previous vesting periods have completed) // edge case one - the vesting account's end time is in the past (ie, all previous vesting periods have completed)
// append a new period to the vesting account, update the end time, update the account in the store and return // append a new period to the vesting account, update the end time, update the account in the store and return
newPeriodLength := (ctx.BlockTime().Unix() - vacc.EndTime) + length newPeriodLength := (ctx.BlockTime().Unix() - vacc.EndTime) + length // 110 - 100 + 6 = 16
newPeriod := types.NewPeriod(amt, newPeriodLength) newPeriod := types.NewPeriod(amt, newPeriodLength)
vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod) vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod)
vacc.EndTime = ctx.BlockTime().Unix() + length vacc.EndTime = ctx.BlockTime().Unix() + length
k.accountKeeper.SetAccount(ctx, vacc) k.accountKeeper.SetAccount(ctx, vacc)
return return
} }
// StartTime = 110
// BlockTime = 100
// length = 6
if vacc.StartTime > ctx.BlockTime().Unix() { if vacc.StartTime > ctx.BlockTime().Unix() {
// edge case two - the vesting account's start time is in the future (all periods have not started) // edge case two - the vesting account's start time is in the future (all periods have not started)
// update the start time to now and adjust the period lengths in place - a new period will be inserted in the next code block // update the start time to now and adjust the period lengths in place - a new period will be inserted in the next code block
@ -158,7 +167,7 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
for i, period := range vacc.VestingPeriods { for i, period := range vacc.VestingPeriods {
updatedPeriod := period updatedPeriod := period
if i == 0 { if i == 0 {
updatedPeriod = types.NewPeriod(period.Amount, (vacc.StartTime-ctx.BlockTime().Unix())+period.Length) updatedPeriod = types.NewPeriod(period.Amount, (vacc.StartTime-ctx.BlockTime().Unix())+period.Length) // 110 - 100 + 6 = 16
} }
updatedPeriods = append(updatedPeriods, updatedPeriod) updatedPeriods = append(updatedPeriods, updatedPeriod)
} }
@ -167,11 +176,12 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
} }
// logic for inserting a new vesting period into the existing vesting schedule // logic for inserting a new vesting period into the existing vesting schedule
totalPeriodLength := types.GetTotalVestingPeriodLength(vacc.VestingPeriods) remainingLength := vacc.EndTime - ctx.BlockTime().Unix()
elapsedTime := ctx.BlockTime().Unix() - vacc.StartTime
proposedEndTime := ctx.BlockTime().Unix() + length proposedEndTime := ctx.BlockTime().Unix() + length
if totalPeriodLength < length { if remainingLength < length {
// in the case that the proposed length is longer than the sum of all previous period lengths, create a new period with length equal to the difference between the proposed length and the previous total length // in the case that the proposed length is longer than the remaining length of all vesting periods, create a new period with length equal to the difference between the proposed length and the previous total length
newPeriodLength := length - totalPeriodLength newPeriodLength := length - remainingLength
newPeriod := types.NewPeriod(amt, newPeriodLength) newPeriod := types.NewPeriod(amt, newPeriodLength)
vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod) vacc.VestingPeriods = append(vacc.VestingPeriods, newPeriod)
// update the end time so that the sum of all period lengths equals endTime - startTime // update the end time so that the sum of all period lengths equals endTime - startTime
@ -184,6 +194,19 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
// Expected result: // Expected result:
// {[l: 1, a: 1], [l:2, a: 1], [l:2, a:x], [l:6, a:3], [l:5, a:3]} // {[l: 1, a: 1], [l:2, a: 1], [l:2, a:x], [l:6, a:3], [l:5, a:3]}
// StartTime = 100
// Periods = [5,5,5,5]
// EndTime = 120
// BlockTime = 101
// length = 2
// for period in Periods:
// iteration 1:
// lengthCounter = 5
// if 5 < 101 - 100 + 2 - no
// if 5 = 3 - no
// else
// newperiod = 2 - 0
newPeriods := vesting.Periods{} newPeriods := vesting.Periods{}
lengthCounter := int64(0) lengthCounter := int64(0)
appendRemaining := false appendRemaining := false
@ -193,14 +216,14 @@ func (k Keeper) addCoinsToVestingSchedule(ctx sdk.Context, addr sdk.AccAddress,
continue continue
} }
lengthCounter += period.Length lengthCounter += period.Length
if lengthCounter < length { if lengthCounter < elapsedTime+length { // 1
newPeriods = append(newPeriods, period) newPeriods = append(newPeriods, period)
} else if lengthCounter == length { } else if lengthCounter == elapsedTime+length {
newPeriod := types.NewPeriod(period.Amount.Add(amt...), period.Length) newPeriod := types.NewPeriod(period.Amount.Add(amt...), period.Length)
newPeriods = append(newPeriods, newPeriod) newPeriods = append(newPeriods, newPeriod)
appendRemaining = true appendRemaining = true
} else { } else {
newPeriod := types.NewPeriod(amt, length-types.GetTotalVestingPeriodLength(newPeriods)) newPeriod := types.NewPeriod(amt, elapsedTime+length-types.GetTotalVestingPeriodLength(newPeriods))
previousPeriod := types.NewPeriod(period.Amount, period.Length-newPeriod.Length) previousPeriod := types.NewPeriod(period.Amount, period.Length-newPeriod.Length)
newPeriods = append(newPeriods, newPeriod, previousPeriod) newPeriods = append(newPeriods, newPeriod, previousPeriod)
appendRemaining = true appendRemaining = true

View File

@ -2,6 +2,7 @@ package keeper_test
import ( import (
"errors" "errors"
"strings"
"time" "time"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -35,7 +36,7 @@ func (suite *KeeperTestSuite) setupChain() {
) )
supplyKeeper := tApp.GetSupplyKeeper() supplyKeeper := tApp.GetSupplyKeeper()
macc := supplyKeeper.GetModuleAccount(ctx, kavadist.ModuleName) macc := supplyKeeper.GetModuleAccount(ctx, kavadist.ModuleName)
err := supplyKeeper.MintCoins(ctx, macc.GetName(), cs(c("ukava", 500))) err := supplyKeeper.MintCoins(ctx, macc.GetName(), cs(c("ukava", 600)))
suite.Require().NoError(err) suite.Require().NoError(err)
// sets addrs[0] to be a periodic vesting account // sets addrs[0] to be a periodic vesting account
@ -99,157 +100,290 @@ func (suite *KeeperTestSuite) setupExpiredClaims() {
suite.addrs = addrs suite.addrs = addrs
} }
func (suite *KeeperTestSuite) TestSendCoinsToPeriodicVestingAccount() { func createPeriodicVestingAccount(origVesting sdk.Coins, periods vesting.Periods, startTime, endTime int64) (*vesting.PeriodicVestingAccount, error) {
suite.setupChain() _, addr := app.GeneratePrivKeyAddressPairs(1)
bacc := auth.NewBaseAccountWithAddress(addr[0])
type args struct { bacc.Coins = origVesting
coins sdk.Coins bva, err := vesting.NewBaseVestingAccount(&bacc, origVesting, endTime)
length int64 if err != nil {
return &vesting.PeriodicVestingAccount{}, err
} }
pva := vesting.NewPeriodicVestingAccountRaw(bva, startTime, periods)
err = pva.Validate()
if err != nil {
return &vesting.PeriodicVestingAccount{}, err
}
return pva, nil
}
func (suite *KeeperTestSuite) TestSendCoinsToPeriodicVestingAccount() {
type accountArgs struct {
periods vesting.Periods
origVestingCoins sdk.Coins
startTime int64
endTime int64
}
type args struct {
accArgs accountArgs
period vesting.Period
ctxTime time.Time
mintModAccountCoins bool
expectedPeriods vesting.Periods
expectedStartTime int64
expectedEndTime int64
}
type errArgs struct { type errArgs struct {
expectErr bool expectErr bool
errType error contains string
} }
type testCase struct {
type vestingAccountTest struct { name string
name string args args
blockTime time.Time errArgs errArgs
args args
errArgs errArgs
expectedPeriods vesting.Periods
expectedOriginalVesting sdk.Coins
expectedCoins sdk.Coins
expectedStartTime int64
expectedEndTime int64
} }
type testCases []testCase
type vestingAccountTests []vestingAccountTest tests := testCases{
{
testCases := vestingAccountTests{ name: "insert period at beginning schedule",
vestingAccountTest{ args: args{
name: "insert period into an existing vesting schedule", accArgs: accountArgs{
blockTime: time.Unix(100, 0), periods: vesting.Periods{
args: args{coins: cs(c("ukava", 100)), length: 5}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
errArgs: errArgs{expectErr: false, errType: nil}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
expectedPeriods: vesting.Periods{ vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, origVestingCoins: cs(c("ukava", 20)),
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, startTime: 100,
vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))}, endTime: 120,
vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))}, },
period: vesting.Period{Length: 2, Amount: cs(c("ukava", 6))},
ctxTime: time.Unix(101, 0),
mintModAccountCoins: true,
expectedPeriods: vesting.Periods{
vesting.Period{Length: 3, Amount: cs(c("ukava", 6))},
vesting.Period{Length: 2, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
expectedStartTime: 100,
expectedEndTime: 120,
}, },
expectedOriginalVesting: cs(c("ukava", 500)), errArgs: errArgs{
expectedCoins: cs(c("ukava", 500)), expectErr: false,
expectedStartTime: int64(100), contains: "",
expectedEndTime: int64(116),
},
vestingAccountTest{
name: "append period to the end of an existing vesting schedule",
blockTime: time.Unix(100, 0),
args: args{coins: cs(c("ukava", 100)), length: 17},
errArgs: errArgs{expectErr: false, errType: nil},
expectedPeriods: vesting.Periods{
vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
}, },
expectedOriginalVesting: cs(c("ukava", 600)),
expectedCoins: cs(c("ukava", 600)),
expectedStartTime: int64(100),
expectedEndTime: int64(117),
}, },
vestingAccountTest{ {
name: "append period to the end of a completed vesting schedule", name: "insert period at beginning with new start time",
blockTime: time.Unix(120, 0), args: args{
args: args{coins: cs(c("ukava", 100)), length: 5}, accArgs: accountArgs{
errArgs: errArgs{expectErr: false, errType: nil}, periods: vesting.Periods{
expectedPeriods: vesting.Periods{ vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))}, origVestingCoins: cs(c("ukava", 20)),
vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))}, startTime: 100,
vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))}, endTime: 120,
vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))}, },
period: vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
ctxTime: time.Unix(80, 0),
mintModAccountCoins: true,
expectedPeriods: vesting.Periods{
vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
vesting.Period{Length: 18, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
expectedStartTime: 80,
expectedEndTime: 120,
}, },
expectedOriginalVesting: cs(c("ukava", 700)), errArgs: errArgs{
expectedCoins: cs(c("ukava", 700)), expectErr: false,
expectedStartTime: int64(100), contains: "",
expectedEndTime: int64(125),
},
vestingAccountTest{
name: "prepend period to to an upcoming vesting schedule",
blockTime: time.Unix(90, 0),
args: args{coins: cs(c("ukava", 100)), length: 5},
errArgs: errArgs{expectErr: false, errType: nil},
expectedPeriods: vesting.Periods{
vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))},
vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))},
}, },
expectedOriginalVesting: cs(c("ukava", 800)),
expectedCoins: cs(c("ukava", 800)),
expectedStartTime: int64(90),
expectedEndTime: int64(125),
}, },
vestingAccountTest{ {
name: "add period that coincides with an existing end time", name: "insert period in middle of schedule",
blockTime: time.Unix(90, 0), args: args{
args: args{coins: cs(c("ukava", 100)), length: 11}, accArgs: accountArgs{
errArgs: errArgs{expectErr: false, errType: nil}, periods: vesting.Periods{
expectedPeriods: vesting.Periods{ vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: int64(6), Amount: cs(c("ukava", 200))}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, origVestingCoins: cs(c("ukava", 20)),
vesting.Period{Length: int64(6), Amount: cs(c("ukava", 100))}, startTime: 100,
vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))}, endTime: 120,
vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))}, },
vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))}, period: vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
ctxTime: time.Unix(101, 0),
mintModAccountCoins: true,
expectedPeriods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 3, Amount: cs(c("ukava", 6))},
vesting.Period{Length: 2, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
expectedStartTime: 100,
expectedEndTime: 120,
},
errArgs: errArgs{
expectErr: false,
contains: "",
}, },
expectedOriginalVesting: cs(c("ukava", 900)),
expectedCoins: cs(c("ukava", 900)),
expectedStartTime: int64(90),
expectedEndTime: int64(125),
}, },
vestingAccountTest{ {
name: "insufficient module account balance", name: "append to end of schedule",
blockTime: time.Unix(90, 0), args: args{
args: args{coins: cs(c("ukava", 1000)), length: 11}, accArgs: accountArgs{
errArgs: errArgs{expectErr: true, errType: types.ErrInsufficientModAccountBalance}, periods: vesting.Periods{
expectedPeriods: vesting.Periods{}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
expectedOriginalVesting: sdk.Coins{}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
expectedCoins: sdk.Coins{}, vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
expectedStartTime: int64(0), vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
expectedEndTime: int64(0), origVestingCoins: cs(c("ukava", 20)),
startTime: 100,
endTime: 120,
},
period: vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
ctxTime: time.Unix(125, 0),
mintModAccountCoins: true,
expectedPeriods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 12, Amount: cs(c("ukava", 6))}},
expectedStartTime: 100,
expectedEndTime: 132,
},
errArgs: errArgs{
expectErr: false,
contains: "",
},
},
{
name: "add coins to existing period",
args: args{
accArgs: accountArgs{
periods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
origVestingCoins: cs(c("ukava", 20)),
startTime: 100,
endTime: 120,
},
period: vesting.Period{Length: 5, Amount: cs(c("ukava", 6))},
ctxTime: time.Unix(110, 0),
mintModAccountCoins: true,
expectedPeriods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 11))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
expectedStartTime: 100,
expectedEndTime: 120,
},
errArgs: errArgs{
expectErr: false,
contains: "",
},
},
{
name: "insufficient mod account balance",
args: args{
accArgs: accountArgs{
periods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
origVestingCoins: cs(c("ukava", 20)),
startTime: 100,
endTime: 120,
},
period: vesting.Period{Length: 7, Amount: cs(c("ukava", 6))},
ctxTime: time.Unix(125, 0),
mintModAccountCoins: false,
expectedPeriods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 12, Amount: cs(c("ukava", 6))}},
expectedStartTime: 100,
expectedEndTime: 132,
},
errArgs: errArgs{
expectErr: true,
contains: "insufficient funds",
},
},
{
name: "add large period mid schedule",
args: args{
accArgs: accountArgs{
periods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))}},
origVestingCoins: cs(c("ukava", 20)),
startTime: 100,
endTime: 120,
},
period: vesting.Period{Length: 50, Amount: cs(c("ukava", 6))},
ctxTime: time.Unix(110, 0),
mintModAccountCoins: true,
expectedPeriods: vesting.Periods{
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 5, Amount: cs(c("ukava", 5))},
vesting.Period{Length: 40, Amount: cs(c("ukava", 6))}},
expectedStartTime: 100,
expectedEndTime: 160,
},
errArgs: errArgs{
expectErr: false,
contains: "",
},
}, },
} }
for _, tc := range tests {
for _, tc := range testCases {
suite.Run(tc.name, func() { suite.Run(tc.name, func() {
suite.ctx = suite.ctx.WithBlockTime(tc.blockTime) // create the periodic vesting account
err := suite.keeper.SendTimeLockedCoinsToAccount(suite.ctx, kavadist.ModuleName, suite.addrs[0], tc.args.coins, tc.args.length) pva, err := createPeriodicVestingAccount(tc.args.accArgs.origVestingCoins, tc.args.accArgs.periods, tc.args.accArgs.startTime, tc.args.accArgs.endTime)
suite.Require().NoError(err)
// setup store state with account and kavadist module account
suite.ctx = suite.ctx.WithBlockTime(tc.args.ctxTime)
ak := suite.app.GetAccountKeeper()
ak.SetAccount(suite.ctx, pva)
// mint module account coins if required
if tc.args.mintModAccountCoins {
sk := suite.app.GetSupplyKeeper()
err = sk.MintCoins(suite.ctx, kavadist.ModuleName, tc.args.period.Amount)
suite.Require().NoError(err)
}
err = suite.keeper.SendTimeLockedCoinsToPeriodicVestingAccount(suite.ctx, kavadist.ModuleName, pva.Address, tc.args.period.Amount, tc.args.period.Length)
if tc.errArgs.expectErr { if tc.errArgs.expectErr {
suite.Require().True(errors.Is(err, tc.errArgs.errType)) suite.Require().Error(err)
suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains))
} else { } else {
suite.Require().NoError(err) suite.Require().NoError(err)
acc := suite.getAccount(suite.addrs[0])
acc := suite.getAccount(pva.Address)
vacc, ok := acc.(*vesting.PeriodicVestingAccount) vacc, ok := acc.(*vesting.PeriodicVestingAccount)
suite.True(ok) suite.Require().True(ok)
suite.Equal(tc.expectedPeriods, vacc.VestingPeriods) suite.Require().Equal(tc.args.expectedPeriods, vacc.VestingPeriods)
suite.Equal(tc.expectedOriginalVesting, vacc.OriginalVesting) suite.Require().Equal(tc.args.expectedStartTime, vacc.StartTime)
suite.Equal(tc.expectedCoins, vacc.Coins) suite.Require().Equal(tc.args.expectedEndTime, vacc.EndTime)
suite.Equal(tc.expectedStartTime, vacc.StartTime)
suite.Equal(tc.expectedEndTime, vacc.EndTime)
} }
}) })
} }
@ -300,7 +434,7 @@ func (suite *KeeperTestSuite) TestPayoutClaim() {
suite.keeper.SetClaim(suite.ctx, c3) suite.keeper.SetClaim(suite.ctx, c3)
// existing claim with corresponding claim period successfully claimed by existing periodic vesting account // existing claim with corresponding claim period successfully claimed by existing periodic vesting account
err := suite.keeper.PayoutClaim(suite.ctx, suite.addrs[0], "bnb", 1) err := suite.keeper.PayoutClaim(suite.ctx.WithBlockTime(time.Unix(3700, 0)), suite.addrs[0], "bnb", 1)
suite.Require().NoError(err) suite.Require().NoError(err)
acc := suite.getAccount(suite.addrs[0]) acc := suite.getAccount(suite.addrs[0])
// account is a periodic vesting account // account is a periodic vesting account