Skip to content

Commit

Permalink
removed validator pointer from liquid staking accounting functions
Browse files Browse the repository at this point in the history
  • Loading branch information
sampocs committed Jul 31, 2023
1 parent 04843f4 commit 3024452
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 32 deletions.
16 changes: 8 additions & 8 deletions x/staking/keeper/liquid_stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,36 +138,36 @@ func (k Keeper) DecreaseTotalLiquidStakedTokens(ctx sdk.Context, amount sdk.Int)
// and the total liquid staked shares cannot exceed the validator bond cap
// 1) (TotalLiquidStakedTokens / TotalStakedTokens) <= ValidatorLiquidStakingCap
// 2) LiquidShares <= (ValidatorBondShares * ValidatorBondFactor)
func (k Keeper) SafelyIncreaseValidatorLiquidShares(ctx sdk.Context, validator *types.Validator, shares sdk.Dec) error {
func (k Keeper) SafelyIncreaseValidatorLiquidShares(ctx sdk.Context, validator types.Validator, shares sdk.Dec) error {
// Confirm the validator bond factor and validator liquid staking cap will not be exceeded
if k.CheckExceedsValidatorBondCap(ctx, *validator, shares) {
if k.CheckExceedsValidatorBondCap(ctx, validator, shares) {
return types.ErrInsufficientValidatorBondShares
}
if k.CheckExceedsValidatorLiquidStakingCap(ctx, *validator, shares) {
if k.CheckExceedsValidatorLiquidStakingCap(ctx, validator, shares) {
return types.ErrValidatorLiquidStakingCapExceeded
}

// Increment the validator's liquid shares
validator.LiquidShares = validator.LiquidShares.Add(shares)
k.SetValidator(ctx, *validator)
k.SetValidator(ctx, validator)

return nil
}

// DecreaseValidatorLiquidShares decrements the liquid shares on a validator
func (k Keeper) DecreaseValidatorLiquidShares(ctx sdk.Context, validator *types.Validator, shares sdk.Dec) error {
func (k Keeper) DecreaseValidatorLiquidShares(ctx sdk.Context, validator types.Validator, shares sdk.Dec) error {
if shares.GT(validator.LiquidShares) {
return types.ErrValidatorLiquidSharesUnderflow
}
validator.LiquidShares = validator.LiquidShares.Sub(shares)
k.SetValidator(ctx, *validator)
k.SetValidator(ctx, validator)
return nil
}

// SafelyDecreaseValidatorBond decrements the validator's self bond
// so long as it will not cause the current delegations to exceed the threshold
// set by validator bond factor
func (k Keeper) SafelyDecreaseValidatorBond(ctx sdk.Context, validator *types.Validator, shares sdk.Dec) error {
func (k Keeper) SafelyDecreaseValidatorBond(ctx sdk.Context, validator types.Validator, shares sdk.Dec) error {
// Check if the decreased self bond will cause the validator bond threshold to be exceeded
validatorBondFactor := k.ValidatorBondFactor(ctx)
validatorBondEnabled := !validatorBondFactor.Equal(types.ValidatorBondCapDisabled)
Expand All @@ -179,7 +179,7 @@ func (k Keeper) SafelyDecreaseValidatorBond(ctx sdk.Context, validator *types.Va

// Decrement the validator's self bond
validator.ValidatorBondShares = validator.ValidatorBondShares.Sub(shares)
k.SetValidator(ctx, *validator)
k.SetValidator(ctx, validator)

return nil
}
Expand Down
24 changes: 9 additions & 15 deletions x/staking/keeper/liquid_stake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -665,8 +665,7 @@ func TestSafelyIncreaseValidatorLiquidShares(t *testing.T) {

// Attempt to increase the validator liquid shares, it should throw an
// error that the validator bond cap was exceeded
validator := initialValidator
err := app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, &validator, firstIncreaseAmount)
err := app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, initialValidator, firstIncreaseAmount)
require.ErrorIs(t, err, types.ErrInsufficientValidatorBondShares)
checkValidatorLiquidShares(initialLiquidShares, "shares after low bond factor")

Expand All @@ -675,15 +674,13 @@ func TestSafelyIncreaseValidatorLiquidShares(t *testing.T) {
app.StakingKeeper.SetParams(ctx, params)

// Try the increase again and check that it succeeded
validator = initialValidator
expectedLiquidSharesAfterFirstStake := initialLiquidShares.Add(firstIncreaseAmount)
err = app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, &validator, firstIncreaseAmount)
err = app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, initialValidator, firstIncreaseAmount)
require.NoError(t, err)
checkValidatorLiquidShares(expectedLiquidSharesAfterFirstStake, "shares with cap loose bond cap")

// Attempt another increase, it should fail from the liquid staking cap
validator = initialValidator
err = app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, &validator, secondIncreaseAmount)
err = app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, initialValidator, secondIncreaseAmount)
require.ErrorIs(t, err, types.ErrValidatorLiquidStakingCapExceeded)
checkValidatorLiquidShares(expectedLiquidSharesAfterFirstStake, "shares after liquid staking cap hit")

Expand All @@ -692,9 +689,8 @@ func TestSafelyIncreaseValidatorLiquidShares(t *testing.T) {
app.StakingKeeper.SetParams(ctx, params)

// Finally confirm that the increase succeeded this time
validator = initialValidator
expectedLiquidSharesAfterSecondStake := initialLiquidShares.Add(secondIncreaseAmount)
err = app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, &validator, secondIncreaseAmount)
err = app.StakingKeeper.SafelyIncreaseValidatorLiquidShares(ctx, initialValidator, secondIncreaseAmount)
require.NoError(t, err, "no error expected after increasing liquid staking cap")
checkValidatorLiquidShares(expectedLiquidSharesAfterSecondStake, "shares after loose liquid stake cap")
}
Expand All @@ -718,15 +714,15 @@ func TestDecreaseValidatorLiquidShares(t *testing.T) {
app.StakingKeeper.SetValidator(ctx, initialValidator)

// Decrease the validator liquid shares, and confirm the new share amount has been updated
err := app.StakingKeeper.DecreaseValidatorLiquidShares(ctx, &initialValidator, decreaseAmount)
err := app.StakingKeeper.DecreaseValidatorLiquidShares(ctx, initialValidator, decreaseAmount)
require.NoError(t, err, "no error expected when decreasing validator liquid shares")

actualValidator, found := app.StakingKeeper.GetValidator(ctx, valAddress)
require.True(t, found)
require.Equal(t, initialLiquidShares.Sub(decreaseAmount), actualValidator.LiquidShares, "liquid shares")

// Attempt to decrease by a larger amount than it has, it should fail
err = app.StakingKeeper.DecreaseValidatorLiquidShares(ctx, &actualValidator, initialLiquidShares)
err = app.StakingKeeper.DecreaseValidatorLiquidShares(ctx, actualValidator, initialLiquidShares)
require.ErrorIs(t, err, types.ErrValidatorLiquidSharesUnderflow)
}

Expand Down Expand Up @@ -762,7 +758,7 @@ func TestSafelyDecreaseValidatorBond(t *testing.T) {
// from (100 * 10 = 1000) to (100 * 5 = 500)
// Since this is still above the initial liquid shares of 200, this will succeed
decreaseAmount, expectedBondShares := sdk.NewDec(5), sdk.NewDec(5)
err := app.StakingKeeper.SafelyDecreaseValidatorBond(ctx, &initialValidator, decreaseAmount)
err := app.StakingKeeper.SafelyDecreaseValidatorBond(ctx, initialValidator, decreaseAmount)
require.NoError(t, err)

actualValidator, found := app.StakingKeeper.GetValidator(ctx, valAddress)
Expand All @@ -773,17 +769,15 @@ func TestSafelyDecreaseValidatorBond(t *testing.T) {
// This time, the cap will be reduced to (factor * shares) = (100 * 1) = 100
// However, the liquid shares are currently 200, so this should fail
decreaseAmount, expectedBondShares = sdk.NewDec(4), sdk.NewDec(1)
validator := actualValidator
err = app.StakingKeeper.SafelyDecreaseValidatorBond(ctx, &validator, decreaseAmount)
err = app.StakingKeeper.SafelyDecreaseValidatorBond(ctx, actualValidator, decreaseAmount)
require.ErrorIs(t, err, types.ErrInsufficientValidatorBondShares)

// Finally, disable the cap and attempt to decrease again
// This time it should succeed
params.ValidatorBondFactor = types.ValidatorBondCapDisabled
app.StakingKeeper.SetParams(ctx, params)

validator = actualValidator
err = app.StakingKeeper.SafelyDecreaseValidatorBond(ctx, &validator, decreaseAmount)
err = app.StakingKeeper.SafelyDecreaseValidatorBond(ctx, actualValidator, decreaseAmount)
require.NoError(t, err)

actualValidator, found = app.StakingKeeper.GetValidator(ctx, valAddress)
Expand Down
70 changes: 61 additions & 9 deletions x/staking/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,15 @@ func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*typ
if err := k.SafelyIncreaseTotalLiquidStakedTokens(ctx, tokens, false); err != nil {
return nil, err
}
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, &validator, shares); err != nil {
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, validator, shares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of the validator variable
// since the validator's liquid shares were updated above
validator, found = k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

// NOTE: source funds are always unbonded
Expand Down Expand Up @@ -301,21 +307,37 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed

// if this is a validator self-bond, the new liquid delegation cannot fall below the self-bond * bond factor
if delegation.ValidatorBond {
if err := k.SafelyDecreaseValidatorBond(ctx, &srcValidator, srcShares); err != nil {
if err := k.SafelyDecreaseValidatorBond(ctx, srcValidator, srcShares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of the srcValidator variable
// since the validator bond shares were updated above
srcValidator, found = k.GetValidator(ctx, valSrcAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

// If this delegation from a liquid staker, the delegation on the new validator
// cannot exceed that validator's self-bond cap
// The liquid shares from the source validator should get moved to the destination validator
if k.DelegatorIsLiquidStaker(delegatorAddress) {
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, &dstValidator, dstShares); err != nil {
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, dstValidator, dstShares); err != nil {
return nil, err
}
if err := k.DecreaseValidatorLiquidShares(ctx, &srcValidator, srcShares); err != nil {
if err := k.DecreaseValidatorLiquidShares(ctx, srcValidator, srcShares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of each validator variable
// since the liquid shares were updated above
srcValidator, found = k.GetValidator(ctx, valSrcAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
dstValidator, found = k.GetValidator(ctx, valDstAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

bondDenom := k.BondDenom(ctx)
Expand Down Expand Up @@ -400,9 +422,15 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (

// if this is a validator self-bond, the new liquid delegation cannot fall below the self-bond * bond factor
if delegation.ValidatorBond {
if err := k.SafelyDecreaseValidatorBond(ctx, &validator, shares); err != nil {
if err := k.SafelyDecreaseValidatorBond(ctx, validator, shares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of the validator variable
// since the validator bond shares was updated above
validator, found = k.GetValidator(ctx, addr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

// if this delegation is from a liquid staking provider (identified if the delegator
Expand All @@ -411,9 +439,15 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
if err := k.DecreaseTotalLiquidStakedTokens(ctx, tokens); err != nil {
return nil, err
}
if err := k.DecreaseValidatorLiquidShares(ctx, &validator, shares); err != nil {
if err := k.DecreaseValidatorLiquidShares(ctx, validator, shares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of the validator variable
// since the liquid shares were updated above
validator, found = k.GetValidator(ctx, addr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

bondDenom := k.BondDenom(ctx)
Expand Down Expand Up @@ -521,9 +555,15 @@ func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.M
if err := k.SafelyIncreaseTotalLiquidStakedTokens(ctx, tokens, false); err != nil {
return nil, err
}
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, &validator, shares); err != nil {
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, validator, shares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of the validator variable
// since the validator's liquid shares were updated above
validator, found = k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

var (
Expand Down Expand Up @@ -678,9 +718,15 @@ func (k msgServer) TokenizeShares(goCtx context.Context, msg *types.MsgTokenizeS
if err := k.SafelyIncreaseTotalLiquidStakedTokens(ctx, msg.Amount.Amount, true); err != nil {
return nil, err
}
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, &validator, shares); err != nil {
if err := k.SafelyIncreaseValidatorLiquidShares(ctx, validator, shares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of the validator variable
// since the validator's liquid shares were updated above
validator, found = k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

recordID := k.GetLastTokenizeShareRecordID(ctx) + 1
Expand Down Expand Up @@ -820,9 +866,15 @@ func (k msgServer) RedeemTokensForShares(goCtx context.Context, msg *types.MsgRe
if err := k.DecreaseTotalLiquidStakedTokens(ctx, tokens); err != nil {
return nil, err
}
if err := k.DecreaseValidatorLiquidShares(ctx, &validator, shares); err != nil {
if err := k.DecreaseValidatorLiquidShares(ctx, validator, shares); err != nil {
return nil, err
}
// Note: this is required for downstream uses of the validator variable
// since the liquid shares were updated above
validator, found = k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
}

returnAmount, err := k.Unbond(ctx, record.GetModuleAddress(), valAddr, shares)
Expand Down

0 comments on commit 3024452

Please sign in to comment.