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

feat: custom bank hooks #201

Merged
merged 6 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 64 additions & 6 deletions custom/bank/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
accountkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"

errorsmod "cosmossdk.io/errors"
custombankkeeper "github.com/terra-money/alliance/custom/bank/keeper"
customterratypes "github.com/terra-money/core/v2/custom/bank/types"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

type Keeper struct {
Expand Down Expand Up @@ -51,7 +51,6 @@ func (k *Keeper) SetHooks(bh customterratypes.BankHooks) *Keeper {
// SendCoins transfers amt coins from a sending account to a receiving account.
// An error is returned upon failure.
func (k Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error {
// BlockBeforeSend hook should always be called before the TrackBeforeSend hook.
err := k.BlockBeforeSend(ctx, fromAddr, toAddr, amt)
if err != nil {
return err
Expand All @@ -67,13 +66,72 @@ func (k Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.A
func (k Keeper) SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error {
senderAddr := k.ak.GetModuleAddress(senderModule)
if senderAddr == nil {
panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule))
panic(errorsmod.Wrapf(customterratypes.ErrUnknownAddress, "senderModule address %s is nil", senderModule))
}

recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule)
if recipientAcc == nil {
panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule))
panic(errorsmod.Wrapf(customterratypes.ErrUnknownAddress, "recipientModule address %s is nil", recipientModule))
}

return k.Keeper.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
}

// UndelegateCoins performs undelegation by crediting amt coins to an account with
// address addr. For vesting accounts, undelegation amounts are tracked for both
// vesting and vested coins. The coins are then transferred from a ModuleAccount
// address to the delegator address. If any of the undelegation amounts are
// negative, an error is returned.
func (k Keeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error {
err := k.BlockBeforeSend(ctx, moduleAccAddr, delegatorAddr, amt)
if err != nil {
return err
}
k.TrackBeforeSend(ctx, moduleAccAddr, delegatorAddr, amt)

return k.Keeper.UndelegateCoins(ctx, moduleAccAddr, delegatorAddr, amt)
}

// DelegateCoins performs delegation by deducting amt coins from an account with
// address addr. For vesting accounts, delegations amounts are tracked for both
// vesting and vested coins. The coins are then transferred from the delegator
// address to a ModuleAccount address. If any of the delegation amounts are negative,
// an error is returned.
func (k Keeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error {
err := k.BlockBeforeSend(ctx, delegatorAddr, moduleAccAddr, amt)
if err != nil {
return err
}
k.TrackBeforeSend(ctx, delegatorAddr, moduleAccAddr, amt)

return k.Keeper.DelegateCoins(ctx, delegatorAddr, moduleAccAddr, amt)
}

// InputOutputCoins performs multi-send functionality. It accepts a series of
// inputs that correspond to a series of outputs. It returns an error if the
// inputs and outputs don't line up or if any single transfer of tokens fails.
func (k Keeper) InputOutputCoins(ctx sdk.Context, inputs []banktypes.Input, outputs []banktypes.Output) error {
emidev98 marked this conversation as resolved.
Show resolved Hide resolved
// Only 1 input is allowed for all outputs check the following url:
// https://github.com/terra-money/cosmos-sdk/blob/release/v0.47.x/x/bank/types/msgs.go#L87-L89
//
// This if statement is added here too so we know
// when multiple inputs are allowed in the future
// because ErrMultipleSenders will fail to import
// because will be removed from the code.
if len(inputs) != 1 {
return banktypes.ErrMultipleSenders
}
input := inputs[0]
inputaddress := sdk.MustAccAddressFromBech32(input.Address)

for _, output := range outputs {
outputaddress := sdk.MustAccAddressFromBech32(output.Address)

err := k.BlockBeforeSend(ctx, inputaddress, outputaddress, output.Coins)
if err != nil {
return err
}
k.TrackBeforeSend(ctx, inputaddress, outputaddress, output.Coins)
}

return k.Keeper.InputOutputCoins(ctx, inputs, outputs)
}
12 changes: 12 additions & 0 deletions custom/bank/types/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package types

// DONTCOVER

import (
sdkerrors "cosmossdk.io/errors"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

var (
ErrUnknownAddress = sdkerrors.Register(banktypes.ModuleName, 383838, "module account does not exist")
)
Loading