diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index eaa8d1a95..8af28ed44 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -357,15 +357,19 @@ func (k BaseKeeper) DeferredSendCoinsFromModuleToAccount( return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", recipientAddr) } - // Branch Context for validation and fail if the module doesn't have enough coins - // but don't write this to the underlying store - validationContext, _ := ctx.CacheContext() - err := k.subUnlockedCoins(validationContext, moduleAddr, amount) - if err != nil { - return err + // Subtract from any pending sends fist + ok := ctx.ContextMemCache().SafeSubDeferredSends(moduleAccount, amount) + if !ok { + // Branch Context for validation and fail if the module doesn't have enough coins + // but don't write this to the underlying store + validationContext, _ := ctx.CacheContext() + err := k.subUnlockedCoins(validationContext, moduleAddr, amount) + if err != nil { + return err + } } - err = k.addCoins(ctx, recipientAddr, amount) + err := k.addCoins(ctx, recipientAddr, amount) if err != nil { return err } @@ -619,6 +623,14 @@ func (k BaseKeeper) destroyCoins(ctx sdk.Context, moduleName string, amounts sdk // It will panic if the module account does not exist or is unauthorized. func (k BaseKeeper) BurnCoins(ctx sdk.Context, moduleName string, amounts sdk.Coins) error { subFn := func(ctx sdk.Context, moduleName string, amounts sdk.Coins) error { + + // Try subtract from the in mem var first, prevents the condition where + // the module may have a pending deposit that would be enough to pay for this send + ok := ctx.ContextMemCache().SafeSubDeferredSends(moduleName, amounts) + if ok { + return nil + } + acc := k.ak.GetModuleAccount(ctx, moduleName) return k.subUnlockedCoins(ctx, acc.GetAddress(), amounts) } @@ -642,8 +654,16 @@ func (k BaseKeeper) DeferredBurnCoins(ctx sdk.Context, moduleName string, amount // Branch Context for validation and fail if the module doesn't have enough coins // but don't write this to the underlying store validationContext, _ := ctx.CacheContext() - acc := k.ak.GetModuleAccount(ctx, moduleName) - err := k.subUnlockedCoins(validationContext, acc.GetAddress(), amounts) + moduleAcc := k.ak.GetModuleAccount(ctx, moduleName) + + // Try subtract from the in mem var first, prevents the condition where + // the module may have a pending deposit that would be enough to pay for this send + ok := ctx.ContextMemCache().SafeSubDeferredSends(moduleName, amounts) + if ok { + return nil + } + + err := k.subUnlockedCoins(validationContext, moduleAcc.GetAddress(), amounts) if err != nil { return err }