Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epoch Logs Cleanup - Day Epoch Pt. 2 #518

Merged
merged 9 commits into from
Dec 17, 2022
12 changes: 10 additions & 2 deletions x/epochs/keeper/abci.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package keeper

import (
"fmt"
"strconv"
"strings"
"time"

"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/Stride-Labs/stride/v4/utils"
"github.com/Stride-Labs/stride/v4/x/epochs/types"
)

Expand All @@ -26,10 +29,15 @@ func (k Keeper) BeginBlocker(ctx sdk.Context) {
switch {
case shouldInitialEpochStart:
epochInfo = startInitialEpoch(epochInfo)
logger.Info("starting epoch", "identifier", epochInfo.Identifier)
logger.Info(fmt.Sprintf("initial %s epoch", epochInfo.Identifier))
case shouldEpochStart:
epochInfo = endEpoch(epochInfo)
logger.Info("ending epoch", "identifier", epochInfo.Identifier)

// Capitalize the epoch identifier for the logs
epochAlias := strings.ToUpper(strings.ReplaceAll(epochInfo.Identifier, "_epoch", ""))
logger.Info(utils.LogHeader("%s EPOCH %d", epochAlias, epochInfo.CurrentEpoch))
logger.Info(utils.LogHeader("Epoch Start Time: %s", epochInfo.CurrentEpochStartTime))

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeEpochEnd,
Expand Down
8 changes: 4 additions & 4 deletions x/stakeibc/keeper/deposit_records.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (k Keeper) TransferExistingDepositsToHostZones(ctx sdk.Context, epochNumber

for _, depositRecord := range transferDepositRecords {
k.Logger(ctx).Info(utils.LogWithHostZone(depositRecord.HostZoneId,
"Processing deposit record %d: %d%s", depositRecord.Id, depositRecord.Amount, depositRecord.Denom))
"Processing deposit record %d: %v%s", depositRecord.Id, depositRecord.Amount, depositRecord.Denom))

// if a TRANSFER_QUEUE record has 0 balance and was created in the previous epoch, it's safe to remove since it will never be updated or used
if depositRecord.Amount.LTE(sdk.ZeroInt()) && depositRecord.DepositEpochNumber < epochNumber {
Expand All @@ -70,7 +70,7 @@ func (k Keeper) TransferExistingDepositsToHostZones(ctx sdk.Context, epochNumber
}
delegateAddress := delegateAccount.Address

k.Logger(ctx).Info(utils.LogWithHostZone(depositRecord.HostZoneId, "Transferring %d%s", depositRecord.Amount, hostZone.HostDenom))
k.Logger(ctx).Info(utils.LogWithHostZone(depositRecord.HostZoneId, "Transferring %v%s", depositRecord.Amount, hostZone.HostDenom))
transferCoin := sdk.NewCoin(hostZone.IbcDenom, depositRecord.Amount)

// timeout 30 min in the future
Expand Down Expand Up @@ -118,7 +118,7 @@ func (k Keeper) StakeExistingDepositsOnHostZones(ctx sdk.Context, epochNumber ui

for _, depositRecord := range stakeDepositRecords[:maxDepositRecordsToStake] {
k.Logger(ctx).Info(utils.LogWithHostZone(depositRecord.HostZoneId,
"Processing deposit record %d: %d%s", depositRecord.Id, depositRecord.Amount, depositRecord.Denom))
"Processing deposit record %d: %v%s", depositRecord.Id, depositRecord.Amount, depositRecord.Denom))

hostZone, hostZoneFound := k.GetHostZone(ctx, depositRecord.HostZoneId)
if !hostZoneFound {
Expand All @@ -132,7 +132,7 @@ func (k Keeper) StakeExistingDepositsOnHostZones(ctx sdk.Context, epochNumber ui
continue
}

k.Logger(ctx).Info(utils.LogWithHostZone(depositRecord.HostZoneId, "Staking %d%s", depositRecord.Amount, hostZone.HostDenom))
k.Logger(ctx).Info(utils.LogWithHostZone(depositRecord.HostZoneId, "Staking %v%s", depositRecord.Amount, hostZone.HostDenom))
stakeAmount := sdk.NewCoin(hostZone.HostDenom, depositRecord.Amount)

err := k.DelegateOnHost(ctx, hostZone, stakeAmount, depositRecord)
Expand Down
11 changes: 2 additions & 9 deletions x/stakeibc/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import (
)

func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInfo) {
k.Logger(ctx).Info(utils.LogHeader("EPOCH %d - %s", epochInfo.CurrentEpoch, epochInfo.CurrentEpochStartTime))

// Update the stakeibc epoch tracker
epochNumber, err := k.UpdateEpochTracker(ctx, epochInfo)
if err != nil {
Expand All @@ -24,8 +22,6 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInf

// Day Epoch - Process Unbondings
if epochInfo.Identifier == epochstypes.DAY_EPOCH {
k.Logger(ctx).Info(utils.LogHeader("DAY EPOCH %d", epochNumber))

// Initiate unbondings from any hostZone where it's appropriate
k.InitiateAllHostZoneUnbondings(ctx, epochNumber)
// Check previous epochs to see if unbondings finished, and sweep the tokens if so
Expand All @@ -38,8 +34,6 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInf

// Stride Epoch - Process Deposits and Delegations
if epochInfo.Identifier == epochstypes.STRIDE_EPOCH {
k.Logger(ctx).Info(utils.LogHeader("STRIDE EPOCH %d", epochNumber))

// Get cadence intervals
redemptionRateInterval := k.GetParam(ctx, types.KeyRedemptionRateInterval)
depositInterval := k.GetParam(ctx, types.KeyDepositInterval)
Expand Down Expand Up @@ -165,12 +159,12 @@ func (k Keeper) UpdateRedemptionRates(ctx sdk.Context, depositRecords []recordst
}

k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId,
"Redemption Rate Components - Undelegated Balance: %d, Staked Balance: %d, Module Account Balance: %d, stToken Supply: %d",
"Redemption Rate Components - Undelegated Balance: %v, Staked Balance: %v, Module Account Balance: %v, stToken Supply: %v",
undelegatedBalance, stakedBalance, moduleAcctBalance, stSupply))

// Calculate the redemption rate
redemptionRate := (sdk.NewDecFromInt(undelegatedBalance).Add(sdk.NewDecFromInt(stakedBalance)).Add(sdk.NewDecFromInt(moduleAcctBalance))).Quo(sdk.NewDecFromInt(stSupply))
k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, "New Redemption Rate: %d (vs Prev Rate: %d)", redemptionRate, hostZone.RedemptionRate))
k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, "New Redemption Rate: %v (vs Prev Rate: %v)", redemptionRate, hostZone.RedemptionRate))

// Update the host zone
hostZone.LastRedemptionRate = hostZone.RedemptionRate
Expand Down Expand Up @@ -233,6 +227,5 @@ func (k Keeper) ReinvestRewards(ctx sdk.Context) {
k.Logger(ctx).Error(fmt.Sprintf("Error updating withdrawal balance for host zone %s: %s", hostZone.ConnectionId, err.Error()))
continue
}
k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, "Updated withdrawal balance"))
}
}
27 changes: 16 additions & 11 deletions x/stakeibc/keeper/host_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,28 +93,31 @@ func (k Keeper) GetAllHostZone(ctx sdk.Context) (list []types.HostZone) {
return
}

func (k Keeper) AddDelegationToValidator(ctx sdk.Context, hostZone types.HostZone, valAddr string, amt sdk.Int) (success bool) {
for _, val := range hostZone.GetValidators() {
if val.GetAddress() == valAddr {
k.Logger(ctx).Info(fmt.Sprintf("Validator %s, Current Delegation: %d, Delegation Change: %d", val.GetAddress(), val.DelegationAmt, amt))
if amt.GTE(sdk.ZeroInt()) {
val.DelegationAmt = val.DelegationAmt.Add(amt)
func (k Keeper) AddDelegationToValidator(ctx sdk.Context, hostZone types.HostZone, validatorAddress string, amount sdk.Int) (success bool) {
for _, validator := range hostZone.Validators {
if validator.Address == validatorAddress {
k.Logger(ctx).Info(fmt.Sprintf("Validator %s, Current Delegation: %v, Delegation Change: %v", validator.Address, validator.DelegationAmt, amount))
if amount.GTE(sdk.ZeroInt()) {
validator.DelegationAmt = validator.DelegationAmt.Add(amount)
return true
} else {
absAmt := amt.Abs()
if absAmt.GT(val.DelegationAmt) {
k.Logger(ctx).Error(fmt.Sprintf("Delegation amount %d is greater than validator %s delegation amount %d", absAmt, valAddr, val.DelegationAmt))
absAmt := amount.Abs()
if absAmt.GT(validator.DelegationAmt) {
k.Logger(ctx).Error(fmt.Sprintf("Delegation amount %v is greater than validator %s delegation amount %v", absAmt, validatorAddress, validator.DelegationAmt))
return false
}
val.DelegationAmt = val.DelegationAmt.Sub(absAmt)
validator.DelegationAmt = validator.DelegationAmt.Sub(absAmt)
return true
}
}
}
k.Logger(ctx).Error(fmt.Sprintf("Could not find validator %s on host zone %s", valAddr, hostZone.GetChainId()))
k.Logger(ctx).Error(fmt.Sprintf("Could not find validator %s on host zone %s", validatorAddress, hostZone.ChainId))
return false
}

// Appends a validator to host zone (if the host zone is not already at capacity)
// If the validator is added through governance, the weight is equal to the minimum weight across the set
// If the validator is added through an admin transactions, the weight is specified in the message
func (k Keeper) AddValidatorToHostZone(ctx sdk.Context, msg *types.MsgAddValidator, fromGovernance bool) error {
// Get the corresponding host zone
hostZone, found := k.GetHostZone(ctx, msg.HostZone)
Expand Down Expand Up @@ -171,6 +174,8 @@ func (k Keeper) AddValidatorToHostZone(ctx sdk.Context, msg *types.MsgAddValidat
return nil
}

// Removes a validator from a host zone
// The validator must be zero-weight and have no delegations in order to be removed
func (k Keeper) RemoveValidatorFromHostZone(ctx sdk.Context, chainId string, validatorAddress string) error {
hostZone, found := k.GetHostZone(ctx, chainId)
if !found {
Expand Down
2 changes: 1 addition & 1 deletion x/stakeibc/keeper/icacallbacks_delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func DelegateCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, ack

for _, splitDelegation := range delegateCallback.SplitDelegations {
validator := splitDelegation.Validator
k.Logger(ctx).Info(fmt.Sprintf("incrementing stakedBal %d on %s", splitDelegation.Amount, validator))
k.Logger(ctx).Info(fmt.Sprintf("incrementing stakedBal %v on %s", splitDelegation.Amount, validator))

zone.StakedBal = zone.StakedBal.Add(splitDelegation.Amount)
success := k.AddDelegationToValidator(ctx, zone, validator, splitDelegation.Amount)
Expand Down
16 changes: 8 additions & 8 deletions x/stakeibc/keeper/icacallbacks_undelegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,18 @@ func UndelegateCallback(k Keeper, ctx sdk.Context, packet channeltypes.Packet, a
func (k Keeper) UpdateDelegationBalances(ctx sdk.Context, zone types.HostZone, undelegateCallback types.UndelegateCallback) error {
// Undelegate from each validator and update host zone staked balance, if successful
for _, undelegation := range undelegateCallback.SplitDelegations {
k.Logger(ctx).Info(fmt.Sprintf("UndelegateCallback, Undelegation: %d, validator: %s", undelegation.Amount, undelegation.Validator))
k.Logger(ctx).Info(fmt.Sprintf("UndelegateCallback, Undelegation: %v, validator: %s", undelegation.Amount, undelegation.Validator))

undelegateVal := undelegation.Validator
success := k.AddDelegationToValidator(ctx, zone, undelegateVal, undelegation.Amount.Neg())
if !success {
return sdkerrors.Wrapf(types.ErrValidatorDelegationChg, "Failed to remove delegation to validator")
}

if undelegation.Amount.GT(zone.StakedBal) {
// handle incoming underflow
// Once we add a killswitch, we should also stop liquid staking on the zone here
return sdkerrors.Wrapf(types.ErrUndelegationAmount, "undelegation.Amount > zone.StakedBal, undelegation.Amount: %d, zone.StakedBal %d", undelegation.Amount, zone.StakedBal)
return sdkerrors.Wrapf(types.ErrUndelegationAmount, "undelegation.Amount > zone.StakedBal, undelegation.Amount: %v, zone.StakedBal %v", undelegation.Amount, zone.StakedBal)
} else {
zone.StakedBal = zone.StakedBal.Sub(undelegation.Amount)
}
Expand Down Expand Up @@ -154,16 +154,16 @@ func (k Keeper) GetLatestCompletionTime(ctx sdk.Context, txMsgData *sdk.TxMsgDat
return &latestCompletionTime, nil
}

// UpdateHostZoneUnbondings does two things:
// 1. Update the status and time of each hostZoneUnbonding on each epochUnbondingRecord
// 2. Return the number of stTokens that need to be burned
func (k Keeper) UpdateHostZoneUnbondings(
ctx sdk.Context,
latestCompletionTime time.Time,
zone types.HostZone,
undelegateCallback types.UndelegateCallback,
) (stTokenBurnAmount sdk.Int, err error) {
stTokenBurnAmount = sdk.ZeroInt()
// UpdateHostZoneUnbondings does two things:
// 1. Update the status and time of each hostZoneUnbonding on each epochUnbondingRecord
// 2. Return the number of stTokens that need to be burned
for _, epochNumber := range undelegateCallback.EpochUnbondingRecordIds {
epochUnbondingRecord, found := k.RecordsKeeper.GetEpochUnbondingRecord(ctx, epochNumber)
if !found {
Expand All @@ -187,7 +187,7 @@ func (k Keeper) UpdateHostZoneUnbondings(
hostZoneUnbonding.UnbondingTime = cast.ToUint64(latestCompletionTime.UnixNano())
updatedEpochUnbondingRecord, success := k.RecordsKeeper.AddHostZoneToEpochUnbondingRecord(ctx, epochUnbondingRecord.EpochNumber, zone.ChainId, hostZoneUnbonding)
if !success {
k.Logger(ctx).Error(fmt.Sprintf("Failed to set host zone epoch unbonding record: epochNumber %d, chainId %s, hostZoneUnbonding %v", epochUnbondingRecord.EpochNumber, zone.ChainId, hostZoneUnbonding))
k.Logger(ctx).Error(fmt.Sprintf("Failed to set host zone epoch unbonding record: epochNumber %d, chainId %s, hostZoneUnbonding %+v", epochUnbondingRecord.EpochNumber, zone.ChainId, hostZoneUnbonding))
return sdk.ZeroInt(), sdkerrors.Wrapf(types.ErrEpochNotFound, "couldn't set host zone epoch unbonding record. err: %s", err.Error())
}
k.RecordsKeeper.SetEpochUnbondingRecord(ctx, *updatedEpochUnbondingRecord)
Expand Down Expand Up @@ -217,7 +217,7 @@ func (k Keeper) BurnTokens(ctx sdk.Context, zone types.HostZone, stTokenBurnAmou
err = k.bankKeeper.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(stCoin))
if err != nil {
k.Logger(ctx).Error(fmt.Sprintf("Failed to burn stAssets upon successful unbonding %s", err.Error()))
return sdkerrors.Wrapf(types.ErrInsufficientFunds, "couldn't burn %d %s tokens in module account. err: %s", stTokenBurnAmount, stCoinDenom, err.Error())
return sdkerrors.Wrapf(types.ErrInsufficientFunds, "couldn't burn %v%s tokens in module account. err: %s", stTokenBurnAmount, stCoinDenom, err.Error())
}
k.Logger(ctx).Info(fmt.Sprintf("Total supply %s", k.bankKeeper.GetSupply(ctx, stCoinDenom)))
return nil
Expand Down
6 changes: 3 additions & 3 deletions x/stakeibc/keeper/icqcallbacks_delegator_shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func DelegatorSharesCallback(k Keeper, ctx sdk.Context, args []byte, query icqty
// TODO: make sure conversion math precision matches the sdk's staking module's version (we did it slightly differently)
// note: truncateInt per https://github.com/cosmos/cosmos-sdk/blob/cb31043d35bad90c4daa923bb109f38fd092feda/x/staking/types/validator.go#L431
validatorTokens := queriedDelgation.Shares.Mul(validator.InternalExchangeRate.InternalTokensToSharesRate).TruncateInt()
k.Logger(ctx).Info(fmt.Sprintf("DelegationCallback: HostZone: %s, Validator: %s, Previous NumTokens: %d, Current NumTokens: %v",
k.Logger(ctx).Info(fmt.Sprintf("DelegationCallback: HostZone: %s, Validator: %s, Previous NumTokens: %v, Current NumTokens: %v",
hostZone.ChainId, validator.Address, validator.DelegationAmt, validatorTokens))

// Confirm the validator has actually been slashed
Expand All @@ -98,7 +98,7 @@ func DelegatorSharesCallback(k Keeper, ctx sdk.Context, args []byte, query icqty

// Get slash percentage
slashAmount := validator.DelegationAmt.Sub(validatorTokens)

weight, err := cast.ToInt64E(validator.Weight)
if err != nil {
errMsg := fmt.Sprintf("unable to convert validator weight to int64, err: %s", err.Error())
Expand All @@ -107,7 +107,7 @@ func DelegatorSharesCallback(k Keeper, ctx sdk.Context, args []byte, query icqty
}

slashPct := sdk.NewDecFromInt(slashAmount).Quo(sdk.NewDecFromInt(validator.DelegationAmt))
k.Logger(ctx).Info(fmt.Sprintf("ICQ'd Delegation Amoount Mismatch, HostZone: %s, Validator: %s, Delegator: %s, Records Tokens: %d, Tokens from ICQ %v, Slash Amount: %d, Slash Pct: %v!",
k.Logger(ctx).Info(fmt.Sprintf("ICQ'd Delegation Amount Mismatch, HostZone: %s, Validator: %s, Delegator: %s, Records Tokens: %v, Tokens from ICQ %v, Slash Amount: %v, Slash Pct: %v!",
hostZone.ChainId, validator.Address, queriedDelgation.DelegatorAddress, validator.DelegationAmt, validatorTokens, slashAmount, slashPct))

// Abort if the slash was greater than 10%
Expand Down
8 changes: 4 additions & 4 deletions x/stakeibc/keeper/icqcallbacks_withdrawal_balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ func WithdrawalBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icq
}

// Confirm the balance is greater than zero
if withdrawalBalanceCoin.Amount.Int64() <= 0 {
if withdrawalBalanceCoin.Amount.LTE(sdk.ZeroInt()) {
sampocs marked this conversation as resolved.
Show resolved Hide resolved
k.Logger(ctx).Info(fmt.Sprintf("WithdrawalBalanceCallback: no balance to transfer for zone: %s, accAddr: %v, coin: %v",
hostZone.ChainId, hostZone.WithdrawalAccount.GetAddress(), withdrawalBalanceCoin.String()))
return nil
}

// Sweep the withdrawal account balance, to the commission and the delegation accounts
k.Logger(ctx).Info(fmt.Sprintf("ICA Bank Sending %d%s from withdrawalAddr to delegationAddr.",
withdrawalBalanceCoin.Amount.Int64(), withdrawalBalanceCoin.Denom))
k.Logger(ctx).Info(fmt.Sprintf("ICA Bank Sending %v%s from withdrawalAddr to delegationAddr.",
withdrawalBalanceCoin.Amount, withdrawalBalanceCoin.Denom))

withdrawalAccount := hostZone.GetWithdrawalAccount()
if withdrawalAccount == nil {
Expand Down Expand Up @@ -92,7 +92,7 @@ func WithdrawalBalanceCallback(k Keeper, ctx sdk.Context, args []byte, query icq

// TODO(TEST-112) safety check, balances should add to original amount
if (strideClaimFloored.Int64() + reinvestAmountCeil.Int64()) != withdrawalBalanceAmount.Int64() {
ctx.Logger().Error(fmt.Sprintf("Error with withdraw logic: %d, Fee portion: %d, reinvestPortion %d", withdrawalBalanceAmount.Int64(), strideClaimFloored.Int64(), reinvestAmountCeil.Int64()))
ctx.Logger().Error(fmt.Sprintf("Error with withdraw logic: %v, Fee portion: %v, reinvestPortion %v", withdrawalBalanceAmount, strideClaimFloored, reinvestAmountCeil))
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Failed to subdivide rewards to feeAccount and delegationAccount")
}
strideCoin := sdk.NewCoin(withdrawalBalanceCoin.Denom, strideClaimFloored)
Expand Down
8 changes: 4 additions & 4 deletions x/stakeibc/keeper/msg_server_redeem_stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (k msgServer) RedeemStake(goCtx context.Context, msg *types.MsgRedeemStake)
nativeAmount := sdk.NewDecFromInt(msg.Amount).Mul(hostZone.RedemptionRate).RoundInt()

if nativeAmount.GT(hostZone.StakedBal) {
return nil, sdkerrors.Wrapf(types.ErrInvalidAmount, "cannot unstake an amount g.t. staked balance on host zone: %d", msg.Amount)
return nil, sdkerrors.Wrapf(types.ErrInvalidAmount, "cannot unstake an amount g.t. staked balance on host zone: %v", msg.Amount)
}

// safety check: redemption rate must be within safety bounds
Expand All @@ -70,14 +70,14 @@ func (k msgServer) RedeemStake(goCtx context.Context, msg *types.MsgRedeemStake)
// safety checks on the coin
// - Redemption amount must be positive
if !nativeAmount.IsPositive() {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "amount must be greater than 0. found: %d", msg.Amount)
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "amount must be greater than 0. found: %v", msg.Amount)
}
// - Creator owns at least "amount" stAssets
balance := k.bankKeeper.GetBalance(ctx, sender, stDenom)
k.Logger(ctx).Info(fmt.Sprintf("Redemption issuer IBCDenom balance: %v%s", balance.Amount, balance.Denom))
k.Logger(ctx).Info(fmt.Sprintf("Redemption requested redemotion amount: %v%s", inCoin.Amount, inCoin.Denom))
if balance.Amount.LT(msg.Amount) {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "balance is lower than redemption amount. redemption amount: %d, balance %d: ", msg.Amount, balance.Amount)
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "balance is lower than redemption amount. redemption amount: %v, balance %v: ", msg.Amount, balance.Amount)
}
// UNBONDING RECORD KEEPING
userRedemptionRecord := recordstypes.UserRedemptionRecord{
Expand Down Expand Up @@ -115,7 +115,7 @@ func (k msgServer) RedeemStake(goCtx context.Context, msg *types.MsgRedeemStake)
err = k.bankKeeper.SendCoins(ctx, sender, bech32ZoneAddress, redeemCoin)
if err != nil {
k.Logger(ctx).Error("Failed to send sdk.NewCoins(inCoins) from account to module")
return nil, sdkerrors.Wrapf(types.ErrInsufficientFunds, "couldn't send %d derivative %s tokens to module account. err: %s", msg.Amount, hostZone.HostDenom, err.Error())
return nil, sdkerrors.Wrapf(types.ErrInsufficientFunds, "couldn't send %v derivative %s tokens to module account. err: %s", msg.Amount, hostZone.HostDenom, err.Error())
}

// record the number of stAssets that should be burned after unbonding
Expand Down
Loading