Skip to content

Commit

Permalink
refactor(assets): care out ValidateID function
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxMustermann2 committed Apr 3, 2024
1 parent 5ab5ddc commit 49efe17
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 24 deletions.
39 changes: 16 additions & 23 deletions x/assets/types/genesis.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package types

import (
"strings"

errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -115,38 +113,21 @@ func (gs GenesisState) Validate() error {
for _, depositByStaker := range gs.Deposits {
stakerID := depositByStaker.StakerID
// validate the stakerID
if stakerID != strings.ToLower(stakerID) {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"stakerID not lowercase: %s",
stakerID,
)
}
var stakerClientAddress string
var lzID uint64
var stakerClientChainID uint64
var err error
if stakerClientAddress, lzID, err = ParseID(stakerID); err != nil {
if _, stakerClientChainID, err = ValidateID(stakerID, true); err != nil {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"invalid stakerID: %s",
stakerID,
)
}
// check that the chain is registered
if _, ok := lzIDs[lzID]; !ok {
if _, ok := lzIDs[stakerClientChainID]; !ok {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"unknown LayerZeroChainID for staker %s: %d",
stakerID, lzID,
)
}
// build for 0x addresses only.
// TODO: consider removing this check for non-EVM client chains.
if !common.IsHexAddress(stakerClientAddress) {
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"not hex staker address for staker %s: %s",
stakerID, stakerClientAddress,
stakerID, stakerClientChainID,
)
}
// check that it is not a duplicate
Expand All @@ -172,6 +153,18 @@ func (gs GenesisState) Validate() error {
stakerID, assetID,
)
}
// #nosec G703 // if it's invalid, we will not reach here.
_, assetClientChainID, _ := ParseID(assetID)
if assetClientChainID != stakerClientChainID {
// we can reach here if there are multiple chains
// and it tries to deposit assets from one chain
// under a staker from another chain.
return errorsmod.Wrapf(
ErrInvalidGenesisData,
"mismatched client chain IDs for staker %s and asset %s",
stakerID, assetID,
)
}
// check that it is not a duplicate
if _, ok := tokensForStaker[assetID]; ok {
return errorsmod.Wrapf(
Expand Down
53 changes: 52 additions & 1 deletion x/assets/types/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,11 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
},
expPass: false,
malleate: func(gs *types.GenesisState) {
gs.Deposits[0].StakerID = "fakeStaker_0x63"
stakerID, _ := types.GetStakeIDAndAssetIDFromStr(
usdtClientChainAsset.LayerZeroChainID+1,
ethAddress.String(), usdtClientChainAsset.Address,
)
gs.Deposits[0].StakerID = stakerID
},
unmalleate: func(gs *types.GenesisState) {
gs.Deposits[0].StakerID = stakerID
Expand Down Expand Up @@ -303,6 +307,52 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
gs.Deposits[0].Deposits[0].AssetID = assetID
},
},
{
name: "invalid genesis due to different chain ids for asset and staker",
genState: &types.GenesisState{
Params: types.DefaultParams(),
ClientChains: []types.ClientChainInfo{
ethClientChain, ethClientChain,
},
Tokens: []types.StakingAssetInfo{
stakingInfo, stakingInfo,
},
Deposits: []types.DepositsByStaker{genesisDeposit, genesisDeposit},
},
expPass: false,
malleate: func(gs *types.GenesisState) {
// new chain with different layer zero chain id
gs.ClientChains[1].LayerZeroChainID += 1
// new asset (old asset is a pointer so can't alter that)
tokenAddress := utiltx.GenerateAddress().String()
usdcClientChainAsset := types.AssetInfo{
Name: "Circle USD",
Symbol: "USDC",
Address: tokenAddress,
Decimals: 18,
LayerZeroChainID: ethClientChain.LayerZeroChainID + 1,
MetaInfo: "Circle USD token",
TotalSupply: math.NewInt(500000000),
}
stakingInfo := types.StakingAssetInfo{
AssetBasicInfo: &usdcClientChainAsset,
StakingTotalAmount: math.NewInt(0),
}
gs.Tokens[1] = stakingInfo
stakerID, _ := types.GetStakeIDAndAssetIDFromStr(
usdtClientChainAsset.LayerZeroChainID+1,
ethAddress.String(), usdtClientChainAsset.Address,
)
// change stakerID to be that of the second chain
gs.Deposits[1].StakerID = stakerID
// but keep the assetID the same
},
unmalleate: func(gs *types.GenesisState) {
gs.ClientChains[1].LayerZeroChainID -= 1
gs.Tokens[1].AssetBasicInfo.LayerZeroChainID -= 1
gs.Deposits[1].StakerID = stakerID
},
},
{
name: "invalid genesis due to duplicate asset id for staker",
genState: &types.GenesisState{
Expand Down Expand Up @@ -480,5 +530,6 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
if tc.unmalleate != nil {
tc.unmalleate(tc.genState)
}
// fmt.Println(tc.name, ",", err)
}
}
24 changes: 24 additions & 0 deletions x/assets/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,27 @@ func ParseID(key string) (string, uint64, error) {
}
return keys[0], id, nil
}

func ValidateID(key string, validateEth bool) (string, uint64, error) {
// check lowercase
if key != strings.ToLower(key) {
return "", 0, errorsmod.Wrapf(ErrParseAssetsStateKey, "ID not lowercase: %s", key)
}
// parse it
var clientAddress string
var lzID uint64
var err error
if clientAddress, lzID, err = ParseID(key); err != nil {
return "", 0, errorsmod.Wrapf(
ErrParseAssetsStateKey, "invalid key: %s", key,
)
}
// check hex address
if validateEth && !common.IsHexAddress(clientAddress) {
return "", 0, errorsmod.Wrapf(
ErrParseAssetsStateKey, "not hex address %s: %s",
key, clientAddress,
)
}
return clientAddress, lzID, nil
}

0 comments on commit 49efe17

Please sign in to comment.