/
denom.go
93 lines (84 loc) · 3.22 KB
/
denom.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package keeper
import (
"errors"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/provenance-io/provenance/x/marker/types"
)
// ValidateDenomMetadata performs extended validation of the denom metadata fields.
// It checks that:
// - The proposed metadata passes ValidateDenomMetadataBasic.
// - The marker status is one that allows the denom metadata to be manipulated.
// - All DenomUnit Denom and Aliases strings pass the unrestricted denom regex.
// If there is an existing record:
// - The Base doesn't change.
// If marker status is active or finalized:
// - No DenomUnit entries are removed.
// - DenomUnit Denom fields aren't changed.
// - No aliases are removed from a DenomUnit.
func (k Keeper) ValidateDenomMetadata(ctx sdk.Context, proposed banktypes.Metadata, existing *banktypes.Metadata, markerStatus types.MarkerStatus) error {
// Run all of the basic validation.
if err := types.ValidateDenomMetadataBasic(proposed); err != nil {
return fmt.Errorf("invalid proposed metadata: %w", err)
}
// Make sure the marker is in a status to allow any denom metadata adding or updating.
if !markerStatus.IsOneOf(types.StatusProposed, types.StatusActive, types.StatusFinalized) {
return fmt.Errorf("cannot add or update denom metadata for a marker with status [%s]", markerStatus)
}
// Make sure all the DenomUnit Denom and alias strings pass the extra validation regex.
for _, du := range proposed.DenomUnits {
if err := k.ValidateUnrestictedDenom(ctx, du.Denom); err != nil {
return fmt.Errorf("invalid denom unit denom: %w", err)
}
for _, a := range du.Aliases {
if err := k.ValidateUnrestictedDenom(ctx, a); err != nil {
return fmt.Errorf("invalid denom unit alias: %w", err)
}
}
}
if existing != nil {
// No matter what, the base cannot change.
if proposed.Base != existing.Base {
return errors.New("denom metadata base value cannot be changed")
}
// Some further restrictions apply for active and finalized entries.
// Note: If you add or remove a status here, you might also need to alter a similar call above.
if markerStatus.IsOneOf(types.StatusActive, types.StatusFinalized) {
for _, edu := range existing.DenomUnits {
// Make sure the existing DenomUnit hasn't been removed.
var pdu *banktypes.DenomUnit
for _, du := range proposed.DenomUnits {
if edu.Exponent == du.Exponent {
pdu = du
break
}
}
if pdu == nil {
return fmt.Errorf("cannot remove denom unit [%s] for a marker with status [%s]",
edu.Denom, markerStatus)
}
// Make sure the Denom value hasn't changed.
if edu.Denom != pdu.Denom {
return fmt.Errorf("cannot change denom unit Denom from [%s] to [%s] for a marker with status [%s]",
edu.Denom, pdu.Denom, markerStatus)
}
// Make sure none of the aliases have been removed.
for _, ea := range edu.Aliases {
found := false
for _, pa := range pdu.Aliases {
if ea == pa {
found = true
break
}
}
if !found {
return fmt.Errorf("cannot remove alias [%s] from denom unit [%s] for a marker with status [%s]",
ea, edu.Denom, markerStatus)
}
}
}
}
}
return nil
}