Skip to content

Commit

Permalink
add more checks to zrc20 is valid
Browse files Browse the repository at this point in the history
  • Loading branch information
fbac committed Nov 19, 2024
1 parent ef1de9c commit a19085e
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 13 deletions.
2 changes: 1 addition & 1 deletion precompiles/bank/method_deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (c *Contract) deposit(
// this way we map ZRC20 addresses to cosmos denoms "zevm/0x12345".
// - Mint coins to the fungible module.
// - Send coins from fungible to the caller.
coinSet, err := precompiletypes.CreateCoinSet(zrc20Addr, amount)
coinSet, err := precompiletypes.CreateZRC20CoinSet(zrc20Addr, amount)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion precompiles/bank/method_withdraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (c *Contract) withdraw(
}
}

coinSet, err := precompiletypes.CreateCoinSet(zrc20Addr, amount)
coinSet, err := precompiletypes.CreateZRC20CoinSet(zrc20Addr, amount)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion precompiles/staking/method_distribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (c *Contract) distribute(
}

// Create the coinSet in advance, if this step fails do not lock ZRC20.
coinSet, err := precompiletypes.CreateCoinSet(zrc20Addr, amount)
coinSet, err := precompiletypes.CreateZRC20CoinSet(zrc20Addr, amount)
if err != nil {
return nil, err
}
Expand Down
31 changes: 31 additions & 0 deletions precompiles/staking/method_get_validators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"cosmossdk.io/math"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
precompiletypes "github.com/zeta-chain/node/precompiles/types"
"github.com/zeta-chain/node/testutil/sample"
Expand Down Expand Up @@ -44,6 +45,36 @@ func Test_GetValidators(t *testing.T) {
require.Len(t, list, 0)
})

t.Run("should return an empty list for an invalid staker", func(t *testing.T) {
/* ARRANGE */
s := newTestSuite(t)

// Create validator.
validator := sample.Validator(t, rand.New(rand.NewSource(42)))
s.sdkKeepers.StakingKeeper.SetValidator(s.ctx, validator)

/* ACT */
// Call getRewards.
getValidatorsMethod := s.stkContractABI.Methods[GetValidatorsMethodName]

s.mockVMContract.Input = packInputArgs(
t,
getValidatorsMethod,
[]interface{}{common.Address{}}...,
)

bytes, err := s.stkContract.Run(s.mockEVM, s.mockVMContract, false)
require.NoError(t, err)

res, err := getValidatorsMethod.Outputs.Unpack(bytes)
require.NoError(t, err)
require.NotEmpty(t, res)

list, ok := res[0].([]string)
require.True(t, ok)
require.Len(t, list, 0)
})

t.Run("should return staker's validator list", func(t *testing.T) {
/* ARRANGE */
s := newTestSuite(t)
Expand Down
20 changes: 18 additions & 2 deletions precompiles/types/coin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ func ZRC20ToCosmosDenom(ZRC20Address common.Address) string {
return config.ZRC20DenomPrefix + ZRC20Address.String()
}

func CreateCoinSet(zrc20address common.Address, amount *big.Int) (sdk.Coins, error) {
func CreateZRC20CoinSet(zrc20address common.Address, amount *big.Int) (sdk.Coins, error) {
defer func() {
if r := recover(); r != nil {
return
}
}()

if (zrc20address == common.Address{}) {
return nil, &ErrInvalidAddr{
Got: zrc20address.String(),
Reason: "empty address",
}
}

Check warning on line 32 in precompiles/types/coin.go

View check run for this annotation

Codecov / codecov/patch

precompiles/types/coin.go#L28-L32

Added lines #L28 - L32 were not covered by tests

denom := ZRC20ToCosmosDenom(zrc20address)

coin := sdk.NewCoin(denom, math.NewIntFromBigInt(amount))
Expand Down Expand Up @@ -53,5 +60,14 @@ func CreateCoinSet(zrc20address common.Address, amount *big.Int) (sdk.Coins, err

// CoinIsZRC20 checks if a given coin is a ZRC20 coin based on its denomination.
func CoinIsZRC20(denom string) bool {
return strings.HasPrefix(denom, config.ZRC20DenomPrefix)
// Fail fast if the prefix is not set.
if !strings.HasPrefix(denom, config.ZRC20DenomPrefix) {
return false
}

// Prefix is correctly set, extract the zrc20 address.
zrc20Addr := strings.TrimPrefix(denom, config.ZRC20DenomPrefix)

// Return true only if address is not empty and is a valid hex address.
return common.HexToAddress(zrc20Addr) != common.Address{} && common.IsHexAddress(zrc20Addr)
}
17 changes: 9 additions & 8 deletions precompiles/types/coin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func Test_createCoinSet(t *testing.T) {
tokenDenom := ZRC20ToCosmosDenom(tokenAddr)
amount := big.NewInt(100)

coinSet, err := CreateCoinSet(tokenAddr, amount)
coinSet, err := CreateZRC20CoinSet(tokenAddr, amount)
require.NoError(t, err, "createCoinSet should not return an error")
require.NotNil(t, coinSet, "coinSet should not be nil")

Expand All @@ -34,18 +34,19 @@ func Test_CoinIsZRC20(t *testing.T) {
denom string
expected bool
}{
{"zrc20/0x0123456789abcdef", true},
{"zrc20/0xabcdef0123456789", true},
{"zrc200xabcdef", false},
{"foo/0x0123456789", false},
{"", false}, // Empty string.
{"zrc20/", false}, // Missing address.
{"zrc20/0x514910771af9ca656af840dff83e8264ecf986ca", true}, // Valid ZRC20 address.
{"zrc20/0xCa14007Eff0dB1f8135f4C25B34De49AB0d42766", true}, // Valid ZRC20 address.
{"zrc200xabcdef", false}, // Malformed prefix.
{"foo/0x0123456789", false}, // Invalid prefix.
{"ZRC20/0x0123456789abcdef", false}, // Invalid prefix.
}

for _, tt := range test {
t.Run(tt.denom, func(t *testing.T) {
result := CoinIsZRC20(tt.denom)
if result != tt.expected {
t.Errorf("got %v, want %v", result, tt.expected)
}
require.Equal(t, tt.expected, result, "got %v, want %v", result, tt.expected)
})
}
}

0 comments on commit a19085e

Please sign in to comment.