github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/supply/internal/keeper/bank.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 6 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 7 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 8 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply/internal/types" 9 ) 10 11 // SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress. 12 // It will panic if the module account does not exist. 13 func (k Keeper) SendCoinsFromModuleToAccount( 14 ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, 15 ) error { 16 if k.bk.BlacklistedAddr(recipientAddr) { 17 return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "Address <%s> in blacklist is not allowed", recipientAddr) 18 } 19 senderAddr := k.GetModuleAddress(senderModule) 20 if senderAddr == nil { 21 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) 22 } 23 24 return k.bk.SendCoins(ctx, senderAddr, recipientAddr, amt) 25 } 26 27 // SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another. 28 // It will panic if either module account does not exist. 29 func (k Keeper) SendCoinsFromModuleToModule( 30 ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins, 31 ) error { 32 33 senderAddr := k.GetModuleAddress(senderModule) 34 if senderAddr == nil { 35 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) 36 } 37 38 recipientAcc := k.GetModuleAccount(ctx, recipientModule) 39 if recipientAcc == nil { 40 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) 41 } 42 43 return k.bk.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) 44 } 45 46 // SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount. 47 // It will panic if the module account does not exist. 48 func (k Keeper) SendCoinsFromAccountToModule( 49 ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins, 50 ) error { 51 recipientAcc := k.GetModuleAccount(ctx, recipientModule) 52 if recipientAcc == nil { 53 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) 54 } 55 56 // GetModuleAccount may create a new module account, we don't know does the gas consumed contains the gas of new account creation 57 ctx.UpdateToAccountCache(recipientAcc, 0) 58 59 return k.bk.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) 60 } 61 62 // DelegateCoinsFromAccountToModule delegates coins and transfers them from a 63 // delegator account to a module account. It will panic if the module account 64 // does not exist or is unauthorized. 65 func (k Keeper) DelegateCoinsFromAccountToModule( 66 ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins, 67 ) error { 68 69 recipientAcc := k.GetModuleAccount(ctx, recipientModule) 70 if recipientAcc == nil { 71 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)) 72 } 73 74 if !recipientAcc.HasPermission(types.Staking) { 75 panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to receive delegated coins", recipientModule)) 76 } 77 78 return k.bk.DelegateCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt) 79 } 80 81 // UndelegateCoinsFromModuleToAccount undelegates the unbonding coins and transfers 82 // them from a module account to the delegator account. It will panic if the 83 // module account does not exist or is unauthorized. 84 func (k Keeper) UndelegateCoinsFromModuleToAccount( 85 ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, 86 ) error { 87 88 acc := k.GetModuleAccount(ctx, senderModule) 89 if acc == nil { 90 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)) 91 } 92 93 if !acc.HasPermission(types.Staking) { 94 panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to undelegate coins", senderModule)) 95 } 96 97 return k.bk.UndelegateCoins(ctx, acc.GetAddress(), recipientAddr, amt) 98 } 99 100 // MintCoins creates new coins from thin air and adds it to the module account. 101 // It will panic if the module account does not exist or is unauthorized. 102 func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { 103 acc := k.GetModuleAccount(ctx, moduleName) 104 if acc == nil { 105 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) 106 } 107 108 if !acc.HasPermission(types.Minter) { 109 panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to mint tokens", moduleName)) 110 } 111 112 _, err := k.bk.AddCoins(ctx, acc.GetAddress(), amt) 113 if err != nil { 114 return err 115 } 116 117 // update supply 118 for i := 0; i < len(amt); i++ { 119 k.inflate(ctx, amt[i].Denom, amt[i].Amount) 120 } 121 122 logger := k.Logger(ctx) 123 logger.Info(fmt.Sprintf("minted %s from %s module account", amt.String(), moduleName)) 124 125 return nil 126 } 127 128 // BurnCoins burns coins deletes coins from the balance of the module account. 129 // It will panic if the module account does not exist or is unauthorized. 130 func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error { 131 acc := k.GetModuleAccount(ctx, moduleName) 132 if acc == nil { 133 panic(sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)) 134 } 135 136 if !acc.HasPermission(types.Burner) { 137 panic(sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to burn tokens", moduleName)) 138 } 139 140 _, err := k.bk.SubtractCoins(ctx, acc.GetAddress(), amt) 141 if err != nil { 142 return err 143 } 144 145 // update supply 146 for i := 0; i < len(amt); i++ { 147 if err = k.deflate(ctx, amt[i].Denom, amt[i].Amount); err != nil { 148 return err 149 } 150 } 151 152 logger := k.Logger(ctx) 153 logger.Info(fmt.Sprintf("burned %s from %s module account", amt.String(), moduleName)) 154 155 return nil 156 } 157 158 // GetSupplyByDenom gets the amount of a token supply from the store 159 func (k Keeper) GetSupplyByDenom(ctx sdk.Context, denom string) sdk.Dec { 160 tokenSupplyAmount := sdk.ZeroDec() 161 bytes := ctx.KVStore(k.storeKey).Get(getTokenSupplyKey(denom)) 162 if bytes == nil { 163 return tokenSupplyAmount 164 } 165 166 k.cdc.MustUnmarshalBinaryLengthPrefixed(bytes, &tokenSupplyAmount) 167 return tokenSupplyAmount 168 } 169 170 // inflate adds the amount of a token in the store 171 func (k Keeper) inflate(ctx sdk.Context, tokenSymbol string, amount sdk.Dec) { 172 if amount.Equal(sdk.ZeroDec()) { 173 return 174 } 175 176 originalSupplyAmount := k.GetSupplyByDenom(ctx, tokenSymbol) 177 k.setTokenSupplyAmount(ctx, tokenSymbol, originalSupplyAmount.Add(amount)) 178 } 179 180 // deflate subtracts the amount of a token from the original in the store 181 func (k Keeper) deflate(ctx sdk.Context, tokenSymbol string, deflationAmount sdk.Dec) error { 182 currentSupplyAmount := k.GetSupplyByDenom(ctx, tokenSymbol) 183 supplyAmount := currentSupplyAmount.Sub(deflationAmount) 184 if supplyAmount.IsNegative() { 185 return types.ErrInvalidDeflation 186 } 187 188 k.setTokenSupplyAmount(ctx, tokenSymbol, supplyAmount) 189 return nil 190 }