Merge 1ad7d09c44
into 2712dd3f3f
This commit is contained in:
commit
89696b5200
|
@ -0,0 +1,59 @@
|
|||
package ictest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
|
||||
)
|
||||
|
||||
// TestCancelUpgrade will start on wormchain v2.18.1.1, schedule an upgrade to v2.23.0, cancel the upgrade,
|
||||
// and verify that block production does not stop at the cancelled scheduled upgrade height.
|
||||
func TestCancelUpgrade(t *testing.T) {
|
||||
// Base setup
|
||||
numVals := 2
|
||||
guardians := guardians.CreateValSet(t, numVals)
|
||||
chains := CreateChains(t, "v2.18.1.1", *guardians)
|
||||
ctx, _, _, _ := BuildInterchain(t, chains)
|
||||
|
||||
// Chains
|
||||
wormchain := chains[0].(*cosmos.CosmosChain)
|
||||
|
||||
// Set up upgrade
|
||||
blocksAfterUpgrade := uint64(10)
|
||||
height, err := wormchain.Height(ctx)
|
||||
require.NoError(t, err, "error fetching height before upgrade")
|
||||
fmt.Println("Height at sending schedule upgrade: ", height)
|
||||
|
||||
haltHeight := height + blocksAfterUpgrade
|
||||
fmt.Println("Height for scheduled upgrade: ", haltHeight)
|
||||
|
||||
// Schedule upgrade
|
||||
helpers.ScheduleUpgrade(t, ctx, wormchain, "faucet", "v2.23.0", haltHeight, guardians)
|
||||
|
||||
// Cancel upgrade
|
||||
testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||
helpers.CancelUpgrade(t, ctx, wormchain, "faucet", guardians)
|
||||
|
||||
timeoutCtx3, timeoutCtxCancel3 := context.WithTimeout(ctx, time.Second*45)
|
||||
defer timeoutCtxCancel3()
|
||||
|
||||
// Wait for chain to reach/exceed originally scheduled upgrade height
|
||||
// If it times-out, the cancel upgrade did not work and the chain will have halted at the scheduled upgrade height
|
||||
// If it does not timeout, it will be one block after the originally scheduled upgrade height
|
||||
testutil.WaitForBlocks(timeoutCtx3, int(blocksAfterUpgrade), wormchain)
|
||||
|
||||
height, err = wormchain.Height(ctx)
|
||||
require.NoError(t, err, "error fetching height after chain should have halted")
|
||||
|
||||
// Ensure that the chain continued making blocks passed the upgrade height
|
||||
require.NotEqual(t, haltHeight, height, "height is equal to halt height, it shouldn't be")
|
||||
fmt.Println("***** Cancel upgrade test passed ******")
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
[alias]
|
||||
wasm = "build --release --target wasm32-unknown-unknown"
|
||||
wasm-debug = "build --target wasm32-unknown-unknown"
|
||||
unit-test = "test --lib --features backtraces"
|
||||
integration-test = "test --test integration"
|
|
@ -0,0 +1,690 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-crypto"
|
||||
version = "1.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb64554a91d6a9231127f4355d351130a0b94e663d5d9dc8b3a54ca17d83de49"
|
||||
dependencies = [
|
||||
"digest 0.10.7",
|
||||
"ed25519-zebra",
|
||||
"k256",
|
||||
"rand_core 0.6.4",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-derive"
|
||||
version = "1.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0fb2ce09f41a3dae1a234d56a9988f9aff4c76441cd50ef1ee9a4f20415b028"
|
||||
dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-schema"
|
||||
version = "1.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "230e5d1cefae5331db8934763c81b9c871db6a2cd899056a5694fa71d292c815"
|
||||
dependencies = [
|
||||
"cosmwasm-schema-derive",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-schema-derive"
|
||||
version = "1.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43dadf7c23406cb28079d69e6cb922c9c29b9157b0fe887e3b79c783b7d4bcb8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-std"
|
||||
version = "1.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4337eef8dfaf8572fe6b6b415d6ec25f9308c7bb09f2da63789209fb131363be"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cosmwasm-crypto",
|
||||
"cosmwasm-derive",
|
||||
"derivative",
|
||||
"forward_ref",
|
||||
"hex",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde-json-wasm",
|
||||
"sha2 0.10.7",
|
||||
"thiserror",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"digest 0.9.0",
|
||||
"rand_core 0.5.1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.4",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.14.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
|
||||
dependencies = [
|
||||
"der",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-zebra"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"hashbrown",
|
||||
"hex",
|
||||
"rand_core 0.6.4",
|
||||
"serde",
|
||||
"sha2 0.9.9",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
"der",
|
||||
"digest 0.10.7",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"group",
|
||||
"pkcs8",
|
||||
"rand_core 0.6.4",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "forward_ref"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ibc-hooks"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
|
||||
[[package]]
|
||||
name = "k256"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"sha2 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
|
||||
dependencies = [
|
||||
"crypto-bigint",
|
||||
"hmac",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"schemars_derive",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"der",
|
||||
"generic-array",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-json-wasm"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "1.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
||||
dependencies = [
|
||||
"digest 0.10.7",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crunchy",
|
||||
"hex",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
|
@ -0,0 +1,37 @@
|
|||
[package]
|
||||
name = "ibc-hooks"
|
||||
version = "0.1.0"
|
||||
authors = ["Wormhole Project Contributors"]
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[profile.release]
|
||||
opt-level = 0
|
||||
debug = true
|
||||
rpath = false
|
||||
lto = false
|
||||
debug-assertions = false
|
||||
codegen-units = 1
|
||||
panic = 'abort'
|
||||
incremental = false
|
||||
overflow-checks = true
|
||||
|
||||
[features]
|
||||
# for more explicit tests, cargo test --features=backtraces
|
||||
backtraces = ["cosmwasm-std/backtraces"]
|
||||
# use library feature to disable all instantiate/execute/query/reply exports
|
||||
library = []
|
||||
|
||||
[package.metadata.scripts]
|
||||
optimize = """docker run --rm -v "$(pwd)":/code \
|
||||
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
|
||||
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
|
||||
cosmwasm/rust-optimizer:0.12.6
|
||||
"""
|
||||
|
||||
[dependencies]
|
||||
cosmwasm-std = {version="1.2.7", features = ["ibc3"] }
|
||||
cosmwasm-schema = "1.2.7"
|
||||
anyhow = "1"
|
|
@ -0,0 +1,54 @@
|
|||
#[cfg(not(feature = "library"))]
|
||||
use cosmwasm_std::entry_point;
|
||||
|
||||
use anyhow::{Context, ensure};
|
||||
use cosmwasm_std::{
|
||||
BankMsg, CosmosMsg, DepsMut, Empty, Env, MessageInfo, Response,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
msg::{ExecuteMsg, InstantiateMsg},
|
||||
};
|
||||
|
||||
#[cfg_attr(not(feature = "library"), entry_point)]
|
||||
pub fn instantiate(
|
||||
_deps: DepsMut,
|
||||
_env: Env,
|
||||
_info: MessageInfo,
|
||||
_msg: InstantiateMsg,
|
||||
) -> Result<Response, anyhow::Error> {
|
||||
Ok(Response::new())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "library"), entry_point)]
|
||||
pub fn migrate(_deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, anyhow::Error> {
|
||||
Ok(Response::default())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "library"), entry_point)]
|
||||
pub fn execute(
|
||||
_deps: DepsMut,
|
||||
_env: Env,
|
||||
info: MessageInfo,
|
||||
msg: ExecuteMsg,
|
||||
) -> Result<Response, anyhow::Error> {
|
||||
match msg {
|
||||
ExecuteMsg::ForwardTokens { recipient } => {
|
||||
// bank tokens sent to the contract will be in info.funds
|
||||
ensure!(
|
||||
info.funds.len() == 1,
|
||||
"info.funds should contain only 1 coin"
|
||||
);
|
||||
|
||||
// batch calls together
|
||||
let mut response: Response = Response::new();
|
||||
response = response.add_message(BankMsg::Send {
|
||||
to_address: recipient,
|
||||
amount: info.funds,
|
||||
//amount: vec![amount],
|
||||
});
|
||||
|
||||
Ok(response)
|
||||
},
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
pub mod contract;
|
||||
pub mod msg;
|
|
@ -0,0 +1,11 @@
|
|||
use cosmwasm_schema::cw_serde;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct InstantiateMsg {}
|
||||
|
||||
#[cw_serde]
|
||||
pub enum ExecuteMsg {
|
||||
ForwardTokens {
|
||||
recipient: String,
|
||||
},
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,225 @@
|
|||
module github.com/wormhole-foundation/wormchain/interchaintest
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/cosmos/cosmos-sdk v0.45.14
|
||||
github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/wormhole-foundation/wormchain v0.0.0-00010101000000-000000000000
|
||||
go.uber.org/zap v1.24.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3
|
||||
github.com/cosmos/ibc-go/v4 v4.3.0
|
||||
github.com/docker/docker v20.10.19+incompatible
|
||||
github.com/ethereum/go-ethereum v1.11.6
|
||||
github.com/strangelove-ventures/interchaintest/v4 v4.0.0-20230815125617-67bc301715ea
|
||||
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
|
||||
github.com/wormhole-foundation/wormhole/sdk v0.0.0-20230614161948-7f6213019abf
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/api v0.2.6 // indirect
|
||||
cosmossdk.io/core v0.5.1 // indirect
|
||||
cosmossdk.io/depinject v1.0.0-alpha.3 // indirect
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel/1 v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/CosmWasm/wasmd v0.31.0 // indirect
|
||||
github.com/CosmWasm/wasmvm v1.2.1 // indirect
|
||||
github.com/DataDog/zstd v1.5.2 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/StirlingMarketingGroup/go-namecase v1.0.0 // indirect
|
||||
github.com/armon/go-metrics v0.4.0 // indirect
|
||||
github.com/avast/retry-go/v4 v4.0.4 // indirect
|
||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
|
||||
github.com/btcsuite/btcd v0.23.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
|
||||
github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.4 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cockroachdb/errors v1.9.1 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect
|
||||
github.com/cockroachdb/redact v1.1.3 // indirect
|
||||
github.com/confio/ics23/go v0.9.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect
|
||||
github.com/cosmos/go-bip39 v1.0.0 // indirect
|
||||
github.com/cosmos/gogoproto v1.4.6 // indirect
|
||||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.19.5 // indirect
|
||||
github.com/cosmos/interchain-security v1.0.0 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deckarep/golang-set v1.8.0 // indirect
|
||||
github.com/decred/base58 v1.0.3 // indirect
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.18.0 // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/gateway v1.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.3 // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
github.com/gtank/merlin v0.1.1 // indirect
|
||||
github.com/gtank/ristretto255 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
|
||||
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/ipfs/go-cid v0.0.7 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/klauspost/compress v1.15.15 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/libp2p/go-libp2p-core v0.15.1 // indirect
|
||||
github.com/libp2p/go-openssl v0.0.7 // indirect
|
||||
github.com/linxGnu/grocksdb v1.7.10 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/multiformats/go-base32 v0.0.3 // indirect
|
||||
github.com/multiformats/go-base36 v0.1.0 // indirect
|
||||
github.com/multiformats/go-multiaddr v0.4.1 // indirect
|
||||
github.com/multiformats/go-multibase v0.0.3 // indirect
|
||||
github.com/multiformats/go-multicodec v0.4.1 // indirect
|
||||
github.com/multiformats/go-multihash v0.1.0 // indirect
|
||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||
github.com/pierrec/xxHash v0.1.5 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.39.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/rakyll/statik v0.1.7 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/regen-network/cosmos-proto v0.3.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/rs/cors v1.8.2 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.7.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.14.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tendermint/tendermint v0.34.26 // indirect
|
||||
github.com/tendermint/tm-db v0.6.7 // indirect
|
||||
github.com/tidwall/btree v1.5.0 // indirect
|
||||
github.com/vedhavyas/go-subkey v1.0.3 // indirect
|
||||
github.com/zondax/hid v0.9.1 // indirect
|
||||
github.com/zondax/ledger-go v0.14.1 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
golang.org/x/crypto v0.5.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
|
||||
golang.org/x/mod v0.9.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/term v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa // indirect
|
||||
google.golang.org/grpc v1.53.0 // indirect
|
||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.1.6 // indirect
|
||||
lukechampine.com/uint128 v1.1.1 // indirect
|
||||
modernc.org/cc/v3 v3.36.0 // indirect
|
||||
modernc.org/ccgo/v3 v3.16.6 // indirect
|
||||
modernc.org/libc v1.16.7 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.1.1 // indirect
|
||||
modernc.org/opt v0.1.1 // indirect
|
||||
modernc.org/sqlite v1.17.3 // indirect
|
||||
modernc.org/strutil v1.1.1 // indirect
|
||||
modernc.org/token v1.0.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
|
||||
github.com/ChainSafe/go-schnorrkel => github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d
|
||||
github.com/ChainSafe/go-schnorrkel/1 => github.com/ChainSafe/go-schnorrkel v1.0.0
|
||||
// specify the version of btcd used so we don't get the btcec issue
|
||||
github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.2
|
||||
// use cosmos-sdk with ics support
|
||||
github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.45.14-ics
|
||||
//github.com/cosmos/cosmos-sdk => github.com/wormhole-foundation/cosmos-sdk v0.45.9-wormhole-2
|
||||
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
|
||||
|
||||
//github.com/strangelove-ventures/interchaintest/v4 => ../../../../../strangelove-ventures/interchaintest_v4
|
||||
|
||||
// pin version! 126854af5e6d has issues with the store so that queries fail
|
||||
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||
// use informal tendermint
|
||||
github.com/tendermint/tendermint => github.com/informalsystems/tendermint v0.34.23
|
||||
github.com/vedhavyas/go-subkey => github.com/strangelove-ventures/go-subkey v1.0.7
|
||||
github.com/wormhole-foundation/wormchain => ../
|
||||
github.com/wormhole-foundation/wormhole/sdk => ../../sdk
|
||||
|
||||
)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,56 @@
|
|||
package guardians
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type ValSet struct {
|
||||
Vals []Val
|
||||
Total int
|
||||
}
|
||||
|
||||
type Val struct {
|
||||
Addr []byte
|
||||
Priv *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
func CreateVal(t *testing.T) *Val {
|
||||
priv, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
signer := crypto.PubkeyToAddress(priv.PublicKey).Bytes()
|
||||
|
||||
return &Val{
|
||||
Addr: signer,
|
||||
Priv: priv,
|
||||
}
|
||||
}
|
||||
|
||||
func CreateValSet(t *testing.T, total int) *ValSet {
|
||||
// If total == 1, mirror the guardian keys in scripts/devnet-consts.json
|
||||
if total == 1 {
|
||||
privHex := "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"
|
||||
priv, err := crypto.HexToECDSA(privHex)
|
||||
require.NoError(t, err)
|
||||
signer := crypto.PubkeyToAddress(priv.PublicKey).Bytes()
|
||||
|
||||
return &ValSet{
|
||||
Vals: []Val{
|
||||
{signer, priv},
|
||||
},
|
||||
Total: 1,
|
||||
}
|
||||
}
|
||||
|
||||
var valSet ValSet
|
||||
for i := 0; i < total; i++ {
|
||||
valSet.Vals = append(valSet.Vals, *CreateVal(t))
|
||||
}
|
||||
|
||||
valSet.Total = total
|
||||
return &valSet
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func GetDenomsMetadata(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain) QueryDenomsMetadataResponse {
|
||||
node := chain.GetFullNode()
|
||||
|
||||
stdoutBz, _, err := node.ExecQuery(ctx, "bank", "denom-metadata")
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Println("Stdout: ", string(stdoutBz))
|
||||
res := QueryDenomsMetadataResponse{}
|
||||
err = json.Unmarshal(stdoutBz, &res)
|
||||
require.NoError(t, err)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC
|
||||
// method.
|
||||
type QueryDenomsMetadataResponse struct {
|
||||
// metadata provides the client information for all the registered tokens.
|
||||
Metadatas []banktypes.Metadata `json:"metadatas"`
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type Cw20InstantiateMsg struct {
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
AssetChain uint16 `json:"asset_chain"`
|
||||
AssetAddr []byte `json:"asset_address"`
|
||||
Decimals uint8 `json:"decimals"`
|
||||
InitHook InitHook `json:"init_hook"`
|
||||
}
|
||||
|
||||
type InitHook struct {
|
||||
Msg []byte `json:"msg"`
|
||||
ContractAddr string `json:"contract_addr"`
|
||||
}
|
||||
|
||||
type TbRegisterAssetHookMsg struct {
|
||||
RegisterAssetHook RegisterAssetHook `json:"register_asset_hook,omitempty"`
|
||||
}
|
||||
|
||||
type RegisterAssetHook struct {
|
||||
Chain uint16 `json:"chain,omitempty"`
|
||||
TokenAddr ExternalTokenId `json:"token_address,omitempty"`
|
||||
}
|
||||
|
||||
type ExternalTokenId struct {
|
||||
Bytes [32]byte `json:"bytes,omitempty"`
|
||||
}
|
||||
|
||||
func Cw20ContractInstantiateMsg(
|
||||
t *testing.T,
|
||||
name string,
|
||||
symbol string,
|
||||
chainID uint16,
|
||||
assetAddr string,
|
||||
decimals uint8,
|
||||
tbContractAddr string,
|
||||
) string {
|
||||
index := 32
|
||||
assetAddr32 := [32]byte{}
|
||||
for i := len(assetAddr); i > 0; i-- {
|
||||
assetAddr32[index-1] = assetAddr[i-1]
|
||||
index--
|
||||
}
|
||||
|
||||
tbMsg := TbRegisterAssetHookMsg{
|
||||
RegisterAssetHook: RegisterAssetHook{
|
||||
Chain: chainID,
|
||||
TokenAddr: ExternalTokenId{
|
||||
Bytes: assetAddr32,
|
||||
},
|
||||
},
|
||||
}
|
||||
tbMsgBz, err := json.Marshal(tbMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := Cw20InstantiateMsg{
|
||||
Name: name,
|
||||
Symbol: symbol,
|
||||
AssetChain: chainID,
|
||||
AssetAddr: assetAddr32[:],
|
||||
Decimals: decimals,
|
||||
InitHook: InitHook{
|
||||
Msg: tbMsgBz,
|
||||
ContractAddr: tbContractAddr,
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
|
||||
}
|
||||
|
||||
type Cw20WrappedQueryMsg struct {
|
||||
TokenInfo Cw20TokenInfo `json:"token_info"`
|
||||
}
|
||||
|
||||
type Cw20TokenInfo struct{}
|
||||
|
||||
type Cw20WrappedBalanceQueryMsg struct {
|
||||
Balance Cw20BalanceQuery `json:"balance"`
|
||||
}
|
||||
|
||||
type Cw20BalanceQuery struct {
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
type Cw20WrappedQueryRsp struct {
|
||||
Data *Cw20WrappedQueryRspObj `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type Cw20WrappedQueryRspObj struct {
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Decimals uint8 `json:"decimals"`
|
||||
TotalSupply string `json:"total_supply"`
|
||||
}
|
||||
|
||||
type Cw20WrappedBalanceQueryRsp struct {
|
||||
Data *Cw20WrappedBalanceQueryRspObj `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type Cw20WrappedBalanceQueryRspObj struct {
|
||||
Balance string `json:"balance"`
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
)
|
||||
|
||||
func GetMiddlewareContract(
|
||||
t *testing.T,
|
||||
ctx context.Context,
|
||||
chain *cosmos.CosmosChain,
|
||||
) string {
|
||||
node := chain.GetFullNode()
|
||||
stdout, _, err := node.ExecQuery(ctx, "wormhole", "show-ibc-composability-mw-contract")
|
||||
require.NoError(t, err)
|
||||
return string(stdout)
|
||||
}
|
||||
|
||||
func SetMiddlewareContract(
|
||||
t *testing.T,
|
||||
ctx context.Context,
|
||||
chain *cosmos.CosmosChain,
|
||||
keyName string,
|
||||
cfg ibc.ChainConfig,
|
||||
contractBech32Addr string,
|
||||
guardians *guardians.ValSet,
|
||||
) {
|
||||
node := chain.GetFullNode()
|
||||
|
||||
contractAddr := [32]byte{}
|
||||
copy(contractAddr[:], MustAccAddressFromBech32(contractBech32Addr, cfg.Bech32Prefix).Bytes())
|
||||
payload := vaa.BodyGatewayIbcComposabilityMwContract{
|
||||
ContractAddr: contractAddr,
|
||||
}
|
||||
payloadBz := payload.Serialize()
|
||||
v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
vHex := hex.EncodeToString(vBz)
|
||||
|
||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "execute-gateway-governance-vaa", vHex, "--gas", "auto")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func ScheduleUpgrade(
|
||||
t *testing.T,
|
||||
ctx context.Context,
|
||||
chain *cosmos.CosmosChain,
|
||||
keyName string,
|
||||
name string,
|
||||
height uint64,
|
||||
guardians *guardians.ValSet,
|
||||
) {
|
||||
node := chain.GetFullNode()
|
||||
|
||||
payload := vaa.BodyGatewayScheduleUpgrade{
|
||||
Name: name,
|
||||
Height: height,
|
||||
}
|
||||
payloadBz := payload.Serialize()
|
||||
v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payloadBz)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
vHex := hex.EncodeToString(vBz)
|
||||
|
||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "execute-gateway-governance-vaa", vHex, "--gas", "auto")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func CancelUpgrade(
|
||||
t *testing.T,
|
||||
ctx context.Context,
|
||||
chain *cosmos.CosmosChain,
|
||||
keyName string,
|
||||
guardians *guardians.ValSet,
|
||||
) {
|
||||
node := chain.GetFullNode()
|
||||
|
||||
payloadBz := vaa.EmptyPayloadVaa(vaa.GatewayModuleStr, vaa.ActionCancelUpgrade, vaa.ChainIDWormchain)
|
||||
v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
vHex := hex.EncodeToString(vBz)
|
||||
|
||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "execute-gateway-governance-vaa", vHex, "--gas", "auto")
|
||||
require.NoError(t, err)
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type IbcHooks struct {
|
||||
Payload IbcHooksPayload `json:"wasm"`
|
||||
}
|
||||
|
||||
type IbcHooksPayload struct {
|
||||
Contract string `json:"contract"`
|
||||
Msg IbcHooksExecute `json:"msg"`
|
||||
}
|
||||
|
||||
type IbcHooksExecute struct {
|
||||
Forward IbcHooksForward `json:"forward_tokens"`
|
||||
}
|
||||
|
||||
type IbcHooksForward struct {
|
||||
Recipient string `json:"recipient"`
|
||||
}
|
||||
|
||||
func CreateIbcHooksMsg(t *testing.T, contract string, recipient string) []byte {
|
||||
msg := IbcHooks{
|
||||
Payload: IbcHooksPayload{
|
||||
Contract: contract,
|
||||
Msg: IbcHooksExecute{
|
||||
Forward: IbcHooksForward{
|
||||
Recipient: recipient,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return msgBz
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
)
|
||||
|
||||
func SubmitAllowlistInstantiateContract(
|
||||
t *testing.T,
|
||||
ctx context.Context,
|
||||
chain *cosmos.CosmosChain,
|
||||
keyName string,
|
||||
cfg ibc.ChainConfig,
|
||||
contractBech32Addr string,
|
||||
codeIdStr string,
|
||||
guardians *guardians.ValSet,
|
||||
) {
|
||||
node := chain.GetFullNode()
|
||||
codeId, err := strconv.ParseUint(codeIdStr, 10, 64)
|
||||
require.NoError(t, err)
|
||||
|
||||
contractAddr := [32]byte{}
|
||||
copy(contractAddr[:], MustAccAddressFromBech32(contractBech32Addr, cfg.Bech32Prefix).Bytes())
|
||||
payload := vaa.BodyWormchainWasmAllowlistInstantiate{
|
||||
ContractAddr: contractAddr,
|
||||
CodeId: codeId,
|
||||
}
|
||||
payloadBz := payload.Serialize(vaa.ActionAddWasmInstantiateAllowlist)
|
||||
v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
vHex := hex.EncodeToString(vBz)
|
||||
|
||||
// add-wasm-instantiate-allowlist [bech32 contract addr] [codeId] [vaa-hex]
|
||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "add-wasm-instantiate-allowlist", contractBech32Addr, codeIdStr, vHex, "--gas", "auto")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
type IbcTranslatorInstantiateMsg struct {
|
||||
TokenBridgeContract string `json:"token_bridge_contract"`
|
||||
}
|
||||
|
||||
func IbcTranslatorContractInstantiateMsg(t *testing.T, tbContract string) string {
|
||||
msg := IbcTranslatorInstantiateMsg{
|
||||
TokenBridgeContract: tbContract,
|
||||
}
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
||||
|
||||
type IbcTranslatorSubmitUpdateChainToChannelMap struct {
|
||||
SubmitUpdateChainToChannelMap SubmitUpdateChainToChannelMap `json:"submit_update_chain_to_channel_map"`
|
||||
}
|
||||
|
||||
type SubmitUpdateChainToChannelMap struct {
|
||||
Vaa []byte `json:"vaa"`
|
||||
}
|
||||
|
||||
func SubmitUpdateChainToChannelMapMsg(t *testing.T, allowlistChainID uint16, allowlistChannel string, guardians *guardians.ValSet) string {
|
||||
payload := new(bytes.Buffer)
|
||||
module := vaa.LeftPadBytes("IbcTranslator", 32)
|
||||
payload.Write(module.Bytes())
|
||||
vaa.MustWrite(payload, binary.BigEndian, uint8(1))
|
||||
vaa.MustWrite(payload, binary.BigEndian, uint16(0))
|
||||
channelPadded := vaa.LeftPadBytes(allowlistChannel, 64)
|
||||
payload.Write(channelPadded.Bytes())
|
||||
vaa.MustWrite(payload, binary.BigEndian, allowlistChainID)
|
||||
|
||||
v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payload.Bytes())
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := IbcTranslatorSubmitUpdateChainToChannelMap{
|
||||
SubmitUpdateChainToChannelMap: SubmitUpdateChainToChannelMap{
|
||||
Vaa: vBz,
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
||||
|
||||
type IbcTranslatorCompleteTransferAndConvert struct {
|
||||
CompleteTransferAndConvert CompleteTransferAndConvert `json:"complete_transfer_and_convert"`
|
||||
}
|
||||
|
||||
type CompleteTransferAndConvert struct {
|
||||
Vaa []byte `json:"vaa"`
|
||||
}
|
||||
|
||||
// TODO: replace amount's uint64 with big int or equivalent
|
||||
func CreatePayload1(amount uint64, tokenAddr string, tokenChain uint16, recipient []byte, recipientChain uint16, fee uint64) []byte {
|
||||
payload := new(bytes.Buffer)
|
||||
vaa.MustWrite(payload, binary.BigEndian, uint8(1)) // Payload 1: Transfer
|
||||
payload.Write(make([]byte, 24))
|
||||
vaa.MustWrite(payload, binary.BigEndian, amount)
|
||||
|
||||
tokenAddrPadded := vaa.LeftPadBytes(tokenAddr, 32)
|
||||
payload.Write(tokenAddrPadded.Bytes())
|
||||
vaa.MustWrite(payload, binary.BigEndian, tokenChain)
|
||||
|
||||
payload.Write(recipient)
|
||||
vaa.MustWrite(payload, binary.BigEndian, recipientChain)
|
||||
|
||||
payload.Write(make([]byte, 24))
|
||||
vaa.MustWrite(payload, binary.BigEndian, fee)
|
||||
|
||||
return payload.Bytes()
|
||||
}
|
||||
|
||||
// TODO: replace amount's uint64 with big int or equivalent
|
||||
func CreatePayload3(cfg ibc.ChainConfig, amount uint64, tokenAddr string, tokenChain uint16, recipient string, recipientChain uint16, from []byte, contractPayload []byte) []byte {
|
||||
payload := new(bytes.Buffer)
|
||||
vaa.MustWrite(payload, binary.BigEndian, uint8(3)) // Payload 3: TransferWithPayload
|
||||
payload.Write(make([]byte, 24))
|
||||
vaa.MustWrite(payload, binary.BigEndian, amount)
|
||||
|
||||
tokenAddrPadded := vaa.LeftPadBytes(tokenAddr, 32)
|
||||
payload.Write(tokenAddrPadded.Bytes())
|
||||
vaa.MustWrite(payload, binary.BigEndian, tokenChain)
|
||||
|
||||
recipientAddr := MustAccAddressFromBech32(recipient, cfg.Bech32Prefix)
|
||||
payload.Write(recipientAddr.Bytes())
|
||||
vaa.MustWrite(payload, binary.BigEndian, recipientChain)
|
||||
|
||||
payload.Write(from)
|
||||
|
||||
payload.Write(contractPayload)
|
||||
|
||||
return payload.Bytes()
|
||||
}
|
||||
|
||||
func IbcTranslatorCompleteTransferAndConvertMsg(t *testing.T, emitterChainID uint16, emitterAddr string, payload []byte, guardians *guardians.ValSet) string {
|
||||
emitterBz := [32]byte{}
|
||||
eIndex := 32
|
||||
for i := len(emitterAddr); i > 0; i-- {
|
||||
emitterBz[eIndex-1] = emitterAddr[i-1]
|
||||
eIndex--
|
||||
}
|
||||
v := generateVaa(0, guardians, vaa.ChainID(emitterChainID), vaa.Address(emitterBz), payload)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := IbcTranslatorCompleteTransferAndConvert{
|
||||
CompleteTransferAndConvert: CompleteTransferAndConvert{
|
||||
Vaa: vBz,
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
||||
|
||||
type GatewayIbcTokenBridgePayloadTransfer struct {
|
||||
GatewayTransfer GatewayTransfer `json:"gateway_transfer"`
|
||||
}
|
||||
|
||||
type GatewayTransfer struct {
|
||||
Chain uint16 `json:"chain"`
|
||||
Recipient []byte `json:"recipient"`
|
||||
Fee string `json:"fee"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
}
|
||||
|
||||
func CreateGatewayIbcTokenBridgePayloadTransfer(t *testing.T, chainID uint16, recipient string, fee uint64, nonce uint32) []byte {
|
||||
msg := GatewayIbcTokenBridgePayloadTransfer{
|
||||
GatewayTransfer: GatewayTransfer{
|
||||
Chain: chainID,
|
||||
Recipient: []byte(recipient),
|
||||
Fee: fmt.Sprint(fee),
|
||||
Nonce: nonce,
|
||||
},
|
||||
}
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return msgBz
|
||||
}
|
||||
|
||||
type GatewayIbcTokenBridgePayloadTransferWithPayload struct {
|
||||
GatewayTransferWithPayload GatewayTransferWithPayload `json:"gateway_transfer_with_payload"`
|
||||
}
|
||||
|
||||
type GatewayTransferWithPayload struct {
|
||||
Chain uint16 `json:"chain"`
|
||||
Contract []byte `json:"contract"`
|
||||
Payload []byte `json:"payload"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
}
|
||||
|
||||
func CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t *testing.T, chainID uint16, contract string, payload []byte, nonce uint32) []byte {
|
||||
msg := GatewayIbcTokenBridgePayloadTransferWithPayload{
|
||||
GatewayTransferWithPayload: GatewayTransferWithPayload{
|
||||
Chain: chainID,
|
||||
Contract: []byte(contract),
|
||||
Payload: payload,
|
||||
Nonce: nonce,
|
||||
},
|
||||
}
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return msgBz
|
||||
}
|
||||
|
||||
type IbcTranslatorQueryMsg struct {
|
||||
IbcChannel QueryIbcChannel `json:"ibc_channel"`
|
||||
}
|
||||
|
||||
type QueryIbcChannel struct {
|
||||
ChainID uint16 `json:"chain_id"`
|
||||
}
|
||||
|
||||
type IbcTranslatorQueryRspMsg struct {
|
||||
Data *IbcTranslatorQueryRspObj `json:"data"`
|
||||
}
|
||||
|
||||
type IbcTranslatorQueryRspObj struct {
|
||||
Channel string `json:"channel,omitempty"`
|
||||
}
|
||||
|
||||
type IbcComposabilityMwMemoGatewayTransfer struct {
|
||||
GatewayIbcTokenBridgePayloadTransfer GatewayIbcTokenBridgePayloadTransfer `json:"gateway_ibc_token_bridge_payload"`
|
||||
}
|
||||
|
||||
func CreateIbcComposabilityMwMemoGatewayTransfer(t *testing.T, chainID uint16, recipient []byte, fee uint64, nonce uint32) string {
|
||||
msg := IbcComposabilityMwMemoGatewayTransfer{
|
||||
GatewayIbcTokenBridgePayloadTransfer{
|
||||
GatewayTransfer: GatewayTransfer{
|
||||
Chain: chainID,
|
||||
Recipient: recipient,
|
||||
Fee: fmt.Sprint(fee),
|
||||
Nonce: nonce,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
||||
|
||||
type IbcComposabilityMwMemoGatewayTransferWithPayload struct {
|
||||
GatewayIbcTokenBridgePayloadTransferWithPayload GatewayIbcTokenBridgePayloadTransferWithPayload `json:"gateway_ibc_token_bridge_payload"`
|
||||
}
|
||||
|
||||
func CreateIbcComposabilityMwMemoGatewayTransferWithPayload(t *testing.T, chainID uint16, externalContract []byte, payload []byte, nonce uint32) string {
|
||||
msg := IbcComposabilityMwMemoGatewayTransferWithPayload{
|
||||
GatewayIbcTokenBridgePayloadTransferWithPayload{
|
||||
GatewayTransferWithPayload: GatewayTransferWithPayload{
|
||||
Chain: chainID,
|
||||
Contract: externalContract,
|
||||
Payload: payload,
|
||||
Nonce: nonce,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
)
|
||||
|
||||
func createWasmInstantiatePayload(code_id uint64, label string, json_msg string) []byte {
|
||||
// governance message with sha3 of arguments to instantiate
|
||||
// - code_id (big endian)
|
||||
// - label
|
||||
// - json_msg
|
||||
expected_hash := vaa.CreateInstatiateCosmwasmContractHash(code_id, label, []byte(json_msg))
|
||||
|
||||
var payload bytes.Buffer
|
||||
payload.Write(vaa.WasmdModule[:])
|
||||
payload.Write([]byte{byte(vaa.ActionInstantiateContract)})
|
||||
binary.Write(&payload, binary.BigEndian, uint16(vaa.ChainIDWormchain))
|
||||
// custom payload
|
||||
payload.Write(expected_hash[:])
|
||||
return payload.Bytes()
|
||||
}
|
||||
|
||||
func InstantiateContract(
|
||||
t *testing.T,
|
||||
ctx context.Context,
|
||||
chain *cosmos.CosmosChain,
|
||||
keyName string,
|
||||
codeId string,
|
||||
label string,
|
||||
message string,
|
||||
guardians *guardians.ValSet,
|
||||
) (contract string) {
|
||||
|
||||
node := chain.GetFullNode()
|
||||
|
||||
code_id, err := strconv.ParseUint(codeId, 10, 64)
|
||||
require.NoError(t, err)
|
||||
payload := createWasmInstantiatePayload(code_id, label, message)
|
||||
v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
vHex := hex.EncodeToString(vBz)
|
||||
|
||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "instantiate", label, codeId, message, vHex, "--gas", "auto")
|
||||
require.NoError(t, err)
|
||||
|
||||
stdout, _, err := node.ExecQuery(ctx, "wasm", "list-contract-by-code", codeId)
|
||||
require.NoError(t, err)
|
||||
|
||||
contactsRes := QueryContractResponse{}
|
||||
err = json.Unmarshal([]byte(stdout), &contactsRes)
|
||||
require.NoError(t, err)
|
||||
|
||||
contractAddr := contactsRes.Contracts[len(contactsRes.Contracts)-1]
|
||||
return contractAddr
|
||||
}
|
||||
|
||||
type QueryContractResponse struct {
|
||||
Contracts []string `json:"contracts"`
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
)
|
||||
|
||||
func createWasmMigrationPayload(code_id uint64, contractAddr string, json_msg string) []byte {
|
||||
expected_hash := vaa.CreateMigrateCosmwasmContractHash(code_id, contractAddr, []byte(json_msg))
|
||||
|
||||
var payload bytes.Buffer
|
||||
payload.Write(vaa.WasmdModule[:])
|
||||
payload.Write([]byte{byte(vaa.ActionMigrateContract)})
|
||||
binary.Write(&payload, binary.BigEndian, uint16(vaa.ChainIDWormchain))
|
||||
// custom payload
|
||||
payload.Write(expected_hash[:])
|
||||
return payload.Bytes()
|
||||
}
|
||||
|
||||
func MigrateContract(
|
||||
t *testing.T,
|
||||
ctx context.Context,
|
||||
chain *cosmos.CosmosChain,
|
||||
keyName string,
|
||||
contractAddr string,
|
||||
codeId string,
|
||||
message string,
|
||||
guardians *guardians.ValSet,
|
||||
) {
|
||||
|
||||
node := chain.GetFullNode()
|
||||
|
||||
code_id, err := strconv.ParseUint(codeId, 10, 64)
|
||||
require.NoError(t, err)
|
||||
payload := createWasmMigrationPayload(code_id, contractAddr, message)
|
||||
v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
vHex := hex.EncodeToString(vBz)
|
||||
|
||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "migrate", contractAddr, codeId, message, vHex, "--gas", "auto")
|
||||
require.NoError(t, err)
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type PacketMetadata struct {
|
||||
Forward *ForwardMetadata `json:"forward"`
|
||||
}
|
||||
|
||||
type ForwardMetadata struct {
|
||||
Receiver string `json:"receiver"`
|
||||
Port string `json:"port"`
|
||||
Channel string `json:"channel"`
|
||||
Timeout time.Duration `json:"timeout"`
|
||||
Retries *uint8 `json:"retries,omitempty"`
|
||||
Next *string `json:"next,omitempty"`
|
||||
RefundSequence *uint64 `json:"refund_sequence,omitempty"`
|
||||
}
|
||||
|
||||
func CreatePfmSimpleMsg(t *testing.T, recipient string, channel string) string {
|
||||
retries := uint8(0)
|
||||
msg := &PacketMetadata{
|
||||
Forward: &ForwardMetadata{
|
||||
Receiver: recipient,
|
||||
Port: "transfer",
|
||||
Channel: channel,
|
||||
Timeout: time.Minute * 10,
|
||||
Retries: &retries,
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
||||
|
||||
func CreatePfmContractControlledMsg(t *testing.T, contract string, channel string, recipient string) string {
|
||||
ibchooks := &IbcHooks{
|
||||
Payload: IbcHooksPayload{
|
||||
Contract: contract,
|
||||
Msg: IbcHooksExecute{
|
||||
Forward: IbcHooksForward{
|
||||
Recipient: recipient,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
nextBz, err := json.Marshal(ibchooks)
|
||||
require.NoError(t, err)
|
||||
|
||||
next := string(nextBz)
|
||||
|
||||
retries := uint8(0)
|
||||
msg := &PacketMetadata{
|
||||
Forward: &ForwardMetadata{
|
||||
Receiver: contract,
|
||||
Port: "transfer",
|
||||
Channel: channel,
|
||||
Timeout: 1 * time.Minute,
|
||||
Retries: &retries,
|
||||
Next: &next,
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/crypto/sha3"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormchain/x/wormhole/types"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
)
|
||||
|
||||
func createWasmStoreCodePayload(wasmBytes []byte) []byte {
|
||||
// governance message with sha3 of wasmBytes as the payload
|
||||
var hashWasm [32]byte
|
||||
keccak := sha3.NewLegacyKeccak256()
|
||||
keccak.Write(wasmBytes)
|
||||
keccak.Sum(hashWasm[:0])
|
||||
|
||||
gov_msg := types.NewGovernanceMessage(vaa.WasmdModule, byte(vaa.ActionStoreCode), uint16(vaa.ChainIDWormchain), hashWasm[:])
|
||||
return gov_msg.MarshalBinary()
|
||||
}
|
||||
|
||||
// wormchaind tx wormhole store [wasm file] [vaa-hex] [flags]
|
||||
func StoreContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyName string, fileLoc string, guardians *guardians.ValSet) (codeId string) {
|
||||
node := chain.GetFullNode()
|
||||
|
||||
_, file := filepath.Split(fileLoc)
|
||||
err := node.CopyFile(ctx, fileLoc, file)
|
||||
require.NoError(t, err, fmt.Errorf("writing contract file to docker volume: %w", err))
|
||||
|
||||
content, err := os.ReadFile(fileLoc)
|
||||
require.NoError(t, err)
|
||||
|
||||
// gzip the wasm file
|
||||
if IsWasm(content) {
|
||||
content, err = GzipIt(content)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
payload := createWasmStoreCodePayload(content)
|
||||
v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
vHex := hex.EncodeToString(vBz)
|
||||
|
||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "store", path.Join(node.HomeDir(), file), vHex, "--gas", "auto")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = testutil.WaitForBlocks(ctx, 2, node.Chain)
|
||||
require.NoError(t, err)
|
||||
|
||||
stdoutBz, _, err := node.ExecQuery(ctx, "wasm", "list-code", "--reverse")
|
||||
require.NoError(t, err)
|
||||
|
||||
res := CodeInfosResponse{}
|
||||
err = json.Unmarshal(stdoutBz, &res)
|
||||
require.NoError(t, err)
|
||||
|
||||
return res.CodeInfos[0].CodeID
|
||||
}
|
||||
|
||||
// IsWasm checks if the file contents are of wasm binary
|
||||
func IsWasm(input []byte) bool {
|
||||
wasmIdent := []byte("\x00\x61\x73\x6D")
|
||||
return bytes.Equal(input[:4], wasmIdent)
|
||||
}
|
||||
|
||||
// GzipIt compresses the input ([]byte)
|
||||
func GzipIt(input []byte) ([]byte, error) {
|
||||
// Create gzip writer.
|
||||
var b bytes.Buffer
|
||||
w := gzip.NewWriter(&b)
|
||||
_, err := w.Write(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = w.Close() // You must close this first to flush the bytes to the buffer.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
type CodeInfo struct {
|
||||
CodeID string `json:"code_id"`
|
||||
}
|
||||
type CodeInfosResponse struct {
|
||||
CodeInfos []CodeInfo `json:"code_infos"`
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
)
|
||||
|
||||
type TbInstantiateMsg struct {
|
||||
GovChain uint16 `json:"gov_chain"`
|
||||
GovAddress []byte `json:"gov_address"`
|
||||
|
||||
WormholeContract string `json:"wormhole_contract"`
|
||||
WrappedAssetCodeId uint64 `json:"wrapped_asset_code_id"`
|
||||
|
||||
ChainId uint16 `json:"chain_id"`
|
||||
NativeDenom string `json:"native_denom"`
|
||||
NativeSymbol string `json:"native_symbol"`
|
||||
NativeDecimals uint8 `json:"native_decimals"`
|
||||
}
|
||||
|
||||
func TbContractInstantiateMsg(t *testing.T, cfg ibc.ChainConfig, whContract string, wrappedAssetCodeId string) string {
|
||||
codeId, err := strconv.ParseUint(wrappedAssetCodeId, 10, 64)
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := TbInstantiateMsg{
|
||||
GovChain: uint16(vaa.GovernanceChain),
|
||||
GovAddress: vaa.GovernanceEmitter[:],
|
||||
WormholeContract: whContract,
|
||||
WrappedAssetCodeId: codeId,
|
||||
ChainId: uint16(vaa.ChainIDWormchain),
|
||||
NativeDenom: cfg.Denom,
|
||||
NativeSymbol: "WORM",
|
||||
NativeDecimals: 6,
|
||||
}
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
||||
|
||||
type TbSubmitVaaMsg struct {
|
||||
SubmitVaa SubmitVaa `json:"submit_vaa,omitempty"`
|
||||
}
|
||||
|
||||
type SubmitVaa struct {
|
||||
Data []byte `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func TbRegisterChainMsg(t *testing.T, chainID uint16, emitterAddr string, guardians *guardians.ValSet) []byte {
|
||||
emitterBz := [32]byte{}
|
||||
eIndex := 32
|
||||
for i := len(emitterAddr); i > 0; i-- {
|
||||
emitterBz[eIndex-1] = emitterAddr[i-1]
|
||||
eIndex--
|
||||
}
|
||||
bodyTbRegisterChain := vaa.BodyTokenBridgeRegisterChain{
|
||||
Module: "TokenBridge",
|
||||
ChainID: vaa.ChainID(chainID),
|
||||
EmitterAddress: vaa.Address(emitterBz),
|
||||
}
|
||||
|
||||
payload := bodyTbRegisterChain.Serialize()
|
||||
v := generateVaa(0, guardians, vaa.ChainID(vaa.GovernanceChain), vaa.Address(vaa.GovernanceEmitter), payload)
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := TbSubmitVaaMsg{
|
||||
SubmitVaa: SubmitVaa{
|
||||
Data: vBz,
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return msgBz
|
||||
}
|
||||
|
||||
func TbRegisterForeignAsset(t *testing.T, tokenAddr string, chainID uint16, emitterAddr string, decimals uint8, symbol string, name string, guardians *guardians.ValSet) []byte {
|
||||
payload := new(bytes.Buffer)
|
||||
vaa.MustWrite(payload, binary.BigEndian, uint8(2))
|
||||
tokenAddrPadded := vaa.LeftPadBytes(tokenAddr, 32)
|
||||
payload.Write(tokenAddrPadded.Bytes())
|
||||
vaa.MustWrite(payload, binary.BigEndian, chainID)
|
||||
vaa.MustWrite(payload, binary.BigEndian, decimals)
|
||||
symbolPad := make([]byte, 32)
|
||||
copy(symbolPad, []byte(symbol))
|
||||
payload.Write(symbolPad)
|
||||
namePad := make([]byte, 32)
|
||||
copy(namePad, []byte(name))
|
||||
payload.Write(namePad)
|
||||
|
||||
emitterBz := [32]byte{}
|
||||
eIndex := 32
|
||||
for i := len(emitterAddr); i > 0; i-- {
|
||||
emitterBz[eIndex-1] = emitterAddr[i-1]
|
||||
eIndex--
|
||||
}
|
||||
v := generateVaa(0, guardians, vaa.ChainID(chainID), vaa.Address(emitterBz), payload.Bytes())
|
||||
vBz, err := v.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
msg := TbSubmitVaaMsg{
|
||||
SubmitVaa: SubmitVaa{
|
||||
Data: vBz,
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return msgBz
|
||||
}
|
||||
|
||||
type TbQueryMsg struct {
|
||||
WrappedRegistry WrappedRegistry `json:"wrapped_registry"`
|
||||
}
|
||||
|
||||
type WrappedRegistry struct {
|
||||
Chain uint16 `json:"chain"`
|
||||
Address []byte `json:"address"`
|
||||
}
|
||||
|
||||
func CreateCW20Query(t *testing.T, chainID uint16, address string) TbQueryMsg {
|
||||
addressBz := vaa.LeftPadBytes(address, 32)
|
||||
msg := TbQueryMsg{
|
||||
WrappedRegistry: WrappedRegistry{
|
||||
Chain: chainID,
|
||||
Address: addressBz.Bytes(),
|
||||
},
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
type TbQueryRsp struct {
|
||||
Data *TbQueryRspObj `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type TbQueryRspObj struct {
|
||||
Address string `json:"address"`
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func MustAccAddressFromBech32(address string, bech32Prefix string) sdk.AccAddress {
|
||||
if len(strings.TrimSpace(address)) == 0 {
|
||||
panic("empty address string is not allowed")
|
||||
}
|
||||
|
||||
bz, err := sdk.GetFromBech32(address, bech32Prefix)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = sdk.VerifyAddressFormat(bz)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return sdk.AccAddress(bz)
|
||||
}
|
||||
|
||||
func FindEventAttribute(t *testing.T, chain *cosmos.CosmosChain, txHash string, eventType string, attributeKey string, attributeValue string) bool {
|
||||
tx, err := chain.GetTransaction(txHash)
|
||||
require.NoError(t, err)
|
||||
for _, event := range tx.Events {
|
||||
if event.Type == eventType {
|
||||
for _, attribute := range event.Attributes {
|
||||
if string(attribute.Key) == attributeKey && string(attribute.Value) == attributeValue {
|
||||
fmt.Println("Found: ", eventType, " ", attributeKey, " ", attributeValue)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("Not found: ", eventType, " ", attributeKey, " ", attributeValue, "!")
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
)
|
||||
|
||||
var latestSequence = 1
|
||||
|
||||
func signVaa(vaaToSign vaa.VAA, signers *guardians.ValSet) vaa.VAA {
|
||||
for i, key := range signers.Vals {
|
||||
vaaToSign.AddSignature(key.Priv, uint8(i))
|
||||
}
|
||||
return vaaToSign
|
||||
}
|
||||
|
||||
func generateVaa(index uint32, signers *guardians.ValSet, emitterChain vaa.ChainID, emitterAddr vaa.Address, payload []byte) vaa.VAA {
|
||||
v := vaa.VAA{
|
||||
Version: uint8(1),
|
||||
GuardianSetIndex: index,
|
||||
Signatures: nil,
|
||||
Timestamp: time.Unix(0, 0),
|
||||
Nonce: uint32(1),
|
||||
Sequence: uint64(latestSequence),
|
||||
ConsistencyLevel: uint8(32),
|
||||
EmitterChain: emitterChain,
|
||||
EmitterAddress: emitterAddr,
|
||||
Payload: payload,
|
||||
}
|
||||
latestSequence = latestSequence + 1
|
||||
return signVaa(v, signers)
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
)
|
||||
|
||||
type CoreInstantiateMsg struct {
|
||||
GovChain uint16 `json:"gov_chain"`
|
||||
GovAddress []byte `json:"gov_address"`
|
||||
InitialGuardianSet GuardianSetInfo `json:"initial_guardian_set"`
|
||||
GuardianSetExpirity uint64 `json:"guardian_set_expirity"`
|
||||
ChainId uint16 `json:"chain_id"`
|
||||
FeeDenom string `json:"fee_denom"`
|
||||
}
|
||||
|
||||
type GuardianSetInfo struct {
|
||||
Addresses []GuardianAddress `json:"addresses"`
|
||||
ExpirationTime uint64 `json:"expiration_time"`
|
||||
}
|
||||
|
||||
type GuardianAddress struct {
|
||||
Bytes []byte `json:"bytes"`
|
||||
}
|
||||
|
||||
func CoreContractInstantiateMsg(t *testing.T, cfg ibc.ChainConfig, guardians *guardians.ValSet) string {
|
||||
guardianAddresses := []GuardianAddress{}
|
||||
for i := 0; i < guardians.Total; i++ {
|
||||
guardianAddresses = append(guardianAddresses, GuardianAddress{
|
||||
Bytes: guardians.Vals[i].Addr,
|
||||
})
|
||||
}
|
||||
|
||||
msg := CoreInstantiateMsg{
|
||||
GovChain: uint16(vaa.GovernanceChain),
|
||||
GovAddress: vaa.GovernanceEmitter[:],
|
||||
InitialGuardianSet: GuardianSetInfo{
|
||||
Addresses: guardianAddresses,
|
||||
ExpirationTime: 0,
|
||||
},
|
||||
GuardianSetExpirity: 86400,
|
||||
ChainId: uint16(vaa.ChainIDWormchain),
|
||||
FeeDenom: cfg.Denom,
|
||||
}
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(msgBz)
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
package ictest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil/base58"
|
||||
"github.com/strangelove-ventures/interchaintest/v4"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types"
|
||||
)
|
||||
|
||||
// TestMalformedPayload tests the state of wormhole/osmosis chains when a GatewayIbcTokenBridge payload is malformed
|
||||
// and what tokens are created
|
||||
func TestMalformedPayload(t *testing.T) {
|
||||
// Base setup
|
||||
numVals := 1
|
||||
guardians := guardians.CreateValSet(t, numVals)
|
||||
chains := CreateChains(t, "v2.23.0", *guardians)
|
||||
ctx, r, eRep, _ := BuildInterchain(t, chains)
|
||||
|
||||
// Chains
|
||||
wormchain := chains[0].(*cosmos.CosmosChain)
|
||||
gaia := chains[1].(*cosmos.CosmosChain)
|
||||
osmosis := chains[2].(*cosmos.CosmosChain)
|
||||
|
||||
osmoToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, osmosis.Config().ChainID, wormchain.Config().ChainID)
|
||||
wormToOsmoChannel := osmoToWormChannel.Counterparty
|
||||
gaiaToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, gaia.Config().ChainID, wormchain.Config().ChainID)
|
||||
wormToGaiaChannel := gaiaToWormChannel.Counterparty
|
||||
|
||||
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), wormchain, gaia, osmosis, osmosis)
|
||||
osmoUser1 := users[2]
|
||||
osmoUser2 := users[3]
|
||||
|
||||
ibcHooksCodeId, err := osmosis.StoreContract(ctx, osmoUser1.KeyName, "./contracts/ibc_hooks.wasm")
|
||||
require.NoError(t, err)
|
||||
fmt.Println("IBC hooks code id: ", ibcHooksCodeId)
|
||||
|
||||
ibcHooksContractAddr, err := osmosis.InstantiateContract(ctx, osmoUser1.KeyName, ibcHooksCodeId, "{}", true)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("IBC hooks contract addr: ", ibcHooksContractAddr)
|
||||
|
||||
// Store wormhole core contract
|
||||
coreContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/wormhole_core.wasm", guardians)
|
||||
fmt.Println("Core contract code id: ", coreContractCodeId)
|
||||
|
||||
// Instantiate wormhole core contract
|
||||
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
||||
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
||||
fmt.Println("Core contract address: ", coreContractAddr)
|
||||
|
||||
// Store cw20_wrapped_2 contract
|
||||
wrappedAssetCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/cw20_wrapped_2.wasm", guardians)
|
||||
fmt.Println("CW20 wrapped_2 code id: ", wrappedAssetCodeId)
|
||||
|
||||
// Store token bridge contract
|
||||
tbContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/token_bridge.wasm", guardians)
|
||||
fmt.Println("Token bridge contract code id: ", tbContractCodeId)
|
||||
|
||||
// Instantiate token bridge contract
|
||||
tbInstantiateMsg := helpers.TbContractInstantiateMsg(t, wormchainConfig, coreContractAddr, wrappedAssetCodeId)
|
||||
tbContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", tbContractCodeId, "token_bridge", tbInstantiateMsg, guardians)
|
||||
fmt.Println("Token bridge contract address: ", tbContractAddr)
|
||||
|
||||
helpers.SubmitAllowlistInstantiateContract(t, ctx, wormchain, "faucet", wormchain.Config(), tbContractAddr, wrappedAssetCodeId, guardians)
|
||||
|
||||
// Register a new external chain
|
||||
tbRegisterChainMsg := helpers.TbRegisterChainMsg(t, ExternalChainId, ExternalChainEmitterAddr, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterChainMsg))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Register a new foreign asset (Asset1) originating on externalChain
|
||||
tbRegisterForeignAssetMsg := helpers.TbRegisterForeignAsset(t, Asset1ContractAddr, Asset1ChainID, ExternalChainEmitterAddr, Asset1Decimals, Asset1Symbol, Asset1Name, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterForeignAssetMsg))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Store ibc translator contract
|
||||
ibcTranslatorCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/ibc_translator.wasm", guardians)
|
||||
fmt.Println("ibc_translator code id: ", ibcTranslatorCodeId)
|
||||
|
||||
// Instantiate ibc translator contract
|
||||
ibcTranslatorInstantiateMsg := helpers.IbcTranslatorContractInstantiateMsg(t, tbContractAddr)
|
||||
ibcTranslatorContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", ibcTranslatorCodeId, "ibc_translator", ibcTranslatorInstantiateMsg, guardians)
|
||||
fmt.Println("Ibc translator contract address: ", ibcTranslatorContractAddr)
|
||||
|
||||
helpers.SetMiddlewareContract(t, ctx, wormchain, "faucet", wormchain.Config(), ibcTranslatorContractAddr, guardians)
|
||||
|
||||
// Allowlist worm/osmo chain id / channel
|
||||
wormOsmoAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, OsmoChainID, wormToOsmoChannel.ChannelID, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormOsmoAllowlistMsg)
|
||||
|
||||
// Allowlist worm/gaia chain id / channel
|
||||
wormGaiaAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, GaiaChainID, wormToGaiaChannel.ChannelID, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormGaiaAllowlistMsg)
|
||||
|
||||
// Get Asset 1 CW20 contract address
|
||||
var tbQueryRsp helpers.TbQueryRsp
|
||||
tbQueryReq := helpers.CreateCW20Query(t, Asset1ChainID, Asset1ContractAddr)
|
||||
wormchain.QueryContract(ctx, tbContractAddr, tbQueryReq, &tbQueryRsp)
|
||||
cw20Address := tbQueryRsp.Data.Address
|
||||
|
||||
// Set up cw20 req/resp
|
||||
var cw20QueryRsp helpers.Cw20WrappedQueryRsp
|
||||
cw20QueryReq := helpers.Cw20WrappedQueryMsg{TokenInfo: helpers.Cw20TokenInfo{}}
|
||||
|
||||
// Get the Osmo/IBC denom of asset1
|
||||
cw20AddressBz := helpers.MustAccAddressFromBech32(cw20Address, wormchain.Config().Bech32Prefix)
|
||||
subdenom := base58.Encode(cw20AddressBz)
|
||||
asset1TokenFactoryDenom := fmt.Sprint("factory/", ibcTranslatorContractAddr, "/", subdenom)
|
||||
osmoAsset1Denom := transfertypes.GetPrefixedDenom("transfer", osmoToWormChannel.ChannelID, asset1TokenFactoryDenom)
|
||||
osmoIbcAsset1Denom := transfertypes.ParseDenomTrace(osmoAsset1Denom).IBCDenom()
|
||||
|
||||
// ***************** Start of interesting test cases ***************************************************************************************
|
||||
// # Test | Result |
|
||||
// | Cw20 minted | TB minted | Final location |
|
||||
// -----------------------------------------------------------------------------------------------------------------------------------------
|
||||
// 1. GW Transfer: chain id isn't allowlisted | X (0) X (0) X (0) |
|
||||
// 2. GW Transfer: recipient has invalid bech32 addr | + (100) + (100) wormchain (100) |
|
||||
// 3. GW TransferWithPayload: recipient is valid, but not a contract | + (200) + (200) wormchain (200) |
|
||||
// 4. GW TransferWithPayload: Memo malformed: ibc hooks: invalid "wasm" root keyword | + (300) + (300) osmosis (100) |
|
||||
// 5. GW TransferWithPayload: Memo malformed: ibc hooks: invalid recipient (bech32 invalid) | + (400) + (400) wormchain (300) |
|
||||
// 6. GW TransferWithPayload: Memo malformed: ibc hooks: invalid recipient (not a contract) | + (500) + (500) wormchain (400) |
|
||||
// 7. GW TransferWithPayload: Memo malformed: ibc hooks: msg: invalid execute method | + (600) + (600) wormchain (500) |
|
||||
// 8. GW TransferWithPayload: Memo malformed: ibc hooks: msg: invalid "forward to" recipient | + (700) + (700) wormchain (600) |
|
||||
// -----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Test 1 (GW Tranfer has 100 added to osmo chain id to make it denied / no chain id -> channel mapping)
|
||||
simplePayload := helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, OsmoChainID+100, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), 0, 1)
|
||||
externalSender := []byte{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}
|
||||
payload3 := helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
|
||||
completeTransferAndConvertMsg := helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 1, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "0", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 0")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err := wormchain.GetBalance(ctx, ibcTranslatorContractAddr, asset1TokenFactoryDenom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), asset1DenomBalance, "Ibc translator asset 1 denom balance should be 0")
|
||||
|
||||
// Test 2 (GW Transfer has a cosmos/gaia prefix for recipient address)
|
||||
simplePayload = helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, OsmoChainID, osmoUser1.Bech32Address(gaia.Config().Bech32Prefix), 0, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 20, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "100", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 100")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err = wormchain.GetBalance(ctx, ibcTranslatorContractAddr, asset1TokenFactoryDenom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(100), asset1DenomBalance, "Ibc translator asset 1 denom balance should be 100")
|
||||
|
||||
// Test 3 (GW TransferWithPayload has osmo user1 as recipient and not a contract)
|
||||
ibcHooksPayload := helpers.CreateIbcHooksMsg(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
contractControlledPayload := helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 20, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "200", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 200")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err = wormchain.GetBalance(ctx, ibcTranslatorContractAddr, asset1TokenFactoryDenom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(200), asset1DenomBalance, "Ibc translator asset 1 denom balance should be 200")
|
||||
|
||||
// Test 4 (GW TransferWithPayload - change wasm root in memo)
|
||||
ibcHooksPayload = CreateInvalidIbcHooksMsgWasm(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
contractControlledPayload = helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 20, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "300", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 300")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err = osmosis.GetBalance(ctx, ibcHooksContractAddr, osmoIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(100), asset1DenomBalance, "Ibchooks asset 1 denom balance should be 100")
|
||||
|
||||
// Test 5 (GW TransferWithPayload's ibc hook payload has osmo user1 as recipient and not a contract)
|
||||
cosmosIbcHooksContractAddr := swapBech32Prefix(ibcHooksContractAddr, osmosis.Config().Bech32Prefix, gaia.Config().Bech32Prefix)
|
||||
ibcHooksPayload = helpers.CreateIbcHooksMsg(t, cosmosIbcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
contractControlledPayload = helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 20, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "400", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 400")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err = wormchain.GetBalance(ctx, ibcTranslatorContractAddr, asset1TokenFactoryDenom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(300), asset1DenomBalance, "Ibc translator asset 1 denom balance should be 300")
|
||||
|
||||
// Test 6 (GW TransferWithPayload's ibc hook payload has osmo user1 as recipient and not a contract)
|
||||
ibcHooksPayload = helpers.CreateIbcHooksMsg(t, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
contractControlledPayload = helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 20, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "500", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 500")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err = wormchain.GetBalance(ctx, ibcTranslatorContractAddr, asset1TokenFactoryDenom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(400), asset1DenomBalance, "Ibc translator asset 1 denom balance should be 400")
|
||||
|
||||
// Test 7 (GW TransferWithPayload has invalid execute method for ibc hooks contract)
|
||||
ibcHooksPayload = CreateInvalidIbcHooksMsgExecute(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
contractControlledPayload = helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 20, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "600", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 600")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err = wormchain.GetBalance(ctx, ibcTranslatorContractAddr, asset1TokenFactoryDenom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(500), asset1DenomBalance, "Ibc translator asset 1 denom balance should be 500")
|
||||
|
||||
// Test 8 (GW TransferWithPayload's ibc hook payload has recipient with cosmos/gaia bech32 prefix)
|
||||
ibcHooksPayload = helpers.CreateIbcHooksMsg(t, ibcHooksContractAddr, osmoUser2.Bech32Address(gaia.Config().Bech32Prefix))
|
||||
contractControlledPayload = helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), 100, Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
err = testutil.WaitForBlocks(ctx, 20, wormchain, osmosis)
|
||||
|
||||
// Check the asset 1 CW20 total supply
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
require.Equal(t, "700", cw20QueryRsp.Data.TotalSupply, "Asset 1 CW20 total supply should be 700")
|
||||
|
||||
// Check ibc-translator asset 1 denom balance
|
||||
asset1DenomBalance, err = wormchain.GetBalance(ctx, ibcTranslatorContractAddr, asset1TokenFactoryDenom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(600), asset1DenomBalance, "Ibc translator asset 1 denom balance should be 600")
|
||||
}
|
||||
|
||||
type IbcHooksWasm struct {
|
||||
Payload helpers.IbcHooksPayload `json:"was"` // invalid keyword
|
||||
}
|
||||
|
||||
func CreateInvalidIbcHooksMsgWasm(t *testing.T, contract string, recipient string) []byte {
|
||||
msg := IbcHooksWasm{
|
||||
Payload: helpers.IbcHooksPayload{
|
||||
Contract: contract,
|
||||
Msg: helpers.IbcHooksExecute{
|
||||
Forward: helpers.IbcHooksForward{
|
||||
Recipient: recipient,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return msgBz
|
||||
}
|
||||
|
||||
type IbcHooks struct {
|
||||
Payload IbcHooksPayload `json:"wasm"`
|
||||
}
|
||||
|
||||
type IbcHooksPayload struct {
|
||||
Contract string `json:"contract"`
|
||||
Msg IbcHooksExecute `json:"msg"`
|
||||
}
|
||||
|
||||
type IbcHooksExecute struct {
|
||||
Forward helpers.IbcHooksForward `json:"forward_tokens1"` // invalid method
|
||||
}
|
||||
|
||||
func CreateInvalidIbcHooksMsgExecute(t *testing.T, contract string, recipient string) []byte {
|
||||
msg := IbcHooks{
|
||||
Payload: IbcHooksPayload{
|
||||
Contract: contract,
|
||||
Msg: IbcHooksExecute{
|
||||
Forward: helpers.IbcHooksForward{
|
||||
Recipient: recipient,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
msgBz, err := json.Marshal(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
return msgBz
|
||||
}
|
||||
|
||||
func swapBech32Prefix(address string, currentBech32Prefix string, newBech32Prefix string) string {
|
||||
accAddr := helpers.MustAccAddressFromBech32(address, currentBech32Prefix)
|
||||
return sdk.MustBech32ifyAddressBytes(newBech32Prefix, accAddr)
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
package ictest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/icza/dyno"
|
||||
|
||||
interchaintest "github.com/strangelove-ventures/interchaintest/v4"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos/wasm"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/testreporter"
|
||||
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
|
||||
wormholetypes "github.com/wormhole-foundation/wormchain/x/wormhole/types"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
)
|
||||
|
||||
var (
|
||||
pathWormchainGaia = "wormchain-gaia" // Replace with 2nd cosmos chain supporting wormchain
|
||||
genesisWalletAmount = int64(10_000_000)
|
||||
votingPeriod = "10s"
|
||||
maxDepositPeriod = "10s"
|
||||
coinType = "118"
|
||||
wormchainConfig = ibc.ChainConfig{
|
||||
Type: "cosmos",
|
||||
Name: "wormchain",
|
||||
ChainID: "wormchain-1",
|
||||
Images: []ibc.DockerImage{
|
||||
{
|
||||
Repository: "ghcr.io/strangelove-ventures/heighliner/wormchain",
|
||||
UidGid: "1025:1025",
|
||||
},
|
||||
},
|
||||
Bin: "wormchaind",
|
||||
Bech32Prefix: "wormhole",
|
||||
Denom: "uworm",
|
||||
CoinType: coinType,
|
||||
GasPrices: "0.00uworm",
|
||||
GasAdjustment: 1.8,
|
||||
TrustingPeriod: "112h",
|
||||
NoHostMount: false,
|
||||
EncodingConfig: wormchainEncoding(),
|
||||
}
|
||||
numFullNodes = 1
|
||||
)
|
||||
|
||||
// wormchainEncoding registers the Wormchain specific module codecs so that the associated types and msgs
|
||||
// will be supported when writing to the blocksdb sqlite database.
|
||||
func wormchainEncoding() *simappparams.EncodingConfig {
|
||||
cfg := wasm.WasmEncoding()
|
||||
|
||||
// register custom types
|
||||
wormholetypes.RegisterInterfaces(cfg.InterfaceRegistry)
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func CreateChains(t *testing.T, wormchainVersion string, guardians guardians.ValSet) []ibc.Chain {
|
||||
numWormchainVals := len(guardians.Vals)
|
||||
wormchainConfig.Images[0].Version = wormchainVersion
|
||||
|
||||
// Create chain factory with wormchain
|
||||
wormchainConfig.ModifyGenesis = ModifyGenesis(votingPeriod, maxDepositPeriod, guardians)
|
||||
|
||||
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
|
||||
{
|
||||
ChainName: "wormchain",
|
||||
ChainConfig: wormchainConfig,
|
||||
NumValidators: &numWormchainVals,
|
||||
NumFullNodes: &numFullNodes,
|
||||
},
|
||||
{Name: "gaia", Version: "v10.0.1", ChainConfig: ibc.ChainConfig{
|
||||
GasPrices: "0.0uatom",
|
||||
}},
|
||||
{
|
||||
Name: "osmosis",
|
||||
Version: "v15.1.2",
|
||||
ChainConfig: ibc.ChainConfig{
|
||||
ChainID: "osmosis-1002", // hardcoded handling in osmosis binary for osmosis-1, so need to override to something different.
|
||||
GasPrices: "1.0uosmo",
|
||||
EncodingConfig: wasm.WasmEncoding(),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// Get chains from the chain factory
|
||||
chains, err := cf.Chains(t.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
return chains
|
||||
}
|
||||
|
||||
func BuildInterchain(t *testing.T, chains []ibc.Chain) (context.Context, ibc.Relayer, *testreporter.RelayerExecReporter, *client.Client) {
|
||||
// Create a new Interchain object which describes the chains, relayers, and IBC connections we want to use
|
||||
ic := interchaintest.NewInterchain()
|
||||
|
||||
for _, chain := range chains {
|
||||
ic.AddChain(chain)
|
||||
}
|
||||
|
||||
rep := testreporter.NewNopReporter()
|
||||
eRep := rep.RelayerExecReporter(t)
|
||||
|
||||
wormGaiaPath := "wormgaia"
|
||||
wormOsmoPath := "wormosmo"
|
||||
ctx := context.Background()
|
||||
client, network := interchaintest.DockerSetup(t)
|
||||
r := interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t)).Build(
|
||||
t, client, network)
|
||||
ic.AddRelayer(r, "relayer")
|
||||
ic.AddLink(interchaintest.InterchainLink{
|
||||
Chain1: chains[0], // Wormchain
|
||||
Chain2: chains[1], // Gaia
|
||||
Relayer: r,
|
||||
Path: wormGaiaPath,
|
||||
})
|
||||
ic.AddLink(interchaintest.InterchainLink{
|
||||
Chain1: chains[0], // Wormchain
|
||||
Chain2: chains[2], // Osmosis
|
||||
Relayer: r,
|
||||
Path: wormOsmoPath,
|
||||
})
|
||||
|
||||
err := ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
|
||||
TestName: t.Name(),
|
||||
Client: client,
|
||||
NetworkID: network,
|
||||
SkipPathCreation: false,
|
||||
BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = ic.Close()
|
||||
})
|
||||
|
||||
// Start the relayer
|
||||
err = r.StartRelayer(ctx, eRep, wormGaiaPath, wormOsmoPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(
|
||||
func() {
|
||||
err := r.StopRelayer(ctx, eRep)
|
||||
if err != nil {
|
||||
t.Logf("an error occured while stopping the relayer: %s", err)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
return ctx, r, eRep, client
|
||||
}
|
||||
|
||||
// Modify the genesis file:
|
||||
// * Goverance - i.e. voting period
|
||||
// * Get generated val set
|
||||
// * Get faucet address
|
||||
// * Set Guardian Set List using new val set
|
||||
// * Set Guardian Validator List using new val set
|
||||
// * Allow list the faucet address
|
||||
func ModifyGenesis(votingPeriod string, maxDepositPeriod string, guardians guardians.ValSet) func(ibc.ChainConfig, []byte) ([]byte, error) {
|
||||
return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) {
|
||||
numVals := len(guardians.Vals)
|
||||
g := make(map[string]interface{})
|
||||
if err := json.Unmarshal(genbz, &g); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal genesis file: %w", err)
|
||||
}
|
||||
|
||||
// Modify gov
|
||||
if err := dyno.Set(g, votingPeriod, "app_state", "gov", "voting_params", "voting_period"); err != nil {
|
||||
return nil, fmt.Errorf("failed to set voting period in genesis json: %w", err)
|
||||
}
|
||||
if err := dyno.Set(g, maxDepositPeriod, "app_state", "gov", "deposit_params", "max_deposit_period"); err != nil {
|
||||
return nil, fmt.Errorf("failed to set max deposit period in genesis json: %w", err)
|
||||
}
|
||||
if err := dyno.Set(g, chainConfig.Denom, "app_state", "gov", "deposit_params", "min_deposit", 0, "denom"); err != nil {
|
||||
return nil, fmt.Errorf("failed to set min deposit in genesis json: %w", err)
|
||||
}
|
||||
// Get validators
|
||||
var validators [][]byte
|
||||
for i := 0; i < numVals; i++ {
|
||||
validatorBech32, err := dyno.Get(g, "app_state", "genutil", "gen_txs", i, "body", "messages", 0, "delegator_address")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get validator pub key: %w", err)
|
||||
}
|
||||
validatorAccAddr := helpers.MustAccAddressFromBech32(validatorBech32.(string), chainConfig.Bech32Prefix).Bytes()
|
||||
validators = append(validators, validatorAccAddr)
|
||||
}
|
||||
|
||||
// Get faucet address
|
||||
faucetAddress, err := dyno.Get(g, "app_state", "auth", "accounts", numVals, "address")
|
||||
|
||||
// Get relayer address
|
||||
relayerAddress, err := dyno.Get(g, "app_state", "auth", "accounts", numVals+1, "address")
|
||||
|
||||
// Set guardian set list and validators
|
||||
guardianSetList := []GuardianSet{}
|
||||
guardianSet := GuardianSet{
|
||||
Index: 0,
|
||||
Keys: [][]byte{},
|
||||
}
|
||||
guardianValidators := []GuardianValidator{}
|
||||
for i := 0; i < numVals; i++ {
|
||||
guardianSet.Keys = append(guardianSet.Keys, guardians.Vals[i].Addr)
|
||||
guardianValidators = append(guardianValidators, GuardianValidator{
|
||||
GuardianKey: guardians.Vals[i].Addr,
|
||||
ValidatorAddr: validators[i],
|
||||
})
|
||||
}
|
||||
guardianSetList = append(guardianSetList, guardianSet)
|
||||
if err := dyno.Set(g, guardianSetList, "app_state", "wormhole", "guardianSetList"); err != nil {
|
||||
return nil, fmt.Errorf("failed to set guardian set list: %w", err)
|
||||
}
|
||||
if err := dyno.Set(g, guardianValidators, "app_state", "wormhole", "guardianValidatorList"); err != nil {
|
||||
return nil, fmt.Errorf("failed to set guardian validator list: %w", err)
|
||||
}
|
||||
|
||||
allowedAddresses := []ValidatorAllowedAddress{}
|
||||
allowedAddresses = append(allowedAddresses, ValidatorAllowedAddress{
|
||||
ValidatorAddress: sdk.MustBech32ifyAddressBytes(chainConfig.Bech32Prefix, validators[0]),
|
||||
AllowedAddress: faucetAddress.(string),
|
||||
Name: "Faucet",
|
||||
})
|
||||
allowedAddresses = append(allowedAddresses, ValidatorAllowedAddress{
|
||||
ValidatorAddress: sdk.MustBech32ifyAddressBytes(chainConfig.Bech32Prefix, validators[0]),
|
||||
AllowedAddress: relayerAddress.(string),
|
||||
Name: "Relayer",
|
||||
})
|
||||
if err := dyno.Set(g, allowedAddresses, "app_state", "wormhole", "allowedAddresses"); err != nil {
|
||||
return nil, fmt.Errorf("failed to set guardian validator list: %w", err)
|
||||
}
|
||||
|
||||
config := wormholetypes.Config{
|
||||
GuardianSetExpiration: 86400,
|
||||
GovernanceEmitter: vaa.GovernanceEmitter[:],
|
||||
GovernanceChain: uint32(vaa.GovernanceChain),
|
||||
ChainId: uint32(vaa.ChainIDWormchain),
|
||||
}
|
||||
if err := dyno.Set(g, config, "app_state", "wormhole", "config"); err != nil {
|
||||
return nil, fmt.Errorf("failed to set guardian validator list: %w", err)
|
||||
}
|
||||
out, err := json.Marshal(g)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal genesis bytes to json: %w", err)
|
||||
}
|
||||
fmt.Println("Genesis: ", string(out))
|
||||
return out, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Replace these with reference to x/wormchain/types
|
||||
type GuardianSet struct {
|
||||
Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
|
||||
Keys [][]byte `protobuf:"bytes,2,rep,name=keys,proto3" json:"keys,omitempty"`
|
||||
ExpirationTime uint64 `protobuf:"varint,3,opt,name=expirationTime,proto3" json:"expirationTime,omitempty"`
|
||||
}
|
||||
|
||||
type ValidatorAllowedAddress struct {
|
||||
// the validator/guardian that controls this entry
|
||||
ValidatorAddress string `protobuf:"bytes,1,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"`
|
||||
// the allowlisted account
|
||||
AllowedAddress string `protobuf:"bytes,2,opt,name=allowed_address,json=allowedAddress,proto3" json:"allowed_address,omitempty"`
|
||||
// human readable name
|
||||
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type GuardianValidator struct {
|
||||
GuardianKey []byte `protobuf:"bytes,1,opt,name=guardianKey,proto3" json:"guardianKey,omitempty"`
|
||||
ValidatorAddr []byte `protobuf:"bytes,2,opt,name=validatorAddr,proto3" json:"validatorAddr,omitempty"`
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package ictest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
)
|
||||
|
||||
// TestUpgradeFailure starts wormchain on v2.18.1, then attempts to upgrade 1 validator at a time to v2.23.0
|
||||
func TestUpgradeFailure(t *testing.T) {
|
||||
// Base setup
|
||||
numVals := 5
|
||||
guardians := guardians.CreateValSet(t, numVals)
|
||||
chains := CreateChains(t, "v2.18.1", *guardians)
|
||||
ctx, _, _, client := BuildInterchain(t, chains)
|
||||
|
||||
// Chains
|
||||
wormchain := chains[0].(*cosmos.CosmosChain)
|
||||
|
||||
blocksAfterUpgrade := uint64(5)
|
||||
|
||||
// upgrade version on all nodes
|
||||
wormchain.UpgradeVersion(ctx, client, "v2.23.0")
|
||||
|
||||
for i := 0; i < numVals; i++ {
|
||||
haltHeight, err := wormchain.Height(ctx)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("Halt height:", i, " : ", haltHeight)
|
||||
|
||||
// bring down node to prepare for upgrade
|
||||
err = wormchain.StopANode(ctx, i)
|
||||
require.NoError(t, err, "error stopping node(s)")
|
||||
|
||||
// start node back up with new binary
|
||||
err = wormchain.StartANode(ctx, i)
|
||||
require.NoError(t, err, "error starting upgraded node(s)")
|
||||
|
||||
// Restart the fullnode with the last validator
|
||||
if i+1 == numVals {
|
||||
err = wormchain.StopANode(ctx, i+1)
|
||||
require.NoError(t, err, "error stopping node(s)")
|
||||
err = wormchain.StartANode(ctx, i+1)
|
||||
require.NoError(t, err, "error starting upgraded node(s)")
|
||||
}
|
||||
|
||||
timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, time.Second*20)
|
||||
defer timeoutCtxCancel()
|
||||
|
||||
// Wait for 5 blocks (2sec/block) or 20 seconds
|
||||
testutil.WaitForBlocks(timeoutCtx, int(blocksAfterUpgrade), wormchain)
|
||||
}
|
||||
// Get current height
|
||||
height1, err := wormchain.Height(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, time.Second*20)
|
||||
defer timeoutCtxCancel()
|
||||
|
||||
// Wait for 5 blocks (2sec/block) or 20 seconds
|
||||
testutil.WaitForBlocks(timeoutCtx, int(blocksAfterUpgrade), wormchain)
|
||||
|
||||
height2, err := wormchain.Height(ctx)
|
||||
require.NoError(t, err, "error fetching height after upgrade")
|
||||
fmt.Println("Checked height: ", height2)
|
||||
|
||||
// height1 and height2 should be equal since we don't produce blocks with this upgrade path
|
||||
require.Equal(t, height1, height2, "height incremented after upgrade, so upgrade succeeded and test failed")
|
||||
}
|
|
@ -0,0 +1,392 @@
|
|||
package ictest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil/base58"
|
||||
"github.com/strangelove-ventures/interchaintest/v4"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types"
|
||||
)
|
||||
|
||||
// TestUpgradeTest upgrades from v2.18.1 -> v2.18.1.1 -> V2.23.0 and:
|
||||
// - Setup wormchain, gaia, and osmosis including contracts/allowlists/etc
|
||||
// - External->Cosmos: Send 10.000_018 to gaia user 1 (simple)
|
||||
// - External->Cosmos: Send 1.000_001 to osmo user 1 (simple)
|
||||
// - External->Cosmos: Send 1.000_002 to osmo user 2 (contract controlled via osmo ibc-hooks contract)
|
||||
// - Cosmos->External: Send 1.000_003 to external address (simple) from gaia user 1
|
||||
// -- gaia user 1 now has 9.000_015 of asset 1
|
||||
// - Cosmos->External: Send 1.000_004 to external address (contract controlled) from gaia user 1
|
||||
// -- gaia user 1 now has 8.000_011 of asset 1
|
||||
// - Cosmos->Cosmos: Send 1.000_005 to osmo user 1 (simple) from gaia user 1
|
||||
// -- gaia user 1 now has 7.000_006 of asset 1
|
||||
// -- osmo user 1 now has 2.000_006 of asset 1
|
||||
// - Cosmos->Cosmos: Send 1.000_006 to osmo user 2 (contract controlled via osmo ibc-hooks contract) from gaia user 1
|
||||
// -- gaia user 1 now has 6.000_000 of asset 1
|
||||
// -- osmo user 2 now has 2.000_008 of asset 1
|
||||
// - Verify asset 1 balance of gaia user 1, osmo user 1, osmo user 2, and cw20 contract total supply
|
||||
func TestUpgrade(t *testing.T) {
|
||||
// Base setup
|
||||
numVals := 5
|
||||
guardians := guardians.CreateValSet(t, numVals)
|
||||
chains := CreateChains(t, "v2.18.1", *guardians)
|
||||
ctx, r, eRep, client := BuildInterchain(t, chains)
|
||||
|
||||
// Chains
|
||||
wormchain := chains[0].(*cosmos.CosmosChain)
|
||||
gaia := chains[1].(*cosmos.CosmosChain)
|
||||
osmosis := chains[2].(*cosmos.CosmosChain)
|
||||
|
||||
wormchainFaucetAddrBz, err := wormchain.GetAddress(ctx, "faucet")
|
||||
require.NoError(t, err)
|
||||
wormchainFaucetAddr := sdk.MustBech32ifyAddressBytes(wormchain.Config().Bech32Prefix, wormchainFaucetAddrBz)
|
||||
fmt.Println("Wormchain faucet addr: ", wormchainFaucetAddr)
|
||||
|
||||
osmoToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, osmosis.Config().ChainID, wormchain.Config().ChainID)
|
||||
wormToOsmoChannel := osmoToWormChannel.Counterparty
|
||||
gaiaToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, gaia.Config().ChainID, wormchain.Config().ChainID)
|
||||
wormToGaiaChannel := gaiaToWormChannel.Counterparty
|
||||
|
||||
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), wormchain, gaia, osmosis, osmosis)
|
||||
_ = users[0] // Wormchain user
|
||||
gaiaUser := users[1]
|
||||
osmoUser1 := users[2]
|
||||
osmoUser2 := users[3]
|
||||
|
||||
// *************************************************************
|
||||
// ********* Upgrade to new version of wormchain ***************
|
||||
// *************************************************************
|
||||
|
||||
blocksAfterUpgrade := uint64(5)
|
||||
|
||||
// upgrade version on all nodes
|
||||
wormchain.UpgradeVersion(ctx, client, "v2.18.1.1")
|
||||
|
||||
for i := 0; i < numVals; i++ {
|
||||
haltHeight, err := wormchain.Height(ctx)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("Halt height:", i, " : ", haltHeight)
|
||||
|
||||
// bring down nodes to prepare for upgrade
|
||||
err = wormchain.StopANode(ctx, i)
|
||||
require.NoError(t, err, "error stopping node(s)")
|
||||
|
||||
// start all nodes back up.
|
||||
// validators reach consensus on first block after upgrade height
|
||||
// and chain block production resumes.
|
||||
err = wormchain.StartANode(ctx, i)
|
||||
require.NoError(t, err, "error starting upgraded node(s)")
|
||||
|
||||
// Restart the fullnode with the last validator
|
||||
if i+1 == numVals {
|
||||
err = wormchain.StopANode(ctx, i+1)
|
||||
require.NoError(t, err, "error stopping node(s)")
|
||||
err = wormchain.StartANode(ctx, i+1)
|
||||
require.NoError(t, err, "error starting upgraded node(s)")
|
||||
}
|
||||
|
||||
timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, time.Second*45)
|
||||
defer timeoutCtxCancel()
|
||||
|
||||
err = testutil.WaitForBlocks(timeoutCtx, int(blocksAfterUpgrade), wormchain)
|
||||
require.NoError(t, err, "chain did not produce blocks after upgrade1")
|
||||
|
||||
height, err := wormchain.Height(ctx)
|
||||
require.NoError(t, err, "error fetching height after upgrade")
|
||||
fmt.Println("Checked height: ", height)
|
||||
|
||||
require.GreaterOrEqual(t, height, haltHeight+blocksAfterUpgrade, "height did not increment enough after upgrade")
|
||||
}
|
||||
|
||||
fmt.Println("***** PASS upgrade #1 **********")
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// upgrade version on all nodes
|
||||
blocksAfterUpgrade = uint64(10)
|
||||
|
||||
height, err := wormchain.Height(ctx)
|
||||
require.NoError(t, err, "error fetching height before upgrade")
|
||||
fmt.Println("Height at sending schedule upgrade: ", height)
|
||||
|
||||
haltHeight := height + blocksAfterUpgrade
|
||||
fmt.Println("Height for scheduled upgrade: ", haltHeight)
|
||||
|
||||
helpers.ScheduleUpgrade(t, ctx, wormchain, "faucet", "v2.23.0", haltHeight, guardians)
|
||||
|
||||
timeoutCtx3, timeoutCtxCancel3 := context.WithTimeout(ctx, time.Second*45)
|
||||
defer timeoutCtxCancel3()
|
||||
|
||||
// this should timeout due to chain halt at upgrade height.
|
||||
testutil.WaitForBlocks(timeoutCtx3, int(blocksAfterUpgrade)+2, wormchain)
|
||||
|
||||
height, err = wormchain.Height(ctx)
|
||||
require.NoError(t, err, "error fetching height after chain should have halted")
|
||||
fmt.Println("Height when chains should have halted: ", height)
|
||||
|
||||
require.Equal(t, haltHeight, height, "height is not equal to halt height")
|
||||
|
||||
// bring down nodes to prepare for upgrade
|
||||
err = wormchain.StopAllNodes(ctx)
|
||||
require.NoError(t, err, "error stopping node(s)")
|
||||
|
||||
// upgrade version on all nodes
|
||||
wormchain.UpgradeVersion(ctx, client, "v2.23.0")
|
||||
|
||||
// start all nodes back up.
|
||||
// validators reach consensus on first block after upgrade height
|
||||
// and chain block production resumes.
|
||||
err = wormchain.StartAllNodes(ctx)
|
||||
require.NoError(t, err, "error starting upgraded node(s)")
|
||||
|
||||
timeoutCtx4, timeoutCtxCancel4 := context.WithTimeout(ctx, time.Second*45)
|
||||
defer timeoutCtxCancel4()
|
||||
|
||||
err = testutil.WaitForBlocks(timeoutCtx4, int(blocksAfterUpgrade)+1, wormchain)
|
||||
require.NoError(t, err, "chain did not produce blocks after upgrade")
|
||||
|
||||
height, err = wormchain.Height(ctx)
|
||||
require.NoError(t, err, "error fetching height after upgrade")
|
||||
fmt.Println("Height after upgrade >10 blocks after scheduled halt: ", height)
|
||||
|
||||
require.GreaterOrEqual(t, height, haltHeight+blocksAfterUpgrade, "height did not increment enough after upgrade")
|
||||
fmt.Println("***** PASS 2nd upgrade **********")
|
||||
|
||||
// *************************************************************
|
||||
// ******************* Continue with test **********************
|
||||
// *************************************************************
|
||||
|
||||
ibcHooksCodeId, err := osmosis.StoreContract(ctx, osmoUser1.KeyName, "./contracts/ibc_hooks.wasm")
|
||||
require.NoError(t, err)
|
||||
fmt.Println("IBC hooks code id: ", ibcHooksCodeId)
|
||||
|
||||
ibcHooksContractAddr, err := osmosis.InstantiateContract(ctx, osmoUser1.KeyName, ibcHooksCodeId, "{}", true)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("IBC hooks contract addr: ", ibcHooksContractAddr)
|
||||
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||
require.NoError(t, err, "error waiting for 2 blocks")
|
||||
|
||||
// Store wormhole core contract
|
||||
coreContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/wormhole_core.wasm", guardians)
|
||||
fmt.Println("Core contract code id: ", coreContractCodeId)
|
||||
|
||||
// Instantiate wormhole core contract
|
||||
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
||||
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
||||
fmt.Println("Core contract address: ", coreContractAddr)
|
||||
|
||||
// Store cw20_wrapped_2 contract
|
||||
wrappedAssetCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/cw20_wrapped_2.wasm", guardians)
|
||||
fmt.Println("CW20 wrapped_2 code id: ", wrappedAssetCodeId)
|
||||
|
||||
// Store token bridge contract
|
||||
tbContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/token_bridge.wasm", guardians)
|
||||
fmt.Println("Token bridge contract code id: ", tbContractCodeId)
|
||||
|
||||
// Instantiate token bridge contract
|
||||
tbInstantiateMsg := helpers.TbContractInstantiateMsg(t, wormchainConfig, coreContractAddr, wrappedAssetCodeId)
|
||||
tbContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", tbContractCodeId, "token_bridge", tbInstantiateMsg, guardians)
|
||||
fmt.Println("Token bridge contract address: ", tbContractAddr)
|
||||
|
||||
helpers.SubmitAllowlistInstantiateContract(t, ctx, wormchain, "faucet", wormchain.Config(), tbContractAddr, wrappedAssetCodeId, guardians)
|
||||
|
||||
// Register a new external chain
|
||||
tbRegisterChainMsg := helpers.TbRegisterChainMsg(t, ExternalChainId, ExternalChainEmitterAddr, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterChainMsg))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Register a new foreign asset (Asset1) originating on externalChain
|
||||
tbRegisterForeignAssetMsg := helpers.TbRegisterForeignAsset(t, Asset1ContractAddr, Asset1ChainID, ExternalChainEmitterAddr, Asset1Decimals, Asset1Symbol, Asset1Name, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterForeignAssetMsg))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Store ibc translator contract
|
||||
ibcTranslatorCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/ibc_translator.wasm", guardians)
|
||||
fmt.Println("Ibc translator code id: ", ibcTranslatorCodeId)
|
||||
|
||||
// Instantiate ibc translator contract
|
||||
ibcTranslatorInstantiateMsg := helpers.IbcTranslatorContractInstantiateMsg(t, tbContractAddr)
|
||||
ibcTranslatorContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", ibcTranslatorCodeId, "ibc_translator", ibcTranslatorInstantiateMsg, guardians)
|
||||
fmt.Println("Ibc translator contract address: ", ibcTranslatorContractAddr)
|
||||
|
||||
helpers.SetMiddlewareContract(t, ctx, wormchain, "faucet", wormchain.Config(), ibcTranslatorContractAddr, guardians)
|
||||
|
||||
// Allowlist worm/osmo chain id / channel
|
||||
wormOsmoAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, OsmoChainID, wormToOsmoChannel.ChannelID, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormOsmoAllowlistMsg)
|
||||
|
||||
// Allowlist worm/gaia chain id / channel
|
||||
wormGaiaAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, GaiaChainID, wormToGaiaChannel.ChannelID, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormGaiaAllowlistMsg)
|
||||
|
||||
// Create and process a simple ibc payload3: Transfers 10.000_018 of asset1 from external chain through wormchain to gaia user
|
||||
simplePayload := helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, GaiaChainID, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), 0, 1)
|
||||
externalSender := []byte{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}
|
||||
payload3 := helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToGaiaUser1), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
|
||||
completeTransferAndConvertMsg := helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
|
||||
// Create and process a simple ibc payload3: Transfers 1.000_001 of asset1 from external chain through wormchain to osmo user1
|
||||
simplePayload = helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, OsmoChainID, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), 0, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToOsmoUser1), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
|
||||
// Create and process a contract controlled ibc payload3
|
||||
// Transfers 1.000_002 of asset1 from external chain through wormchain to ibc hooks contract addr
|
||||
// IBC hooks is used to route the contract controlled payload to a test contract which forwards tokens to osmo user2
|
||||
ibcHooksPayload := helpers.CreateIbcHooksMsg(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
contractControlledPayload := helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToOsmoUser2), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 10, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Query the CW20 address of asset1
|
||||
var tbQueryRsp helpers.TbQueryRsp
|
||||
tbQueryReq := helpers.CreateCW20Query(t, Asset1ChainID, Asset1ContractAddr)
|
||||
wormchain.QueryContract(ctx, tbContractAddr, tbQueryReq, &tbQueryRsp)
|
||||
cw20Address := tbQueryRsp.Data.Address
|
||||
fmt.Println("Asset1 cw20 addr: ", cw20Address)
|
||||
|
||||
// Get the Gaia/IBC denom of asset1
|
||||
cw20AddressBz := helpers.MustAccAddressFromBech32(cw20Address, wormchain.Config().Bech32Prefix)
|
||||
subdenom := base58.Encode(cw20AddressBz)
|
||||
tokenFactoryDenom := fmt.Sprint("factory/", ibcTranslatorContractAddr, "/", subdenom)
|
||||
gaiaAsset1Denom := transfertypes.GetPrefixedDenom("transfer", gaiaToWormChannel.ChannelID, tokenFactoryDenom)
|
||||
gaiaIbcAsset1Denom := transfertypes.ParseDenomTrace(gaiaAsset1Denom).IBCDenom()
|
||||
|
||||
// Get the Osmo/IBC denom of asset1
|
||||
osmoAsset1Denom := transfertypes.GetPrefixedDenom("transfer", osmoToWormChannel.ChannelID, tokenFactoryDenom)
|
||||
osmoIbcAsset1Denom := transfertypes.ParseDenomTrace(osmoAsset1Denom).IBCDenom()
|
||||
|
||||
// Verify Gaia user 1 has expected asset 1 balance
|
||||
gaiaUser1Asset1BalanceTemp, err := gaia.GetBalance(ctx, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), gaiaIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("Gaia user asset1 coins: ", gaiaUser1Asset1BalanceTemp)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify Gaia user 1 has expected asset 1 balance
|
||||
gaiaUser1Asset1BalanceTemp, err = gaia.GetBalance(ctx, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), gaiaIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("Gaia user asset1 coins: ", gaiaUser1Asset1BalanceTemp)
|
||||
|
||||
// ************* Cosmos->External: Simple payload (wormhole-mw + ibc-hooks) ****************
|
||||
// Send 1.000_003 asset 1 from gaia user 1 to external
|
||||
simpleMemo := helpers.CreateIbcComposabilityMwMemoGatewayTransfer(t, Asset1ChainID, externalSender, 0, 1)
|
||||
transfer := ibc.WalletAmount{
|
||||
Address: ibcTranslatorContractAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToExternalSimple),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{Memo: simpleMemo})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ************* Cosmos->External: Contract controlled payload (wormhole-mw + ibc-hooks) ****************
|
||||
// Send 1.000_004 asset 1 from gaia user 1 to external
|
||||
ccIbcHooksMsg := helpers.CreateIbcComposabilityMwMemoGatewayTransferWithPayload(t, Asset1ChainID, externalSender, []byte("ExternalContractPayload"), 1)
|
||||
transfer = ibc.WalletAmount{
|
||||
Address: ibcTranslatorContractAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToExternalCC),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{Memo: ccIbcHooksMsg})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ************** Cosmos->Cosmos: Simple payload (wormhole-mw + PFM) ****************
|
||||
// Send 1.000_005 asset 1 from gaia user 1 to osmo user 1
|
||||
simplePfmMsg := helpers.CreateIbcComposabilityMwMemoGatewayTransfer(t, OsmoChainID, []byte(osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix)), 0, 1)
|
||||
transfer = ibc.WalletAmount{
|
||||
Address: wormchainFaucetAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToOsmoUser1),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{
|
||||
Timeout: &ibc.IBCTimeout{
|
||||
NanoSeconds: 30_000_000_000,
|
||||
},
|
||||
Memo: simplePfmMsg,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ************** Cosmos->Cosmos: Contract controlled payload (wormhole-mw + PFM) ****************
|
||||
// Send 1.000_006 asset 1 from gaia user 1 to osmo user 2
|
||||
ccPayload := helpers.CreateIbcHooksMsg(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
ccPfmMsg := helpers.CreateIbcComposabilityMwMemoGatewayTransferWithPayload(t, OsmoChainID, []byte(ibcHooksContractAddr), ccPayload, 1)
|
||||
transfer = ibc.WalletAmount{
|
||||
Address: ibcTranslatorContractAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToOsmoUser2),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{
|
||||
Timeout: &ibc.IBCTimeout{
|
||||
NanoSeconds: 30_000_000_000,
|
||||
},
|
||||
Memo: ccPfmMsg,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 15, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify Gaia user 1 has expected asset 1 balance
|
||||
gaiaUser1Asset1Balance, err := gaia.GetBalance(ctx, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), gaiaIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
expectedGaiaUser1Amount := AmountExternalToGaiaUser1 - AmountGaiaUser1ToExternalCC - AmountGaiaUser1ToExternalSimple - AmountGaiaUser1ToOsmoUser1 - AmountGaiaUser1ToOsmoUser2
|
||||
require.Equal(t, int64(expectedGaiaUser1Amount), gaiaUser1Asset1Balance)
|
||||
fmt.Println("Gaia user asset1 coins: ", gaiaUser1Asset1Balance)
|
||||
|
||||
// Verify osmo user 1 has expected asset 1 balance
|
||||
osmoUser1Asset1Balance, err := osmosis.GetBalance(ctx, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), osmoIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(AmountExternalToOsmoUser1+AmountGaiaUser1ToOsmoUser1), osmoUser1Asset1Balance)
|
||||
fmt.Println("Osmo user1 asset1 coins: ", osmoUser1Asset1Balance)
|
||||
|
||||
// Verify osmo user 2 has expected asset 1 balance
|
||||
osmoUser2Asset1Balance, err := osmosis.GetBalance(ctx, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix), osmoIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(AmountExternalToOsmoUser2+AmountGaiaUser1ToOsmoUser2), osmoUser2Asset1Balance)
|
||||
fmt.Println("Osmo user2 asset1 coins: ", osmoUser2Asset1Balance)
|
||||
|
||||
// Verify asset 1 cw20 contract has expected final total supply
|
||||
var cw20QueryRsp helpers.Cw20WrappedQueryRsp
|
||||
cw20QueryReq := helpers.Cw20WrappedQueryMsg{TokenInfo: helpers.Cw20TokenInfo{}}
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
fmt.Println("Asset1 supply: ", cw20QueryRsp.Data.TotalSupply)
|
||||
totalSupply, err := strconv.ParseUint(cw20QueryRsp.Data.TotalSupply, 10, 64)
|
||||
require.NoError(t, err)
|
||||
expectedTotalSupply := AmountExternalToGaiaUser1 + AmountExternalToOsmoUser1 + AmountExternalToOsmoUser2 - AmountGaiaUser1ToExternalSimple - AmountGaiaUser1ToExternalCC
|
||||
require.Equal(t, uint64(expectedTotalSupply), totalSupply)
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
package ictest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil/base58"
|
||||
"github.com/strangelove-ventures/interchaintest/v4"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types"
|
||||
)
|
||||
|
||||
var (
|
||||
GaiaChainID = uint16(11)
|
||||
OsmoChainID = uint16(12)
|
||||
|
||||
ExternalChainId = uint16(123)
|
||||
ExternalChainEmitterAddr = "0x123EmitterAddress"
|
||||
|
||||
Asset1Name = "Wrapped BTC"
|
||||
Asset1Symbol = "XBTC"
|
||||
Asset1ContractAddr = "0xXBTC"
|
||||
Asset1ChainID = ExternalChainId
|
||||
Asset1Decimals = uint8(6)
|
||||
|
||||
AmountExternalToGaiaUser1 = 10_000_018
|
||||
AmountExternalToOsmoUser1 = 1_000_001
|
||||
AmountExternalToOsmoUser2 = 1_000_002
|
||||
AmountGaiaUser1ToExternalSimple = 1_000_003
|
||||
AmountGaiaUser1ToExternalCC = 1_000_004
|
||||
AmountGaiaUser1ToOsmoUser1 = 1_000_005
|
||||
AmountGaiaUser1ToOsmoUser2 = 1_000_006
|
||||
)
|
||||
|
||||
// TestWormchain runs through a simple test case for each deliverable
|
||||
// - Setup wormchain, gaia, and osmosis including contracts/allowlists/etc
|
||||
// - External->Cosmos: Send 10.000_018 to gaia user 1 (simple)
|
||||
// - External->Cosmos: Send 1.000_001 to osmo user 1 (simple)
|
||||
// - External->Cosmos: Send 1.000_002 to osmo user 2 (contract controlled via osmo ibc-hooks contract)
|
||||
// - Cosmos->External: Send 1.000_003 to external address (simple) from gaia user 1
|
||||
// -- gaia user 1 now has 9.000_015 of asset 1
|
||||
// - Cosmos->External: Send 1.000_004 to external address (contract controlled) from gaia user 1
|
||||
// -- gaia user 1 now has 8.000_011 of asset 1
|
||||
// - Cosmos->Cosmos: Send 1.000_005 to osmo user 1 (simple) from gaia user 1
|
||||
// -- gaia user 1 now has 7.000_006 of asset 1
|
||||
// -- osmo user 1 now has 2.000_006 of asset 1
|
||||
// - Cosmos->Cosmos: Send 1.000_006 to osmo user 2 (contract controlled via osmo ibc-hooks contract) from gaia user 1
|
||||
// -- gaia user 1 now has 6.000_000 of asset 1
|
||||
// -- osmo user 2 now has 2.000_008 of asset 1
|
||||
// - Verify asset 1 balance of gaia user 1, osmo user 1, osmo user 2, and cw20 contract total supply
|
||||
func TestWormchain(t *testing.T) {
|
||||
// Base setup
|
||||
numVals := 2
|
||||
guardians := guardians.CreateValSet(t, numVals)
|
||||
chains := CreateChains(t, "v2.23.0", *guardians)
|
||||
ctx, r, eRep, _ := BuildInterchain(t, chains)
|
||||
|
||||
// Chains
|
||||
wormchain := chains[0].(*cosmos.CosmosChain)
|
||||
gaia := chains[1].(*cosmos.CosmosChain)
|
||||
osmosis := chains[2].(*cosmos.CosmosChain)
|
||||
|
||||
wormchainFaucetAddrBz, err := wormchain.GetAddress(ctx, "faucet")
|
||||
require.NoError(t, err)
|
||||
wormchainFaucetAddr := sdk.MustBech32ifyAddressBytes(wormchain.Config().Bech32Prefix, wormchainFaucetAddrBz)
|
||||
fmt.Println("Wormchain faucet addr: ", wormchainFaucetAddr)
|
||||
|
||||
osmoToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, osmosis.Config().ChainID, wormchain.Config().ChainID)
|
||||
wormToOsmoChannel := osmoToWormChannel.Counterparty
|
||||
gaiaToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, gaia.Config().ChainID, wormchain.Config().ChainID)
|
||||
wormToGaiaChannel := gaiaToWormChannel.Counterparty
|
||||
|
||||
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), wormchain, gaia, osmosis, osmosis)
|
||||
_ = users[0] // Wormchain user
|
||||
gaiaUser := users[1]
|
||||
osmoUser1 := users[2]
|
||||
osmoUser2 := users[3]
|
||||
|
||||
ibcHooksCodeId, err := osmosis.StoreContract(ctx, osmoUser1.KeyName, "./contracts/ibc_hooks.wasm")
|
||||
require.NoError(t, err)
|
||||
fmt.Println("IBC hooks code id: ", ibcHooksCodeId)
|
||||
|
||||
ibcHooksContractAddr, err := osmosis.InstantiateContract(ctx, osmoUser1.KeyName, ibcHooksCodeId, "{}", true)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("IBC hooks contract addr: ", ibcHooksContractAddr)
|
||||
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||
require.NoError(t, err, "error waiting for 2 blocks")
|
||||
|
||||
// Store wormhole core contract
|
||||
coreContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/wormhole_core.wasm", guardians)
|
||||
fmt.Println("Core contract code id: ", coreContractCodeId)
|
||||
|
||||
// Instantiate wormhole core contract
|
||||
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
||||
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
||||
fmt.Println("Core contract address: ", coreContractAddr)
|
||||
|
||||
// Store cw20_wrapped_2 contract
|
||||
wrappedAssetCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/cw20_wrapped_2.wasm", guardians)
|
||||
fmt.Println("CW20 wrapped_2 code id: ", wrappedAssetCodeId)
|
||||
|
||||
// Store token bridge contract
|
||||
tbContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/token_bridge.wasm", guardians)
|
||||
fmt.Println("Token bridge contract code id: ", tbContractCodeId)
|
||||
|
||||
// Instantiate token bridge contract
|
||||
tbInstantiateMsg := helpers.TbContractInstantiateMsg(t, wormchainConfig, coreContractAddr, wrappedAssetCodeId)
|
||||
tbContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", tbContractCodeId, "token_bridge", tbInstantiateMsg, guardians)
|
||||
fmt.Println("Token bridge contract address: ", tbContractAddr)
|
||||
|
||||
helpers.SubmitAllowlistInstantiateContract(t, ctx, wormchain, "faucet", wormchain.Config(), tbContractAddr, wrappedAssetCodeId, guardians)
|
||||
|
||||
// Register a new external chain
|
||||
tbRegisterChainMsg := helpers.TbRegisterChainMsg(t, ExternalChainId, ExternalChainEmitterAddr, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterChainMsg))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Register a new foreign asset (Asset1) originating on externalChain
|
||||
tbRegisterForeignAssetMsg := helpers.TbRegisterForeignAsset(t, Asset1ContractAddr, Asset1ChainID, ExternalChainEmitterAddr, Asset1Decimals, Asset1Symbol, Asset1Name, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterForeignAssetMsg))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Store ibc translator contract
|
||||
ibcTranslatorCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/ibc_translator.wasm", guardians)
|
||||
fmt.Println("Ibc translator code id: ", ibcTranslatorCodeId)
|
||||
|
||||
// Instantiate ibc translator contract
|
||||
ibcTranslatorInstantiateMsg := helpers.IbcTranslatorContractInstantiateMsg(t, tbContractAddr)
|
||||
ibcTranslatorContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", ibcTranslatorCodeId, "ibc_translator", ibcTranslatorInstantiateMsg, guardians)
|
||||
fmt.Println("Ibc translator contract address: ", ibcTranslatorContractAddr)
|
||||
|
||||
helpers.SetMiddlewareContract(t, ctx, wormchain, "faucet", wormchain.Config(), ibcTranslatorContractAddr, guardians)
|
||||
|
||||
// Allowlist worm/osmo chain id / channel
|
||||
wormOsmoAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, OsmoChainID, wormToOsmoChannel.ChannelID, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormOsmoAllowlistMsg)
|
||||
|
||||
// Allowlist worm/gaia chain id / channel
|
||||
wormGaiaAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, GaiaChainID, wormToGaiaChannel.ChannelID, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormGaiaAllowlistMsg)
|
||||
|
||||
// Create and process a simple ibc payload3: Transfers 10.000_018 of asset1 from external chain through wormchain to gaia user
|
||||
simplePayload := helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, GaiaChainID, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), 0, 1)
|
||||
externalSender := []byte{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}
|
||||
payload3 := helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToGaiaUser1), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
|
||||
completeTransferAndConvertMsg := helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
|
||||
// Create and process a simple ibc payload3: Transfers 1.000_001 of asset1 from external chain through wormchain to osmo user1
|
||||
simplePayload = helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, OsmoChainID, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), 0, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToOsmoUser1), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
|
||||
// Create and process a contract controlled ibc payload3
|
||||
// Transfers 1.000_002 of asset1 from external chain through wormchain to ibc hooks contract addr
|
||||
// IBC hooks is used to route the contract controlled payload to a test contract which forwards tokens to osmo user2
|
||||
ibcHooksPayload := helpers.CreateIbcHooksMsg(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
contractControlledPayload := helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
|
||||
payload3 = helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToOsmoUser2), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
|
||||
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
|
||||
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 10, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Query the CW20 address of asset1
|
||||
var tbQueryRsp helpers.TbQueryRsp
|
||||
tbQueryReq := helpers.CreateCW20Query(t, Asset1ChainID, Asset1ContractAddr)
|
||||
wormchain.QueryContract(ctx, tbContractAddr, tbQueryReq, &tbQueryRsp)
|
||||
cw20Address := tbQueryRsp.Data.Address
|
||||
fmt.Println("Asset1 cw20 addr: ", cw20Address)
|
||||
|
||||
// Get the Gaia/IBC denom of asset1
|
||||
cw20AddressBz := helpers.MustAccAddressFromBech32(cw20Address, wormchain.Config().Bech32Prefix)
|
||||
subdenom := base58.Encode(cw20AddressBz)
|
||||
tokenFactoryDenom := fmt.Sprint("factory/", ibcTranslatorContractAddr, "/", subdenom)
|
||||
gaiaAsset1Denom := transfertypes.GetPrefixedDenom("transfer", gaiaToWormChannel.ChannelID, tokenFactoryDenom)
|
||||
gaiaIbcAsset1Denom := transfertypes.ParseDenomTrace(gaiaAsset1Denom).IBCDenom()
|
||||
|
||||
// Get the Osmo/IBC denom of asset1
|
||||
osmoAsset1Denom := transfertypes.GetPrefixedDenom("transfer", osmoToWormChannel.ChannelID, tokenFactoryDenom)
|
||||
osmoIbcAsset1Denom := transfertypes.ParseDenomTrace(osmoAsset1Denom).IBCDenom()
|
||||
|
||||
// Verify Gaia user 1 has expected asset 1 balance
|
||||
gaiaUser1Asset1BalanceTemp, err := gaia.GetBalance(ctx, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), gaiaIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("Gaia user asset1 coins: ", gaiaUser1Asset1BalanceTemp)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify Gaia user 1 has expected asset 1 balance
|
||||
gaiaUser1Asset1BalanceTemp, err = gaia.GetBalance(ctx, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), gaiaIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
fmt.Println("Gaia user asset1 coins: ", gaiaUser1Asset1BalanceTemp)
|
||||
|
||||
// ************* Cosmos->External: Simple payload (wormhole-mw + ibc-hooks) ****************
|
||||
// Send 1.000_003 asset 1 from gaia user 1 to external
|
||||
simpleMemo := helpers.CreateIbcComposabilityMwMemoGatewayTransfer(t, Asset1ChainID, externalSender, 0, 1)
|
||||
transfer := ibc.WalletAmount{
|
||||
Address: ibcTranslatorContractAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToExternalSimple),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{Memo: simpleMemo})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ************* Cosmos->External: Contract controlled payload (wormhole-mw + ibc-hooks) ****************
|
||||
// Send 1.000_004 asset 1 from gaia user 1 to external
|
||||
ccIbcHooksMsg := helpers.CreateIbcComposabilityMwMemoGatewayTransferWithPayload(t, Asset1ChainID, externalSender, []byte("ExternalContractPayload"), 1)
|
||||
transfer = ibc.WalletAmount{
|
||||
Address: ibcTranslatorContractAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToExternalCC),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{Memo: ccIbcHooksMsg})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ************** Cosmos->Cosmos: Simple payload (wormhole-mw + PFM) ****************
|
||||
// Send 1.000_005 asset 1 from gaia user 1 to osmo user 1
|
||||
simplePfmMsg := helpers.CreateIbcComposabilityMwMemoGatewayTransfer(t, OsmoChainID, []byte(osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix)), 0, 1)
|
||||
transfer = ibc.WalletAmount{
|
||||
Address: wormchainFaucetAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToOsmoUser1),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{
|
||||
Timeout: &ibc.IBCTimeout{
|
||||
NanoSeconds: 30_000_000_000,
|
||||
},
|
||||
Memo: simplePfmMsg,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 2, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ************** Cosmos->Cosmos: Contract controlled payload (wormhole-mw + PFM) ****************
|
||||
// Send 1.000_006 asset 1 from gaia user 1 to osmo user 2
|
||||
ccPayload := helpers.CreateIbcHooksMsg(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
|
||||
ccPfmMsg := helpers.CreateIbcComposabilityMwMemoGatewayTransferWithPayload(t, OsmoChainID, []byte(ibcHooksContractAddr), ccPayload, 1)
|
||||
transfer = ibc.WalletAmount{
|
||||
Address: ibcTranslatorContractAddr,
|
||||
Denom: gaiaIbcAsset1Denom,
|
||||
Amount: int64(AmountGaiaUser1ToOsmoUser2),
|
||||
}
|
||||
_, err = gaia.SendIBCTransfer(ctx, gaiaToWormChannel.ChannelID, gaiaUser.KeyName, transfer, ibc.TransferOptions{
|
||||
Timeout: &ibc.IBCTimeout{
|
||||
NanoSeconds: 30_000_000_000,
|
||||
},
|
||||
Memo: ccPfmMsg,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for transfer to ack
|
||||
err = testutil.WaitForBlocks(ctx, 15, wormchain, gaia)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify Gaia user 1 has expected asset 1 balance
|
||||
gaiaUser1Asset1Balance, err := gaia.GetBalance(ctx, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), gaiaIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
expectedGaiaUser1Amount := AmountExternalToGaiaUser1 - AmountGaiaUser1ToExternalCC - AmountGaiaUser1ToExternalSimple - AmountGaiaUser1ToOsmoUser1 - AmountGaiaUser1ToOsmoUser2
|
||||
require.Equal(t, int64(expectedGaiaUser1Amount), gaiaUser1Asset1Balance)
|
||||
fmt.Println("Gaia user asset1 coins: ", gaiaUser1Asset1Balance)
|
||||
|
||||
// Verify osmo user 1 has expected asset 1 balance
|
||||
osmoUser1Asset1Balance, err := osmosis.GetBalance(ctx, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), osmoIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(AmountExternalToOsmoUser1+AmountGaiaUser1ToOsmoUser1), osmoUser1Asset1Balance)
|
||||
fmt.Println("Osmo user1 asset1 coins: ", osmoUser1Asset1Balance)
|
||||
|
||||
// Verify osmo user 2 has expected asset 1 balance
|
||||
osmoUser2Asset1Balance, err := osmosis.GetBalance(ctx, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix), osmoIbcAsset1Denom)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(AmountExternalToOsmoUser2+AmountGaiaUser1ToOsmoUser2), osmoUser2Asset1Balance)
|
||||
fmt.Println("Osmo user2 asset1 coins: ", osmoUser2Asset1Balance)
|
||||
|
||||
// Verify asset 1 cw20 contract has expected final total supply
|
||||
var cw20QueryRsp helpers.Cw20WrappedQueryRsp
|
||||
cw20QueryReq := helpers.Cw20WrappedQueryMsg{TokenInfo: helpers.Cw20TokenInfo{}}
|
||||
wormchain.QueryContract(ctx, cw20Address, cw20QueryReq, &cw20QueryRsp)
|
||||
fmt.Println("Asset1 supply: ", cw20QueryRsp.Data.TotalSupply)
|
||||
totalSupply, err := strconv.ParseUint(cw20QueryRsp.Data.TotalSupply, 10, 64)
|
||||
require.NoError(t, err)
|
||||
expectedTotalSupply := AmountExternalToGaiaUser1 + AmountExternalToOsmoUser1 + AmountExternalToOsmoUser2 - AmountGaiaUser1ToExternalSimple - AmountGaiaUser1ToExternalCC
|
||||
require.Equal(t, uint64(expectedTotalSupply), totalSupply)
|
||||
|
||||
denomsMetadata := helpers.GetDenomsMetadata(t, ctx, wormchain)
|
||||
fmt.Println("Denoms metadata: ", denomsMetadata)
|
||||
}
|
||||
|
||||
type QueryMsg struct {
|
||||
GuardianSetInfo *struct{} `json:"guardian_set_info,omitempty"`
|
||||
}
|
||||
|
||||
type QueryRsp struct {
|
||||
Data *QueryRspObj `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type QueryRspObj struct {
|
||||
GuardianSetIndex uint32 `json:"guardian_set_index"`
|
||||
Addresses []helpers.GuardianAddress `json:"addresses"`
|
||||
}
|
Loading…
Reference in New Issue