Skip to content

Commit

Permalink
backport #8479 (#8486)
Browse files Browse the repository at this point in the history
  • Loading branch information
fedekunze authored Feb 2, 2021
1 parent f8a6987 commit a72c975
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ Ref: https://keepachangelog.com/en/1.0.0/

# Changelog

## Unreleased

### Improvements

* (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Aditional client denom metadata validation for `base` and `display` denoms.

## [v0.41.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.0) - 2021-01-26

### State Machine Breaking
Expand Down
39 changes: 37 additions & 2 deletions x/bank/types/metadata.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package types

import (
"errors"
"fmt"
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
)

// Validate performs a basic validation of the coin metadata fields
// Validate performs a basic validation of the coin metadata fields. It checks:
// - 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 err := sdk.ValidateDenom(m.Base); err != nil {
return fmt.Errorf("invalid metadata base denom: %w", err)
Expand All @@ -17,19 +23,48 @@ func (m Metadata) Validate() error {
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 _, denomUnit := range m.DenomUnits {

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
}

Expand Down
55 changes: 54 additions & 1 deletion x/bank/types/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestMetadataValidate(t *testing.T) {
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{"uatom", uint32(0), []string{"microatom"}},
{"uatom", uint32(0), []string{"microatom"}},
{"uatom", uint32(1), []string{"microatom"}},
},
Base: "uatom",
Display: "atom",
Expand Down Expand Up @@ -94,6 +94,59 @@ func TestMetadataValidate(t *testing.T) {
},
true,
},
{
"no base denom unit",
types.Metadata{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{"matom", uint32(3), []string{"milliatom"}},
{"atom", uint32(6), nil},
},
Base: "uatom",
Display: "atom",
},
true,
},
{
"base denom exponent not zero",
types.Metadata{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{"uatom", uint32(1), []string{"microatom"}},
{"matom", uint32(3), []string{"milliatom"}},
{"atom", uint32(6), nil},
},
Base: "uatom",
Display: "atom",
},
true,
},
{
"no display denom unit",
types.Metadata{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{"uatom", uint32(0), []string{"microatom"}},
},
Base: "uatom",
Display: "atom",
},
true,
},
{
"denom units not sorted",
types.Metadata{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{"uatom", uint32(0), []string{"microatom"}},
{"atom", uint32(6), nil},
{"matom", uint32(3), []string{"milliatom"}},
},
Base: "uatom",
Display: "atom",
},
true,
},
}

for _, tc := range testCases {
Expand Down

0 comments on commit a72c975

Please sign in to comment.