Skip to content

Commit

Permalink
fix(x/ecocredit): bridge and bridge receive message validation (#1231)
Browse files Browse the repository at this point in the history
* fix(x/ecocredit): bridge and bridge receive message validation

* add and update tests

* add ethereum contract scenario

* use sdkerros wrap not fmt

* use steps for field length checks

* use custom regen prefix
  • Loading branch information
ryanchristo authored Jul 7, 2022
1 parent 98524a6 commit 6eeabd3
Show file tree
Hide file tree
Showing 15 changed files with 1,234 additions and 666 deletions.
192 changes: 96 additions & 96 deletions api/regen/ecocredit/v1/tx.pulsar.go

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions proto/regen/ecocredit/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -478,15 +478,15 @@ message MsgBridgeReceive {
// issuer is the account address of the service bridging the credits.
string issuer = 1;

// batch defines the credit batch information for the bridged credits.
Batch batch = 2;
// class_id is the unique identifier of the credit class within which the
// project and credit batch already exist or will be created.
string class_id = 2;

// project defines the project information for the bridged credits.
Project project = 3;

// class_id is the unique identifier of the credit class within which the
// project and credit batch already exist or will be created.
string class_id = 4;
// batch defines the credit batch information for the bridged credits.
Batch batch = 4;

// origin_tx is a reference to a transaction which caused the transfer from
// another chain or registry.
Expand Down
13 changes: 13 additions & 0 deletions types/eth/addr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package eth

import (
"fmt"
"regexp"
)

var RegexAddress = `0x[0-9a-fA-F]{40}`

func IsValidAddress(addr string) bool {
re := regexp.MustCompile(fmt.Sprintf(`^%s$`, RegexAddress))
return re.MatchString(addr)
}
33 changes: 33 additions & 0 deletions types/eth/addr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package eth

import (
"testing"

"github.com/stretchr/testify/require"
"pgregory.net/rapid"
)

var genValidAddress = rapid.OneOf(
rapid.StringMatching(RegexAddress),
)

var genInvalidAddress = rapid.OneOf(
rapid.StringMatching(`0x[g-zG-Z]{40}`),
rapid.StringMatching(`0x[0-9a-fA-F]{0,39}`),
rapid.StringMatching(`0x[0-9a-fA-F]{41,}`),
)

func TestAddr(t *testing.T) {
t.Run("TestValidAddress", rapid.MakeCheck(testValidAddress))
t.Run("TestInvalidAddress", rapid.MakeCheck(testInvalidAddress))
}

func testValidAddress(t *rapid.T) {
addr := genValidAddress.Draw(t, "addr").(string)
require.True(t, IsValidAddress(addr))
}

func testInvalidAddress(t *rapid.T) {
addr := genInvalidAddress.Draw(t, "addr").(string)
require.False(t, IsValidAddress(addr))
}
13 changes: 13 additions & 0 deletions types/eth/tx_hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package eth

import (
"fmt"
"regexp"
)

var RegexTxHash = `0x[0-9a-fA-F]{64}`

func IsValidTxHash(txHash string) bool {
re := regexp.MustCompile(fmt.Sprintf(`^%s$`, RegexTxHash))
return re.MatchString(txHash)
}
33 changes: 33 additions & 0 deletions types/eth/tx_hash_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package eth

import (
"testing"

"github.com/stretchr/testify/require"
"pgregory.net/rapid"
)

var genValidTxHash = rapid.OneOf(
rapid.StringMatching(RegexTxHash),
)

var genInvalidTxHash = rapid.OneOf(
rapid.StringMatching(`0x[g-zG-Z]{64}`),
rapid.StringMatching(`0x[0-9a-fA-F]{0,63}`),
rapid.StringMatching(`0x[0-9a-fA-F]{65,}`),
)

func TestTxHash(t *testing.T) {
t.Run("TestValidTxHash", rapid.MakeCheck(testValidTxHash))
t.Run("TestInvalidTxHash", rapid.MakeCheck(testInvalidTxHash))
}

func testValidTxHash(t *rapid.T) {
txHash := genValidTxHash.Draw(t, "txHash").(string)
require.True(t, IsValidTxHash(txHash))
}

func testInvalidTxHash(t *rapid.T) {
txHash := genInvalidTxHash.Draw(t, "txHash").(string)
require.False(t, IsValidTxHash(txHash))
}
182 changes: 182 additions & 0 deletions x/ecocredit/core/features/msg_bridge.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
Feature: MsgBridge

Scenario: a valid message
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"credits": [
{
"batch_denom": "C01-001-20200101-20210101-001",
"amount": "100"
}
]
}
"""
When the message is validated
Then expect no error

Scenario: a valid message with multiple credits
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"credits": [
{
"batch_denom": "C01-001-20200101-20210101-001",
"amount": "100"
},
{
"batch_denom": "C01-001-20200101-20210101-002",
"amount": "100"
}
]
}
"""
When the message is validated
Then expect no error

Scenario: an error is returned if owner is empty
Given the message
"""
{}
"""
When the message is validated
Then expect the error "owner: empty address string is not allowed: invalid address"

Scenario: an error is returned if owner is not a valid bech32 address
Given the message
"""
{
"owner": "foo"
}
"""
When the message is validated
Then expect the error "owner: decoding bech32 failed: invalid bech32 string length 3: invalid address"

Scenario: an error is returned if target is empty
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6"
}
"""
When the message is validated
Then expect the error "target cannot be empty: invalid request"

Scenario: an error is returned if target is not polygon
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "foo"
}
"""
When the message is validated
Then expect the error "target must be polygon: invalid request"

Scenario: an error is returned if recipient is empty
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon"
}
"""
When the message is validated
Then expect the error "recipient cannot be empty: invalid request"

Scenario: an error is returned if recipient is not an ethereum address
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "foo"
}
"""
When the message is validated
Then expect the error "recipient must be a valid ethereum address: invalid address"

Scenario: an error is returned if credits is empty
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d"
}
"""
When the message is validated
Then expect the error "credits cannot be empty: invalid request"

Scenario: an error is returned if credits batch denom is empty
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"credits": [
{}
]
}
"""
When the message is validated
Then expect the error "credits[0]: batch denom cannot be empty: invalid request"

Scenario: an error is returned if credits batch denom is not formatted
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"credits": [
{
"batch_denom": "foo"
}
]
}
"""
When the message is validated
Then expect the error "credits[0]: invalid batch denom: expected format A00-000-00000000-00000000-000: parse error"

Scenario: an error is returned if credits amount is empty
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"credits": [
{
"batch_denom": "C01-001-20200101-20210101-001"
}
]
}
"""
When the message is validated
Then expect the error "credits[0]: amount cannot be empty: invalid request"

Scenario: an error is returned if credits amount is not a positive decimal
Given the message
"""
{
"owner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"target": "polygon",
"recipient": "0x323b5d4c32345ced77393b3530b1eed0f346429d",
"credits": [
{
"batch_denom": "C01-001-20200101-20210101-001",
"amount": "-100"
}
]
}
"""
When the message is validated
Then expect the error "credits[0]: amount: expected a positive decimal, got -100: invalid decimal string"
Loading

0 comments on commit 6eeabd3

Please sign in to comment.