diff --git a/x/interchainstaking/keeper/keeper.go b/x/interchainstaking/keeper/keeper.go index 7e190c826..4036f700a 100644 --- a/x/interchainstaking/keeper/keeper.go +++ b/x/interchainstaking/keeper/keeper.go @@ -733,6 +733,10 @@ func (k *Keeper) GetRatio(ctx sdk.Context, zone *types.Zone, epochRewards sdkmat 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) + k.IterateZoneStatusWithdrawalRecords(ctx, zone.ChainId, types.WithdrawStatusQueued, func(_ int64, record types.WithdrawalRecord) (stop bool) { + qAssetAmount = qAssetAmount.Add(record.BurnAmount.Amount) + return false + }) // check if zone is fully withdrawn (no qAssets remain) if qAssetAmount.IsZero() { diff --git a/x/interchainstaking/keeper/keeper_test.go b/x/interchainstaking/keeper/keeper_test.go index d58e2c388..d444f8efa 100644 --- a/x/interchainstaking/keeper/keeper_test.go +++ b/x/interchainstaking/keeper/keeper_test.go @@ -460,6 +460,27 @@ func (suite *KeeperTestSuite) TestGetRatio() { supply: math.NewInt(17500000), expected: sdk.OneDec(), }, + { + name: "multi unbonding withdrawal, inc queued, delegation, expect 1.0", + records: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) []icstypes.WithdrawalRecord { + out := make([]icstypes.WithdrawalRecord, 0) + out = append(out, + icstypes.WithdrawalRecord{ChainId: zone.ChainId, Delegator: zone.DelegationAddress.Address, Recipient: addressutils.GenerateAddressForTestWithPrefix(zone.AccountPrefix), Amount: sdk.NewCoins(sdk.NewCoin(zone.BaseDenom, math.NewInt(3000000))), Status: icstypes.WithdrawStatusQueued, Txhash: randomutils.GenerateRandomHashAsHex(64), BurnAmount: sdk.NewCoin(zone.LocalDenom, math.NewInt(3000000))}, + icstypes.WithdrawalRecord{ChainId: zone.ChainId, Delegator: zone.DelegationAddress.Address, Recipient: addressutils.GenerateAddressForTestWithPrefix(zone.AccountPrefix), Amount: sdk.NewCoins(sdk.NewCoin(zone.BaseDenom, math.NewInt(10000000))), Status: icstypes.WithdrawStatusUnbond, Txhash: randomutils.GenerateRandomHashAsHex(64), BurnAmount: sdk.NewCoin(zone.LocalDenom, math.NewInt(10000000))}, + icstypes.WithdrawalRecord{ChainId: zone.ChainId, Delegator: zone.DelegationAddress.Address, Recipient: addressutils.GenerateAddressForTestWithPrefix(zone.AccountPrefix), Amount: sdk.NewCoins(sdk.NewCoin(zone.BaseDenom, math.NewInt(1500000))), Status: icstypes.WithdrawStatusUnbond, Txhash: randomutils.GenerateRandomHashAsHex(64), BurnAmount: sdk.NewCoin(zone.LocalDenom, math.NewInt(1500000))}, + ) + return out + }, + delegations: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) []icstypes.Delegation { + validators := qs.InterchainstakingKeeper.GetValidatorAddresses(ctx, zone.ChainId) + out := make([]icstypes.Delegation, 0) + out = append(out, icstypes.NewDelegation(zone.DepositAddress.Address, validators[0], sdk.NewCoin(zone.BaseDenom, sdk.NewInt(3000000)))) + out = append(out, icstypes.NewDelegation(zone.DepositAddress.Address, validators[1], sdk.NewCoin(zone.BaseDenom, sdk.NewInt(3000000)))) + return out + }, + supply: math.NewInt(17500000), // supply 17.5; unbonding 11.5; queued 3.0; delegated 6.0. + expected: sdk.OneDec(), + }, { name: "multi unbonding withdrawal, delegation, sub 1.0", records: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) []icstypes.WithdrawalRecord { @@ -499,6 +520,27 @@ func (suite *KeeperTestSuite) TestGetRatio() { supply: math.NewInt(22500000), expected: sdk.NewDec(54).Quo(sdk.NewDec(39)), }, + { + name: "multi unbonding withdrawal inc. withdrawal, delegation, gt 1.0", + records: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) []icstypes.WithdrawalRecord { + out := make([]icstypes.WithdrawalRecord, 0) + out = append(out, icstypes.WithdrawalRecord{ChainId: zone.ChainId, Delegator: zone.DelegationAddress.Address, Recipient: addressutils.GenerateAddressForTestWithPrefix(zone.AccountPrefix), Amount: sdk.NewCoins(sdk.NewCoin(zone.BaseDenom, math.NewInt(3300000))), Status: icstypes.WithdrawStatusUnbond, Txhash: randomutils.GenerateRandomHashAsHex(64), BurnAmount: sdk.NewCoin(zone.LocalDenom, math.NewInt(3000000))}) + out = append(out, icstypes.WithdrawalRecord{ChainId: zone.ChainId, Delegator: zone.DelegationAddress.Address, Recipient: addressutils.GenerateAddressForTestWithPrefix(zone.AccountPrefix), Amount: sdk.NewCoins(), Status: icstypes.WithdrawStatusQueued, Txhash: randomutils.GenerateRandomHashAsHex(64), BurnAmount: sdk.NewCoin(zone.LocalDenom, math.NewInt(2000000))}) + return out + }, + delegations: func(ctx sdk.Context, qs *app.Quicksilver, zone icstypes.Zone) []icstypes.Delegation { + validators := qs.InterchainstakingKeeper.GetValidatorAddresses(ctx, zone.ChainId) + out := make([]icstypes.Delegation, 0) + out = append(out, + icstypes.NewDelegation(zone.DepositAddress.Address, validators[0], sdk.NewCoin(zone.BaseDenom, sdk.NewInt(3300000))), + icstypes.NewDelegation(zone.DepositAddress.Address, validators[1], sdk.NewCoin(zone.BaseDenom, sdk.NewInt(17600000))), + icstypes.NewDelegation(zone.DepositAddress.Address, validators[2], sdk.NewCoin(zone.BaseDenom, sdk.NewInt(9100000))), + ) + return out + }, + supply: math.NewInt(23000000), + expected: sdk.NewDec(3).Quo(sdk.NewDec(2)), + }, } for _, tt := range tc {