-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(x/ecocredit): bridge and bridge receive message validation (#1231)
* 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
1 parent
98524a6
commit 6eeabd3
Showing
15 changed files
with
1,234 additions
and
666 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
Oops, something went wrong.