Skip to content
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
31 changes: 18 additions & 13 deletions x/tokenfactory/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,31 +96,36 @@ func (server msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.
return nil, err
}

// verify that denom is an x/tokenfactory denom, and if it is not, then sudo mint capability must be enabled
if _, _, err := types.DeconstructDenom(msg.Amount.GetDenom()); err == nil {
// Denomination *MUST* already exist:
_, denomExists := server.bankKeeper.GetDenomMetaData(ctx, msg.Amount.Denom)
if !denomExists {
return nil, types.ErrDenomDoesNotExist.Wrapf("denom: %s", msg.Amount.Denom)
}
} else {
sudoEnabled := server.IsCapabilityEnabled(types.EnableSudoMint)
if !sudoEnabled {
return nil, types.ErrCapabilityNotEnabled.Wrapf("the '%s' capability is NOT enabled", types.EnableSudoMint)
}
}

// The following code section is exclusively for case when:
// * either burning someone's else's tokens
// * or burning own tokens, but EnableBurnOwn is disabled
// In both cases denom admin must be the one executing the burn.
if !(isBurningOwn && server.IsCapabilityEnabled(types.EnableBurnOwn)) {
// Denom admin *can* burn its own tokens even if the EnableBurnFrom is *disabled*.
// This is sensical, as the admin burns it sown tokens and *not* tokens from another account.
if !isBurningOwn && !server.IsCapabilityEnabled(types.EnableBurnFrom) {
return nil, types.ErrCapabilityNotEnabled.Wrapf("the '%s' capability is NOT enabled", types.EnableBurnFrom)
}

// verify that denom is an x/tokenfactory denom, and if it is not, then sudo mint capability must be enabled
if _, _, err := types.DeconstructDenom(msg.Amount.GetDenom()); err == nil {
// Denomination *MUST* already exist:
_, denomExists := server.bankKeeper.GetDenomMetaData(ctx, msg.Amount.Denom)
if !denomExists {
return nil, types.ErrDenomDoesNotExist.Wrapf("denom: %s", msg.Amount.Denom)
}
} else {
sudoEnabled := server.IsCapabilityEnabled(types.EnableSudoMint)
if !sudoEnabled {
return nil, types.ErrCapabilityNotEnabled.Wrapf("the '%s' capability is NOT enabled", types.EnableSudoMint)
}
if !isRegistered {
return nil, types.ErrUnauthorized.Wrapf("the '%s' denomination is not registered in tokenfactory", msg.Amount.GetDenom())
}

if !isRegistered || msg.Sender != authorityMetadata.GetAdmin() {
if msg.Sender != authorityMetadata.GetAdmin() {
return nil, types.ErrUnauthorized.Wrapf("the '%s' sender is NOT '%s' admin of the '%s' denomination", msg.Sender, authorityMetadata.GetAdmin(), msg.Amount.GetDenom())
}
}
Expand Down
24 changes: 16 additions & 8 deletions x/tokenfactory/types/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ package types
const (
EnableSetMetadata = "enable_metadata"
EnableForceTransfer = "enable_force_transfer"
// Allows to *ANY* owner of tokens (with *ANY* denomination) to burn these self-owned tokens.
// If disabled (not present), only admin of a denom or sudoer can execute the burn *IF* EnableBurnFrom is enabled.
// EnableBurnOwn Allows owner of tokens with *any* denomination registered in tokenfactory to burn these self-owned
// tokens.
// If disabled (not present), only admin of a denom can execute the burn (*IF* EnableBurnFrom is enabled).
EnableBurnOwn = "enable_burn_own"
// If enabled, token owner can burn its own tokens of any denomination which is *NOT* registred in tokenfactory.
// This capability depends on EnableBurnOwn = so, if enabled, it has *no* effect if the EnableBurnOwn is not enabled.
// EnableBurnOwnUnregistered If enabled, token owner can burn its own tokens of denominations, which are *not*
// registered in tokenfactory.
// This EnableBurnOwnUnregistered has an effect only if the EnableBurnOwn is enabled as well.
EnableBurnOwnUnregistered = "enable_burn_unregistered"
EnableBurnFrom = "enable_burn_from"
// Allows addresses registered as sudo admins imn genesis store to mint tokens of *ANY* denominations.
// NOTE: with SudoMint enabled, the sudo admin can mint `any` token, not just tokenfactory tokens.
// This is intended behavior as requested by other teams, rather than having its own module with very minor logic.
// If you do not wish for this behavior, then either do NOT enable this capability, or implement your own logic.
// EnableSudoMint is a High level enabler for minting and burning unbound denominations(= any denominations which
// do *NOT* conform to the tokenfactory denomination format `factory/<CREATOR_ADDRESS>/<SUB_DENOM>`).
// In order to enable minting of unbound denominations, such denominations *MUST* be registered in tokenfactory and
// EnableSudoMint must be enabled.
// By design, it *NOT* possible to register unbound denomination via tokenfactory MsgCreateDenom message, instead
// it *MUST* be registered either in `genesis.json` file, or during chain software upgrade using the
// `UnboundDenomCreator` interface.
// In order to enable burning of unbound denominations, the EnableSudoMint must be enabled. It is possible to burn
// unbound denominations which are not registered in token factory, however both - the EnableBurnOwn and
// EnableBurnOwnUnregistered must be enabled.
EnableSudoMint = "enable_admin_sudo_mint"
// EnableCommunityPoolFeeFunding sends tokens to the community pool when a new fee is charged (if one is set in params).
// This is useful for ICS chains, or networks who wish to just have the fee tokens burned (not gas fees, just the extra on top).
Expand Down
Loading