Merge PR #4681: Add check before minting empty coins

This commit is contained in:
Federico Kunze 2019-07-05 14:32:42 +02:00 committed by Alexander Bezobchuk
parent 01d4425658
commit e0b55a89a7
6 changed files with 41 additions and 39 deletions

View File

@ -0,0 +1,2 @@
#4681 panic on invalid amount on `MintCoins` and `BurnCoins`
- skip minting if inflation is set to zero

View File

@ -97,6 +97,10 @@ func (k Keeper) BondedRatio(ctx sdk.Context) sdk.Dec {
// MintCoins implements an alias call to the underlying supply keeper's
// MintCoins to be used in BeginBlocker.
func (k Keeper) MintCoins(ctx sdk.Context, newCoins sdk.Coins) sdk.Error {
if newCoins.Empty() {
// skip as no coins need to be minted
return nil
}
return k.supplyKeeper.MintCoins(ctx, types.ModuleName, newCoins)
}

View File

@ -37,6 +37,7 @@ func (k Keeper) notBondedTokensToBonded(ctx sdk.Context, tokens sdk.Int) {
// burnBondedTokens removes coins from the bonded pool module account
func (k Keeper) burnBondedTokens(ctx sdk.Context, amt sdk.Int) sdk.Error {
if !amt.IsPositive() {
// skip as no coins need to be burned
return nil
}
coins := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), amt))
@ -46,6 +47,7 @@ func (k Keeper) burnBondedTokens(ctx sdk.Context, amt sdk.Int) sdk.Error {
// burnNotBondedTokens removes coins from the not bonded pool module account
func (k Keeper) burnNotBondedTokens(ctx sdk.Context, amt sdk.Int) sdk.Error {
if !amt.IsPositive() {
// skip as no coins need to be burned
return nil
}
coins := sdk.NewCoins(sdk.NewCoin(k.BondDenom(ctx), amt))

View File

@ -6,7 +6,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/supply/internal/types"
)
// GetModuleAddress returns a an address based on the name
// GetModuleAddress returns a an address based on the module name
func (k Keeper) GetModuleAddress(moduleName string) sdk.AccAddress {
permAddr, ok := k.permAddrs[moduleName]
if !ok {
@ -15,7 +15,7 @@ func (k Keeper) GetModuleAddress(moduleName string) sdk.AccAddress {
return permAddr.address
}
// GetModuleAddressAndPermission returns an address and permission based on the name
// GetModuleAddressAndPermission returns an address and permission based on the module name
func (k Keeper) GetModuleAddressAndPermission(moduleName string) (addr sdk.AccAddress, permission string) {
permAddr, ok := k.permAddrs[moduleName]
if !ok {
@ -24,7 +24,8 @@ func (k Keeper) GetModuleAddressAndPermission(moduleName string) (addr sdk.AccAd
return permAddr.address, permAddr.permission
}
// GetModuleAccount gets the module account to the auth account store
// GetModuleAccountAndPermission gets the module account from the auth account store and its
// registered permission
func (k Keeper) GetModuleAccountAndPermission(ctx sdk.Context, moduleName string) (exported.ModuleAccountI, string) {
addr, perm := k.GetModuleAddressAndPermission(moduleName)
if addr == nil {
@ -48,7 +49,7 @@ func (k Keeper) GetModuleAccountAndPermission(ctx sdk.Context, moduleName string
return maccI, perm
}
// GetModuleAccount gets the module account to the auth account store
// GetModuleAccount gets the module account from the auth account store
func (k Keeper) GetModuleAccount(ctx sdk.Context, moduleName string) exported.ModuleAccountI {
acc, _ := k.GetModuleAccountAndPermission(ctx, moduleName)
return acc

View File

@ -28,12 +28,12 @@ func (k Keeper) SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recip
}
// create the account if it doesn't yet exist
recipientAddr := k.GetModuleAccount(ctx, recipientModule).GetAddress()
if recipientAddr == nil {
recipientAcc := k.GetModuleAccount(ctx, recipientModule)
if recipientAcc == nil {
panic(fmt.Sprintf("module account %s isn't able to be created", recipientModule))
}
return k.bk.SendCoins(ctx, senderAddr, recipientAddr, amt)
return k.bk.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
}
// SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount
@ -41,12 +41,12 @@ func (k Keeper) SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.Acc
recipientModule string, amt sdk.Coins) sdk.Error {
// create the account if it doesn't yet exist
recipientAddr := k.GetModuleAccount(ctx, recipientModule).GetAddress()
if recipientAddr == nil {
recipientAcc := k.GetModuleAccount(ctx, recipientModule)
if recipientAcc == nil {
panic(fmt.Sprintf("module account %s isn't able to be created", recipientModule))
}
return k.bk.SendCoins(ctx, senderAddr, recipientAddr, amt)
return k.bk.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
}
// DelegateCoinsFromAccountToModule delegates coins and transfers
@ -55,12 +55,12 @@ func (k Keeper) DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk
recipientModule string, amt sdk.Coins) sdk.Error {
// create the account if it doesn't yet exist
recipientAddr := k.GetModuleAccount(ctx, recipientModule).GetAddress()
if recipientAddr == nil {
recipientAcc := k.GetModuleAccount(ctx, recipientModule)
if recipientAcc == nil {
panic(fmt.Sprintf("module account %s isn't able to be created", recipientModule))
}
return k.bk.DelegateCoins(ctx, senderAddr, recipientAddr, amt)
return k.bk.DelegateCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
}
// UndelegateCoinsFromModuleToAccount undelegates the unbonding coins and transfers
@ -76,27 +76,25 @@ func (k Keeper) UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule
return k.bk.UndelegateCoins(ctx, senderAddr, recipientAddr, amt)
}
// MintCoins creates new coins from thin air and adds it to the MinterAccount.
// Panics if the name maps to a non-minter module account.
// MintCoins creates new coins from thin air and adds it to the module account.
// Panics if the name maps to a non-minter module account or if the amount is invalid.
func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error {
if amt.Empty() {
panic("cannot mint empty coins")
}
// create the account if it doesn't yet exist
acc, perm := k.GetModuleAccountAndPermission(ctx, moduleName)
addr := acc.GetAddress()
if addr == nil {
if acc == nil {
return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleName))
}
addr := acc.GetAddress()
if perm != types.Minter {
panic(fmt.Sprintf("Account %s does not have permissions to mint tokens", moduleName))
panic(fmt.Sprintf("module account %s does not have permissions to mint tokens", moduleName))
}
_, err := k.bk.AddCoins(ctx, addr, amt)
if err != nil {
return err
panic(err)
}
// update total supply
@ -110,11 +108,9 @@ func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk
return nil
}
// BurnCoins burns coins deletes coins from the balance of the module account
// BurnCoins burns coins deletes coins from the balance of the module account.
// Panics if the name maps to a non-burner module account or if the amount is invalid.
func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk.Error {
if amt.Empty() {
panic("cannot burn empty coins")
}
addr, perm := k.GetModuleAddressAndPermission(moduleName)
if addr == nil {
@ -122,12 +118,12 @@ func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) sdk
}
if perm != types.Burner {
panic(fmt.Sprintf("Account %s does not have permissions to burn tokens", moduleName))
panic(fmt.Sprintf("module account %s does not have permissions to burn tokens", moduleName))
}
_, err := k.bk.SubtractCoins(ctx, addr, amt)
if err != nil {
return err
panic(err)
}
// update total supply

View File

@ -81,35 +81,32 @@ func TestMintCoins(t *testing.T) {
initialSupply := keeper.GetSupply(ctx)
require.Panics(t, func() { keeper.MintCoins(ctx, "", initCoins) })
require.Error(t, keeper.MintCoins(ctx, "", initCoins), "no module account")
require.Panics(t, func() { keeper.MintCoins(ctx, types.Burner, initCoins) }, "invalid permission")
require.Panics(t, func() { keeper.MintCoins(ctx, types.Minter, sdk.Coins{sdk.Coin{"denom", sdk.NewInt(-10)}}) }, "insufficient coins") //nolint
err := keeper.MintCoins(ctx, types.Minter, initCoins)
require.NoError(t, err)
require.Equal(t, initCoins, getCoinsByName(ctx, keeper, types.Minter))
require.Equal(t, initialSupply.Total.Add(initCoins), keeper.GetSupply(ctx).Total)
require.Panics(t, func() { keeper.MintCoins(ctx, types.Burner, initCoins) })
}
func TestBurnCoins(t *testing.T) {
nAccs := int64(4)
ctx, _, keeper := createTestInput(t, false, initialPower, nAccs)
err := burnerAcc.SetCoins(initCoins)
require.NoError(t, err)
require.NoError(t, burnerAcc.SetCoins(initCoins))
keeper.SetModuleAccount(ctx, burnerAcc)
initialSupply := keeper.GetSupply(ctx)
initialSupply.Inflate(initCoins)
keeper.SetSupply(ctx, initialSupply)
err = keeper.BurnCoins(ctx, "", initCoins)
require.Error(t, err)
require.Error(t, keeper.BurnCoins(ctx, "", initCoins), "no module account")
require.Panics(t, func() { keeper.BurnCoins(ctx, types.Minter, initCoins) }, "invalid permission")
require.Panics(t, func() { keeper.BurnCoins(ctx, types.Burner, initialSupply.Total) }, "insufficient coins")
err = keeper.BurnCoins(ctx, types.Burner, initialSupply.Total)
require.Error(t, err)
err = keeper.BurnCoins(ctx, types.Burner, initCoins)
err := keeper.BurnCoins(ctx, types.Burner, initCoins)
require.NoError(t, err)
require.Equal(t, sdk.Coins(nil), getCoinsByName(ctx, keeper, types.Burner))
require.Equal(t, initialSupply.Total.Sub(initCoins), keeper.GetSupply(ctx).Total)