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 }