cosmos-sdk/x/bank/types/metadata.go

101 lines
2.6 KiB
Go

package types
import (
"errors"
"fmt"
"strings"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Validate performs a basic validation of the coin metadata fields. It checks:
// - Name and Symbol are not blank
// - Base and Display denominations are valid coin denominations
// - Base and Display denominations are present in the DenomUnit slice
// - Base denomination has exponent 0
// - Denomination units are sorted in ascending order
// - Denomination units not duplicated
func (m Metadata) Validate() error {
if strings.TrimSpace(m.Name) == "" {
return errors.New("name field cannot be blank")
}
if strings.TrimSpace(m.Symbol) == "" {
return errors.New("symbol field cannot be blank")
}
if err := sdk.ValidateDenom(m.Base); err != nil {
return fmt.Errorf("invalid metadata base denom: %w", err)
}
if err := sdk.ValidateDenom(m.Display); err != nil {
return fmt.Errorf("invalid metadata display denom: %w", err)
}
var (
hasDisplay bool
currentExponent uint32 // check that the exponents are increasing
)
seenUnits := make(map[string]bool)
for i, denomUnit := range m.DenomUnits {
// The first denomination unit MUST be the base
if i == 0 {
// validate denomination and exponent
if denomUnit.Denom != m.Base {
return fmt.Errorf("metadata's first denomination unit must be the one with base denom '%s'", m.Base)
}
if denomUnit.Exponent != 0 {
return fmt.Errorf("the exponent for base denomination unit %s must be 0", m.Base)
}
} else if currentExponent >= denomUnit.Exponent {
return errors.New("denom units should be sorted asc by exponent")
}
currentExponent = denomUnit.Exponent
if seenUnits[denomUnit.Denom] {
return fmt.Errorf("duplicate denomination unit %s", denomUnit.Denom)
}
if denomUnit.Denom == m.Display {
hasDisplay = true
}
if err := denomUnit.Validate(); err != nil {
return err
}
seenUnits[denomUnit.Denom] = true
}
if !hasDisplay {
return fmt.Errorf("metadata must contain a denomination unit with display denom '%s'", m.Display)
}
return nil
}
// Validate performs a basic validation of the denomination unit fields
func (du DenomUnit) Validate() error {
if err := sdk.ValidateDenom(du.Denom); err != nil {
return fmt.Errorf("invalid denom unit: %w", err)
}
seenAliases := make(map[string]bool)
for _, alias := range du.Aliases {
if seenAliases[alias] {
return fmt.Errorf("duplicate denomination unit alias %s", alias)
}
if strings.TrimSpace(alias) == "" {
return fmt.Errorf("alias for denom unit %s cannot be blank", du.Denom)
}
seenAliases[alias] = true
}
return nil
}