Skip to content

Commit 0c07186

Browse files
committed
feat(x/auth/vesting): change TrackDelegation and TrackUndelegation to return errors instead of panicking
- Update TrackDelegation and TrackUndelegation methods to return errors - Modify all vesting account implementations accordingly - Add proper error handling in bank keeper - Update tests to expect errors instead of panics Signed-off-by: Hwangjae Lee <[email protected]>
1 parent b6b58e4 commit 0c07186

File tree

5 files changed

+157
-97
lines changed

5 files changed

+157
-97
lines changed

x/auth/vesting/exported/exported.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ type VestingAccount interface {
2222
// delegating from a vesting account. It accepts the current block time, the
2323
// delegation amount and balance of all coins whose denomination exists in
2424
// the account's original vesting balance.
25-
TrackDelegation(blockTime time.Time, balance, amount sdk.Coins)
25+
// Returns an error if the delegation is invalid (e.g., non-positive amount or insufficient funds).
26+
TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) error
2627

2728
// TrackUndelegation performs internal vesting accounting necessary when a
2829
// vesting account performs an undelegation.
29-
TrackUndelegation(amount sdk.Coins)
30+
// Returns an error if the undelegation is invalid (e.g., non-positive amount).
31+
TrackUndelegation(amount sdk.Coins) error
3032

3133
GetVestedCoins(blockTime time.Time) sdk.Coins
3234
GetVestingCoins(blockTime time.Time) sdk.Coins

x/auth/vesting/types/vesting_account.go

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66
"time"
77

88
"cosmossdk.io/math"
9+
errorsmod "cosmossdk.io/errors"
910

1011
sdk "github.com/cosmos/cosmos-sdk/types"
12+
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
1113
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
1214
vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
1315
)
@@ -56,16 +58,18 @@ func (bva BaseVestingAccount) LockedCoinsFromVesting(vestingCoins sdk.Coins) sdk
5658
//
5759
// CONTRACT: The account's coins, delegation coins, vesting coins, and delegated
5860
// vesting coins must be sorted.
59-
func (bva *BaseVestingAccount) TrackDelegation(balance, vestingCoins, amount sdk.Coins) {
61+
func (bva *BaseVestingAccount) TrackDelegation(balance, vestingCoins, amount sdk.Coins) error {
6062
for _, coin := range amount {
6163
baseAmt := balance.AmountOf(coin.Denom)
6264
vestingAmt := vestingCoins.AmountOf(coin.Denom)
6365
delVestingAmt := bva.DelegatedVesting.AmountOf(coin.Denom)
6466

65-
// Panic if the delegation amount is zero or if the base coins does not
66-
// exceed the desired delegation amount.
67-
if coin.Amount.IsZero() || baseAmt.LT(coin.Amount) {
68-
panic("delegation attempt with zero coins or insufficient funds")
67+
// Return error if the delegation amount is non-positive or if the base balance is insufficient.
68+
if coin.Amount.IsZero() {
69+
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "delegation amount must be > 0")
70+
}
71+
if baseAmt.LT(coin.Amount) {
72+
return errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, "balance %s, requested %s", baseAmt, coin.Amount)
6973
}
7074

7175
// compute x and y per the specification, where:
@@ -84,6 +88,7 @@ func (bva *BaseVestingAccount) TrackDelegation(balance, vestingCoins, amount sdk
8488
bva.DelegatedFree = bva.DelegatedFree.Add(yCoin)
8589
}
8690
}
91+
return nil
8792
}
8893

8994
// TrackUndelegation tracks an undelegation amount by setting the necessary
@@ -96,11 +101,11 @@ func (bva *BaseVestingAccount) TrackDelegation(balance, vestingCoins, amount sdk
96101
// the undelegated tokens are non-integral.
97102
//
98103
// CONTRACT: The account's coins and undelegation coins must be sorted.
99-
func (bva *BaseVestingAccount) TrackUndelegation(amount sdk.Coins) {
104+
func (bva *BaseVestingAccount) TrackUndelegation(amount sdk.Coins) error {
100105
for _, coin := range amount {
101-
// panic if the undelegation amount is zero
106+
// Return error if the undelegation amount is zero
102107
if coin.Amount.IsZero() {
103-
panic("undelegation attempt with zero coins")
108+
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "undelegation amount must be > 0")
104109
}
105110
delegatedFree := bva.DelegatedFree.AmountOf(coin.Denom)
106111
delegatedVesting := bva.DelegatedVesting.AmountOf(coin.Denom)
@@ -121,6 +126,7 @@ func (bva *BaseVestingAccount) TrackUndelegation(amount sdk.Coins) {
121126
bva.DelegatedVesting = bva.DelegatedVesting.Sub(yCoin)
122127
}
123128
}
129+
return nil
124130
}
125131

126132
// GetOriginalVesting returns a vesting account's original vesting amount
@@ -235,8 +241,8 @@ func (cva ContinuousVestingAccount) LockedCoins(blockTime time.Time) sdk.Coins {
235241
// TrackDelegation tracks a desired delegation amount by setting the appropriate
236242
// values for the amount of delegated vesting, delegated free, and reducing the
237243
// overall amount of base coins.
238-
func (cva *ContinuousVestingAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) {
239-
cva.BaseVestingAccount.TrackDelegation(balance, cva.GetVestingCoins(blockTime), amount)
244+
func (cva *ContinuousVestingAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) error {
245+
return cva.BaseVestingAccount.TrackDelegation(balance, cva.GetVestingCoins(blockTime), amount)
240246
}
241247

242248
// GetStartTime returns the time when vesting starts for a continuous vesting
@@ -340,8 +346,8 @@ func (pva PeriodicVestingAccount) LockedCoins(blockTime time.Time) sdk.Coins {
340346
// TrackDelegation tracks a desired delegation amount by setting the appropriate
341347
// values for the amount of delegated vesting, delegated free, and reducing the
342348
// overall amount of base coins.
343-
func (pva *PeriodicVestingAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) {
344-
pva.BaseVestingAccount.TrackDelegation(balance, pva.GetVestingCoins(blockTime), amount)
349+
func (pva *PeriodicVestingAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) error {
350+
return pva.BaseVestingAccount.TrackDelegation(balance, pva.GetVestingCoins(blockTime), amount)
345351
}
346352

347353
// GetStartTime returns the time when vesting starts for a periodic vesting
@@ -439,8 +445,8 @@ func (dva DelayedVestingAccount) LockedCoins(blockTime time.Time) sdk.Coins {
439445
// TrackDelegation tracks a desired delegation amount by setting the appropriate
440446
// values for the amount of delegated vesting, delegated free, and reducing the
441447
// overall amount of base coins.
442-
func (dva *DelayedVestingAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) {
443-
dva.BaseVestingAccount.TrackDelegation(balance, dva.GetVestingCoins(blockTime), amount)
448+
func (dva *DelayedVestingAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) error {
449+
return dva.BaseVestingAccount.TrackDelegation(balance, dva.GetVestingCoins(blockTime), amount)
444450
}
445451

446452
// GetStartTime returns zero since a delayed vesting account has no start time.
@@ -495,8 +501,8 @@ func (plva PermanentLockedAccount) LockedCoins(_ time.Time) sdk.Coins {
495501
// TrackDelegation tracks a desired delegation amount by setting the appropriate
496502
// values for the amount of delegated vesting, delegated free, and reducing the
497503
// overall amount of base coins.
498-
func (plva *PermanentLockedAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) {
499-
plva.BaseVestingAccount.TrackDelegation(balance, plva.OriginalVesting, amount)
504+
func (plva *PermanentLockedAccount) TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) error {
505+
return plva.BaseVestingAccount.TrackDelegation(balance, plva.OriginalVesting, amount)
500506
}
501507

502508
// GetStartTime returns zero since a permanent locked vesting account has no start time.

0 commit comments

Comments
 (0)