Skip to content

Commit

Permalink
add completion time field to unbonding record, and populate on acknow…
Browse files Browse the repository at this point in the history
…ledgement; make RR logic ignore unbonding and escrowed tokens, add v1.7.0 upgrade handler (#1742)
  • Loading branch information
Joe Bowman authored Nov 13, 2024
1 parent 89e6e2b commit ae8f053
Show file tree
Hide file tree
Showing 13 changed files with 324 additions and 172 deletions.
2 changes: 2 additions & 0 deletions app/upgrades/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const (
V010602UpgradeName = "v1.6.2"
V010603UpgradeName = "v1.6.3"
V010604UpgradeName = "v1.6.4"

V010700UpgradeName = "v1.7.0"
)

// Upgrade defines a struct containing necessary fields that a SoftwareUpgradeProposal
Expand Down
1 change: 1 addition & 0 deletions app/upgrades/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func Upgrades() []Upgrade {
{UpgradeName: V010602UpgradeName, CreateUpgradeHandler: NoOpHandler},
{UpgradeName: V010603UpgradeName, CreateUpgradeHandler: V010603UpgradeHandler},
{UpgradeName: V010604UpgradeName, CreateUpgradeHandler: V010604UpgradeHandler},
{UpgradeName: V010700UpgradeName, CreateUpgradeHandler: V010700UpgradeHandler},
}
}

Expand Down
50 changes: 50 additions & 0 deletions app/upgrades/v1_7.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package upgrades

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

"github.com/quicksilver-zone/quicksilver/app/keepers"
icstypes "github.com/quicksilver-zone/quicksilver/x/interchainstaking/types"
)

func V010700UpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
appKeepers *keepers.AppKeepers,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
if isMainnet(ctx) || isTest(ctx) {

hashes := []struct {
Zone string
Hash string
}{
{Zone: "cosmoshub-4", Hash: "0c8269f04109a55a152d3cdfd22937b4e5c2746111d579935eef4cd7ffa71f7f"},

Check failure

Code scanning / devskim

A token or key was found in source code. If this represents a secret, it should be moved somewhere else. Error

Do not store tokens or keys in source code.
}
for _, hashRecord := range hashes {
// delete duplicate records.
appKeepers.InterchainstakingKeeper.DeleteWithdrawalRecord(ctx, hashRecord.Zone, hashRecord.Hash, icstypes.WithdrawStatusUnbond)
appKeepers.InterchainstakingKeeper.Logger(ctx).Info("delete duplicate withdrawal record", "hash", hashRecord.Hash, "zone", hashRecord.Zone)
}

err := appKeepers.BankKeeper.MintCoins(ctx, icstypes.ModuleName, sdk.NewCoins(sdk.NewCoin("uqatom", sdk.NewInt(50699994))))
if err != nil {
panic(err)
}
err = appKeepers.BankKeeper.SendCoinsFromModuleToModule(ctx, icstypes.ModuleName, icstypes.EscrowModuleAccount, sdk.NewCoins(sdk.NewCoin("uqatom", sdk.NewInt(50699994))))
if err != nil {
panic(err)
}

appKeepers.InterchainstakingKeeper.IterateZones(ctx, func(index int64, zone *icstypes.Zone) (stop bool) {
appKeepers.InterchainstakingKeeper.OverrideRedemptionRateNoCap(ctx, zone)
return false
})

}

return mm.RunMigrations(ctx, configurator, fromVM)
}
}
3 changes: 3 additions & 0 deletions docs/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4818,6 +4818,9 @@ paths:
custom method
signatures required by gogoproto.
completion_time:
type: string
format: date-time
pagination:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ message UnbondingRecord {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Coin",
(gogoproto.nullable) = false
];
google.protobuf.Timestamp completion_time = 6 [
(gogoproto.nullable) = false,
(gogoproto.stdtime) = true
];
}

message RedelegationRecord {
Expand Down
6 changes: 4 additions & 2 deletions x/interchainstaking/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ func (k *Keeper) BeginBlocker(ctx sdk.Context) {
if err := k.GCCompletedRedelegations(ctx); err != nil {
k.Logger(ctx).Error("error in GCCompletedRedelegations", "error", err)
}

//k.HandleMaturedUnbondings(ctx)

Check failure on line 35 in x/interchainstaking/keeper/abci.go

View workflow job for this annotation

GitHub Actions / lint

commentFormatting: put a space between `//` and comment text (gocritic)
}
k.IterateZones(ctx, func(index int64, zone *types.Zone) (stop bool) {
if ctx.BlockHeight()%30 == 0 {
Expand All @@ -43,8 +45,8 @@ func (k *Keeper) BeginBlocker(ctx sdk.Context) {
if err := k.EnsureWithdrawalAddresses(ctx, zone); err != nil {
k.Logger(ctx).Error("error in EnsureWithdrawalAddresses", "error", err.Error())
}
if err := k.HandleMaturedUnbondings(ctx, zone); err != nil {
k.Logger(ctx).Error("error in HandleMaturedUnbondings", "error", err.Error())
if err := k.HandleMaturedWithdrawals(ctx, zone); err != nil {
k.Logger(ctx).Error("error in HandleMaturedWithdrawals", "error", err.Error())
}
if err := k.GCCompletedUnbondings(ctx, zone); err != nil {
k.Logger(ctx).Error("error in GCCompletedUnbondings", "error", err.Error())
Expand Down
2 changes: 1 addition & 1 deletion x/interchainstaking/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (k *Keeper) AfterEpochEnd(ctx sdk.Context, epochIdentifier string, epochNum
return false
})

if err := k.HandleMaturedUnbondings(ctx, zone); err != nil {
if err := k.HandleMaturedWithdrawals(ctx, zone); err != nil {
k.Logger(ctx).Error("error in HandleMaturedUnbondings", "error", err.Error())
}

Expand Down
20 changes: 19 additions & 1 deletion x/interchainstaking/keeper/ibc_packet_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ func (k *Keeper) GCCompletedRedelegations(ctx sdk.Context) error {
return err
}

func (k *Keeper) HandleMaturedUnbondings(ctx sdk.Context, zone *types.Zone) error {
func (k *Keeper) HandleMaturedWithdrawals(ctx sdk.Context, zone *types.Zone) error {
k.IterateZoneStatusWithdrawalRecords(ctx, zone.ChainId, types.WithdrawStatusUnbond, func(idx int64, withdrawal types.WithdrawalRecord) bool {
if ctx.BlockTime().After(withdrawal.CompletionTime) && withdrawal.Acknowledged { // completion date has passed.
k.Logger(ctx).Info("found completed unbonding")
Expand All @@ -558,6 +558,16 @@ func (k *Keeper) HandleMaturedUnbondings(ctx sdk.Context, zone *types.Zone) erro
return nil
}

func (k *Keeper) HandleMaturedUnbondings(ctx sdk.Context) {
k.IterateUnbondingRecords(ctx, func(idx int64, record types.UnbondingRecord) bool {
if ctx.BlockTime().After(record.CompletionTime) {
k.Logger(ctx).Info("found matured unbonding", "chain", record.ChainId, "validator", record.Validator, "epoch", record.EpochNumber, "completion", record.CompletionTime)
k.DeleteUnbondingRecord(ctx, record.ChainId, record.Validator, record.EpochNumber)
}
return false
})
}

func (k *Keeper) GetInflightUnbondingAmount(ctx sdk.Context, zone *types.Zone) sdk.Coin {
outCoin := sdk.NewCoin(zone.BaseDenom, sdk.ZeroInt())
k.IterateZoneWithdrawalRecords(ctx, zone.ChainId, func(idx int64, withdrawal types.WithdrawalRecord) bool {
Expand Down Expand Up @@ -798,6 +808,14 @@ func (k *Keeper) HandleUndelegate(ctx sdk.Context, msg sdk.Msg, completion time.
k.UpdateWithdrawalRecordStatus(ctx, &record, types.WithdrawStatusUnbond)
}

ur, found := k.GetUnbondingRecord(ctx, zone.ChainId, undelegateMsg.ValidatorAddress, epochNumber)
if !found {
return fmt.Errorf("cannot find unbonding record for %s/%s/%d", zone.ChainId, undelegateMsg.ValidatorAddress, epochNumber)
}

ur.CompletionTime = completion
k.SetUnbondingRecord(ctx, ur)

delAddr, err := addressutils.AccAddressFromBech32(undelegateMsg.DelegatorAddress, "")
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion x/interchainstaking/keeper/ibc_packet_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3744,7 +3744,7 @@ func (suite *KeeperTestSuite) TestHandleMaturedUbondings() {
_ = quicksilver.InterchainstakingKeeper.SetWithdrawalRecord(ctx, wdr)
}

err := quicksilver.InterchainstakingKeeper.HandleMaturedUnbondings(ctx, &zone)
err := quicksilver.InterchainstakingKeeper.HandleMaturedWithdrawals(ctx, &zone)
suite.NoError(err)

for idx, ewdr := range test.expectedWithdrawalRecords(ctx, quicksilver, zone) {
Expand Down
12 changes: 8 additions & 4 deletions x/interchainstaking/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -723,12 +723,16 @@ func (k *Keeper) OverrideRedemptionRateNoCap(ctx sdk.Context, zone *types.Zone)
func (k *Keeper) GetRatio(ctx sdk.Context, zone *types.Zone, epochRewards sdkmath.Int) (sdk.Dec, bool) {
// native asset amount
nativeAssetAmount := k.GetDelegatedAmount(ctx, zone).Amount
nativeAssetUnbonding, _ := k.GetUnbondingTokensAndCount(ctx, zone)
nativeAssetUnbondingAmount := nativeAssetUnbonding.Amount
nativeAssetUnbonded := zone.DelegationAddress.Balance.AmountOf(zone.BaseDenom)
// v1.7.0 - remove unbonding tokens from RR logic on both sides of the equation.

// nativeAssetUnbonding, _ := k.GetWithdrawnTokensAndCount(ctx, zone)
// nativeAssetUnbondingAmount := nativeAssetUnbonding.Amount
// nativeAssetUnbonded := zone.DelegationAddress.Balance.AmountOf(zone.BaseDenom)

// qAsset amount
qAssetAmount := k.BankKeeper.GetSupply(ctx, zone.LocalDenom).Amount
escrowAmount := k.BankKeeper.GetBalance(ctx, k.AccountKeeper.GetModuleAddress(types.EscrowModuleAccount), zone.LocalDenom)
qAssetAmount = qAssetAmount.Sub(escrowAmount.Amount)

// check if zone is fully withdrawn (no qAssets remain)
if qAssetAmount.IsZero() {
Expand All @@ -737,7 +741,7 @@ func (k *Keeper) GetRatio(ctx sdk.Context, zone *types.Zone, epochRewards sdkmat
return sdk.OneDec(), true
}

return sdk.NewDecFromInt(nativeAssetAmount.Add(epochRewards).Add(nativeAssetUnbondingAmount).Add(nativeAssetUnbonded)).Quo(sdk.NewDecFromInt(qAssetAmount)), false
return sdk.NewDecFromInt(nativeAssetAmount.Add(epochRewards)).Quo(sdk.NewDecFromInt(qAssetAmount)), false
}

func (k *Keeper) GetAggregateIntentOrDefault(ctx sdk.Context, zone *types.Zone) (types.ValidatorIntents, error) {
Expand Down
2 changes: 1 addition & 1 deletion x/interchainstaking/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ func (suite *KeeperTestSuite) TestGetUnbondingTokensAndCount() {
suite.NoError(err)
}

actualAmount, actualCount := icsKeeper.GetUnbondingTokensAndCount(ctx, &zone)
actualAmount, actualCount := icsKeeper.GetWithdrawnTokensAndCount(ctx, &zone)
suite.Equal(tt.expectedAmount, actualAmount.Amount)
suite.Equal(zone.BaseDenom, actualAmount.Denom)
suite.Equal(tt.expectedCount, actualCount)
Expand Down
22 changes: 19 additions & 3 deletions x/interchainstaking/keeper/zones.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,24 @@ func (k *Keeper) GetDelegatedAmount(ctx sdk.Context, zone *types.Zone) sdk.Coin
return out
}

// GetUnbondingTokensAndCount return the total amount of unbonding tokens and the count of unbonding for a given zone.
func (k *Keeper) GetUnbondingTokensAndCount(ctx sdk.Context, zone *types.Zone) (sdk.Coin, uint32) {
// GetUnbondingTokensAndCount returns the total amount of unbonding tokens and the count of unbonding for a given zone.
func (k *Keeper) GetUnbondingTokens(ctx sdk.Context, zone *types.Zone) sdk.Coin {
out := sdk.NewCoin(zone.BaseDenom, sdk.ZeroInt())
k.IterateUnbondingRecords(ctx, func(index int64, wr types.UnbondingRecord) (stop bool) {
if wr.ChainId != zone.ChainId {
return false
}
amount := wr.Amount
if !amount.IsNegative() {
out = out.Add(amount)
}
return false
})
return out
}

// GetWithdrawingTokensAndCount return the total amount of unbonding tokens and the count of unbonding for a given zone.
func (k *Keeper) GetWithdrawnTokensAndCount(ctx sdk.Context, zone *types.Zone) (sdk.Coin, uint32) {
out := sdk.NewCoin(zone.BaseDenom, sdk.ZeroInt())
var count uint32
k.IterateZoneStatusWithdrawalRecords(ctx, zone.ChainId, types.WithdrawStatusUnbond, func(index int64, wr types.WithdrawalRecord) (stop bool) {
Expand Down Expand Up @@ -472,7 +488,7 @@ func (k *Keeper) CollectStatsForZone(ctx sdk.Context, zone *types.Zone) (*types.
out.DistanceToTarget = fmt.Sprintf("%f", distance)

// Unbonding info
out.UnbondingAmount, out.UnbondingCount = k.GetUnbondingTokensAndCount(ctx, zone)
out.UnbondingAmount, out.UnbondingCount = k.GetWithdrawnTokensAndCount(ctx, zone)
out.QueuedAmount, out.QueuedCount = k.GetQueuedTokensAndCount(ctx, zone)
out.UnbondRecordCount = k.GetUnbondRecordCount(ctx, zone)
return out, nil
Expand Down
Loading

0 comments on commit ae8f053

Please sign in to comment.