github.com/Finschia/finschia-sdk@v0.48.1/x/bankplus/keeper/keeper.go (about)

     1  package keeper
     2  
     3  import (
     4  	"github.com/Finschia/finschia-sdk/codec"
     5  	sdk "github.com/Finschia/finschia-sdk/types"
     6  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
     7  	bankkeeper "github.com/Finschia/finschia-sdk/x/bank/keeper"
     8  	"github.com/Finschia/finschia-sdk/x/bank/types"
     9  	paramtypes "github.com/Finschia/finschia-sdk/x/params/types"
    10  )
    11  
    12  var _ Keeper = (*BaseKeeper)(nil)
    13  
    14  type Keeper interface {
    15  	bankkeeper.Keeper
    16  
    17  	AddToInactiveAddr(ctx sdk.Context, address sdk.AccAddress)
    18  	DeleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress)
    19  	IsInactiveAddr(address sdk.AccAddress) bool
    20  
    21  	InitializeBankPlus(ctx sdk.Context)
    22  }
    23  
    24  type BaseKeeper struct {
    25  	bankkeeper.BaseKeeper
    26  
    27  	ak             types.AccountKeeper
    28  	cdc            codec.Codec
    29  	storeKey       sdk.StoreKey
    30  	inactiveAddrs  map[string]bool
    31  	deactMultiSend bool
    32  }
    33  
    34  func NewBaseKeeper(
    35  	cdc codec.Codec, storeKey sdk.StoreKey, ak types.AccountKeeper, paramSpace paramtypes.Subspace,
    36  	blockedAddr map[string]bool, deactMultiSend bool,
    37  ) BaseKeeper {
    38  	return BaseKeeper{
    39  		BaseKeeper:     bankkeeper.NewBaseKeeper(cdc, storeKey, ak, paramSpace, blockedAddr),
    40  		ak:             ak,
    41  		cdc:            cdc,
    42  		storeKey:       storeKey,
    43  		inactiveAddrs:  map[string]bool{},
    44  		deactMultiSend: deactMultiSend,
    45  	}
    46  }
    47  
    48  func (keeper BaseKeeper) InitializeBankPlus(ctx sdk.Context) {
    49  	keeper.loadAllInactiveAddrs(ctx)
    50  }
    51  
    52  // SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress.
    53  // It will panic if the module account does not exist.
    54  func (keeper BaseKeeper) SendCoinsFromModuleToAccount(
    55  	ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins,
    56  ) error {
    57  	senderAddr := keeper.ak.GetModuleAddress(senderModule)
    58  	if senderAddr.Empty() {
    59  		panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule))
    60  	}
    61  
    62  	if keeper.BlockedAddr(recipientAddr) {
    63  		return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", recipientAddr)
    64  	}
    65  
    66  	return keeper.SendCoins(ctx, senderAddr, recipientAddr, amt)
    67  }
    68  
    69  // SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another.
    70  // It will panic if either module account does not exist.
    71  func (keeper BaseKeeper) SendCoinsFromModuleToModule(
    72  	ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins,
    73  ) error {
    74  	senderAddr := keeper.ak.GetModuleAddress(senderModule)
    75  	if senderAddr.Empty() {
    76  		panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule))
    77  	}
    78  
    79  	recipientAcc := keeper.ak.GetModuleAccount(ctx, recipientModule)
    80  	if recipientAcc == nil {
    81  		panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule))
    82  	}
    83  
    84  	return keeper.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
    85  }
    86  
    87  // SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount.
    88  // It will panic if the module account does not exist.
    89  func (keeper BaseKeeper) SendCoinsFromAccountToModule(
    90  	ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins,
    91  ) error {
    92  	recipientAcc := keeper.ak.GetModuleAccount(ctx, recipientModule)
    93  	if recipientAcc == nil {
    94  		panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule))
    95  	}
    96  
    97  	return keeper.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
    98  }
    99  
   100  func (keeper BaseKeeper) isInactiveAddr(addr sdk.AccAddress) bool {
   101  	return keeper.inactiveAddrs[addr.String()]
   102  }
   103  
   104  // SendCoins transfers amt coins from a sending account to a receiving account.
   105  // This is wrapped bank the `SendKeeper` interface of `bank` module,
   106  // and checks if `toAddr` is a inactiveAddr managed by the module.
   107  func (keeper BaseKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error {
   108  	// if toAddr is smart contract, check the status of contract.
   109  	if keeper.isInactiveAddr(toAddr) {
   110  		return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", toAddr)
   111  	}
   112  
   113  	return keeper.BaseSendKeeper.SendCoins(ctx, fromAddr, toAddr, amt)
   114  }
   115  
   116  // AddToInactiveAddr adds the address to `inactiveAddr`.
   117  func (keeper BaseKeeper) AddToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) {
   118  	if !keeper.inactiveAddrs[address.String()] {
   119  		keeper.inactiveAddrs[address.String()] = true
   120  
   121  		keeper.addToInactiveAddr(ctx, address)
   122  	}
   123  }
   124  
   125  // DeleteFromInactiveAddr removes the address from `inactiveAddr`.
   126  func (keeper BaseKeeper) DeleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) {
   127  	if keeper.inactiveAddrs[address.String()] {
   128  		delete(keeper.inactiveAddrs, address.String())
   129  
   130  		keeper.deleteFromInactiveAddr(ctx, address)
   131  	}
   132  }
   133  
   134  // IsInactiveAddr returns if the address is added in inactiveAddr.
   135  func (keeper BaseKeeper) IsInactiveAddr(address sdk.AccAddress) bool {
   136  	return keeper.inactiveAddrs[address.String()]
   137  }
   138  
   139  func (keeper BaseKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error {
   140  	if keeper.deactMultiSend {
   141  		return sdkerrors.ErrNotSupported.Wrap("MultiSend was deactivated")
   142  	}
   143  
   144  	for _, out := range outputs {
   145  		if keeper.inactiveAddrs[out.Address] {
   146  			return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", out.Address)
   147  		}
   148  	}
   149  
   150  	return keeper.BaseSendKeeper.InputOutputCoins(ctx, inputs, outputs)
   151  }