From 6b5bbe41c43f05f7f271326fb7878d8a2253e85c Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Mon, 4 Dec 2023 17:06:16 +0000 Subject: [PATCH 01/12] terra/contracts: migrate to cosmwasm 1.1.0 use `classic-bindings` crate instead of terra-cosmwasm. This is the updated version that calls the correct query post chain upgrade --- terra/Cargo.lock | 1734 +++++++++++++---- terra/Cargo.toml | 3 + terra/contracts/cw20-wrapped/Cargo.toml | 10 +- terra/contracts/cw20-wrapped/src/contract.rs | 8 +- .../cw20-wrapped/tests/integration.rs | 2 +- .../mock-bridge-integration/Cargo.toml | 6 +- terra/contracts/token-bridge/Cargo.toml | 12 +- terra/contracts/token-bridge/src/contract.rs | 93 +- terra/contracts/wormhole/Cargo.toml | 7 +- terra/contracts/wormhole/tests/integration.rs | 2 +- 10 files changed, 1390 insertions(+), 487 deletions(-) diff --git a/terra/Cargo.lock b/terra/Cargo.lock index 134ae0c0ab..b7fceb377d 100644 --- a/terra/Cargo.lock +++ b/terra/Cargo.lock @@ -4,11 +4,11 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli 0.26.1", + "gimli 0.28.1", ] [[package]] @@ -17,32 +17,55 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +dependencies = [ + "getrandom 0.2.11", + "once_cell", + "version_check", +] + [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.63" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.27.1", + "object 0.32.1", "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" -version = "0.13.0" +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 = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bigint" @@ -60,6 +83,24 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -70,23 +111,69 @@ 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 = "block-padding" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytecheck" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -94,6 +181,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "classic-bindings" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff5f775aae6e8b7b9237559522ec4cbc4870ab42706d55488ee1353d6b97304" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std 1.1.0", + "schemars", + "serde", +] + [[package]] name = "clru" version = "0.4.0" @@ -106,70 +205,154 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "corosensei" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "scopeguard", + "windows-sys 0.33.0", +] + [[package]] name = "cosmwasm-crypto" -version = "0.16.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec9bdd1f4da5fc0d085251b0322661c5aaf773ab299e3e205fb18130b7f6ba3" +checksum = "a965098e28b1338513185746efe1f57c974aebb9e3869ded3361dc3bffbc780d" dependencies = [ - "digest", - "ed25519-zebra", - "k256", + "digest 0.9.0", + "ed25519-zebra 2.2.0", + "k256 0.9.5", "rand_core 0.5.1", "thiserror", ] +[[package]] +name = "cosmwasm-crypto" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bb3c77c3b7ce472056968c745eb501c440fbc07be5004eba02782c35bfbbe3" +dependencies = [ + "digest 0.10.7", + "ecdsa 0.16.9", + "ed25519-zebra 3.1.0", + "k256 0.13.2", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0faf9bad5eb0a43a00406e64f8d33407a06bd1826fa976195a69db70e6c18d9d" +dependencies = [ + "syn 1.0.109", +] + [[package]] name = "cosmwasm-derive" -version = "0.16.2" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea73e9162e6efde00018d55ed0061e93a108b5d6ec4548b4f8ce3c706249687" +dependencies = [ + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-schema" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df41ea55f2946b6b43579659eec048cc2f66e8c8e2e3652fc5e5e476f673856" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43609e92ce1b9368aa951b334dd354a2d0dd4d484931a5f83ae10e12a26c8ba9" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-std" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac17a14b4ab09a5d89b5301218067acca33d9311376e5c34c9877f09e562395" +checksum = "a14b383575cc9a579d1bb5b7d5eaee74fda8449c25f9d6c736fee282dc025013" dependencies = [ - "syn", + "base64", + "cosmwasm-crypto 0.16.1", + "cosmwasm-derive 0.16.7", + "schemars", + "serde", + "serde-json-wasm 0.3.2", + "thiserror", + "uint", ] [[package]] name = "cosmwasm-std" -version = "0.16.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47306c113f4d964c35a74a87ceb8ccfb5811e9810a9dc427101148b5b9134ca" +checksum = "eb8da0ae28693d892af2944319b48adc23c42725dc0fe7271b8baa38c10865da" dependencies = [ "base64", - "cosmwasm-crypto", - "cosmwasm-derive", + "cosmwasm-crypto 1.5.0", + "cosmwasm-derive 1.5.0", + "derivative", + "forward_ref", "schemars", "serde", - "serde-json-wasm", + "serde-json-wasm 0.4.1", "thiserror", "uint", ] [[package]] name = "cosmwasm-storage" -version = "0.16.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e3472d8e0e7155c5f4d89674ad47adede4b1491ad14f4141610e1522028a6a7" +checksum = "3205d5210ba4c7b7cc7329b9607c37d00dc08263c2479fd99541a2194ebe3b22" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.1.0", "serde", ] [[package]] name = "cosmwasm-vm" -version = "0.16.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d90f1d30e2d01d815c520dad2738f93188f2e64b3dda3e11609c13eb73109b8" +checksum = "f83ecbf1f663e440fdfbc533e2a5c4e041737b4e8b51aadcf0ca8968b029807d" dependencies = [ "clru", - "cosmwasm-crypto", - "cosmwasm-std", + "cosmwasm-crypto 1.5.0", + "cosmwasm-std 1.1.0", "hex", "loupe", "parity-wasm", "schemars", "serde", "serde_json", - "sha2", + "sha2 0.10.8", "thiserror", "wasmer", "wasmer-middlewares", @@ -177,33 +360,33 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.1" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] [[package]] name = "cranelift-bforest" -version = "0.74.0" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ca3560686e7c9c7ed7e0fe77469f2410ba5d7781b1acaa9adc8d8deea28e3e" +checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.74.0" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf9bf1ffffb6ce3d2e5ebc83549bd2436426c99b31cc550d521364cbe35d276" +checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-entity", - "gimli 0.24.0", + "gimli 0.26.2", "log", "regalloc", "smallvec", @@ -212,31 +395,30 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.74.0" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc21936a5a6d07e23849ffe83e5c1f6f50305c074f4b2970ca50c13bf55b821" +checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" dependencies = [ "cranelift-codegen-shared", - "cranelift-entity", ] [[package]] name = "cranelift-codegen-shared" -version = "0.74.0" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5b6ffaa87560bebe69a5446449da18090b126037920b0c1c6d5945f72faf6b" +checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" [[package]] name = "cranelift-entity" -version = "0.74.0" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6b4a8bef04f82e4296782646f733c641d09497df2fabf791323fefaa44c64c" +checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" [[package]] name = "cranelift-frontend" -version = "0.74.0" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b783b351f966fce33e3c03498cb116d16d97a8f9978164a60920bd0d3a99c" +checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" dependencies = [ "cranelift-codegen", "log", @@ -246,28 +428,18 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", - "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -276,25 +448,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ + "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", - "memoffset", + "memoffset 0.9.0", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", - "lazy_static", ] [[package]] @@ -311,21 +482,43 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.2.11" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8658c15c5d921ddf980f7fe25b1e82f4b7a4083b2c4985fea4922edb8e43e07d" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core 0.6.3", + "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 = "crypto-mac" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" dependencies = [ "generic-array", "subtle", @@ -338,7 +531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", - "digest", + "digest 0.9.0", "rand_core 0.5.1", "subtle", "zeroize", @@ -350,18 +543,64 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1e867b9972b83b32e00e878dfbff48299ba26618dabeb19b9c56fae176dc225" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 0.16.1", "schemars", "serde", ] +[[package]] +name = "cw-storage-plus" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b8b840947313c1a1cccf056836cd79a60b4526bdcd6582995be37dc97be4ae" +dependencies = [ + "cosmwasm-std 1.1.0", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" +dependencies = [ + "cosmwasm-std 1.1.0", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b" +dependencies = [ + "cosmwasm-std 1.1.0", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "cw0" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c497f885a40918a02df7d938c81809965fa05cfc21b3dc591e9950237b5de0a9" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 0.16.1", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw0" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae676b6cced78a3d38ad4b01ab4ed66fc78ac191c3c0d6bfd5372cb2efd473b" +dependencies = [ + "cosmwasm-std 1.1.0", "schemars", "serde", "thiserror", @@ -373,8 +612,32 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d48454f96494aa1018556cd457977375cc8c57ef3e5c767cfa2ea5ec24b0258" dependencies = [ - "cosmwasm-std", - "cw-storage-plus", + "cosmwasm-std 0.16.1", + "cw-storage-plus 0.8.1", + "schemars", + "serde", +] + +[[package]] +name = "cw2" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7002e6f9c1a1ef3915dca704a6306ba00c39495efd928551d6077c734f9a3d8" +dependencies = [ + "cosmwasm-std 1.1.0", + "cw-storage-plus 0.10.3", + "schemars", + "serde", +] + +[[package]] +name = "cw2" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cf4639517490dd36b333bbd6c4fbd92e325fd0acf4683b41753bc5eb63bfc1" +dependencies = [ + "cosmwasm-std 1.1.0", + "cw-storage-plus 0.13.4", "schemars", "serde", ] @@ -385,8 +648,32 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a11a2adbd52258f5b4ed5323f62bc6e559f2cefbe52ef0e58290016fde5bb083" dependencies = [ - "cosmwasm-std", - "cw0", + "cosmwasm-std 0.16.1", + "cw0 0.8.1", + "schemars", + "serde", +] + +[[package]] +name = "cw20" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56fc9d54b9b365801beb101a5c0375dceaa5a285bfc14438a7b6007f9d362142" +dependencies = [ + "cosmwasm-std 1.1.0", + "cw0 0.10.3", + "schemars", + "serde", +] + +[[package]] +name = "cw20" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cb782b8f110819a4eb5dbbcfed25ffba49ec16bbe32b4ad8da50a5ce68fec05" +dependencies = [ + "cosmwasm-std 1.1.0", + "cw-utils", "schemars", "serde", ] @@ -397,11 +684,27 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe3791e0f6b4a0a82b86541d48dcc67c2d607da8e5691a91b40b2c06ddf09c52" dependencies = [ - "cosmwasm-std", - "cw-storage-plus", - "cw0", - "cw2", - "cw20", + "cosmwasm-std 0.16.1", + "cw-storage-plus 0.8.1", + "cw0 0.8.1", + "cw2 0.8.1", + "cw20 0.8.1", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw20-base" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0306e606581f4fb45e82bcbb7f0333179ed53dd949c6523f01a99b4bfc1475a0" +dependencies = [ + "cosmwasm-std 1.1.0", + "cw-storage-plus 0.13.4", + "cw-utils", + "cw2 0.13.4", + "cw20 0.13.4", "schemars", "serde", "thiserror", @@ -410,16 +713,15 @@ dependencies = [ [[package]] name = "cw20-legacy" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d27b11827323369993519abb494f3ae9b6aac4d716d058bea5e181b9b0074b7" +source = "git+https://github.com/wormhole-foundation/cw20-legacy/?rev=d127247#d12724701ffb9920cb1fdf1eee49efdcc20048e5" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.1.0", "cosmwasm-storage", - "cw-storage-plus", - "cw0", - "cw2", - "cw20", - "cw20-base", + "cw-storage-plus 0.13.4", + "cw0 0.10.3", + "cw2 0.13.4", + "cw20 0.13.4", + "cw20-base 0.13.4", "schemars", "serde", "thiserror", @@ -429,11 +731,11 @@ dependencies = [ name = "cw20-wrapped" version = "0.1.0" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.1.0", "cosmwasm-storage", - "cw-storage-plus", - "cw2", - "cw20", + "cw-storage-plus 0.8.1", + "cw2 0.10.3", + "cw20 0.13.4", "cw20-legacy", "schemars", "serde", @@ -442,9 +744,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.0" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ "darling_core", "darling_macro", @@ -452,36 +754,56 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.0" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim", - "syn", + "syn 2.0.39", ] [[package]] name = "darling_macro" -version = "0.13.0" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.39", +] + +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid 0.6.2", ] [[package]] name = "der" -version = "0.4.4" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e98c534e9c8a0483aa01d6f6913bc063de254311bd267c9cf535e9b70e15b2" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ - "const-oid", + "const-oid 0.9.5", + "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]] @@ -493,36 +815,48 @@ 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", + "const-oid 0.9.5", + "crypto-common", + "subtle", +] + [[package]] name = "dyn-clone" -version = "1.0.4" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "dynasm" -version = "1.2.0" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab1096ebdaa974cd6a41a743e94dfa00cce9bfbf4690bcc73fdec6a903938ccc" +checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "dynasmrt" -version = "1.2.0" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c69d1e16ae47889b47c301c790f48615cd9bfbdf586e3f6d4fde64af3d259" +checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2 0.5.0", + "memmap2", ] [[package]] @@ -531,10 +865,24 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" dependencies = [ - "der", - "elliptic-curve", - "hmac", - "signature", + "der 0.4.5", + "elliptic-curve 0.10.4", + "hmac 0.11.0", + "signature 1.3.2", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der 0.7.8", + "digest 0.10.7", + "elliptic-curve 0.13.8", + "rfc6979", + "signature 2.2.0", + "spki 0.7.3", ] [[package]] @@ -547,51 +895,115 @@ dependencies = [ "hex", "rand_core 0.5.1", "serde", - "sha2", + "sha2 0.9.9", "thiserror", ] +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "either" -version = "1.6.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" -version = "0.10.6" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b" +checksum = "83e5c176479da93a0983f0a6fdc3c1b8e7d5be0d7fe3fe05a99f15b96582b9a8" dependencies = [ - "crypto-bigint", - "ff", + "crypto-bigint 0.2.5", + "ff 0.10.1", "generic-array", - "group", - "pkcs8", - "rand_core 0.6.3", + "group 0.10.0", + "pkcs8 0.7.6", + "rand_core 0.6.4", "subtle", "zeroize", ] +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint 0.5.5", + "digest 0.10.7", + "ff 0.13.0", + "generic-array", + "group 0.13.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "enumset" -version = "1.0.8" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6216d2c19a6fb5f29d1ada1dc7bc4367a8cbf0fa4af5cf12e07b5bbdde6b5b2c" +checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.5.5" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6451128aa6655d880755345d085494cf7561a6bee7c8dc821e5d77e6d267ecd4" +checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.39", +] + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -600,13 +1012,29 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "ff" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", "subtle", ] @@ -616,14 +1044,27 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -639,20 +1080,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.24.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", "indexmap", @@ -661,9 +1102,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "group" @@ -671,8 +1112,19 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" dependencies = [ - "ff", - "rand_core 0.6.3", + "ff 0.10.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", + "rand_core 0.6.4", "subtle", ] @@ -681,14 +1133,17 @@ name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "libc", + "ahash", ] [[package]] @@ -704,7 +1159,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ "crypto-mac", - "digest", + "digest 0.9.0", +] + +[[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 = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", ] [[package]] @@ -715,38 +1188,64 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "1.7.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "serde", ] [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "008b0281ca8032567c9711cd48631781c15228301860a39b32deb28d63125e46" +dependencies = [ + "cfg-if", + "ecdsa 0.12.4", + "elliptic-curve 0.10.4", + "sha2 0.9.9", +] [[package]] name = "k256" -version = "0.9.6" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea" +checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", - "sha2", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "once_cell", + "sha2 0.10.8", + "signature 2.2.0", ] [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] [[package]] name = "lazy_static" @@ -762,28 +1261,31 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.108" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "log" -version = "0.4.14" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "loupe" @@ -803,7 +1305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -817,45 +1319,44 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap2" -version = "0.2.3" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" dependencies = [ "libc", ] [[package]] -name = "memmap2" -version = "0.5.0" +name = "memoffset" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4647a11b578fead29cdbb34d4adef8dd3dc35b876c9c6d5240d83f205abfe96e" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "libc", + "autocfg", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", - "autocfg", ] [[package]] @@ -863,15 +1364,15 @@ name = "mock-bridge-integration" version = "0.1.0" dependencies = [ "bigint", - "cosmwasm-std", + "cosmwasm-std 1.1.0", "cosmwasm-storage", "cosmwasm-vm", - "cw20", - "cw20-base", + "cw20 0.8.1", + "cw20-base 0.8.1", "cw20-wrapped", "generic-array", "hex", - "k256", + "k256 0.9.5", "lazy_static", "schemars", "serde", @@ -889,36 +1390,33 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" -[[package]] -name = "num_cpus" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" -version = "0.25.3" +version = "0.28.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ "crc32fast", + "hashbrown 0.11.2", "indexmap", "memchr", ] [[package]] name = "object" -version = "0.27.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] +[[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" @@ -933,9 +1431,9 @@ checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pkcs8" @@ -943,15 +1441,19 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" dependencies = [ - "der", - "spki", + "der 0.4.5", + "spki 0.4.1", ] [[package]] -name = "ppv-lite86" -version = "0.2.15" +name = "pkcs8" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.8", + "spki 0.7.3", +] [[package]] name = "proc-macro-error" @@ -962,7 +1464,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -979,11 +1481,20 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ - "unicode-xid", + "unicode-ident", +] + +[[package]] +name = "protobuf" +version = "2.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +dependencies = [ + "bytes", ] [[package]] @@ -1003,39 +1514,23 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core 0.6.3", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" +name = "radium" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.3", -] +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand_core" @@ -1048,61 +1543,47 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.3", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "rand_core 0.6.3", + "getrandom 0.2.11", ] [[package]] name = "rayon" -version = "1.5.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", - "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "regalloc" -version = "0.0.31" +version = "0.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" +checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" dependencies = [ "log", "rustc-hash", @@ -1111,53 +1592,68 @@ dependencies = [ [[package]] name = "region" -version = "2.2.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" +checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "mach", "winapi", ] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "rend" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" dependencies = [ - "winapi", + "bytecheck", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", ] [[package]] name = "rkyv" -version = "0.6.7" +version = "0.7.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb135b3e5e3311f0a254bfb00333f4bac9ef1d89888b84242a89eb8722b09a07" +checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" dependencies = [ - "memoffset", + "bitvec", + "bytecheck", + "hashbrown 0.12.3", "ptr_meta", + "rend", "rkyv_derive", "seahash", + "tinyvec", + "uuid", ] [[package]] name = "rkyv_derive" -version = "0.6.7" +version = "0.7.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba8f489f6b6d8551bb15904293c1ad58a6abafa7d8390d15f7ed05a2afcd87d5" +checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" @@ -1165,23 +1661,36 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustix" +version = "0.38.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "rustversion" -version = "1.0.5" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "schemars" -version = "0.8.7" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271ac0c667b8229adf70f0f957697c96fafd7486ab7481e15dc5e45e3e6a4368" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", @@ -1191,21 +1700,21 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.7" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ebda811090b257411540779860bc09bf321bc587f58d2c5864309d1566214e7" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 1.0.109", ] [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "seahash" @@ -1213,60 +1722,83 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der 0.7.8", + "generic-array", + "pkcs8 0.10.2", + "subtle", + "zeroize", +] + [[package]] name = "serde" -version = "1.0.130" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde-json-wasm" -version = "0.3.1" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-json-wasm" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50eef3672ec8fa45f3457fd423ba131117786784a895548021976117c1ded449" +checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" dependencies = [ "serde", ] [[package]] name = "serde_bytes" -version = "0.11.5" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] name = "serde_derive_internals" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "serde_json" -version = "1.0.71" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063bf466a64011ac24040a49009724ee60a57da1b437617ceb32e53ad61bfb19" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -1275,25 +1807,36 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha3" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.9.0", + "digest 0.9.0", "keccak", "opaque-debug", ] @@ -1304,15 +1847,31 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2807892cfa58e081aa1f1111391c7a0649d4fa127a4ffbe34bcbfb35a1171a4" dependencies = [ - "digest", - "rand_core 0.6.3", + "digest 0.9.0", + "rand_core 0.6.4", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", ] +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "smallvec" -version = "1.7.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "spki" @@ -1320,7 +1879,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" dependencies = [ - "der", + "der 0.4.5", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.8", ] [[package]] @@ -1336,112 +1905,127 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "strsim" -version = "0.10.0" +name = "subtle" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] -name = "subtle" -version = "2.4.1" +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] name = "syn" -version = "1.0.81" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" -version = "0.12.2" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.2.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", - "libc", - "rand", + "fastrand", "redox_syscall", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "terra-cosmwasm" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552f18cba2b535d1f8c0e3b3f37696820b954bc7535d2e33909f2a6342302718" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", + "rustix", + "windows-sys 0.48.0", ] [[package]] name = "terraswap" -version = "2.4.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96f2c2a6371e9ddf2c942368e64645cc3e8fc2855da70c8c6bed238dcdd5522f" +checksum = "73bbfb46c586aeaaa91da9532bff8b12fd909dcc80ff2817d58b87eab2f3a2b5" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.1.0", "cosmwasm-storage", - "cw20", + "cw2 0.13.4", + "cw20 0.13.4", + "protobuf", "schemars", "serde", - "terra-cosmwasm", ] [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", ] +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "token-bridge-terra" version = "0.1.0" dependencies = [ "bigint", - "cosmwasm-std", + "classic-bindings", + "cosmwasm-std 1.1.0", "cosmwasm-storage", - "cw20", - "cw20-base", + "cw20 0.10.3", + "cw20-base 0.13.4", "cw20-wrapped", "generic-array", "hex", - "k256", + "k256 0.9.5", "lazy_static", "schemars", "serde", "serde_json", "sha3", - "terra-cosmwasm", "terraswap", "thiserror", "wormhole-bridge-terra", @@ -1449,11 +2033,11 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1461,35 +2045,35 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] name = "typenum" -version = "1.14.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uint" -version = "0.9.1" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy 0.2.2", @@ -1498,16 +2082,22 @@ dependencies = [ ] [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "uuid" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" @@ -1517,22 +2107,79 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasmer" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f52e455a01d0fac439cd7a96ba9b519bdc84e923a5b96034054697ebb17cd75" +checksum = "ea8d8361c9d006ea3d7797de7bd6b1492ffd0f91a22430cfda6c1658ad57bedf" dependencies = [ "cfg-if", "indexmap", + "js-sys", "loupe", "more-asserts", "target-lexicon", "thiserror", + "wasm-bindgen", + "wasmer-artifact", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", @@ -1545,11 +2192,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "wasmer-artifact" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aaf9428c29c1d8ad2ac0e45889ba8a568a835e33fd058964e5e500f2f7ce325" +dependencies = [ + "enumset", + "loupe", + "thiserror", + "wasmer-compiler", + "wasmer-types", +] + [[package]] name = "wasmer-compiler" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc86dda6f715f03104800be575a38382b35c3962953af9e9d8722dcf0bd2458f" +checksum = "e67a6cd866aed456656db2cfea96c18baabbd33f676578482b85c51e1ee19d2c" dependencies = [ "enumset", "loupe", @@ -1560,39 +2220,39 @@ dependencies = [ "target-lexicon", "thiserror", "wasmer-types", - "wasmer-vm", "wasmparser", ] [[package]] name = "wasmer-compiler-cranelift" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a570746cbec434179e2d53357973a34dfdb208043104e8fac3b7b0023015cf6" +checksum = "48be2f9f6495f08649e4f8b946a2cbbe119faf5a654aa1457f9504a99d23dae0" dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", - "gimli 0.24.0", + "gimli 0.26.2", "loupe", "more-asserts", "rayon", "smallvec", + "target-lexicon", "tracing", "wasmer-compiler", "wasmer-types", - "wasmer-vm", ] [[package]] name = "wasmer-compiler-singlepass" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9429b9f7708c582d855b1787f09c7029ff23fb692550d4a1cc351c8ea84c3014" +checksum = "29ca2a35204d8befa85062bc7aac259a8db8070b801b8a783770ba58231d729e" dependencies = [ "byteorder", "dynasm", "dynasmrt", + "gimli 0.26.2", "lazy_static", "loupe", "more-asserts", @@ -1600,37 +2260,38 @@ dependencies = [ "smallvec", "wasmer-compiler", "wasmer-types", - "wasmer-vm", ] [[package]] name = "wasmer-derive" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee7b351bcc1e782997c72dc0b5b328f3ddcad4813b8ce3cac3f25ae5a4ab56b" +checksum = "00e50405cc2a2f74ff574584710a5f2c1d5c93744acce2ca0866084739284b51" dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "wasmer-engine" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8454ead320a4017ba36ddd9ab4fbf7776fceea6ab0b79b5e53664a1682569fc3" +checksum = "3f98f010978c244db431b392aeab0661df7ea0822343334f8f2a920763548e45" dependencies = [ "backtrace", + "enumset", "lazy_static", "loupe", - "memmap2 0.2.3", + "memmap2", "more-asserts", "rustc-demangle", "serde", "serde_bytes", "target-lexicon", "thiserror", + "wasmer-artifact", "wasmer-compiler", "wasmer-types", "wasmer-vm", @@ -1638,18 +2299,22 @@ dependencies = [ [[package]] name = "wasmer-engine-dylib" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aa390d123ebe23d5315c39f6063fcc18319661d03c8000f23d0fe1c011e8135" +checksum = "ad0358af9c154724587731175553805648d9acb8f6657880d165e378672b7e53" dependencies = [ "cfg-if", + "enum-iterator", + "enumset", "leb128", "libloading", "loupe", + "object 0.28.4", "rkyv", "serde", "tempfile", "tracing", + "wasmer-artifact", "wasmer-compiler", "wasmer-engine", "wasmer-object", @@ -1660,27 +2325,45 @@ dependencies = [ [[package]] name = "wasmer-engine-universal" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dffe8015f08915eb4939ebc8e521cde8246f272f5197ea60d46214ac5aef285" +checksum = "440dc3d93c9ca47865a4f4edd037ea81bf983b5796b59b3d712d844b32dbef15" dependencies = [ "cfg-if", + "enumset", "leb128", "loupe", "region", "rkyv", "wasmer-compiler", "wasmer-engine", + "wasmer-engine-universal-artifact", "wasmer-types", "wasmer-vm", "winapi", ] +[[package]] +name = "wasmer-engine-universal-artifact" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f1db3f54152657eb6e86c44b66525ff7801dad8328fe677da48dd06af9ad41" +dependencies = [ + "enum-iterator", + "enumset", + "loupe", + "rkyv", + "thiserror", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-types", +] + [[package]] name = "wasmer-middlewares" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95d2b4722d64c850893f7a7eab3ab76181efbafcd366827801d8bcd64bff525f" +checksum = "d7812438ed2f37203a37007cdb5332b8475cb2b16e15d51299b2647894e9ed3a" dependencies = [ "loupe", "wasmer", @@ -1690,11 +2373,11 @@ dependencies = [ [[package]] name = "wasmer-object" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c541c985799fc1444702501c15d41becfb066c92d9673defc1c7417fd8739e15" +checksum = "8d831335ff3a44ecf451303f6f891175c642488036b92ceceb24ac8623a8fa8b" dependencies = [ - "object 0.25.3", + "object 0.28.4", "thiserror", "wasmer-compiler", "wasmer-types", @@ -1702,12 +2385,15 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91f75d3c31f8b1f8d818ff49624fc974220243cbc07a2252f408192e97c6b51" +checksum = "39df01ea05dc0a9bab67e054c7cb01521e53b35a7bb90bd02eca564ed0b2667f" dependencies = [ + "backtrace", + "enum-iterator", "indexmap", "loupe", + "more-asserts", "rkyv", "serde", "thiserror", @@ -1715,41 +2401,48 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469a12346a4831e7dac639b9646d8c9b24c7d2cf0cf458b77f489edb35060c1f" +checksum = "30d965fa61f4dc4cdb35a54daaf7ecec3563fbb94154a6c35433f879466247dd" dependencies = [ "backtrace", "cc", "cfg-if", + "corosensei", + "enum-iterator", "indexmap", + "lazy_static", "libc", "loupe", - "memoffset", + "mach", + "memoffset 0.6.5", "more-asserts", "region", "rkyv", + "scopeguard", "serde", "thiserror", + "wasmer-artifact", "wasmer-types", "winapi", ] [[package]] name = "wasmparser" -version = "0.78.2" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65" +checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" [[package]] name = "which" -version = "4.2.2" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "lazy_static", - "libc", + "home", + "once_cell", + "rustix", ] [[package]] @@ -1774,19 +2467,191 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" +dependencies = [ + "windows_aarch64_msvc 0.33.0", + "windows_i686_gnu 0.33.0", + "windows_i686_msvc 0.33.0", + "windows_x86_64_gnu 0.33.0", + "windows_x86_64_msvc 0.33.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "wormhole-bridge-terra" version = "0.1.0" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.1.0", "cosmwasm-storage", - "cw20", - "cw20-base", - "cw20-wrapped", "generic-array", - "getrandom 0.2.3", + "getrandom 0.2.11", "hex", - "k256", + "k256 0.9.5", "lazy_static", "schemars", "serde", @@ -1795,8 +2660,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "zeroize" -version = "1.4.3" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/terra/Cargo.toml b/terra/Cargo.toml index 092eb77a98..16cccf66a5 100644 --- a/terra/Cargo.toml +++ b/terra/Cargo.toml @@ -16,3 +16,6 @@ codegen-units = 1 panic = 'abort' incremental = false overflow-checks = true + +[patch.crates-io] +cw20-legacy = { git = "https://github.com/wormhole-foundation/cw20-legacy/", rev = "d127247" } diff --git a/terra/contracts/cw20-wrapped/Cargo.toml b/terra/contracts/cw20-wrapped/Cargo.toml index 43cc739456..a662a2e087 100644 --- a/terra/contracts/cw20-wrapped/Cargo.toml +++ b/terra/contracts/cw20-wrapped/Cargo.toml @@ -14,12 +14,12 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.16.0" } -cosmwasm-storage = { version = "0.16.0" } +cosmwasm-std = { version = "= 1.1.0" } +cosmwasm-storage = { version = "1.0.0" } schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -cw2 = { version = "0.8.0" } -cw20 = { version = "0.8.0" } -cw20-legacy = { version = "0.2.0", features = ["library"]} +cw2 = { version = "0.10.3" } +cw20 = { version = "0.13.2" } +cw20-legacy = { version = "0.2.0", features = ["library"]} cw-storage-plus = { version = "0.8.0" } thiserror = { version = "1.0.20" } diff --git a/terra/contracts/cw20-wrapped/src/contract.rs b/terra/contracts/cw20-wrapped/src/contract.rs index dcfc72bf45..d031f71ddc 100644 --- a/terra/contracts/cw20-wrapped/src/contract.rs +++ b/terra/contracts/cw20-wrapped/src/contract.rs @@ -278,7 +278,7 @@ mod tests { #[test] fn can_mint_by_minter() { - let mut deps = mock_dependencies(&[]); + let mut deps = mock_dependencies(); let minter = HumanAddr::from("minter"); let recipient = HumanAddr::from("recipient"); let amount = Uint128::new(222_222_222); @@ -287,7 +287,7 @@ mod tests { #[test] fn others_cannot_mint() { - let mut deps = mock_dependencies(&[]); + let mut deps = mock_dependencies(); let minter = HumanAddr::from("minter"); let recipient = HumanAddr::from("recipient"); do_init(deps.as_mut(), &minter); @@ -307,7 +307,7 @@ mod tests { #[test] fn transfer_balance_success() { - let mut deps = mock_dependencies(&[]); + let mut deps = mock_dependencies(); let minter = HumanAddr::from("minter"); let owner = HumanAddr::from("owner"); let amount_initial = Uint128::new(222_222_222); @@ -331,7 +331,7 @@ mod tests { #[test] fn transfer_balance_not_enough() { - let mut deps = mock_dependencies(&[]); + let mut deps = mock_dependencies(); let minter = HumanAddr::from("minter"); let owner = HumanAddr::from("owner"); let amount_initial = Uint128::new(222_221); diff --git a/terra/contracts/cw20-wrapped/tests/integration.rs b/terra/contracts/cw20-wrapped/tests/integration.rs index 223d8da9dc..bc23e6d094 100644 --- a/terra/contracts/cw20-wrapped/tests/integration.rs +++ b/terra/contracts/cw20-wrapped/tests/integration.rs @@ -23,7 +23,7 @@ fn get_wrapped_asset_info(storage: &S) -> WrappedAssetInfo { } fn do_init() -> OwnedDeps { - let mut deps = mock_dependencies(&[]); + let mut deps = mock_dependencies(); let init_msg = InstantiateMsg { name: "Integers".into(), symbol: "INT".into(), diff --git a/terra/contracts/mock-bridge-integration/Cargo.toml b/terra/contracts/mock-bridge-integration/Cargo.toml index 2aaeef86a9..cffe756935 100644 --- a/terra/contracts/mock-bridge-integration/Cargo.toml +++ b/terra/contracts/mock-bridge-integration/Cargo.toml @@ -13,8 +13,8 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.16.0" } -cosmwasm-storage = { version = "0.16.0" } +cosmwasm-std = { version = "= 1.1.0" } +cosmwasm-storage = { version = "1.0.0" } schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } cw20 = "0.8.0" @@ -33,5 +33,5 @@ wormhole-bridge-terra = { path = "../wormhole", features = ["library"] } token-bridge-terra = { path = "../token-bridge", features = ["library"] } [dev-dependencies] -cosmwasm-vm = { version = "0.16.0", default-features = false } +cosmwasm-vm = { version = "1.0.0", default-features = false } serde_json = "1.0" diff --git a/terra/contracts/token-bridge/Cargo.toml b/terra/contracts/token-bridge/Cargo.toml index b311fd3b76..afbe47b068 100644 --- a/terra/contracts/token-bridge/Cargo.toml +++ b/terra/contracts/token-bridge/Cargo.toml @@ -14,15 +14,15 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.16.0" } -cosmwasm-storage = { version = "0.16.0" } +cosmwasm-std = { version = "= 1.1.0" } +cosmwasm-storage = { version = "1.0.0" } schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -cw20 = "0.8.0" -cw20-base = { version = "0.8.0", features = ["library"] } +cw20 = "0.10.3" +cw20-base = { version = "0.13.2", features = ["library"] } cw20-wrapped = { path = "../cw20-wrapped", features = ["library"] } -terraswap = "2.4.0" -terra-cosmwasm = "2.2.0" +terraswap = "2.9.0" +classic-bindings = "0.1.1" wormhole-bridge-terra = { path = "../wormhole", features = ["library"] } thiserror = { version = "1.0.20" } k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } diff --git a/terra/contracts/token-bridge/src/contract.rs b/terra/contracts/token-bridge/src/contract.rs index 131301eaba..078b9be7a3 100644 --- a/terra/contracts/token-bridge/src/contract.rs +++ b/terra/contracts/token-bridge/src/contract.rs @@ -11,7 +11,7 @@ use std::{ }; use terraswap::asset::{Asset, AssetInfo}; -use terra_cosmwasm::TerraQuerier; +use classic_bindings::{TerraQuerier, TerraQuery}; use wormhole::{ byte_utils::{ extend_address_to_32, extend_address_to_32_array, extend_string_to_32, get_string_from_32, @@ -26,8 +26,8 @@ use wormhole::{ use cosmwasm_std::entry_point; use cosmwasm_std::{ - coin, to_binary, BankMsg, Binary, CanonicalAddr, Coin, CosmosMsg, Decimal, Deps, DepsMut, - Empty, Env, MessageInfo, QuerierWrapper, QueryRequest, Reply, Response, StdError, StdResult, + coin, to_binary, BankMsg, Binary, CanonicalAddr, Coin, CosmosMsg, CustomQuery, Decimal, Deps, + DepsMut, Env, MessageInfo, QuerierWrapper, QueryRequest, Reply, Response, StdError, StdResult, SubMsg, Uint128, WasmMsg, WasmQuery, }; @@ -177,7 +177,7 @@ pub fn reply(deps: DepsMut, env: Env, _msg: Reply) -> StdResult { .add_attribute("action", "reply_handler")) } -pub fn coins_after_tax(deps: DepsMut, coins: Vec) -> StdResult> { +pub fn coins_after_tax(deps: DepsMut, coins: Vec) -> StdResult> { let mut res = vec![]; for coin in coins { let asset = Asset { @@ -191,7 +191,11 @@ pub fn coins_after_tax(deps: DepsMut, coins: Vec) -> StdResult> Ok(res) } -fn parse_vaa(deps: Deps, block_time: u64, data: &Binary) -> StdResult { +fn parse_vaa( + deps: Deps, + block_time: u64, + data: &Binary, +) -> StdResult { let cfg = config_read(deps.storage).load()?; let vaa: ParsedVAA = deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: cfg.wormhole_contract, @@ -204,7 +208,12 @@ fn parse_vaa(deps: Deps, block_time: u64, data: &Binary) -> StdResult } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> StdResult { match msg { ExecuteMsg::RegisterAssetHook { asset_id } => { handle_register_asset(deps, env, info, asset_id.as_slice()) @@ -258,7 +267,11 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> S } } -fn deposit_tokens(deps: DepsMut, _env: Env, info: MessageInfo) -> StdResult { +fn deposit_tokens( + deps: DepsMut, + _env: Env, + info: MessageInfo, +) -> StdResult { for coin in info.funds { let deposit_key = format!("{}:{}", info.sender, coin.denom); bridge_deposit(deps.storage).update( @@ -273,7 +286,7 @@ fn deposit_tokens(deps: DepsMut, _env: Env, info: MessageInfo) -> StdResult, _env: Env, info: MessageInfo, data: AssetInfo, @@ -304,8 +317,8 @@ fn withdraw_tokens( } /// Handle wrapped asset registration messages -fn handle_register_asset( - deps: DepsMut, +fn handle_register_asset( + deps: DepsMut, _env: Env, info: MessageInfo, asset_id: &[u8], @@ -328,8 +341,8 @@ fn handle_register_asset( .add_attribute("contract_addr", info.sender)) } -fn handle_attest_meta( - deps: DepsMut, +fn handle_attest_meta( + deps: DepsMut, env: Env, emitter_chain: u16, emitter_address: Vec, @@ -400,7 +413,7 @@ fn handle_attest_meta( } fn handle_create_asset_meta( - deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, asset_info: AssetInfo, @@ -417,7 +430,7 @@ fn handle_create_asset_meta( } fn handle_create_asset_meta_token( - deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, asset_address: HumanAddr, @@ -463,7 +476,7 @@ fn handle_create_asset_meta_token( } fn handle_create_asset_meta_native_token( - deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, denom: String, @@ -502,7 +515,7 @@ fn handle_create_asset_meta_native_token( } fn handle_complete_transfer_with_payload( - deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, data: &Binary, @@ -540,7 +553,12 @@ fn handle_complete_transfer_with_payload( } } -fn submit_vaa(deps: DepsMut, env: Env, info: MessageInfo, data: &Binary) -> StdResult { +fn submit_vaa( + deps: DepsMut, + env: Env, + info: MessageInfo, + data: &Binary, +) -> StdResult { let state = config_read(deps.storage).load()?; let vaa = parse_vaa(deps.as_ref(), env.block.time.seconds(), data)?; @@ -584,7 +602,11 @@ fn submit_vaa(deps: DepsMut, env: Env, info: MessageInfo, data: &Binary) -> StdR } } -fn handle_governance_payload(deps: DepsMut, env: Env, data: &[u8]) -> StdResult { +fn handle_governance_payload( + deps: DepsMut, + env: Env, + data: &[u8], +) -> StdResult { let gov_packet = GovernancePacket::deserialize(data)?; let module = get_string_from_32(&gov_packet.module); @@ -605,7 +627,11 @@ fn handle_governance_payload(deps: DepsMut, env: Env, data: &[u8]) -> StdResult< } } -fn handle_upgrade_contract(_deps: DepsMut, env: Env, data: &Vec) -> StdResult { +fn handle_upgrade_contract( + _deps: DepsMut, + env: Env, + data: &Vec, +) -> StdResult { let UpgradeContract { new_contract } = UpgradeContract::deserialize(data)?; Ok(Response::new() @@ -617,7 +643,11 @@ fn handle_upgrade_contract(_deps: DepsMut, env: Env, data: &Vec) -> StdResul .add_attribute("action", "contract_upgrade")) } -fn handle_register_chain(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { +fn handle_register_chain( + deps: DepsMut, + _env: Env, + data: &Vec, +) -> StdResult { let RegisterChain { chain_id, chain_address, @@ -640,7 +670,7 @@ fn handle_register_chain(deps: DepsMut, _env: Env, data: &Vec) -> StdResult< #[allow(clippy::too_many_arguments)] fn handle_complete_transfer( - deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, emitter_chain: u16, @@ -690,8 +720,8 @@ fn handle_complete_transfer( } #[allow(clippy::too_many_arguments)] -fn handle_complete_transfer_token( - deps: DepsMut, +fn handle_complete_transfer_token( + deps: DepsMut, _env: Env, info: MessageInfo, emitter_chain: u16, @@ -837,7 +867,7 @@ fn handle_complete_transfer_token( #[allow(clippy::too_many_arguments)] fn handle_complete_transfer_token_native( - mut deps: DepsMut, + mut deps: DepsMut, _env: Env, info: MessageInfo, emitter_chain: u16, @@ -926,7 +956,7 @@ fn handle_complete_transfer_token_native( #[allow(clippy::too_many_arguments)] fn handle_initiate_transfer( - deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, asset: Asset, @@ -966,7 +996,7 @@ fn handle_initiate_transfer( #[allow(clippy::too_many_arguments)] fn handle_initiate_transfer_token( - mut deps: DepsMut, + mut deps: DepsMut, env: Env, info: MessageInfo, asset: HumanAddr, @@ -1013,12 +1043,11 @@ fn handle_initiate_transfer_token( })?, funds: vec![], })); - let request = QueryRequest::::Wasm(WasmQuery::Smart { + let request = QueryRequest::Wasm(WasmQuery::Smart { contract_addr: asset, msg: to_binary(&WrappedQuery::WrappedAssetInfo {})?, }); - let wrapped_token_info: WrappedAssetInfoResponse = - deps.querier.custom_query(&request)?; + let wrapped_token_info: WrappedAssetInfoResponse = deps.querier.query(&request)?; asset_chain = wrapped_token_info.asset_chain; asset_address = wrapped_token_info.asset_address.to_array()?; @@ -1204,7 +1233,7 @@ fn format_native_denom_symbol(denom: &str) -> String { #[allow(clippy::too_many_arguments)] fn handle_initiate_transfer_native_token( - deps: DepsMut, + deps: DepsMut, env: Env, info: MessageInfo, denom: String, @@ -1406,7 +1435,7 @@ fn is_governance_emitter(cfg: &ConfigInfo, emitter_chain: u16, emitter_address: static DECIMAL_FRACTION: Uint128 = Uint128::new(1_000_000_000_000_000_000u128); -pub fn compute_tax(asset: &Asset, querier: &QuerierWrapper) -> StdResult { +pub fn compute_tax(asset: &Asset, querier: &QuerierWrapper) -> StdResult { let amount = asset.amount; if let AssetInfo::NativeToken { denom } = &asset.info { let terra_querier = TerraQuerier::new(querier); @@ -1424,7 +1453,7 @@ pub fn compute_tax(asset: &Asset, querier: &QuerierWrapper) -> StdResult StdResult { +pub fn deduct_tax(asset: &Asset, querier: &QuerierWrapper) -> StdResult { let amount = asset.amount; if let AssetInfo::NativeToken { denom } = &asset.info { Ok(Coin { diff --git a/terra/contracts/wormhole/Cargo.toml b/terra/contracts/wormhole/Cargo.toml index 534d284d4b..defa32b9c5 100644 --- a/terra/contracts/wormhole/Cargo.toml +++ b/terra/contracts/wormhole/Cargo.toml @@ -15,13 +15,10 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.16.0" } -cosmwasm-storage = { version = "0.16.0" } +cosmwasm-std = { version = "= 1.1.0" } +cosmwasm-storage = { version = "1.0.0" } schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -cw20 = "0.8.0" -cw20-base = { version = "0.8.0", features = ["library"] } -cw20-wrapped = { path = "../cw20-wrapped", features = ["library"] } thiserror = { version = "1.0.20" } k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } getrandom = { version = "0.2", features = ["custom"] } diff --git a/terra/contracts/wormhole/tests/integration.rs b/terra/contracts/wormhole/tests/integration.rs index a3a51d37df..4a8f6f91d2 100644 --- a/terra/contracts/wormhole/tests/integration.rs +++ b/terra/contracts/wormhole/tests/integration.rs @@ -21,7 +21,7 @@ fn get_config_info(storage: &S) -> ConfigInfo { } fn do_init(guardians: &[GuardianAddress]) -> OwnedDeps { - let mut deps = mock_dependencies(&[]); + let mut deps = mock_dependencies(); let init_msg = InstantiateMsg { gov_chain: 0, gov_address: GOV_ADDR.into(), From 29262b771d4b695ea7bacda9906814a9fd639d47 Mon Sep 17 00:00:00 2001 From: cs Date: Wed, 6 Dec 2023 17:35:32 +0000 Subject: [PATCH 02/12] terra/Dockerfile: update workspace optimizer --- terra/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/terra/Dockerfile b/terra/Dockerfile index 945631ebad..6defdb4c05 100644 --- a/terra/Dockerfile +++ b/terra/Dockerfile @@ -2,12 +2,12 @@ FROM const-gen AS const-export # This is a multi-stage docker file: # 1. The first stage builds the contracts # 2. The second is an empty image with only the wasm files (useful for exporting) -FROM cosmwasm/workspace-optimizer:0.12.6@sha256:e6565a5e87c830ef3e8775a9035006b38ad0aaf0a96319158c802457b1dd1d08 AS builder +FROM cosmwasm/workspace-optimizer:0.15.0@sha256:e1ba559282ea88cedeb67dd6dd541ad57d1b75c2fb1ce5f476d423458da91b4d AS builder COPY Cargo.lock /code/ COPY Cargo.toml /code/ COPY contracts /code/contracts -RUN --mount=type=cache,target=/target,id=terra_classic_target --mount=type=cache,target=/usr/local/cargo/registry optimize_workspace.sh +RUN --mount=type=cache,target=/target,id=terra_classic_target --mount=type=cache,target=/usr/local/cargo/registry optimize.sh . FROM scratch as artifacts COPY --from=builder /code/artifacts / From f812ecdda04658b602f7d64b75c51ce074848c23 Mon Sep 17 00:00:00 2001 From: Evan Gray Date: Wed, 11 Oct 2023 18:37:32 -0400 Subject: [PATCH 03/12] terra: label is now required on instantiate --- terra/contracts/token-bridge/src/contract.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/terra/contracts/token-bridge/src/contract.rs b/terra/contracts/token-bridge/src/contract.rs index 078b9be7a3..327dbba0eb 100644 --- a/terra/contracts/token-bridge/src/contract.rs +++ b/terra/contracts/token-bridge/src/contract.rs @@ -51,6 +51,7 @@ type HumanAddr = String; const CHAIN_ID: u16 = 3; const WRAPPED_ASSET_UPDATING: &str = "updating"; +const WRAPPED_ASSET_LABEL: &str = "WrappedCW20"; pub enum TransferType { WithoutPayload, @@ -405,7 +406,7 @@ fn handle_attest_meta( }), })?, funds: vec![], - label: String::new(), + label: WRAPPED_ASSET_LABEL.to_string(), }) }; wrapped_asset_seq(deps.storage).save(&asset_id, &sequence)?; From 67900518a274ffbec15799d764fb53383e36b08b Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Fri, 8 Dec 2023 15:53:23 +0000 Subject: [PATCH 04/12] terra: accept either 32 or 20 byte addresses --- terra/contracts/wormhole/src/byte_utils.rs | 74 +++++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/terra/contracts/wormhole/src/byte_utils.rs b/terra/contracts/wormhole/src/byte_utils.rs index b2813e93f5..d25df72a34 100644 --- a/terra/contracts/wormhole/src/byte_utils.rs +++ b/terra/contracts/wormhole/src/byte_utils.rs @@ -64,14 +64,19 @@ impl ByteUtils for &[u8] { } } -/// Left-pad a 20 byte address with 0s +/// Left-pad a 20 byte or 32 byte address with 0s pub fn extend_address_to_32(addr: &CanonicalAddr) -> Vec { extend_address_to_32_array(addr).to_vec() } +/// Left-pad a 20 byte or 32 byte address with 0s pub fn extend_address_to_32_array(addr: &CanonicalAddr) -> [u8; 32] { - let mut v: Vec = vec![0; 12]; - v.extend(addr.as_slice()); + let addr = addr.as_slice(); + let len = addr.len(); + assert!(len == 20 || len == 32, "invalid address length"); + + let mut v: Vec = vec![0; 32 - len]; + v.extend(addr); let mut result: [u8; 32] = [0; 32]; result.copy_from_slice(&v); result @@ -98,3 +103,66 @@ pub fn get_string_from_32(v: &[u8]) -> String { let s = String::from_utf8_lossy(v); s.chars().filter(|c| c != &'\0').collect() } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_extend_20_address_to_32() { + let addr = CanonicalAddr::from(vec![1u8; 20]); + let extended = extend_address_to_32(&addr); + assert_eq!(extended.len(), 32); + assert_eq!(extended[0..12], vec![0u8; 12]); + assert_eq!(extended[12..32], vec![1u8; 20]); + } + + #[test] + fn test_extend_32_address_to_32() { + let addr = CanonicalAddr::from(vec![1u8; 32]); + let extended = extend_address_to_32(&addr); + assert_eq!(extended.len(), 32); + assert_eq!(extended[0..32], vec![1u8; 32]); + } + + #[test] + #[should_panic(expected = "invalid address length")] + fn test_extend_33_address_to_32() { + let addr = CanonicalAddr::from(vec![1u8; 33]); + extend_address_to_32(&addr); + } + + #[test] + fn test_string_to_array() { + let s = "hello"; + let arr = string_to_array::<10>(s); + assert_eq!(arr, [104, 101, 108, 108, 111, 0, 0, 0, 0, 0]); + } + + #[test] + fn test_string_to_array_long() { + let s = "helloasdfadfasdf"; + let arr = string_to_array::<10>(s); + assert_eq!(arr, [104, 101, 108, 108, 111, 97, 115, 100, 102, 97]); + } + + #[test] + fn test_extend_string_to_32() { + let s = "hello"; + let arr = extend_string_to_32(s); + assert_eq!( + arr, + [ + 104, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + ] + ); + } + + #[test] + fn test_get_string_from_32() { + let arr = [104, 101, 108, 108, 111, 0, 0, 0, 0, 0]; + let s = get_string_from_32(&arr); + assert_eq!(s, "hello"); + } +} From e2e7bf70631a25c9ec103326945142c5a0fafc6d Mon Sep 17 00:00:00 2001 From: Evan Gray Date: Wed, 11 Oct 2023 12:59:58 -0400 Subject: [PATCH 05/12] terra: test update --- terra/tools/package-lock.json | 374 +++++++++++++++-- terra/tools/package.json | 5 +- terra/tools/test_interface_update.ts | 607 +++++++++++++++++++++++++++ 3 files changed, 943 insertions(+), 43 deletions(-) create mode 100644 terra/tools/test_interface_update.ts diff --git a/terra/tools/package-lock.json b/terra/tools/package-lock.json index 7cf6dad0a3..dad4bb31a0 100644 --- a/terra/tools/package-lock.json +++ b/terra/tools/package-lock.json @@ -1,19 +1,22 @@ { - "name": "tools", - "version": "1.0.0", + "name": "@wormhole-foundation/tools-terra", + "version": "0.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "tools", - "version": "1.0.0", + "name": "@wormhole-foundation/tools-terra", + "version": "0.0.1", "license": "ISC", "dependencies": { "@cosmjs/encoding": "^0.26.2", - "@terra-money/terra.js": "^2.0.11", + "@terra-money/terra.js": "^3.1.3", "dotenv": "^16.0.0", "ethers": "^5.4.4", "yargs": "^17.0.1" + }, + "devDependencies": { + "@types/node": "^20.10.4" } }, "node_modules/@cosmjs/encoding": { @@ -725,12 +728,90 @@ "@ethersproject/strings": "^5.6.0" } }, + "node_modules/@improbable-eng/grpc-web": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", + "dependencies": { + "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@terra-money/legacy.proto": { + "name": "@terra-money/terra.proto", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", + "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", + "dependencies": { + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, "node_modules/@terra-money/terra.js": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-2.0.11.tgz", - "integrity": "sha512-33MrW3SGEmbHzjAA93dw1VA6IKbp6gYJbOTUkQzQbi+msIUf4m9ZewB6v5b8UZJfTfEe/T5RjXCWQHmANsz11w==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.1.3.tgz", + "integrity": "sha512-80HU5WXrqf3hZTo2GRhIycH17A+SkLD6afbu8MynMDGGD/A861F3zVv6NQ/Z7PWQGHxgddZEK/A0UQ2uK/xfHg==", "dependencies": { - "axios": "^0.21.1", + "@terra-money/legacy.proto": "npm:@terra-money/terra.proto@^0.1.7", + "@terra-money/terra.proto": "~2.0.0", + "axios": "^0.26.1", "bech32": "^2.0.0", "bip32": "^2.0.6", "bip39": "^3.0.3", @@ -741,16 +822,35 @@ "secp256k1": "^4.0.2", "tmp": "^0.2.1", "utf-8-validate": "^5.0.5", - "ws": "^7.4.2" + "ws": "^7.5.5" }, "engines": { - "node": ">=12" + "node": ">=14" } }, + "node_modules/@terra-money/terra.proto": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.0.0.tgz", + "integrity": "sha512-ZjyFOFUzrGn8IwzGIgr1OJFcPSsQoz/XAfoSKThJx+OjJA7CLhdcz51+5h7ehNfb+qB9wr7aNME0h24wu9D4SQ==", + "dependencies": { + "@improbable-eng/grpc-web": "^0.14.1", + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/aes-js": { "version": "3.0.0", @@ -780,11 +880,11 @@ } }, "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", "dependencies": { - "follow-redirects": "^1.14.0" + "follow-redirects": "^1.14.8" } }, "node_modules/balanced-match": { @@ -849,6 +949,11 @@ "node": ">=6.0.0" } }, + "node_modules/bip32/node_modules/@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + }, "node_modules/bip39": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", @@ -884,6 +989,11 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "node_modules/browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, "node_modules/bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", @@ -1072,9 +1182,9 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, "node_modules/follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", "funding": [ { "type": "individual", @@ -1122,6 +1232,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, "node_modules/hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -1189,6 +1304,11 @@ "jscrypto": "bin/cli.js" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -1271,6 +1391,31 @@ "node": ">=0.12" } }, + "node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -1442,6 +1587,11 @@ "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/utf-8-validate": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.6.tgz", @@ -1489,9 +1639,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "engines": { "node": ">=8.3.0" }, @@ -1942,12 +2092,86 @@ "@ethersproject/strings": "^5.6.0" } }, + "@improbable-eng/grpc-web": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", + "requires": { + "browser-headers": "^0.4.1" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "@terra-money/legacy.proto": { + "version": "npm:@terra-money/terra.proto@0.1.7", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", + "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", + "requires": { + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, "@terra-money/terra.js": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-2.0.11.tgz", - "integrity": "sha512-33MrW3SGEmbHzjAA93dw1VA6IKbp6gYJbOTUkQzQbi+msIUf4m9ZewB6v5b8UZJfTfEe/T5RjXCWQHmANsz11w==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.1.3.tgz", + "integrity": "sha512-80HU5WXrqf3hZTo2GRhIycH17A+SkLD6afbu8MynMDGGD/A861F3zVv6NQ/Z7PWQGHxgddZEK/A0UQ2uK/xfHg==", "requires": { - "axios": "^0.21.1", + "@terra-money/legacy.proto": "npm:@terra-money/terra.proto@^0.1.7", + "@terra-money/terra.proto": "~2.0.0", + "axios": "^0.26.1", "bech32": "^2.0.0", "bip32": "^2.0.6", "bip39": "^3.0.3", @@ -1958,13 +2182,32 @@ "secp256k1": "^4.0.2", "tmp": "^0.2.1", "utf-8-validate": "^5.0.5", - "ws": "^7.4.2" + "ws": "^7.5.5" + } + }, + "@terra-money/terra.proto": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.0.0.tgz", + "integrity": "sha512-ZjyFOFUzrGn8IwzGIgr1OJFcPSsQoz/XAfoSKThJx+OjJA7CLhdcz51+5h7ehNfb+qB9wr7aNME0h24wu9D4SQ==", + "requires": { + "@improbable-eng/grpc-web": "^0.14.1", + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" } }, + "@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "requires": { + "undici-types": "~5.26.4" + } }, "aes-js": { "version": "3.0.0", @@ -1985,11 +2228,11 @@ } }, "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", "requires": { - "follow-redirects": "^1.14.0" + "follow-redirects": "^1.14.8" } }, "balanced-match": { @@ -2035,6 +2278,13 @@ "tiny-secp256k1": "^1.1.3", "typeforce": "^1.11.5", "wif": "^2.0.6" + }, + "dependencies": { + "@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + } } }, "bip39": { @@ -2074,6 +2324,11 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, "bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", @@ -2239,9 +2494,9 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, "follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" }, "fs.realpath": { "version": "1.0.0", @@ -2266,6 +2521,11 @@ "path-is-absolute": "^1.0.0" } }, + "google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, "hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -2324,6 +2584,11 @@ "resolved": "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.2.tgz", "integrity": "sha512-r+oNJLGTv1nkNMBBq3c70xYrFDgJOYVgs2OHijz5Ht+0KJ0yObD0oYxC9mN72KLzVfXw+osspg6t27IZvuTUxw==" }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -2392,6 +2657,26 @@ "sha.js": "^2.4.8" } }, + "protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -2517,6 +2802,11 @@ "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "utf-8-validate": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.6.tgz", @@ -2554,9 +2844,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "requires": {} }, "y18n": { diff --git a/terra/tools/package.json b/terra/tools/package.json index 4a2a4963d2..bc194c951e 100644 --- a/terra/tools/package.json +++ b/terra/tools/package.json @@ -11,9 +11,12 @@ "license": "ISC", "dependencies": { "@cosmjs/encoding": "^0.26.2", - "@terra-money/terra.js": "^2.0.11", + "@terra-money/terra.js": "^3.1.3", "dotenv": "^16.0.0", "ethers": "^5.4.4", "yargs": "^17.0.1" + }, + "devDependencies": { + "@types/node": "^20.10.4" } } diff --git a/terra/tools/test_interface_update.ts b/terra/tools/test_interface_update.ts new file mode 100644 index 0000000000..9cce164bca --- /dev/null +++ b/terra/tools/test_interface_update.ts @@ -0,0 +1,607 @@ +// Run with MNEMONIC="" npx tsx test_interface_update.ts + +// The intention of this script is to test the CW < 1 migration to CW > 1. +// 1. Instantiate new core and token bridge contracts from the existing Code IDs, using the devnet Guardian key. +// 2. Migrate those contracts to the same code IDs, triggering any migration-specific effect they may have had. +// 3. Register a foreign bridge and asset. +// 4. Send a foreign asset in and out. (actually, can't create a foreign asset so nvm) +// 5. Store the updated CW > 1 code to new code IDs. +// 6. Upgrade the contracts to the new code IDs. +// 7. Upgrade the contracts to the new code IDs again. +// 8. Send the foreign asset from step 4 in and out again. +// 9. Register another foreign bridge and asset. +// 10. Send a new foreign asset in and out. (skipping since 8 was new anyway due to being unable to complete 4) +// 11. Attest a native token. +// 12. Deposit and withdraw a native token. (This is broken in mainnet, but should be fixed with this upgrade.) +// 13. Send a native token out and back. (This is broken in mainnet, but should be fixed with this upgrade.) + +import "dotenv/config"; +import { + Fee, + LCDClient, + MnemonicKey, + MsgUpdateContractAdmin, +} from "@terra-money/terra.js"; +import { + MsgInstantiateContract, + MsgExecuteContract, + MsgStoreCode, +} from "@terra-money/terra.js"; +import { readFileSync } from "fs"; +import { Bech32, toHex } from "@cosmjs/encoding"; +import { zeroPad } from "ethers/lib/utils.js"; + +// gas estimation wasn't working, so you'll find many hardcoded values in here +// YMMV + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +// look, broadcast and broadcastBlock still resulted in sequence mismatches +// and nobody has time for that +async function broadcastAndWait(terra, tx) { + const response = await terra.tx.broadcast(tx); + if (response?.code !== 0) { + console.error(response); + throw new Error( + `Transaction failed https://finder.terraclassic.community/mainnet/tx/${response?.txhash}` + ); + } + let currentHeight = (await terra.tendermint.blockInfo()).block.header.height; + while (currentHeight <= response.height) { + await sleep(100); + currentHeight = (await terra.tendermint.blockInfo()).block.header.height; + } + return response; +} + +// Terra addresses are "human-readable", but for cross-chain registrations, we +// want the "canonical" version +function convert_terra_address_to_hex(human_addr) { + return "0x" + toHex(zeroPad(Bech32.decode(human_addr).data, 32)); +} + +async function submitCoreBridgeVAA(vaa: string) { + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgExecuteContract(wallet.key.accAddress, addressCoreBridge, { + submit_v_a_a: { + vaa: Buffer.from(vaa, "hex").toString("base64"), + }, + }), + ], + memo: "", + fee: new Fee(1000000, { uluna: 50_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + return response?.txhash; +} + +async function submitTokenBridgeVAA(vaa: string) { + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgExecuteContract(wallet.key.accAddress, addressTokenBridge, { + submit_vaa: { + data: Buffer.from(vaa, "hex").toString("base64"), + }, + }), + ], + memo: "", + fee: new Fee(1000000, { uluna: 50_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + return response?.txhash; +} + +/* Set up terra client & wallet */ + +const terra = new LCDClient({ + URL: "https://terra-classic-lcd.publicnode.com", + chainID: "columbus-5", + isClassic: false, +}); + +if (!process.env.MNEMONIC) { + throw new Error("MNEMONIC is required"); +} +const wallet = terra.wallet( + new MnemonicKey({ + mnemonic: process.env.MNEMONIC, + }) +); + +const existingCodeIds = { + "wormhole.wasm": 557, // current wasm + "token_bridge_terra.wasm": 6097, // current wasm + "cw20_wrapped.wasm": 767, // current wasm +}; + +// default addresses from first run +let addressCoreBridge: string = + "terra1u5t6m3049dyqnspekjjt8p73ulkp759cyj796ld057md8zj4vnms4swc7n"; +let addressTokenBridge: string = + "terra186p2npg6fss9c4td5s9dmd62nghvy7j9vausj7yzysynzjjwtltqkhxczn"; + +async function step1() { + const govChain = 1; + const govAddress = + "0000000000000000000000000000000000000000000000000000000000000004"; + async function instantiate(contract, inst_msg, label) { + var address; + await wallet + .createAndSignTx({ + msgs: [ + new MsgInstantiateContract( + wallet.key.accAddress, + wallet.key.accAddress, + existingCodeIds[contract], + inst_msg, + undefined, + label + ), + ], + memo: "", + fee: new Fee(5000000, { uluna: 200_000_000 }), + }) + .then((tx) => broadcastAndWait(terra, tx)) + .then((rs) => { + address = /"_contract_address","value":"([^"]+)/gm.exec( + rs.raw_log + )?.[1]; + }); + console.log( + `Instantiated ${contract} at ${address} (${convert_terra_address_to_hex( + address + )})` + ); + return address; + } + + // devnet guardian public key + const init_guardians = ["beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe"]; + + addressCoreBridge = await instantiate( + "wormhole.wasm", + { + gov_chain: govChain, + gov_address: Buffer.from(govAddress, "hex").toString("base64"), + guardian_set_expirity: 86400, + initial_guardian_set: { + addresses: init_guardians.map((hex) => { + return { + bytes: Buffer.from(hex, "hex").toString("base64"), + }; + }), + expiration_time: 0, + }, + }, + "wormholeTest" + ); + + addressTokenBridge = await instantiate( + "token_bridge_terra.wasm", + { + gov_chain: govChain, + gov_address: Buffer.from(govAddress, "hex").toString("base64"), + wormhole_contract: addressCoreBridge, + wrapped_asset_code_id: existingCodeIds["cw20_wrapped.wasm"], + }, + "tokenBridgeTest" + ); +} + +async function step2() { + async function updateAdmin(contract: string) { + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgUpdateContractAdmin(wallet.key.accAddress, contract, contract), + ], + memo: "", + fee: new Fee(200000, { uluna: 10_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + console.log( + `Updated ${contract} admin to itself https://finder.terraclassic.community/mainnet/tx/${response?.txhash}` + ); + } + await updateAdmin(addressCoreBridge); + await updateAdmin(addressTokenBridge); + + { + // worm generate upgrade -c terra -a 557 -m Core -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const upgradeCoreVaa = + "01000000000100873cedead0c5a60da23bc23b3705e3b5b0600630d61a955c308307565e54b0cc14914495fc0eb39aee667f81adde5f49aec8bb774bb34121130e24ad6ecacb4c000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000005300d3f0000000000000000000000000000000000000000000000000000000000436f7265010003000000000000000000000000000000000000000000000000000000000000022d"; + const txhash = await submitCoreBridgeVAA(upgradeCoreVaa); + console.log( + `Upgraded core bridge https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } + + { + // worm generate upgrade -c terra -a 6097 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const upgradeTokenBridgeVaa = + "01000000000100c6267b6d66e0ff7fd1b625a94402a5c3ea04cbda7157ab42e172a5844f0cdc495e327c9e1cb9acf2f6c07597d8e746f593253cdaed451994765de1b8ae6fc3d9010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000001be411000000000000000000000000000000000000000000000546f6b656e42726964676502000300000000000000000000000000000000000000000000000000000000000017d1"; + // Unable to run this... 'failed to execute message; message index: 0: Generic error: Querier contract error: codespace: wasm, code: 9: execute wasm contract failed' + // const txhash = await submitTokenBridgeVAA(upgradeCoreVaa); + // console.log( + // `Upgraded token bridge https://finder.terraclassic.community/mainnet/tx/${txhash}` + // ); + } +} + +async function step3() { + { + // Avalanche mainnet token bridge registration + // worm generate registration -c avalanche -a 0e082F06FF657D94310cB8cE8B0D9a04541d8052 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const registerAvalanche = + "010000000001000f4c334aad9d3a3a9025654bdc5b6c544962683d3be6f616e2e8bdb4f0c2d292423c12b62ea1761c208fb2f3c3734dc25110d7ec7bed9d5db64f2f4babd17eaf010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000002cb3d3900000000000000000000000000000000000000000000546f6b656e42726964676501000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052"; + const txhash = await submitTokenBridgeVAA(registerAvalanche); + console.log( + `Registered Avalanche https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } + { + // WAVAX attestation + // worm edit-vaa -v AQAAAAMNAaDxJk8ByJTD1FsV4F2ZHyoV1/ZgDvhf+CsKmVTXt5PsdmTurfZKrcr752G94X6ghbT46rxr0bPy4NkoX7MKQJwAAk/crb5HuZnwmD+C6MFIeIBySqvxDQ/mssXHthZrQFsyLvmGZ8COYM9lZEb9pCoiBxuni4pG8gfSH/hEbIkLfX8AA43O2Ymg124dnkzw1E3dIhMt0qKMJozhXdzL/09cB4aJDWX5qxColViikLBqFqM/H/TUasl6Mq2Adhxb6U0h9LEABHAKcM3HK4mPKvPO/tLHW1obzvfp1Dr9QnrkXa+Nh9NMCzHI/JjaUxqUv+9CWntOX3UkGhSkcG0OnjWT79Z1B6kBBd1hBteD0zsrftlGvKzBC9uK3tJ6qwC/YOt0G5criYsqetYTgYnXpZiNrUBdKsqloNUpYHkkE/ieDDFUYxu8IwQAB6NfbF5YrI97b8EoQpz6IW93rJyymNFjYZpFQ3g4gDnoNQpqU0x6xH9NAVq1jJa1sdXjqFnDFDIPJxVHZvX0nAkBCl+kaIABlDgB2TyYvNop2DHKdLj1/NFVqspxg2OZ+PFpcYWZnhIJpNR2YTS7fppI9chxGGoVaoF2ufGAA155kiYAC/2UFf45V9DrsDiW5oJd74PXz3GvbB7G78me4NBYTlZ6E2U9RUQ8ib2W2G7NyQAh2rA/0v9oVbFMOjHaovp4E0kADIUXrdHj7UphaDMNVmFI8uPbLTNHh1j0yweg9TorA3i9QVG++wJ8mFW/+qCMhcw4M5MkJKhbohEQSTdiENir/hkBDgmH2Mb76kLUpy72LBbuQmbzTxb/72PRSqIpMLQzaCbmMGlpUaK3vgZETvUZjjBgt4pMDzki6KjZ67bXhp8FsFoAD/VLPF3juH6/5ulXqmMKP3VJts/ZTzhvn7yRV+YA5YjXUdzUh3pYbraURIsrXvJKzp9+bLzLh2OX/8XRU3bPfLgAEBhwvU9CUEiZ5+3jwSEl3u7rF7ADfUCFeSc/Tb46brgtZNf06ps56C9GKa/c6pSIXEKFjm6AyptXkCeIA9/MdioBEZcYyMrEYkW+gUFGCAaoSSyQmdTmydElc514U3inTM9FETZNTCFmxK/5VHnbEgLKBiDCXL6VDqr8pqBe5DzPxtoAZXIwrDh5AAAABgAAAAAAAAAAAAAAAA4ILwb/ZX2UMQy4zosNmgRUHYBSAAAAAAABqd0BAgAAAAAAAAAAAAAAALMfZqo8HnhTY/CHWht04nuF/WbHAAYSV0FWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXcmFwcGVkIEFWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const wavaxAttestation = + "01000000000100b1cc54a6b6a3ee8baadc39f7f59b6074ae647d811ffb3deac1036231dfdc26f02a0e6fa6033f549efc358e7443d979bd261ab3ad8f74ce6f90c14cb136a6832701657230ac3879000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9dd0102000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700061257415641580000000000000000000000000000000000000000000000000000005772617070656420415641580000000000000000000000000000000000000000"; + // Unable to run this... 'failed to execute message; message index: 0: dispatch: submessages: label is required: invalid request' + // const txhash = await submitTokenBridgeVAA(wavaxAttestation); + // console.log( + // `Created WAVAX https://finder.terraclassic.community/mainnet/tx/${txhash}` + // ); + } +} + +async function step4() { + // cannot complete step 4 since unable to create the wrapped asset on the existing implementation +} + +// default code id from first run +let newCodeIdCoreBridge: number = 8333; +let newCodeIdTokenBridge: number = 8334; + +async function step5() { + async function deployCode(file: string) { + const contract_bytes = readFileSync(`../artifacts/${file}`); + console.log(`Storing WASM: ${file} (${contract_bytes.length} bytes)`); + + const store_code = new MsgStoreCode( + wallet.key.accAddress, + contract_bytes.toString("base64") + ); + + const tx = await wallet.createAndSignTx({ + msgs: [store_code], + memo: "", + fee: new Fee(5000000, { uluna: 200_000_000 }), + }); + + const rs = await broadcastAndWait(terra, tx); + console.log(rs.raw_log); + console.log( + `Deployed ${file} https://finder.terraclassic.community/mainnet/tx/${rs?.txhash}` + ); + const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)?.[1]; + if (!ci) { + throw new Error("Could not parse code ID from raw_log"); + } + return parseInt(ci); + } + + newCodeIdCoreBridge = await deployCode("wormhole.wasm"); + newCodeIdTokenBridge = await deployCode("token_bridge_terra.wasm"); +} + +async function step6() { + { + // worm generate upgrade -c terra -a 8333 -m Core -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const upgradeCoreVaa = + "01000000000100a5b2ae692d6398838a3c08a3054edfbe9f1d01b4ddc0547c43a7f0b8069f20c12f0dc98202d54bea38c29356bd075cff21a2335cb8c75af689c12db8f2b328b40100000001000000010001000000000000000000000000000000000000000000000000000000000000000400000000015a73fa0000000000000000000000000000000000000000000000000000000000436f7265010003000000000000000000000000000000000000000000000000000000000000208d"; + const txhash = await submitCoreBridgeVAA(upgradeCoreVaa); + console.log( + `Upgraded core bridge https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } + + { + // worm generate upgrade -c terra -a 8334 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const upgradeTokenBridgeVaa = + "010000000001005ab927266b7ed6e35901c4184ab42287d2e2dd209e491102210fccf5448d770f74c21a35f222e29cfd3fffa3be6e00eb140c15a557f2497766bbac7bec1a041e000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000000abd77600000000000000000000000000000000000000000000546f6b656e427269646765020003000000000000000000000000000000000000000000000000000000000000208e"; + const txhash = await submitTokenBridgeVAA(upgradeTokenBridgeVaa); + console.log( + `Upgraded token bridge https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } +} + +async function step7() { + { + // worm generate upgrade -c terra -a 8333 -m Core -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const upgradeCoreVaa = + "0100000000010057c3d1727b5acca25a8a5a1ae31f09cf39fa7e01270c145df8fde315f9c7c0ac08c72b4911bc4ea75d18a97a50157c3dc065f1e91438e8060ea376fc7a562f6e0000000001000000010001000000000000000000000000000000000000000000000000000000000000000400000000051078710000000000000000000000000000000000000000000000000000000000436f7265010003000000000000000000000000000000000000000000000000000000000000208d"; + const txhash = await submitCoreBridgeVAA(upgradeCoreVaa); + console.log( + `Upgraded core bridge https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } + + { + // worm generate upgrade -c terra -a 8334 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const upgradeTokenBridgeVaa = + "010000000001002c7e1404f1451a19f03f2b3e180ab60a11427c289b2e1a8d19067f4c1378114c40460aea7b04299cc6a4d15c3840108f463b4f62bf84b7f552b8ede08a80ecb60100000001000000010001000000000000000000000000000000000000000000000000000000000000000400000000042b8c3a00000000000000000000000000000000000000000000546f6b656e427269646765020003000000000000000000000000000000000000000000000000000000000000208e"; + const txhash = await submitTokenBridgeVAA(upgradeTokenBridgeVaa); + console.log( + `Upgraded token bridge https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } +} + +async function step8a() { + { + // WAVAX attestation + // worm edit-vaa -v AQAAAAMNAaDxJk8ByJTD1FsV4F2ZHyoV1/ZgDvhf+CsKmVTXt5PsdmTurfZKrcr752G94X6ghbT46rxr0bPy4NkoX7MKQJwAAk/crb5HuZnwmD+C6MFIeIBySqvxDQ/mssXHthZrQFsyLvmGZ8COYM9lZEb9pCoiBxuni4pG8gfSH/hEbIkLfX8AA43O2Ymg124dnkzw1E3dIhMt0qKMJozhXdzL/09cB4aJDWX5qxColViikLBqFqM/H/TUasl6Mq2Adhxb6U0h9LEABHAKcM3HK4mPKvPO/tLHW1obzvfp1Dr9QnrkXa+Nh9NMCzHI/JjaUxqUv+9CWntOX3UkGhSkcG0OnjWT79Z1B6kBBd1hBteD0zsrftlGvKzBC9uK3tJ6qwC/YOt0G5criYsqetYTgYnXpZiNrUBdKsqloNUpYHkkE/ieDDFUYxu8IwQAB6NfbF5YrI97b8EoQpz6IW93rJyymNFjYZpFQ3g4gDnoNQpqU0x6xH9NAVq1jJa1sdXjqFnDFDIPJxVHZvX0nAkBCl+kaIABlDgB2TyYvNop2DHKdLj1/NFVqspxg2OZ+PFpcYWZnhIJpNR2YTS7fppI9chxGGoVaoF2ufGAA155kiYAC/2UFf45V9DrsDiW5oJd74PXz3GvbB7G78me4NBYTlZ6E2U9RUQ8ib2W2G7NyQAh2rA/0v9oVbFMOjHaovp4E0kADIUXrdHj7UphaDMNVmFI8uPbLTNHh1j0yweg9TorA3i9QVG++wJ8mFW/+qCMhcw4M5MkJKhbohEQSTdiENir/hkBDgmH2Mb76kLUpy72LBbuQmbzTxb/72PRSqIpMLQzaCbmMGlpUaK3vgZETvUZjjBgt4pMDzki6KjZ67bXhp8FsFoAD/VLPF3juH6/5ulXqmMKP3VJts/ZTzhvn7yRV+YA5YjXUdzUh3pYbraURIsrXvJKzp9+bLzLh2OX/8XRU3bPfLgAEBhwvU9CUEiZ5+3jwSEl3u7rF7ADfUCFeSc/Tb46brgtZNf06ps56C9GKa/c6pSIXEKFjm6AyptXkCeIA9/MdioBEZcYyMrEYkW+gUFGCAaoSSyQmdTmydElc514U3inTM9FETZNTCFmxK/5VHnbEgLKBiDCXL6VDqr8pqBe5DzPxtoAZXIwrDh5AAAABgAAAAAAAAAAAAAAAA4ILwb/ZX2UMQy4zosNmgRUHYBSAAAAAAABqd0BAgAAAAAAAAAAAAAAALMfZqo8HnhTY/CHWht04nuF/WbHAAYSV0FWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXcmFwcGVkIEFWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const wavaxAttestation = + "01000000000100b1cc54a6b6a3ee8baadc39f7f59b6074ae647d811ffb3deac1036231dfdc26f02a0e6fa6033f549efc358e7443d979bd261ab3ad8f74ce6f90c14cb136a6832701657230ac3879000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9dd0102000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700061257415641580000000000000000000000000000000000000000000000000000005772617070656420415641580000000000000000000000000000000000000000"; + const txhash = await submitTokenBridgeVAA(wavaxAttestation); + console.log( + `Created WAVAX https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } +} + +const wavaxAddress = + "terra17v94nk43tw0wx9r6r8a8kfcya0qazw0n8camypc2qdz4cj6cqajqftzyzh"; + +async function step8b() { + // WAVAX transfer in + // worm edit-vaa -v AQAAAAMNAOoKGMdKp40UoEoAQ0qZXVPawkpV4yZ4qCN7XC9KYV2VLLDcitjwRZ0rWh2xzFZVAntuxTSsl7sXXs5bkdKDNVEBAithN161Hu4+xIo7ADSNMTehvD70vg3bjB7/5cDt+ieYWZNeyhPgGlA/31y2vS5xtRGUOgCHoHVyDGTJ7RqRCpgBA6Z/g3R64BdryeqYDbGytx1uSNT7rbqadNkVb0BZvaJFAE5ITG9GW2bOZIAicg8iOcZw7WYa8a6vmuubKfzYp78BBI8OTu8tW72PzIspTYjEwinm7LpfgQ51ERIkAtFug2tmGZTwGiNRXoZeo9m1XpLgR/U01y6VQrIqUJasamVn6XwABv6qxtZkBfgT0T3nu6HEwv88CYXT/FXAYu/7HOVII/OneQQxIT9OS2BTiuMIWVcuvZ2qP2sdGhtOcX1f4crPCMcAB0yP5J7sQu+D2LDUsYjdELtMtj4KeWtjCkCBR6skWe/8IuRndXFvllNo0GRsB6A3XFnXReadRp5jH4A6t5UzS1UBCG6rkvPMMt7oUdSZBt9Lytd554Q5E310keqAB8+SXFumUY1y17U6KSgfTKgnWZBrTINj1RUw1ew8hElFziUKLDMADZE1+TeCwS+7W/59kz2mxBOgYa63j4pwdsB33BRGRfw9aYSQ3mkszyH+88bIKgjWzhJvRjs622L20QnBIbs5EAABDtf8OfUwbyAeOKM5D6m9pkDMlmz0hNwLa1Iuk2sQjLJsLRtbFYXScfgErmSkIgGGoMRtMt7Hk9pkebaD92skGOkADy10mYk73Lm360c2DZsnTCYsv0rKQ+MMrMverp9d8K5uALqZ3huvhJmTKtpNG/Dpzjsolk2aADcPHuEJudy4ZFEBEA19NY1c97Qo+VMwx3E/B6sEFszT8L93zPYhjBkWsuY9HwSsogKKb84170DApcKiXuz2jhw4e/eStObBBn7gc0AAESW+7FjIHqqFL35z/T+Mpq8lrvaPwiZJnKaMipWzre4RIRrBx/UKhGaADniFOOCc1J2/KMwH6E5WXFbO9pexAkoBEpxYKgkPcldCBmwI96Rk6lul3Rflkj3FrJvVrzJumyBffW+NwSdvFP0QltmzVEN39K9prXttF5bTlxcxaxpFU58AZXI6igwiAAAABgAAAAAAAAAAAAAAAA4ILwb/ZX2UMQy4zosNmgRUHYBSAAAAAAABqe0BAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAAAAAAAAsx9mqjweeFNj8IdaG3Tie4X9ZscABgAAAAAAAAAAAAAAAD1aJY70jTtGjw8Tlz+RsqmlzFPYAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const wavaxTransfer = + "0100000000010044dd5206ac105e99c39b2a368e510978f1e18cf61bfbfac399244c9bbcf23b3e61bd5e6ca098855263745890bae05e6450a9d4ccdb395ecd01471e5867db738a0065723a8a0c22000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9ed01010000000000000000000000000000000000000000000000000000000000000064000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700060000000000000000000000003d5a258ef48d3b468f0f13973f91b2a9a5cc53d800030000000000000000000000000000000000000000000000000000000000000000"; + const txhash = await submitTokenBridgeVAA(wavaxTransfer); + console.log( + `Redeemed WAVAX https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); +} + +async function step8c() { + // WAVAX transfer out + const amount = "100"; + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgExecuteContract( + wallet.key.accAddress, + wavaxAddress, + { + increase_allowance: { + spender: addressTokenBridge, + amount, + expires: { + never: {}, + }, + }, + }, + {} + ), + new MsgExecuteContract( + wallet.key.accAddress, + addressTokenBridge, + { + initiate_transfer: { + asset: { + amount, + info: { + token: { + contract_addr: wavaxAddress, + }, + }, + }, + recipient_chain: 4, + recipient: Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000000", + "hex" + ).toString("base64"), + fee: "0", + nonce: 0, + }, + }, + {} + ), + ], + memo: "", + fee: new Fee(1000000, { uluna: 50_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + console.log( + `Transferred WAVAX https://finder.terraclassic.community/mainnet/tx/${response?.txhash}` + ); +} + +async function step9() { + { + // Fantom mainnet token bridge registration + // worm generate registration -c fantom -a 7C9Fc5741288cDFdD83CeB07f3ea7e22618D79D2 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const registerAvalanche = + "01000000000100f4644a32805b1e24eb40d91ffa05196bfa2783c74448070661701db4168a3e55787e1bd1bc4b300309b85990a4a75c8f7ff420c90b5d5a853076e413a02ef98c000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000004eadf0f00000000000000000000000000000000000000000000546f6b656e427269646765010000000a0000000000000000000000007c9fc5741288cdfdd83ceb07f3ea7e22618d79d2"; + const txhash = await submitTokenBridgeVAA(registerAvalanche); + console.log( + `Registered Fantom https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } + { + // WFTM attestation + // worm edit-vaa -v AQAAAAMNAGZLTJJ7k9izhrCiPU4vVY7CYp2c5592bObi2AKLGlj4CCxEGiQMva1F92+4kiX96CQoHG6iGSLX/uIwWZ0LdxkBAkq/rbbsqsk/Ax1gcowejzzJXgvfuSReU/Ob2sj4om2UY/L5R9b15jNb9uFexIkXitEaMRAzy0pnX1dBHx8ATfkAAyLgNbwTYAuA+sY+99cvm+e7r4V98IgXC4abG18t2K1nR9wxLpUMzNVPqDXVO/nDzvdQGqmHuhsC6IcwBT4CrCIABGWCArnx4DzWkS1Nsr88S7OvVOAWvn7AxTlVo0HT7SSwYhb7TUP2vBwJbA6mC0lK0UeBM3P4yoAKiFwSgqYPaZwABmewrAPd+r8uBGivWWfgsV5MbqwDEPy34mf+4LyhKtlifQc/QA3Mm+ttykD4SBp4ylAbvuwLBu8lqGrlzb/MoIYBBxLvs7gB2//Qx0qbsf7Ujau3g3Ipl1G2KTid1Xbn+5JDXbeJYEZQ3r2oiMB9N7HUNlldVPf3Nxn3oaZRHUvHYJkACzsVuZ0g4d2I2/XlLoanV90ElTFPjfmfe6Yp2Sol4mqOcz1Y+7QNmMm7iaKX9V7zRxvr/h6TWLip/P+mHjHRoywADGY6Vws8S5crT4U38OQoMEt9zFrBi1fttzdzv5P4BBKkWqUGP5ma2QyM39i6sussCgeI5qJae4ro3xXos5Qs218BDfgNXK8IojRwZoL8H+JKVOBv2qVN8rsbIwAN42TM3olCAliJYhhou8iZyjdeztmQRQl+7YESz8DVgLRNYhfPRDQADlQw39Txk19urWtjwb5LgVIWKea8AQqyocY2f3hJqbt9HFzWhR6Ho+gJ/wr7OnVoe9IIn4W5mvyiJYOLrmmNhzgBEEIZ8n6Qevl1+dZR2bdZHn6Cqdk6/UiPcyWmTHrMC8YKD+tKj3eRPHDDldnEJ23tsrtLhiCZm2OhiONefWCv9q8BEQCzPrgDqun4qbYMwAP8Bw8e22fJ5AnCOj6EksJEeYO7Kgwiijbc12wHosCaFD5YZXTqGPJ9zot1XH1tcFzYePABEtMHLrXStHqUtHUaR2KtRTKOL71Yy89SY8lEe70JJw9lVMJggnBVTPAdjic/frvLXFOZWgHmVYxz3fCIJWb0EboAZXMyeXI3AAAACgAAAAAAAAAAAAAAAHyfxXQSiM392DzrB/PqfiJhjXnSAAAAAAAAe34BAgAAAAAAAAAAAAAAACG+Nw1TEvRMtCzjd7ybigzvGkyDAAoSV0ZUTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXcmFwcGVkIEZhbnRvbQAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + const wftmAttestation = + "01000000000100bc136a00a448e2cc01ae1b81ca9d37a301a98fa906893b0735817b79d614b8bb3ede50f3d125bf581bff3640abc4b9ca83171c5e7ff7963f4a9a5517b6cb0009006573327972370000000a0000000000000000000000007c9fc5741288cdfdd83ceb07f3ea7e22618d79d20000000000007b7e010200000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83000a125746544d00000000000000000000000000000000000000000000000000000000577261707065642046616e746f6d000000000000000000000000000000000000"; + const txhash = await submitTokenBridgeVAA(wftmAttestation); + console.log( + `Created WFTM https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } +} + +async function step10() { + // skipping step10 as already covered by 8 +} + +async function step11() { + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgExecuteContract( + wallet.key.accAddress, + addressTokenBridge, + { + create_asset_meta: { + asset_info: { + native_token: { denom: "uluna" }, + }, + nonce: 0, + }, + }, + {} + ), + ], + memo: "", + fee: new Fee(1000000, { uluna: 50_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + console.log( + `Attested uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}` + ); +} + +async function step12() { + { + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgExecuteContract( + wallet.key.accAddress, + addressTokenBridge, + { + deposit_tokens: {}, + }, + { uluna: 10000 } + ), + ], + memo: "", + fee: new Fee(200000, { uluna: 10_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + console.log( + `Deposted uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}` + ); + } + { + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgExecuteContract( + wallet.key.accAddress, + addressTokenBridge, + { + withdraw_tokens: { + asset: { + native_token: { + denom: "uluna", + }, + }, + }, + }, + {} + ), + ], + memo: "", + fee: new Fee(200000, { uluna: 10_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + console.log( + `Withdrew uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}` + ); + } +} + +async function step13() { + { + const tx = await wallet.createAndSignTx({ + msgs: [ + new MsgExecuteContract( + wallet.key.accAddress, + addressTokenBridge, + { + deposit_tokens: {}, + }, + { uluna: 10000 } + ), + new MsgExecuteContract( + wallet.key.accAddress, + addressTokenBridge, + { + initiate_transfer: { + asset: { + amount: "10000", + info: { + native_token: { + denom: "uluna", + }, + }, + }, + recipient_chain: 2, + recipient: Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000000", + "hex" + ).toString("base64"), + fee: "0", + nonce: 1, + }, + }, + {} // no fee? + // { uluna: 10050 } // fee + tax + ), + ], + memo: "", + fee: new Fee(500000, { uluna: 20_000_000 }), + }); + const response = await broadcastAndWait(terra, tx); + console.log( + `Sent uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}` + ); + } + + // 10000 uluna from avax to terra classic + { + const transferVAA = + "010000000001002e1a7f786c42d41047bc4a6c55c2210a00dbeae45d43ead884eb42c163a7d72708a089c1e93779adbcf0603fac904a77c47e0c49cd0663ab250c434f6ceeb1f600652719abea95000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d80520000000000018b9401010000000000000000000000000000000000000000000000000000000000002710010000000000000000000000000000000000000000000000000000756c756e6100030000000000000000000000003d5a258ef48d3b468f0f13973f91b2a9a5cc53d800030000000000000000000000000000000000000000000000000000000000000000"; + const txhash = await submitTokenBridgeVAA(transferVAA); + console.log( + `Redeemed uluna https://finder.terraclassic.community/mainnet/tx/${txhash}` + ); + } +} + +async function main() { + // await step1(); + console.log( + `Core bridge: https://finder.terraclassic.community/mainnet/address/${addressCoreBridge}` + ); + console.log( + `Token bridge: https://finder.terraclassic.community/mainnet/address/${addressTokenBridge}` + ); + // await step2(); + // await step3(); + // await step4(); + // await step5(); + // console.log(`New core bridge code ID: ${newCodeIdCoreBridge}`); + // console.log(`New token bridge code ID: ${newCodeIdTokenBridge}`); + // await step6(); + // await step7(); + // await step8a(); + // await step8b(); + // await step8c(); + await step9(); + await step10(); + await step11(); + await step12(); + await step13(); +} + +main(); From 96a48c9d2d08803565c04c89a4ebf2f2a622203e Mon Sep 17 00:00:00 2001 From: Evan Gray Date: Fri, 8 Dec 2023 17:34:35 -0500 Subject: [PATCH 06/12] terra: update devnet terra classic --- terra/Makefile | 18 +- terra/devnet/Dockerfile | 17 +- terra/devnet/config/app.toml | 105 ++++++-- terra/devnet/config/client.toml | 17 ++ terra/devnet/config/config.toml | 100 +++++++- terra/devnet/config/genesis.json | 112 ++++++--- terra/devnet/config/terrad.toml | 9 - terra/devnet/config/wasm.toml | 17 -- terra/devnet/data/priv_validator_state.json | 5 + terra/devnet/docker-compose.yml | 9 + terra/test/package-lock.json | 254 +++++++++++++------- terra/test/package.json | 2 +- terra/test/src/__tests__/bridge.ts | 57 +++-- terra/test/src/helpers/client.ts | 2 +- terra/test/src/instantiate.ts | 9 +- 15 files changed, 511 insertions(+), 222 deletions(-) create mode 100644 terra/devnet/config/client.toml delete mode 100644 terra/devnet/config/terrad.toml delete mode 100644 terra/devnet/config/wasm.toml create mode 100644 terra/devnet/data/priv_validator_state.json create mode 100644 terra/devnet/docker-compose.yml diff --git a/terra/Makefile b/terra/Makefile index 1598fb4876..6f3b9ebeec 100644 --- a/terra/Makefile +++ b/terra/Makefile @@ -48,14 +48,6 @@ deploy/token_bridge: token_bridge-code-id-$(NETWORK).txt tools/node_modules: tools/package-lock.json cd tools && npm ci -LocalTerra: - mkdir LocalTerra && \ - cd LocalTerra && \ - git init && \ - git remote add origin https://www.github.com/terra-money/LocalTerra.git && \ - git fetch --depth 1 origin 958ff795f261f5ff2efc7b56604e2434eb76f7c4 && \ - git checkout FETCH_HEAD - test/node_modules: test/package-lock.json cd test && npm ci @@ -67,12 +59,12 @@ unit-test: .PHONY: test ## Run unit and integration tests -test: artifacts test/node_modules LocalTerra unit-test +test: artifacts test/node_modules unit-test @if pgrep terrad; then echo "Error: terrad already running. Stop it before running tests"; exit 1; fi - cd LocalTerra && docker compose up --detach - sleep 5 - cd test && npm run test || (cd ../LocalTerra && docker compose down && exit 1) - cd LocalTerra && docker compose down + cd devnet && docker compose up --detach + sleep 10 + cd test && npm run test || (cd ../devnet && docker compose down && exit 1) + cd devnet && docker compose down .PHONY: clean clean: diff --git a/terra/devnet/Dockerfile b/terra/devnet/Dockerfile index bd6b22001a..e662ebc6bc 100644 --- a/terra/devnet/Dockerfile +++ b/terra/devnet/Dockerfile @@ -1,3 +1,18 @@ -FROM terramoney/localterra-core:bombay@sha256:0f93576ae0716f835b2adbd5ac550ef90063b536e99c4dd682b6dd905927f261 +FROM --platform=linux/amd64 docker.io/golang:1.20.10-bullseye@sha256:082569b3303b164cc4a7c88ac59b19b69c1a5d662041ac0dca046ac239632442 AS build + +WORKDIR /root/core + +RUN git init +RUN git remote add origin https://github.com/classic-terra/core.git +RUN git fetch --depth 1 origin 2a8b6db5a0235c29dcc714c48d36387fc0d1d793 +RUN git checkout FETCH_HEAD + +RUN make install COPY config /root/.terra/config +COPY data /root/.terra/data + +EXPOSE 26657 +EXPOSE 1317 +EXPOSE 9090 +EXPOSE 9091 diff --git a/terra/devnet/config/app.toml b/terra/devnet/config/app.toml index 59c583aab1..141a06f067 100644 --- a/terra/devnet/config/app.toml +++ b/terra/devnet/config/app.toml @@ -8,17 +8,16 @@ # The minimum gas prices a validator is willing to accept for processing a # transaction. A transaction's fees must meet the minimum of any denomination # specified in this config (e.g. 0.25token1;0.0001token2). -minimum-gas-prices = "0.01133uluna,0.15uusd,0.104938usdr,169.77ukrw,428.571umnt,0.125ueur,0.98ucny,16.37ujpy,0.11ugbp,10.88uinr,0.19ucad,0.14uchf,0.19uaud,0.2usgd,4.62uthb,1.25usek" +minimum-gas-prices = "0uluna" -# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals +# default: the last 362880 states are kept, pruning at 10 block intervals # nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node) -# everything: all saved states will be deleted, storing only the current state; pruning at 10 block intervals -# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval' +# everything: 2 latest states will be kept; pruning at 10 block intervals. +# custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval' pruning = "default" # These are applied if and only if the pruning strategy is custom. pruning-keep-recent = "0" -pruning-keep-every = "0" pruning-interval = "0" # HaltHeight contains a non-zero block height at which a node will gracefully @@ -44,7 +43,7 @@ halt-time = 0 # It has no bearing on application state pruning which is determined by the # "pruning-*" configurations. # -# Note: Tendermint block pruning is dependant on this parameter in conjunction +# Note: Tendermint block pruning is dependant on this parameter in conunction # with the unbonding (safety threshold) period, state pruning and state sync # snapshot parameters to determine the correct minimum value of # ResponseCommit.RetainHeight. @@ -53,6 +52,12 @@ min-retain-blocks = 0 # InterBlockCache enables inter-block caching. inter-block-cache = true +# InterBlockCacheSize set the size (the number of cache items) of interblock cache item +# Each item consumes 128 bytes, so the value should be dividend by 128 +# Default cache size is 10mb. +# Ex) 100mb = 10,000,000 / 128 = 78,125 +inter-block-cache-size = 78125 + # IndexEvents defines the set of events in the form {eventType}.{attributeKey}, # which informs Tendermint what to index. If empty, all events will be indexed. # @@ -60,6 +65,26 @@ inter-block-cache = true # ["message.sender", "message.recipient"] index-events = [] +# IAVLCacheSize set the cache size (the number of cache items) of the iavl tree. +# Each item size consumes 128 bytes, so the value should be dividend by 128 +# Default cache size is 100mb. +# Ex) 100mb = 100,000,000 / 128 = 781,250 +iavl-cache-size = 781250 + +# IavlDisableFastNode enables or disables the fast node feature of IAVL. +# Default is false. +iavl-disable-fastnode = false + +# EXPERIMENTAL: IAVLLazyLoading enable/disable the lazy loading of iavl store. +# Default is false. +iavl-lazy-loading = false + +# AppDBBackend defines the database backend type to use for the application and snapshots DBs. +# An empty string indicates that a fallback will be used. +# First fallback is the deprecated compile-time types.DBBackend value. +# Second fallback (if the types.DBBackend also isn't set), is the db-backend value set in Tendermint's config.toml. +app-db-backend = "" + ############################################################################### ### Telemetry Configuration ### ############################################################################### @@ -148,6 +173,18 @@ retries = 3 # Offline defines if Rosetta server should run in offline mode. offline = false +# EnableDefaultSuggestedFee defines if the server should suggest fee by default. +# If 'construction/medata' is called without gas limit and gas price, +# suggested fee based on gas-to-suggest and denom-to-suggest will be given. +enable-fee-suggestion = false + +# GasToSuggest defines gas limit when calculating the fee +gas-to-suggest = 200000 + +# DenomToSuggest defines the defult denom for fee suggestion. +# Price must be in minimum-gas-prices. +denom-to-suggest = "uatom" + ############################################################################### ### gRPC Configuration ### ############################################################################### @@ -160,6 +197,14 @@ enable = true # Address defines the gRPC server address to bind to. address = "0.0.0.0:9090" +# MaxRecvMsgSize defines the max message size in bytes the server can receive. +# The default value is 10MB. +max-recv-msg-size = "10485760" + +# MaxSendMsgSize defines the max message size in bytes the server can send. +# The default value is math.MaxInt32. +max-send-msg-size = "2147483647" + ############################################################################### ### gRPC Web Configuration ### ############################################################################### @@ -185,22 +230,48 @@ enable-unsafe-cors = true [state-sync] # snapshot-interval specifies the block interval at which local state sync snapshots are -# taken (0 to disable). Must be a multiple of pruning-keep-every. +# taken (0 to disable). snapshot-interval = 0 # snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all). snapshot-keep-recent = 2 -[wasm] -# The maximum gas amount can be spent for contract query. -# The contract query will invoke contract execution vm, -# so we need to restrict the max usage to prevent DoS attack -contract-query-gas-limit = "3000000" +############################################################################### +### Store / State Streaming ### +############################################################################### + +[store] +streamers = [] + +[streamers] +[streamers.file] +keys = ["*", ] +write_dir = "" +prefix = "" + +# output-metadata specifies if output the metadata file which includes the abci request/responses +# during processing the block. +output-metadata = "true" + +# stop-node-on-error specifies if propagate the file streamer errors to consensus state machine. +stop-node-on-error = "true" + +# fsync specifies if call fsync after writing the files. +fsync = "false" -# The flag to specify whether print contract logs or not -contract-debug-mode = "false" -# The WASM VM memory cache size in MiB not bytes -contract-memory-cache-size = "500" +############################################################################### +### WASM ### +############################################################################### + +[wasm] +# Smart query gas limit is the max gas to be used in a smart query contract call +query_gas_limit = 3000000 + +# in-memory cache for Wasm contracts. Set to 0 to disable. +# The value is in MiB not bytes +memory_cache_size = 100 -contract-logging-whitelist = "*" +# Simulation gas limit is the max gas to be used in a tx simulation call. +# When not set the consensus max block gas is used instead +# simulation_gas_limit = diff --git a/terra/devnet/config/client.toml b/terra/devnet/config/client.toml new file mode 100644 index 0000000000..2dc68254a0 --- /dev/null +++ b/terra/devnet/config/client.toml @@ -0,0 +1,17 @@ +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### Client Configuration ### +############################################################################### + +# The network chain ID +chain-id = "localterra" +# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) +keyring-backend = "os" +# CLI output format (text|json) +output = "text" +# : to Tendermint RPC interface for this chain +node = "tcp://localhost:26657" +# Transaction broadcasting mode (sync|async|block) +broadcast-mode = "sync" diff --git a/terra/devnet/config/config.toml b/terra/devnet/config/config.toml index 69bd69c1ff..507e35950c 100644 --- a/terra/devnet/config/config.toml +++ b/terra/devnet/config/config.toml @@ -3,7 +3,7 @@ # NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or # relative to the home directory (e.g. "data"). The home directory is -# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable +# "$HOME/.cometbft" by default, but could be changed via $CMTHOME env variable # or --home cmd flag. ####################################################################### @@ -11,8 +11,8 @@ ####################################################################### # TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26656" +# or the name of an ABCI application compiled in with the CometBFT binary +proxy_app = "tcp://127.0.0.1:26658" # A custom human readable name for this node moniker = "localterra" @@ -63,7 +63,7 @@ priv_validator_key_file = "config/priv_validator_key.json" # Path to the JSON file containing the last sign state of a validator priv_validator_state_file = "data/priv_validator_state.json" -# TCP or UNIX socket address for Tendermint to listen on for +# TCP or UNIX socket address for CometBFT to listen on for # connections from an external PrivValidator process priv_validator_laddr = "" @@ -136,6 +136,33 @@ max_subscription_clients = 100 # the estimated # maximum number of broadcast_tx_commit calls per block. max_subscriptions_per_client = 5 +# Experimental parameter to specify the maximum number of events a node will +# buffer, per subscription, before returning an error and closing the +# subscription. Must be set to at least 100, but higher values will accommodate +# higher event throughput rates (and will use more memory). +experimental_subscription_buffer_size = 200 + +# Experimental parameter to specify the maximum number of RPC responses that +# can be buffered per WebSocket client. If clients cannot read from the +# WebSocket endpoint fast enough, they will be disconnected, so increasing this +# parameter may reduce the chances of them being disconnected (but will cause +# the node to use more memory). +# +# Must be at least the same as "experimental_subscription_buffer_size", +# otherwise connections could be dropped unnecessarily. This value should +# ideally be somewhat higher than "experimental_subscription_buffer_size" to +# accommodate non-subscription-related RPC responses. +experimental_websocket_write_buffer_size = 200 + +# If a WebSocket client cannot read fast enough, at present we may +# silently drop events instead of generating an error or disconnecting the +# client. +# +# Enabling this experimental parameter will cause the WebSocket connection to +# be closed instead if it cannot read fast enough, allowing for greater +# predictability in subscription behaviour. +experimental_close_on_slow_client = false + # How long to wait for a tx to be committed during /broadcast_tx_commit. # WARNING: Using a value larger than 10s will result in increasing the # global HTTP write timeout, which applies to all connections and endpoints. @@ -149,17 +176,17 @@ max_body_bytes = 4194304 max_header_bytes = 1048576 # The path to a file containing certificate that is used to create the HTTPS server. -# Might be either absolute path or path related to Tendermint's config directory. +# Might be either absolute path or path related to CometBFT's config directory. # If the certificate is signed by a certificate authority, # the certFile should be the concatenation of the server's certificate, any intermediates, # and the CA's certificate. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. +# NOTE: both tls_cert_file and tls_key_file must be present for CometBFT to create HTTPS server. # Otherwise, HTTP server is run. tls_cert_file = "" # The path to a file containing matching private key that is used to create the HTTPS server. -# Might be either absolute path or path related to Tendermint's config directory. -# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server. +# Might be either absolute path or path related to CometBFT's config directory. +# NOTE: both tls-cert-file and tls-key-file must be present for CometBFT to create HTTPS server. # Otherwise, HTTP server is run. tls_key_file = "" @@ -172,12 +199,13 @@ pprof_laddr = "localhost:6060" [p2p] # Address to listen for incoming connections -laddr = "tcp://0.0.0.0:26660" +laddr = "tcp://0.0.0.0:26656" # Address to advertise to peers for them to dial # If empty, will use the same port as the laddr, # and will introspect on the listener or use UPnP -# to figure out the address. +# to figure out the address. ip and port are required +# example: 159.89.10.97:26656 external_address = "" # Comma separated list of seed nodes to connect to @@ -244,6 +272,16 @@ dial_timeout = "3s" ####################################################### [mempool] +# Mempool version to use: +# 1) "v0" - (default) FIFO mempool. +# 2) "v1" - prioritized mempool. +version = "v0" + +# Recheck (default: true) defines whether CometBFT should recheck the +# validity for all remaining transaction in the mempool after a block. +# Since a block affects the application state, some transactions in the +# mempool may become invalid. If this does not apply to your application, +# you can disable rechecking. recheck = true broadcast = true wal_dir = "" @@ -273,6 +311,22 @@ max_tx_bytes = 1048576 # XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 max_batch_bytes = 0 +# ttl-duration, if non-zero, defines the maximum amount of time a transaction +# can exist for in the mempool. +# +# Note, if ttl-num-blocks is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if it's +# insertion time into the mempool is beyond ttl-duration. +ttl-duration = "0s" + +# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction +# can exist for in the mempool. +# +# Note, if ttl-duration is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if +# it's insertion time into the mempool is beyond ttl-duration. +ttl-num-blocks = 0 + ####################################################### ### State Sync Configuration Options ### ####################################################### @@ -302,6 +356,13 @@ discovery_time = "15s" # Will create a new, randomly named directory within, and remove it when done. temp_dir = "" +# The timeout duration before re-requesting a chunk, possibly from a different +# peer (default: 1 minute). +chunk_request_timeout = "10s" + +# The number of concurrent chunk fetchers to run (default: 1). +chunk_fetchers = "4" + ####################################################### ### Fast Sync Configuration Connections ### ####################################################### @@ -354,6 +415,17 @@ create_empty_blocks_interval = "0s" peer_gossip_sleep_duration = "100ms" peer_query_maj23_sleep_duration = "2s" +####################################################### +### Storage Configuration Options ### +####################################################### +[storage] + +# Set to true to discard ABCI responses from the state store, which can save a +# considerable amount of disk space. Set to false to ensure ABCI responses are +# persisted. ABCI responses are required for /block_results RPC queries, and to +# reindex events in the command-line tool. +discard_abci_responses = false + ####################################################### ### Transaction Indexer Configuration Options ### ####################################################### @@ -368,8 +440,14 @@ peer_query_maj23_sleep_duration = "2s" # 1) "null" # 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). # - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed. +# 3) "psql" - the indexer services backed by PostgreSQL. +# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed. indexer = "kv" +# The PostgreSQL connection configuration, the connection format: +# postgresql://:@:/? +psql-conn = "" + ####################################################### ### Instrumentation Configuration Options ### ####################################################### @@ -390,4 +468,4 @@ prometheus_listen_addr = ":26660" max_open_connections = 3 # Instrumentation namespace -namespace = "tendermint" +namespace = "cometbft" diff --git a/terra/devnet/config/genesis.json b/terra/devnet/config/genesis.json index 6e5ad64893..4cbbbe17d9 100644 --- a/terra/devnet/config/genesis.json +++ b/terra/devnet/config/genesis.json @@ -1,5 +1,5 @@ { - "genesis_time": "2021-05-26T10:02:06.396784Z", + "genesis_time": "2023-12-08T21:26:27.82937365Z", "chain_id": "localterra", "initial_height": "1", "consensus_params": { @@ -14,9 +14,7 @@ "max_bytes": "1048576" }, "validator": { - "pub_key_types": [ - "ed25519" - ] + "pub_key_types": ["ed25519"] }, "version": {} }, @@ -431,7 +429,7 @@ }, "distribution": { "params": { - "community_tax": "0.000000000000000000", + "community_tax": "0.020000000000000000", "base_proposer_reward": "0.010000000000000000", "bonus_proposer_reward": "0.040000000000000000", "withdraw_addr_enabled": true @@ -448,12 +446,28 @@ "delegator_starting_infos": [], "validator_slash_events": [] }, + "dyncomm": { + "params": { + "max_zero": "0.500000000000000000", + "slope_base": "2.000000000000000000", + "slope_vp_impact": "10.000000000000000000", + "cap": "0.200000000000000000" + }, + "validator_commission_rates": [] + }, "evidence": { "evidence": [] }, "feegrant": { "allowances": [] }, + "feeibc": { + "identified_fees": [], + "fee_enabled_channels": [], + "registered_payees": [], + "registered_counterparty_payees": [], + "forward_relayers": [] + }, "genutil": { "gen_txs": [ { @@ -531,10 +545,10 @@ "amount": "10000000" } ], - "max_deposit_period": "300s" + "max_deposit_period": "172800s" }, "voting_params": { - "voting_period": "300s" + "voting_period": "172800s" }, "tally_params": { "quorum": "0.334000000000000000", @@ -548,10 +562,7 @@ "clients_consensus": [], "clients_metadata": [], "params": { - "allowed_clients": [ - "06-solomachine", - "07-tendermint" - ] + "allowed_clients": ["06-solomachine", "07-tendermint"] }, "create_localhost": false, "next_client_sequence": "0" @@ -559,7 +570,10 @@ "connection_genesis": { "connections": [], "client_connection_paths": [], - "next_connection_sequence": "0" + "next_connection_sequence": "0", + "params": { + "max_expected_time_per_block": "30000000000" + } }, "channel_genesis": { "channels": [], @@ -572,12 +586,32 @@ "next_channel_sequence": "0" } }, + "interchainaccounts": { + "controller_genesis_state": { + "active_channels": [], + "interchain_accounts": [], + "ports": [], + "params": { + "controller_enabled": true + } + }, + "host_genesis_state": { + "active_channels": [], + "interchain_accounts": [], + "port": "icahost", + "params": { + "host_enabled": true, + "allow_messages": ["*"] + } + } + }, "market": { "params": { - "base_pool": "7000000000000.000000000000000000", - "pool_recovery_period": "200", - "min_stability_spread": "0.005000000000000000" - } + "base_pool": "1000000000000.000000000000000000", + "pool_recovery_period": "14400", + "min_stability_spread": "0.020000000000000000" + }, + "terra_pool_delta": "0.000000000000000000" }, "mint": { "minter": { @@ -586,7 +620,7 @@ }, "params": { "mint_denom": "uluna", - "inflation_rate_change": "0.000000000000000000", + "inflation_rate_change": "0.130000000000000000", "inflation_max": "0.200000000000000000", "inflation_min": "0.070000000000000000", "goal_bonded": "0.670000000000000000", @@ -613,8 +647,8 @@ "tobin_tax": "0.002500000000000000" }, { - "name": "ueur", - "tobin_tax": "0.002500000000000000" + "name": "umnt", + "tobin_tax": "0.020000000000000000" } ], "slash_fraction": "0.000100000000000000", @@ -642,11 +676,12 @@ }, "staking": { "params": { - "unbonding_time": "600s", + "unbonding_time": "1814400s", "max_validators": 100, "max_entries": 7, "historical_entries": 10000, - "bond_denom": "uluna" + "bond_denom": "uluna", + "min_commission_rate": "0.000000000000000000" }, "last_total_power": "0", "last_validator_powers": [], @@ -667,28 +702,30 @@ "treasury": { "params": { "tax_policy": { - "rate_min": "0.000000000000000000", - "rate_max": "0.000000000000000000", + "rate_min": "0.000500000000000000", + "rate_max": "0.010000000000000000", "cap": { "denom": "usdr", - "amount": "0" + "amount": "1000000" }, - "change_rate_max": "0.000000000000000000" + "change_rate_max": "0.000250000000000000" }, "reward_policy": { - "rate_min": "0.000000000000000000", - "rate_max": "1.000000000000000000", + "rate_min": "0.050000000000000000", + "rate_max": "0.500000000000000000", "cap": { "denom": "unused", "amount": "0" }, - "change_rate_max": "0.000000000000000000" + "change_rate_max": "0.025000000000000000" }, "seigniorage_burden_target": "0.670000000000000000", "mining_increment": "1.070000000000000000", "window_short": "4", "window_long": "52", - "window_probation": "12" + "window_probation": "12", + "burn_tax_split": "0.100000000000000000", + "min_initial_deposit_ratio": "0.000000000000000000" }, "tax_rate": "0.001000000000000000", "reward_weight": "0.050000000000000000", @@ -698,17 +735,20 @@ "epoch_states": [] }, "upgrade": {}, - "vesting": null, + "vesting": {}, "wasm": { "params": { - "max_contract_size": "614400", - "max_contract_gas": "20000000", - "max_contract_msg_size": "4096" + "code_upload_access": { + "permission": "Everybody", + "address": "", + "addresses": [] + }, + "instantiate_default_permission": "Everybody" }, - "last_code_id": "0", - "last_instance_id": "0", "codes": [], - "contracts": [] + "contracts": [], + "sequences": [], + "gen_msgs": [] } } } diff --git a/terra/devnet/config/terrad.toml b/terra/devnet/config/terrad.toml deleted file mode 100644 index 2a20681122..0000000000 --- a/terra/devnet/config/terrad.toml +++ /dev/null @@ -1,9 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# The minimum gas prices a validator is willing to accept for processing a -# transaction. A transaction's fees must meet the minimum of any denomination -# specified in this config (e.g. 0.25token1;0.0001token2). -minimum-gas-prices = "" diff --git a/terra/devnet/config/wasm.toml b/terra/devnet/config/wasm.toml deleted file mode 100644 index 945f5c2d47..0000000000 --- a/terra/devnet/config/wasm.toml +++ /dev/null @@ -1,17 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# The maximum gas amount can be spent for contract query. -# The contract query will invoke contract execution vm, -# so we need to restrict the max usage to prevent DoS attack -contract-query-gas-limit = "3000000" - -# Storing instances in the LRU will have no effect on the results -# (still deterministic), but should lower execution time at -# the cost of increased memory usage. We cannot pick universal -# parameters for this, so we should allow node operators to set it. -lru-size = "0" - -contract-logging-whitelist = "*" \ No newline at end of file diff --git a/terra/devnet/data/priv_validator_state.json b/terra/devnet/data/priv_validator_state.json new file mode 100644 index 0000000000..4dfbafad53 --- /dev/null +++ b/terra/devnet/data/priv_validator_state.json @@ -0,0 +1,5 @@ +{ + "height": "0", + "round": 0, + "step": 0 +} diff --git a/terra/devnet/docker-compose.yml b/terra/devnet/docker-compose.yml new file mode 100644 index 0000000000..bbff33d746 --- /dev/null +++ b/terra/devnet/docker-compose.yml @@ -0,0 +1,9 @@ +services: + terrad: + build: . + ports: + - "26657:26657" + - "1317:1317" + - "9090:9090" + - "9091:9091" + command: terrad start diff --git a/terra/test/package-lock.json b/terra/test/package-lock.json index 19c9b01eab..3300b52e37 100644 --- a/terra/test/package-lock.json +++ b/terra/test/package-lock.json @@ -1,16 +1,16 @@ { - "name": "test", - "version": "0.1.0", + "name": "@wormhole-foundation/tests-terra", + "version": "0.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "test", - "version": "0.1.0", + "name": "@wormhole-foundation/tests-terra", + "version": "0.0.1", "license": "ISC", "dependencies": { "@cosmjs/encoding": "^0.26.2", - "@terra-money/terra.js": "^3.0.9", + "@terra-money/terra.js": "^3.1.10", "elliptic": "^6.5.4", "ts-jest": "^27.1.4", "web3-eth-abi": "^1.7.1", @@ -531,6 +531,17 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "peer": true }, + "node_modules/@classic-terra/terra.proto": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@classic-terra/terra.proto/-/terra.proto-1.1.0.tgz", + "integrity": "sha512-bYhQG5LUaGF0KPRY9hYT/HEcd1QExZPQd6zLV/rQkCe/eDxfwFRLzZHpaaAdfWoAAZjsRWqJbUCqCg7gXBbJpw==", + "dependencies": { + "@improbable-eng/grpc-web": "^0.14.1", + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, "node_modules/@cosmjs/encoding": { "version": "0.26.6", "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.26.6.tgz", @@ -893,6 +904,17 @@ "@ethersproject/strings": "^5.6.0" } }, + "node_modules/@improbable-eng/grpc-web": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", + "dependencies": { + "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1529,7 +1551,7 @@ "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", @@ -1544,12 +1566,12 @@ "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -1558,27 +1580,27 @@ "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@sinonjs/commons": { "version": "1.8.3", @@ -1599,12 +1621,13 @@ } }, "node_modules/@terra-money/terra.js": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.0.9.tgz", - "integrity": "sha512-jC7E8SjYiUV7nTk8g3LwQhJXlW5t2aiulB6Qg+K9dWpNzfqMn1ovuOD250gyx9aFaCilbDVLzPiZJLLbKPCO0w==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.1.10.tgz", + "integrity": "sha512-MqR16LjTUyVD4HnEavP1iBW0c1roCoRHH/E1x9P44pXzgtv2wsMeP+2un4Bnck4Nkv/46Xvy/BSKiY90ll3BKA==", "dependencies": { - "@terra-money/terra.proto": "^0.1.7", - "axios": "^0.24.0", + "@classic-terra/terra.proto": "^1.1.0", + "@terra-money/terra.proto": "^2.1.0", + "axios": "^0.27.2", "bech32": "^2.0.0", "bip32": "^2.0.6", "bip39": "^3.0.3", @@ -1615,17 +1638,18 @@ "secp256k1": "^4.0.2", "tmp": "^0.2.1", "utf-8-validate": "^5.0.5", - "ws": "^7.5.5" + "ws": "^7.5.9" }, "engines": { "node": ">=14" } }, "node_modules/@terra-money/terra.proto": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", - "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.1.0.tgz", + "integrity": "sha512-rhaMslv3Rkr+QsTQEZs64FKA4QlfO0DfQHaR6yct/EovenMkibDEQ63dEL6yJA6LCaEQGYhyVB9JO9pTUA8ybw==", "dependencies": { + "@improbable-eng/grpc-web": "^0.14.1", "google-protobuf": "^3.17.3", "long": "^4.0.0", "protobufjs": "~6.11.2" @@ -1720,9 +1744,9 @@ } }, "node_modules/@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/node": { "version": "17.0.23", @@ -1889,15 +1913,28 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "peer": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "node_modules/axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "dependencies": { - "follow-redirects": "^1.14.4" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, "node_modules/babel-jest": { @@ -2181,6 +2218,11 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "node_modules/browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -2418,7 +2460,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "peer": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2576,7 +2617,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "peer": true, "engines": { "node": ">=0.4.0" } @@ -2918,9 +2958,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", "funding": [ { "type": "individual", @@ -3041,9 +3081,9 @@ } }, "node_modules/google-protobuf": { - "version": "3.19.4", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.19.4.tgz", - "integrity": "sha512-OIPNCxsG2lkIvf+P5FNfJ/Km95CsXOBecS9ZcAU6m2Rq3svc0Apl9nB3GMDNKfQ9asNv4KjyAqGwPQFrVle3Yg==" + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" }, "node_modules/graceful-fs": { "version": "4.2.9", @@ -5360,7 +5400,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "peer": true, "engines": { "node": ">= 0.6" } @@ -5369,7 +5408,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -5762,9 +5800,9 @@ } }, "node_modules/protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -6795,9 +6833,9 @@ } }, "node_modules/ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "engines": { "node": ">=8.3.0" }, @@ -7246,6 +7284,17 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "peer": true }, + "@classic-terra/terra.proto": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@classic-terra/terra.proto/-/terra.proto-1.1.0.tgz", + "integrity": "sha512-bYhQG5LUaGF0KPRY9hYT/HEcd1QExZPQd6zLV/rQkCe/eDxfwFRLzZHpaaAdfWoAAZjsRWqJbUCqCg7gXBbJpw==", + "requires": { + "@improbable-eng/grpc-web": "^0.14.1", + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, "@cosmjs/encoding": { "version": "0.26.6", "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.26.6.tgz", @@ -7440,6 +7489,14 @@ "@ethersproject/strings": "^5.6.0" } }, + "@improbable-eng/grpc-web": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", + "requires": { + "browser-headers": "^0.4.1" + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -7923,7 +7980,7 @@ "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, "@protobufjs/base64": { "version": "1.1.2", @@ -7938,12 +7995,12 @@ "@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" }, "@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "requires": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -7952,27 +8009,27 @@ "@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, "@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, "@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" }, "@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, "@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "@sinonjs/commons": { "version": "1.8.3", @@ -7993,12 +8050,13 @@ } }, "@terra-money/terra.js": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.0.9.tgz", - "integrity": "sha512-jC7E8SjYiUV7nTk8g3LwQhJXlW5t2aiulB6Qg+K9dWpNzfqMn1ovuOD250gyx9aFaCilbDVLzPiZJLLbKPCO0w==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.1.10.tgz", + "integrity": "sha512-MqR16LjTUyVD4HnEavP1iBW0c1roCoRHH/E1x9P44pXzgtv2wsMeP+2un4Bnck4Nkv/46Xvy/BSKiY90ll3BKA==", "requires": { - "@terra-money/terra.proto": "^0.1.7", - "axios": "^0.24.0", + "@classic-terra/terra.proto": "^1.1.0", + "@terra-money/terra.proto": "^2.1.0", + "axios": "^0.27.2", "bech32": "^2.0.0", "bip32": "^2.0.6", "bip39": "^3.0.3", @@ -8009,14 +8067,15 @@ "secp256k1": "^4.0.2", "tmp": "^0.2.1", "utf-8-validate": "^5.0.5", - "ws": "^7.5.5" + "ws": "^7.5.9" } }, "@terra-money/terra.proto": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", - "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.1.0.tgz", + "integrity": "sha512-rhaMslv3Rkr+QsTQEZs64FKA4QlfO0DfQHaR6yct/EovenMkibDEQ63dEL6yJA6LCaEQGYhyVB9JO9pTUA8ybw==", "requires": { + "@improbable-eng/grpc-web": "^0.14.1", "google-protobuf": "^3.17.3", "long": "^4.0.0", "protobufjs": "~6.11.2" @@ -8108,9 +8167,9 @@ } }, "@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "@types/node": { "version": "17.0.23", @@ -8246,15 +8305,27 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "peer": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "requires": { - "follow-redirects": "^1.14.4" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } } }, "babel-jest": { @@ -8482,6 +8553,11 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, "browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", @@ -8667,7 +8743,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "peer": true, "requires": { "delayed-stream": "~1.0.0" } @@ -8805,8 +8880,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "peer": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "detect-newline": { "version": "3.1.0", @@ -9077,9 +9151,9 @@ } }, "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" }, "form-data": { "version": "3.0.1", @@ -9152,9 +9226,9 @@ "peer": true }, "google-protobuf": { - "version": "3.19.4", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.19.4.tgz", - "integrity": "sha512-OIPNCxsG2lkIvf+P5FNfJ/Km95CsXOBecS9ZcAU6m2Rq3svc0Apl9nB3GMDNKfQ9asNv4KjyAqGwPQFrVle3Yg==" + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" }, "graceful-fs": { "version": "4.2.9", @@ -10898,14 +10972,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "peer": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "peer": true, "requires": { "mime-db": "1.52.0" } @@ -11200,9 +11272,9 @@ } }, "protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -11973,9 +12045,9 @@ } }, "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "requires": {} }, "xml-name-validator": { diff --git a/terra/test/package.json b/terra/test/package.json index 6f1b4ac056..b0b26666db 100644 --- a/terra/test/package.json +++ b/terra/test/package.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@cosmjs/encoding": "^0.26.2", - "@terra-money/terra.js": "^3.0.9", + "@terra-money/terra.js": "^3.1.10", "elliptic": "^6.5.4", "ts-jest": "^27.1.4", "web3-eth-abi": "^1.7.1", diff --git a/terra/test/src/__tests__/bridge.ts b/terra/test/src/__tests__/bridge.ts index 5180a34540..f2722f975c 100644 --- a/terra/test/src/__tests__/bridge.ts +++ b/terra/test/src/__tests__/bridge.ts @@ -75,22 +75,28 @@ describe("Bridge Tests", () => { ).toString("base64"); // wormhole - const wormhole = await deploy(client, wallet, WASM_WORMHOLE, { - gov_chain: GOVERNANCE_CHAIN, - gov_address: governanceAddress, - guardian_set_expirity: 86400, - initial_guardian_set: { - addresses: [ - { - bytes: Buffer.from( - "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe", - "hex" - ).toString("base64"), - }, - ], - expiration_time: 0, + const wormhole = await deploy( + client, + wallet, + WASM_WORMHOLE, + { + gov_chain: GOVERNANCE_CHAIN, + gov_address: governanceAddress, + guardian_set_expirity: 86400, + initial_guardian_set: { + addresses: [ + { + bytes: Buffer.from( + "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe", + "hex" + ).toString("base64"), + }, + ], + expiration_time: 0, + }, }, - }); + "wormholeTest" + ); // token bridge const wrappedAssetCodeId = await storeCode( @@ -98,12 +104,18 @@ describe("Bridge Tests", () => { wallet, WASM_WRAPPED_ASSET ); - const tokenBridge = await deploy(client, wallet, WASM_TOKEN_BRIDGE, { - gov_chain: GOVERNANCE_CHAIN, - gov_address: governanceAddress, - wormhole_contract: wormhole, - wrapped_asset_code_id: wrappedAssetCodeId, - }); + const tokenBridge = await deploy( + client, + wallet, + WASM_TOKEN_BRIDGE, + { + gov_chain: GOVERNANCE_CHAIN, + gov_address: governanceAddress, + wormhole_contract: wormhole, + wrapped_asset_code_id: wrappedAssetCodeId, + }, + "tokenBridgeTest" + ); // mock bridge integration const mockBridgeIntegration = await deploy( @@ -112,7 +124,8 @@ describe("Bridge Tests", () => { WASM_MOCK_BRIDGE_INTEGRATION, { token_bridge_contract: tokenBridge, - } + }, + "mockBrigeIntegration" ); contracts.set("wormhole", wormhole); contracts.set("tokenBridge", tokenBridge); diff --git a/terra/test/src/helpers/client.ts b/terra/test/src/helpers/client.ts index d634a71a9d..28e2390d0c 100644 --- a/terra/test/src/helpers/client.ts +++ b/terra/test/src/helpers/client.ts @@ -45,7 +45,7 @@ export async function transact( memo: memo, }); - return client.tx.broadcast(tx); + return client.tx.broadcastBlock(tx); } export async function transactWithoutMemo( diff --git a/terra/test/src/instantiate.ts b/terra/test/src/instantiate.ts index 1941dd3309..928938566f 100644 --- a/terra/test/src/instantiate.ts +++ b/terra/test/src/instantiate.ts @@ -29,7 +29,8 @@ export async function deploy( terra: LCDClient, wallet: Wallet, wasm: string, - instantiateMsg: Object + instantiateMsg: Object, + label: string ): Promise { const codeId = await storeCode(terra, wallet, wasm); @@ -38,11 +39,13 @@ export async function deploy( wallet.key.accAddress, wallet.key.accAddress, codeId, - instantiateMsg + instantiateMsg, + undefined, + label ), ]; const receipt = await transactWithoutMemo(terra, wallet, msgs); // @ts-ignore - return /"contract_address","value":"([^"]+)/gm.exec(receipt.raw_log)[1]; + return /"_contract_address","value":"([^"]+)/gm.exec(receipt.raw_log)[1]; } From 50f7f4d3cf8a2f33e9dd9d0bc96d58f006df47e6 Mon Sep 17 00:00:00 2001 From: Evan Gray Date: Sat, 9 Dec 2023 19:17:53 -0500 Subject: [PATCH 07/12] node/cosmwasm: always CW >1 --- node/pkg/watchers/cosmwasm/watcher.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/node/pkg/watchers/cosmwasm/watcher.go b/node/pkg/watchers/cosmwasm/watcher.go index 4baac3baf3..ca21d5a3d6 100644 --- a/node/pkg/watchers/cosmwasm/watcher.go +++ b/node/pkg/watchers/cosmwasm/watcher.go @@ -112,22 +112,9 @@ func NewWatcher( // CosmWasm 1.0.0 contractAddressFilterKey := "execute._contract_address" contractAddressLogKey := "_contract_address" - if chainID == vaa.ChainIDTerra && env == common.UnsafeDevNet { - // Terra Classic upgraded CosmWasm versions, so they now use the new format. Here is a message from their Discord: - // The v2.1.1 upgrade will occur on blockheight 13215800 on June 14th (2023) at approximately 14:00 UTC. - // Queries for transactions before that block no longer work, so we don't have to worry about supporting them. - // It is going to take some work to upgrade our tilt environment, so for now, stick with the old format in dev. - contractAddressFilterKey = "execute_contract.contract_address" - contractAddressLogKey = "contract_address" - } // Do not add a leading slash - latestBlockURL := "blocks/latest" - - // Terra2 and Injective do things slightly differently than terra classic - if chainID == vaa.ChainIDInjective || chainID == vaa.ChainIDTerra2 || (chainID == vaa.ChainIDTerra && env != common.UnsafeDevNet) { - latestBlockURL = "cosmos/base/tendermint/v1beta1/blocks/latest" - } + latestBlockURL := "cosmos/base/tendermint/v1beta1/blocks/latest" // Injective does not base64 encode parameters (as of release v1.11.2). // Terra2 no longer base64 encodes parameters. From 826f05851155922c00c30a4347212cf4f8958b34 Mon Sep 17 00:00:00 2001 From: Evan Gray Date: Sat, 9 Dec 2023 19:19:11 -0500 Subject: [PATCH 08/12] tilt: re-introduce terra classic tests --- Tiltfile | 30 +--- devnet/node.yaml | 2 +- devnet/terra-devnet.yaml | 146 ------------------ devnet/terra2-devnet.yaml | 146 ------------------ docs/devnet.md | 6 +- scripts/devnet-consts.json | 16 +- sdk/devnet_consts.go | 2 +- .../src/nft_bridge/__tests__/utils/consts.ts | 3 - .../__tests__/terra-integration.ts | 134 +++++++--------- .../__tests__/terra2-integration.ts | 7 +- .../token_bridge/__tests__/utils/consts.ts | 6 - .../token_bridge/__tests__/utils/helpers.ts | 5 - .../token_bridge/getIsTransferCompleted.ts | 6 +- sdk/js/src/utils/consts.ts | 5 +- terra/artifacts/cw20_base.wasm | Bin 266211 -> 272632 bytes terra/tools/deploy.js | 79 ++++++---- terra/tools/deploy.sh | 2 +- 17 files changed, 121 insertions(+), 474 deletions(-) diff --git a/Tiltfile b/Tiltfile index 7491eadc0c..cdb7226f43 100644 --- a/Tiltfile +++ b/Tiltfile @@ -227,7 +227,7 @@ def build_node_yaml(): "--terraLCD", "http://terra-terrad:1317", "--terraContract", - "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5", + "terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au", ] if terra2: @@ -633,20 +633,6 @@ if terra_classic: trigger_mode = trigger_mode, ) - k8s_resource( - "terra-postgres", - labels = ["terra"], - trigger_mode = trigger_mode, - ) - - k8s_resource( - "terra-fcd", - resource_deps = ["terra-terrad", "terra-postgres"], - port_forwards = [port_forward(3060, name = "Terra FCD [:3060]", host = webHost)], - labels = ["terra"], - trigger_mode = trigger_mode, - ) - if terra2 or wormchain: docker_build( ref = "cosmwasm_artifacts", @@ -680,20 +666,6 @@ if terra2: trigger_mode = trigger_mode, ) - k8s_resource( - "terra2-postgres", - labels = ["terra2"], - trigger_mode = trigger_mode, - ) - - k8s_resource( - "terra2-fcd", - resource_deps = ["terra2-terrad", "terra2-postgres"], - port_forwards = [port_forward(3061, container_port = 3060, name = "Terra 2 FCD [:3061]", host = webHost)], - labels = ["terra2"], - trigger_mode = trigger_mode, - ) - if algorand: k8s_yaml_with_ns("devnet/algorand-devnet.yaml") diff --git a/devnet/node.yaml b/devnet/node.yaml index a5c0e72b25..58b9fa9183 100644 --- a/devnet/node.yaml +++ b/devnet/node.yaml @@ -123,7 +123,7 @@ spec: # - --terraLCD # - http://terra-terrad:1317 # - --terraContract - # - terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5 + # - terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au # - --terra2WS # - ws://terra2-terrad:26657/websocket # - --terra2LCD diff --git a/devnet/terra-devnet.yaml b/devnet/terra-devnet.yaml index 202b879dbc..68e1cc73d8 100644 --- a/devnet/terra-devnet.yaml +++ b/devnet/terra-devnet.yaml @@ -15,34 +15,6 @@ spec: selector: app: terra-terrad --- -apiVersion: v1 -kind: Service -metadata: - labels: - app: terra-postgres - name: terra-postgres -spec: - ports: - - name: postgres - port: 5432 - protocol: TCP - selector: - app: terra-postgres ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app: terra-fcd - name: terra-fcd -spec: - ports: - - name: fcd - port: 3060 - protocol: TCP - selector: - app: terra-fcd ---- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -88,121 +60,3 @@ spec: periodSeconds: 5 restartPolicy: Always serviceName: terra-terrad ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - labels: - app: terra-postgres - name: terra-postgres -spec: - replicas: 1 - selector: - matchLabels: - app: terra-postgres - template: - metadata: - labels: - app: terra-postgres - spec: - containers: - - image: postgres:12 - name: fcd-postgres - ports: - - containerPort: 5432 - resources: {} - env: - - name: POSTGRES_USER - value: dev - - name: POSTGRES_PASSWORD - value: dev - - name: POSTGRES_DB - value: fcd - restartPolicy: Always - serviceName: terra-postgres ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - labels: - app: terra-fcd - name: terra-fcd -spec: - replicas: 1 - selector: - matchLabels: - app: terra-fcd - template: - metadata: - labels: - app: terra-fcd - spec: - containers: - - image: terramoney/fcd:bombay - name: fcd-collector - command: - - sh - - -c - - "sed -i \"s/level: \\'info\\'/level: \\'warn\\'/g\" src/lib/logger.ts && ./entrypoint.sh collector" - resources: {} - env: - - name: CHAIN_ID - value: localterra - - name: LCD_URI - value: http://terra-terrad:1317 - - name: BYPASS_URI - value: http://terra-terrad:1317 - - name: RPC_URI - value: http://terra-terrad:26657 - - name: TYPEORM_CONNECTION - value: postgres - - name: TYPEORM_HOST - value: terra-postgres - - name: TYPEORM_USERNAME - value: dev - - name: TYPEORM_PASSWORD - value: dev - - name: TYPEORM_DATABASE - value: fcd - - name: TYPEORM_SYNCHRONIZE - value: "true" - - name: TYPEORM_LOGGING - value: "false" - - name: TYPEORM_ENTITIES - value: "src/orm/*Entity.ts" - - image: terramoney/fcd:bombay - name: fcd-api - command: - - sh - - -c - - "sed -i \"s/level: \\'info\\'/level: \\'warn\\'/g\" src/lib/logger.ts && ./entrypoint.sh start" - resources: {} - ports: - - containerPort: 3060 - env: - - name: CHAIN_ID - value: localterra - - name: LCD_URI - value: http://terra-terrad:1317 - - name: BYPASS_URI - value: http://terra-terrad:1317 - - name: RPC_URI - value: http://terra-terrad:26657 - - name: TYPEORM_CONNECTION - value: postgres - - name: TYPEORM_HOST - value: terra-postgres - - name: TYPEORM_USERNAME - value: dev - - name: TYPEORM_PASSWORD - value: dev - - name: TYPEORM_DATABASE - value: fcd - - name: TYPEORM_SYNCHRONIZE - value: "false" - - name: TYPEORM_LOGGING - value: "false" - - name: TYPEORM_ENTITIES - value: "src/orm/*Entity.ts" - restartPolicy: Always - serviceName: terra-fcd diff --git a/devnet/terra2-devnet.yaml b/devnet/terra2-devnet.yaml index 707fa0af4c..0957e565c9 100644 --- a/devnet/terra2-devnet.yaml +++ b/devnet/terra2-devnet.yaml @@ -15,34 +15,6 @@ spec: selector: app: terra2-terrad --- -apiVersion: v1 -kind: Service -metadata: - labels: - app: terra2-postgres - name: terra2-postgres -spec: - ports: - - name: postgres - port: 5432 - protocol: TCP - selector: - app: terra2-postgres ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app: terra2-fcd - name: terra2-fcd -spec: - ports: - - name: fcd - port: 3060 - protocol: TCP - selector: - app: terra2-fcd ---- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -88,121 +60,3 @@ spec: periodSeconds: 5 restartPolicy: Always serviceName: terra2-terrad ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - labels: - app: terra2-postgres - name: terra2-postgres -spec: - replicas: 1 - selector: - matchLabels: - app: terra2-postgres - template: - metadata: - labels: - app: terra2-postgres - spec: - containers: - - image: postgres:12 - name: fcd-postgres - ports: - - containerPort: 5432 - resources: {} - env: - - name: POSTGRES_USER - value: dev - - name: POSTGRES_PASSWORD - value: dev - - name: POSTGRES_DB - value: fcd - restartPolicy: Always - serviceName: terra2-fcd ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - labels: - app: terra2-fcd - name: terra2-fcd -spec: - replicas: 1 - selector: - matchLabels: - app: terra2-fcd - template: - metadata: - labels: - app: terra2-fcd - spec: - containers: - - image: terramoney/fcd:2.0.5 - name: fcd-collector - command: - - sh - - -c - - "sed -i \"s/level: \\'info\\'/level: \\'warn\\'/g\" src/lib/logger.ts && ./entrypoint.sh collector" - resources: {} - env: - - name: CHAIN_ID - value: localterra - - name: LCD_URI - value: http://terra2-terrad:1317 - - name: BYPASS_URI - value: http://terra2-terrad:1317 - - name: RPC_URI - value: http://terra2-terrad:26657 - - name: TYPEORM_CONNECTION - value: postgres - - name: TYPEORM_HOST - value: terra2-postgres - - name: TYPEORM_USERNAME - value: dev - - name: TYPEORM_PASSWORD - value: dev - - name: TYPEORM_DATABASE - value: fcd - - name: TYPEORM_SYNCHRONIZE - value: "true" - - name: TYPEORM_LOGGING - value: "false" - - name: TYPEORM_ENTITIES - value: "src/orm/*Entity.ts" - - image: terramoney/fcd:2.0.5 - name: fcd-api - command: - - sh - - -c - - "sed -i \"s/level: \\'info\\'/level: \\'warn\\'/g\" src/lib/logger.ts && ./entrypoint.sh start" - resources: {} - ports: - - containerPort: 3060 - env: - - name: CHAIN_ID - value: localterra - - name: LCD_URI - value: http://terra2-terrad:1317 - - name: BYPASS_URI - value: http://terra2-terrad:1317 - - name: RPC_URI - value: http://terra2-terrad:26657 - - name: TYPEORM_CONNECTION - value: postgres - - name: TYPEORM_HOST - value: terra2-postgres - - name: TYPEORM_USERNAME - value: dev - - name: TYPEORM_PASSWORD - value: dev - - name: TYPEORM_DATABASE - value: fcd - - name: TYPEORM_SYNCHRONIZE - value: "false" - - name: TYPEORM_LOGGING - value: "false" - - name: TYPEORM_ENTITIES - value: "src/orm/*Entity.ts" - restartPolicy: Always - serviceName: terra2-fcd diff --git a/docs/devnet.md b/docs/devnet.md index 6bfd2a9658..1f8a91d706 100644 --- a/docs/devnet.md +++ b/docs/devnet.md @@ -21,9 +21,9 @@ | NFT Bridge | SOL | NFTWqJR8YnRVqPDvTJrYuLrQDitTG5AScqbeghi4zSA | | | Migration Contract | SOL | Ex9bCdVMSfx7EzB3pgSi2R4UHwJAXvTw18rBQm5YQ8gK | | | Test Wallet | Terra | terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v | Mnemonic: `notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius` | -| Test CW20 | Terra | terra13nkgqrfymug724h8pprpexqj9h629sa3ncw7sh | Tokens minted to Test Wallet | -| Bridge Core | Terra | terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5 | | -| Token Bridge | Terra | terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4 | | +| Test CW20 | Terra | terra1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqynf7kp | Tokens minted to Test Wallet | +| Bridge Core | Terra | terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au | | +| Token Bridge | Terra | terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6 | | | Test Wallet | Terra2 | terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v | Mnemonic: `notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius` | | Test CW20 | Terra2 | terra1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqynf7kp | Tokens minted to Test Wallet | | Bridge Core | Terra2 | terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au | | diff --git a/scripts/devnet-consts.json b/scripts/devnet-consts.json index 7bfd392bc9..318c8130b9 100644 --- a/scripts/devnet-consts.json +++ b/scripts/devnet-consts.json @@ -103,10 +103,10 @@ "rpcUrlLocal": "http://localhost:1317", "rpcPort": "1317", "contracts": { - "coreEmitterAddress": "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5", - "coreNativeAddress": "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5", - "tokenBridgeEmitterAddress": "terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4", - "tokenBridgeNativeAddress": "terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4" + "coreEmitterAddress": "terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au", + "coreNativeAddress": "terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au", + "tokenBridgeEmitterAddress": "terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6", + "tokenBridgeNativeAddress": "terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6" }, "accounts": { "testWallet": { @@ -117,16 +117,10 @@ }, "addresses": { "testToken": { - "address": "terra13nkgqrfymug724h8pprpexqj9h629sa3ncw7sh", + "address": "terra1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqynf7kp", "name": "MOCK", "symbol": "MCK", "decimals": 6 - }, - "testNFT": { - "address": "terra18dt935pdcn2ka6l0syy5gt20wa48n3mktvdvjj", - "name": "MOCK", - "symbol": "MCK", - "decimals": 0 } } }, diff --git a/sdk/devnet_consts.go b/sdk/devnet_consts.go index c7b1431a16..6356b26778 100644 --- a/sdk/devnet_consts.go +++ b/sdk/devnet_consts.go @@ -12,7 +12,7 @@ var KnownDevnetTokenbridgeEmitters = buildEmitterMap(knownDevnetTokenbridgeEmitt var knownDevnetTokenbridgeEmitters = map[vaa.ChainID]string{ vaa.ChainIDSolana: "c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f", vaa.ChainIDEthereum: "0000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16", - vaa.ChainIDTerra: "000000000000000000000000784999135aaa8a3ca5914468852fdddbddd8789d", + vaa.ChainIDTerra: "9e28beafa966b2407bffb0d48651e94972a56e69f3c0897d9e8facbdaeb98386", vaa.ChainIDBSC: "0000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16", vaa.ChainIDAlgorand: "8ec299cb7f3efec28f542397e07f07118d74c875f85409ed8e6b93c17b60e992", vaa.ChainIDWormchain: "45dbea4617971d93188eda21530bc6503d153313b6f575048c2c35dbc6e4fb06", diff --git a/sdk/js/src/nft_bridge/__tests__/utils/consts.ts b/sdk/js/src/nft_bridge/__tests__/utils/consts.ts index 431ee71efa..6a42bc239d 100644 --- a/sdk/js/src/nft_bridge/__tests__/utils/consts.ts +++ b/sdk/js/src/nft_bridge/__tests__/utils/consts.ts @@ -29,9 +29,6 @@ export const TERRA_NODE_URL = ci ? "http://terra-terrad:1317" : "http://localhost:1317"; export const TERRA_CHAIN_ID = "localterra"; -export const TERRA_GAS_PRICES_URL = ci - ? "http://terra-fcd:3060/v1/txs/gas_prices" - : "http://localhost:3060/v1/txs/gas_prices"; export const TERRA_PRIVATE_KEY = "quality vacuum heart guard buzz spike sight swarm shove special gym robust assume sudden deposit grid alcohol choice devote leader tilt noodle tide penalty"; export const TEST_ERC721 = "0x5b9b42d6e4B2e4Bf8d42Eba32D46918e10899B66"; diff --git a/sdk/js/src/token_bridge/__tests__/terra-integration.ts b/sdk/js/src/token_bridge/__tests__/terra-integration.ts index f233572b6d..56e5a93862 100644 --- a/sdk/js/src/token_bridge/__tests__/terra-integration.ts +++ b/sdk/js/src/token_bridge/__tests__/terra-integration.ts @@ -2,9 +2,11 @@ import { parseUnits } from "@ethersproject/units"; import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport"; import { describe, expect, jest, test } from "@jest/globals"; import { + Fee, LCDClient, MnemonicKey, MsgExecuteContract, + Tx, } from "@terra-money/terra.js"; import { ethers } from "ethers"; import { @@ -39,7 +41,6 @@ import { ETH_NODE_URL, ETH_PRIVATE_KEY4, TERRA_CHAIN_ID, - TERRA_GAS_PRICES_URL, TERRA_NODE_URL, TERRA_PRIVATE_KEY, TERRA_PUBLIC_KEY, @@ -48,15 +49,33 @@ import { } from "./utils/consts"; import { getSignedVAABySequence, - getTerraGasPrices, queryBalanceOnTerra, waitForTerraExecution, } from "./utils/helpers"; jest.setTimeout(60000); -// Temporarily disable terra tests until LocalTerra can be upgraded to support v2.1.1 -describe.skip("Terra Integration Tests", () => { +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +// look, broadcast and broadcastBlock still resulted in sequence mismatches +// and nobody has time for that +async function broadcastAndWait(terra: LCDClient, tx: Tx) { + const response = await terra.tx.broadcast(tx); + if ((response as any)?.code !== 0) { + console.error(response); + throw new Error(`Transaction failed ${response?.txhash}`); + } + let currentHeight = (await terra.tendermint.blockInfo()).block.header.height; + while (parseInt(currentHeight) <= response.height) { + await sleep(100); + currentHeight = (await terra.tendermint.blockInfo()).block.header.height; + } + return response; +} + +describe("Terra Classic Integration Tests", () => { describe("Terra deposit and transfer tokens", () => { test("Tokens transferred can't exceed tokens deposited", (done) => { (async () => { @@ -64,13 +83,12 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); const mk = new MnemonicKey({ mnemonic: TERRA_PRIVATE_KEY, }); const wallet = lcd.wallet(mk); - const gasPrices = await getTerraGasPrices(); // deposit some tokens (separate transactions) for (let i = 0; i < 3; i++) { const deposit = new MsgExecuteContract( @@ -81,28 +99,12 @@ describe.skip("Terra Integration Tests", () => { }, { uusd: "900000087654321" } ); - const feeEstimate = await lcd.tx.estimateFee( - [ - { - sequenceNumber: await wallet.sequence(), - publicKey: wallet.key.publicKey, - }, - ], - { - msgs: [deposit], - memo: "localhost", - feeDenoms: ["uluna"], - gasPrices, - } - ); const tx = await wallet.createAndSignTx({ msgs: [deposit], memo: "localhost", - feeDenoms: ["uluna"], - gasPrices, - fee: feeEstimate, + fee: new Fee(200000, { uusd: 10_000_000 }), }); - await lcd.tx.broadcast(tx); + await broadcastAndWait(lcd, tx); } const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL); const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider); @@ -143,7 +145,6 @@ describe.skip("Terra Integration Tests", () => { msgs: [transfer], memo: "localhost", feeDenoms: ["uluna"], - gasPrices, } ); } catch (e) { @@ -176,17 +177,15 @@ describe.skip("Terra Integration Tests", () => { msgs: [withdraw], memo: "localhost", feeDenoms: ["uluna"], - gasPrices, } ); const tx = await wallet.createAndSignTx({ msgs: [withdraw], memo: "test", feeDenoms: ["uluna"], - gasPrices, fee: feeEstimate, }); - await lcd.tx.broadcast(tx); + await broadcastAndWait(lcd, tx); provider.destroy(); done(); } catch (e) { @@ -232,7 +231,7 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); const mk = new MnemonicKey({ mnemonic: TERRA_PRIVATE_KEY, @@ -243,7 +242,6 @@ describe.skip("Terra Integration Tests", () => { wallet.key.accAddress, signedVAA ); - const gasPrices = await getTerraGasPrices(); const feeEstimate = await lcd.tx.estimateFee( [ { @@ -254,18 +252,16 @@ describe.skip("Terra Integration Tests", () => { { msgs: [msg], feeDenoms: ["uluna"], - gasPrices, } ); const tx = await wallet.createAndSignTx({ msgs: [msg], memo: "test", feeDenoms: ["uluna"], - gasPrices, fee: feeEstimate, }); try { - await lcd.tx.broadcast(tx); + await broadcastAndWait(lcd, tx); } catch (e) { // this could fail because the token is already attested (in an unclean env) } @@ -283,7 +279,7 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); const address = getForeignAssetTerra( CONTRACTS.DEVNET.terra.token_bridge, @@ -310,7 +306,7 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); // Get initial wallet balances @@ -399,8 +395,7 @@ describe.skip("Terra Integration Tests", () => { await getIsTransferCompletedTerra( CONTRACTS.DEVNET.terra.token_bridge, signedVAA, - lcd, - TERRA_GAS_PRICES_URL + lcd ) ).toBe(false); const msg = await redeemOnTerra( @@ -408,7 +403,6 @@ describe.skip("Terra Integration Tests", () => { wallet.key.accAddress, signedVAA ); - const gasPrices = await getTerraGasPrices(); const feeEstimate = await lcd.tx.estimateFee( [ { @@ -420,23 +414,20 @@ describe.skip("Terra Integration Tests", () => { msgs: [msg], memo: "localhost", feeDenoms: ["uluna"], - gasPrices, } ); const tx = await wallet.createAndSignTx({ msgs: [msg], memo: "localhost", feeDenoms: ["uluna"], - gasPrices, fee: feeEstimate, }); - await lcd.tx.broadcast(tx); + await broadcastAndWait(lcd, tx); expect( await getIsTransferCompletedTerra( CONTRACTS.DEVNET.terra.token_bridge, signedVAA, - lcd, - TERRA_GAS_PRICES_URL + lcd ) ).toBe(true); @@ -476,7 +467,7 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); const mk = new MnemonicKey({ mnemonic: TERRA_PRIVATE_KEY, @@ -489,7 +480,6 @@ describe.skip("Terra Integration Tests", () => { TerraWalletAddress, Asset ); - const gasPrices = await getTerraGasPrices(); const feeEstimate = await lcd.tx.estimateFee( [ { @@ -501,17 +491,15 @@ describe.skip("Terra Integration Tests", () => { msgs: [msg], memo: "localhost", feeDenoms: ["uusd"], - gasPrices, } ); const executeTx = await wallet.createAndSignTx({ msgs: [msg], memo: "Testing...", feeDenoms: ["uusd"], - gasPrices, fee: feeEstimate, }); - const result = await lcd.tx.broadcast(executeTx); + const result = await broadcastAndWait(lcd, executeTx); const info = await waitForTerraExecution(result.txhash, lcd); if (!info) { throw new Error("info not found"); @@ -550,6 +538,7 @@ describe.skip("Terra Integration Tests", () => { ); success = true; } + provider.destroy(); } catch (e) { console.error("Attestation failure: ", e); } @@ -562,7 +551,7 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); const mk = new MnemonicKey({ mnemonic: TERRA_PRIVATE_KEY, @@ -623,7 +612,6 @@ describe.skip("Terra Integration Tests", () => { CHAIN_ID_ETH, hexToUint8Array(hexStr) // This needs to be ETH wallet ); - const gasPrices = await getTerraGasPrices(); const feeEstimate = await lcd.tx.estimateFee( [ { @@ -635,17 +623,15 @@ describe.skip("Terra Integration Tests", () => { msgs: msgs, memo: "localhost", feeDenoms: [FeeAsset], - gasPrices, } ); const executeTx = await wallet.createAndSignTx({ msgs: msgs, memo: "Testing transfer...", feeDenoms: [FeeAsset], - gasPrices, fee: feeEstimate, }); - const result = await lcd.tx.broadcast(executeTx); + const result = await broadcastAndWait(lcd, executeTx); const info = await waitForTerraExecution(result.txhash, lcd); if (!info) { throw new Error("info not found"); @@ -683,7 +669,8 @@ describe.skip("Terra Integration Tests", () => { // Get final balance of uusd on Terra // const finalFeeBalance: number = await queryBalanceOnTerra(FeeAsset); - expect(initialTerraBalance - 1e6 === finalTerraBalance).toBe(true); + // Not exactly equal because tax + expect(initialTerraBalance - 1e6 >= finalTerraBalance).toBe(true); const lunaBalOnEthAfter = await token.balanceOf( await signer.getAddress() ); @@ -691,6 +678,7 @@ describe.skip("Terra Integration Tests", () => { expect(initialLunaBalOnEthInt + 1e6 === lunaBalOnEthAfterInt).toBe( true ); + provider.destroy(); } catch (e) { console.error("Terra to Ethereum failure: ", e); done("Terra to Ethereum Failure"); @@ -706,7 +694,7 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); const mk = new MnemonicKey({ mnemonic: TERRA_PRIVATE_KEY, @@ -783,7 +771,6 @@ describe.skip("Terra Integration Tests", () => { wallet.key.accAddress, signedVAA ); - const gasPrices = await getTerraGasPrices(); const feeEstimate = await lcd.tx.estimateFee( [ { @@ -795,29 +782,29 @@ describe.skip("Terra Integration Tests", () => { msgs: [msg], memo: "localhost", feeDenoms: ["uusd"], - gasPrices, } ); const tx = await wallet.createAndSignTx({ msgs: [msg], memo: "localhost", feeDenoms: ["uusd"], - gasPrices, fee: feeEstimate, }); - await lcd.tx.broadcast(tx); + await broadcastAndWait(lcd, tx); expect( await getIsTransferCompletedTerra( CONTRACTS.DEVNET.terra.token_bridge, signedVAA, - lcd, - TERRA_GAS_PRICES_URL + lcd ) ).toBe(true); // Check wallet balances after const finalTerraBalance = await queryBalanceOnTerra(Asset); - expect(initialTerraBalance + 1e6 === finalTerraBalance).toBe(true); + // not exactly the transfer size increase due to tax + expect(initialTerraBalance + 1e6 * 0.9 <= finalTerraBalance).toBe( + true + ); const finalLunaBalOnEth = await token.balanceOf( await signer.getAddress() ); @@ -826,6 +813,7 @@ describe.skip("Terra Integration Tests", () => { true ); // const uusdBal = await queryBalanceOnTerra("uusd"); + provider.destroy(); } catch (e) { console.error("Transfer back failure: ", e); done("Transfer back Failure"); @@ -839,7 +827,8 @@ describe.skip("Terra Integration Tests", () => { test("Transfer CW20 token from Terra to Ethereum and back again", (done) => { (async () => { try { - const CW20: string = "terra13nkgqrfymug724h8pprpexqj9h629sa3ncw7sh"; + const CW20: string = + "terra1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqynf7kp"; const Asset: string = "uluna"; const FeeAsset: string = "uusd"; const Amount: string = "1000000"; @@ -852,7 +841,7 @@ describe.skip("Terra Integration Tests", () => { const lcd = new LCDClient({ URL: TERRA_NODE_URL, chainID: TERRA_CHAIN_ID, - isClassic: true, + isClassic: false, }); const mk = new MnemonicKey({ mnemonic: TERRA_PRIVATE_KEY, @@ -865,7 +854,6 @@ describe.skip("Terra Integration Tests", () => { TerraWalletAddress, CW20 ); - const gasPrices = await getTerraGasPrices(); let feeEstimate = await lcd.tx.estimateFee( [ { @@ -877,17 +865,15 @@ describe.skip("Terra Integration Tests", () => { msgs: [msg], memo: "localhost", feeDenoms: [FeeAsset], - gasPrices, } ); let executeTx = await wallet.createAndSignTx({ msgs: [msg], memo: "Testing...", feeDenoms: [FeeAsset], - gasPrices, fee: feeEstimate, }); - let result = await lcd.tx.broadcast(executeTx); + let result = await broadcastAndWait(lcd, executeTx); let info = await waitForTerraExecution(result.txhash, lcd); if (!info) { throw new Error("info not found"); @@ -994,17 +980,15 @@ describe.skip("Terra Integration Tests", () => { msgs: msgs, memo: "localhost", feeDenoms: [FeeAsset], - gasPrices, } ); executeTx = await wallet.createAndSignTx({ msgs: msgs, memo: "Testing transfer...", feeDenoms: [FeeAsset], - gasPrices, fee: feeEstimate, }); - result = await lcd.tx.broadcast(executeTx); + result = await broadcastAndWait(lcd, executeTx); info = await waitForTerraExecution(result.txhash, lcd); if (!info) { throw new Error("info not found"); @@ -1113,23 +1097,20 @@ describe.skip("Terra Integration Tests", () => { msgs: [msg], memo: "localhost", feeDenoms: ["uusd"], - gasPrices, } ); const tx = await wallet.createAndSignTx({ msgs: [msg], memo: "localhost", feeDenoms: ["uusd"], - gasPrices, fee: feeEstimate, }); - await lcd.tx.broadcast(tx); + await broadcastAndWait(lcd, tx); expect( await getIsTransferCompletedTerra( CONTRACTS.DEVNET.terra.token_bridge, signedVAA, - lcd, - TERRA_GAS_PRICES_URL + lcd ) ).toBe(true); @@ -1151,6 +1132,7 @@ describe.skip("Terra Integration Tests", () => { finalCW20BalOnTerra = parseInt(amount); expect(finalCW20BalOnTerra - initialCW20BalOnTerra === 1).toBe(true); // Done checking wallet balances + provider.destroy(); } catch (e) { console.error("CW20 Transfer failure: ", e); done("CW20 Transfer Failure"); diff --git a/sdk/js/src/token_bridge/__tests__/terra2-integration.ts b/sdk/js/src/token_bridge/__tests__/terra2-integration.ts index bcf8247085..4ff902bc15 100644 --- a/sdk/js/src/token_bridge/__tests__/terra2-integration.ts +++ b/sdk/js/src/token_bridge/__tests__/terra2-integration.ts @@ -36,7 +36,6 @@ import { TERRA2_NODE_URL, TERRA2_PRIVATE_KEY, TERRA_CHAIN_ID, - TERRA_GAS_PRICES_URL, TERRA_NODE_URL, TERRA_PRIVATE_KEY2, TEST_ERC20, @@ -225,8 +224,7 @@ describe("Terra Integration Tests", () => { ).toBe(true); }); - // Temporarily disable terra tests until LocalTerra can be upgraded to support v2.1.1 - test.skip("Attest and transfer Terra2 native token to Terra Classic", async () => { + test("Attest and transfer Terra2 native token to Terra Classic", async () => { const attestMsg = await attestFromTerra( CONTRACTS.DEVNET.terra2.token_bridge, terraWalletAddress, @@ -273,8 +271,7 @@ describe("Terra Integration Tests", () => { await getIsTransferCompletedTerra( CONTRACTS.DEVNET.terra.token_bridge, transferSignedVaa, - lcdClassic, - TERRA_GAS_PRICES_URL + lcdClassic ) ).toBe(true); }); diff --git a/sdk/js/src/token_bridge/__tests__/utils/consts.ts b/sdk/js/src/token_bridge/__tests__/utils/consts.ts index 4b1cf8b18d..fdddc59193 100644 --- a/sdk/js/src/token_bridge/__tests__/utils/consts.ts +++ b/sdk/js/src/token_bridge/__tests__/utils/consts.ts @@ -40,12 +40,6 @@ export const TERRA2_NODE_URL = ci ? "http://terra2-terrad:1317" : "http://localhost:1318"; export const TERRA_CHAIN_ID = "localterra"; -export const TERRA_GAS_PRICES_URL = ci - ? "http://terra-fcd:3060/v1/txs/gas_prices" - : "http://localhost:3060/v1/txs/gas_prices"; -export const TERRA2_GAS_PRICES_URL = ci - ? "http://terra2-fcd:3060/v1/txs/gas_prices" - : "http://localhost:3061/v1/txs/gas_prices"; // NOTE: test1 is used by getIsTransferCompletedTerra, so avoid using it in the integration tests // Accounts from https://github.com/terra-money/LocalTerra/blob/main/README.md#accounts export const TERRA_PUBLIC_KEY = "terra17tv2hvwpg0ukqgd2y5ct2w54fyan7z0zxrm2f9"; // test7 diff --git a/sdk/js/src/token_bridge/__tests__/utils/helpers.ts b/sdk/js/src/token_bridge/__tests__/utils/helpers.ts index 72f5ff052b..e73760bdea 100644 --- a/sdk/js/src/token_bridge/__tests__/utils/helpers.ts +++ b/sdk/js/src/token_bridge/__tests__/utils/helpers.ts @@ -6,7 +6,6 @@ import axios from "axios"; import { ChainId, getSignedVAAWithRetry } from "../../.."; import { TERRA_CHAIN_ID, - TERRA_GAS_PRICES_URL, TERRA_NODE_URL, TERRA_PRIVATE_KEY, WORMHOLE_RPC_HOSTS, @@ -95,10 +94,6 @@ export async function queryBalanceOnTerra(asset: string): Promise { return balance; } -export async function getTerraGasPrices() { - return axios.get(TERRA_GAS_PRICES_URL).then((result) => result.data); -} - // https://github.com/microsoft/TypeScript/issues/34523 export const assertIsNotNull: (x: T | null) => asserts x is T = (x) => { expect(x).not.toBeNull(); diff --git a/sdk/js/src/token_bridge/getIsTransferCompleted.ts b/sdk/js/src/token_bridge/getIsTransferCompleted.ts index 69ffad45ca..662acf507e 100644 --- a/sdk/js/src/token_bridge/getIsTransferCompleted.ts +++ b/sdk/js/src/token_bridge/getIsTransferCompleted.ts @@ -41,16 +41,13 @@ export async function getIsTransferCompletedEth( export async function getIsTransferCompletedTerra( tokenBridgeAddress: string, signedVAA: Uint8Array, - client: LCDClient, - gasPriceUrl: string + client: LCDClient ): Promise { const msg = await redeemOnTerra( tokenBridgeAddress, TERRA_REDEEMED_CHECK_WALLET_ADDRESS, signedVAA ); - // TODO: remove gasPriceUrl and just use the client's gas prices - const gasPrices = await axios.get(gasPriceUrl).then((result) => result.data); const account = await client.auth.accountInfo( TERRA_REDEEMED_CHECK_WALLET_ADDRESS ); @@ -66,7 +63,6 @@ export async function getIsTransferCompletedTerra( msgs: [msg], memo: "already redeemed calculation", feeDenoms: ["uluna"], - gasPrices, } ); } catch (e: any) { diff --git a/sdk/js/src/utils/consts.ts b/sdk/js/src/utils/consts.ts index fe6c5ac8d2..e29e732f35 100644 --- a/sdk/js/src/utils/consts.ts +++ b/sdk/js/src/utils/consts.ts @@ -556,8 +556,9 @@ const DEVNET = { nft_bridge: "NFTWqJR8YnRVqPDvTJrYuLrQDitTG5AScqbeghi4zSA", }, terra: { - core: "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5", - token_bridge: "terra10pyejy66429refv3g35g2t7am0was7ya7kz2a4", + core: "terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au", + token_bridge: + "terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6", nft_bridge: undefined, }, ethereum: { diff --git a/terra/artifacts/cw20_base.wasm b/terra/artifacts/cw20_base.wasm index a28e3f3a2da66843b09a2903c91a666e1b07e910..bb3eeaa0cf003fad908b4287949fb087d37f06f1 100644 GIT binary patch literal 272632 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

RFp;1PP6o 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 R$sKYR3O}hO;I@^g{|kjZop}HN diff --git a/terra/tools/deploy.js b/terra/tools/deploy.js index f0b850582f..0ef4e631cb 100644 --- a/terra/tools/deploy.js +++ b/terra/tools/deploy.js @@ -1,7 +1,7 @@ import "dotenv/config"; import { LCDClient, MnemonicKey } from "@terra-money/terra.js"; import { - StdFee, + Fee, MsgInstantiateContract, MsgExecuteContract, MsgStoreCode, @@ -128,7 +128,7 @@ const govChain = 1; const govAddress = "0000000000000000000000000000000000000000000000000000000000000004"; -async function instantiate(contract, inst_msg) { +async function instantiate(contract, inst_msg, label) { var address; await wallet .createAndSignTx({ @@ -137,14 +137,16 @@ async function instantiate(contract, inst_msg) { wallet.key.accAddress, wallet.key.accAddress, codeIds[contract], - inst_msg + inst_msg, + undefined, + label ), ], memo: "", }) .then((tx) => broadcastAndWait(terra, tx)) .then((rs) => { - address = /"contract_address","value":"([^"]+)/gm.exec(rs.raw_log)[1]; + address = /"_contract_address","value":"([^"]+)/gm.exec(rs.raw_log)[1]; }); console.log( `Instantiated ${contract} at ${address} (${convert_terra_address_to_hex( @@ -164,19 +166,23 @@ if (!init_guardians || init_guardians.length === 0) { throw "failed to get initial guardians from .env file."; } -addresses["wormhole.wasm"] = await instantiate("wormhole.wasm", { - gov_chain: govChain, - gov_address: Buffer.from(govAddress, "hex").toString("base64"), - guardian_set_expirity: 86400, - initial_guardian_set: { - addresses: init_guardians.map((hex) => { - return { - bytes: Buffer.from(hex, "hex").toString("base64"), - }; - }), - expiration_time: 0, +addresses["wormhole.wasm"] = await instantiate( + "wormhole.wasm", + { + gov_chain: govChain, + gov_address: Buffer.from(govAddress, "hex").toString("base64"), + guardian_set_expirity: 86400, + initial_guardian_set: { + addresses: init_guardians.map((hex) => { + return { + bytes: Buffer.from(hex, "hex").toString("base64"), + }; + }), + expiration_time: 0, + }, }, -}); + "wormhole" +); addresses["token_bridge_terra.wasm"] = await instantiate( "token_bridge_terra.wasm", @@ -185,25 +191,30 @@ addresses["token_bridge_terra.wasm"] = await instantiate( gov_address: Buffer.from(govAddress, "hex").toString("base64"), wormhole_contract: addresses["wormhole.wasm"], wrapped_asset_code_id: codeIds["cw20_wrapped.wasm"], - } + }, + "tokenBridge" ); -addresses["mock.wasm"] = await instantiate("cw20_base.wasm", { - name: "MOCK", - symbol: "MCK", - decimals: 6, - initial_balances: [ - { - address: wallet.key.accAddress, - amount: "100000000", - }, - { - address: "terra17tv2hvwpg0ukqgd2y5ct2w54fyan7z0zxrm2f9", - amount: "100000000", - }, - ], - mint: null, -}); +addresses["mock.wasm"] = await instantiate( + "cw20_base.wasm", + { + name: "MOCK", + symbol: "MCK", + decimals: 6, + initial_balances: [ + { + address: wallet.key.accAddress, + amount: "100000000", + }, + { + address: "terra17tv2hvwpg0ukqgd2y5ct2w54fyan7z0zxrm2f9", + amount: "100000000", + }, + ], + mint: null, + }, + "mock" +); /* Registrations: tell the bridge contracts to know about each other */ @@ -248,7 +259,7 @@ for (const [contract, registrations] of Object.entries( ), ], memo: "", - fee: new StdFee(2000000, { + fee: new Fee(2000000, { uluna: "100000", }), }) diff --git a/terra/tools/deploy.sh b/terra/tools/deploy.sh index d96fe78209..a258836806 100644 --- a/terra/tools/deploy.sh +++ b/terra/tools/deploy.sh @@ -8,6 +8,6 @@ while [ $(curl localhost:26657/status -ks | jq ".result.sync_info.latest_block_h sleep 1 done -sleep 2 +sleep 5 node deploy.js From c6b7792e8f1b47b862aa957022f4d5774aeeb02c Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Sun, 10 Dec 2023 18:02:08 +0000 Subject: [PATCH 09/12] terra: make get_address support both 20 and 32 byte addresses --- terra/contracts/wormhole/src/byte_utils.rs | 22 ++++++++++++---- terra/contracts/wormhole/src/testing/tests.rs | 25 +++++++++++++++---- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/terra/contracts/wormhole/src/byte_utils.rs b/terra/contracts/wormhole/src/byte_utils.rs index d25df72a34..aa25c8fd23 100644 --- a/terra/contracts/wormhole/src/byte_utils.rs +++ b/terra/contracts/wormhole/src/byte_utils.rs @@ -42,12 +42,24 @@ impl ByteUtils for &[u8] { fn get_u256(&self, index: usize) -> (u128, u128) { (self.get_u128_be(index), self.get_u128_be(index + 128 / 8)) } - fn get_address(&self, index: usize) -> CanonicalAddr { - // 32 bytes are reserved for addresses, but only the last 20 bytes are taken by the actual address - if self.get_u128_be(index) >> 32 != 0 { - panic!("invalid Terra address"); + fn get_address(&self, mut index: usize) -> CanonicalAddr { + // Legacy terra addresses are 20 bytes, but new addresses (after the cosmwasm 1.0 upgrade) + // are 32 bytes. In the Wormhole wire format, addresses are always encoded as 32 bytes, + // so in order to determine which type of address we're dealing with, we check the first + // 12 bytes of the address. If they are all 0, then we have a legacy address, otherwise + // we have a new address. + + // grab the first 16 bytes (u128) then shift right 4 bytes (32 bits) to get the first 12 bytes. + // If the number is 0, then we have a legacy address. + let legacy_address: bool = self.get_u128_be(index) >> 32 == 0; + + if legacy_address { + // legacy addresses are 20 bytes long, so we skip the first 12 bytes + index += 12; + CanonicalAddr::from(&self[index..index + 20]) + } else { + CanonicalAddr::from(&self[index..index + 32]) } - CanonicalAddr::from(&self[index + 32 - 20..index + 32]) } fn get_bytes32(&self, index: usize) -> &[u8] { &self[index..index + 32] diff --git a/terra/contracts/wormhole/src/testing/tests.rs b/terra/contracts/wormhole/src/testing/tests.rs index bfa6d2c7ba..407efe8834 100644 --- a/terra/contracts/wormhole/src/testing/tests.rs +++ b/terra/contracts/wormhole/src/testing/tests.rs @@ -184,11 +184,26 @@ fn get_address_test() -> StdResult<()> { } #[test] -#[should_panic] -fn get_address_test_panic() { - // panics because of junk in first 12 bytes - let ones_32: &[u8] = &[1; 32]; - ones_32.get_address(0); +fn get_address_test_legacy() { + // we construct a byte array with 12 leading zeros, and 20 ones + let mut ones_20: [u8; 32] = [0; 32]; + ones_20[12..32].copy_from_slice(&[1; 20]); + let addr = ones_20.as_slice().get_address(0); + + // we expect the 12 leading zeros to be stripped as this is recognised as a + // legacy address + assert_eq!(addr.as_slice(), [1; 20]); +} + +#[test] +fn get_address_test_new() { + // we construct a byte array with 32 ones + let ones_32: [u8; 32] = [1; 32]; + let addr = ones_32.as_slice().get_address(0); + + // we expect the 32 ones to be preserved as this is recognised as a new + // address + assert_eq!(addr.as_slice(), [1; 32]); } #[test] From 4af697147b9618785283b3826f6e9580ef3d4bc0 Mon Sep 17 00:00:00 2001 From: cs Date: Sun, 10 Dec 2023 19:15:22 +0000 Subject: [PATCH 10/12] terra: fix tests to account for burn tax Since the tests are now ran against the new LocalTerra which has burn tax, the transaction results are different from before --- terra/test/src/__tests__/bridge.ts | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/terra/test/src/__tests__/bridge.ts b/terra/test/src/__tests__/bridge.ts index f2722f975c..44100e9588 100644 --- a/terra/test/src/__tests__/bridge.ts +++ b/terra/test/src/__tests__/bridge.ts @@ -339,7 +339,7 @@ describe("Bridge Tests", () => { denom ); const gasPaid = computeGasPaid(receipt); - const walletExpectedChange = new Int(relayerFee).sub(gasPaid); + const walletExpectedChange = new Int("882906"); // due to rounding, we should expect the balances to reconcile // within 1 unit (equivalent to 1e-6 uusd). Best-case scenario @@ -347,6 +347,7 @@ describe("Bridge Tests", () => { const reconciled = walletBalanceAfter .minus(walletExpectedChange) .minus(walletBalanceBefore); + console.info("reconciled", reconciled.toString()); expect( reconciled.greaterThanOrEqualTo("0") && reconciled.lessThanOrEqualTo("1") @@ -357,20 +358,26 @@ describe("Bridge Tests", () => { recipient, denom ); - const recipientExpectedChange = new Int(amount).sub(relayerFee); + // the expected change is slightly less than the amount - the relayer fee, due to tax + const recipientExpectedChange = new Int("98901098"); expect( recipientBalanceBefore .add(recipientExpectedChange) .eq(recipientBalanceAfter) ).toBeTruthy(); - // cehck bridge balance change - const bridgeExpectedChange = new Int(amount); + // check bridge balance change + // the expected change is slightly less than the amount, due to + // a small rounding error in the tax calculation + const bridgeExpectedChange = new Int("99999998"); const bridgeBalanceAfter = await getNativeBalance( client, tokenBridge, denom ); + console.info("bridgeBalanceAfter", bridgeBalanceAfter.toString()); + console.info("bridgeExpectedChange", bridgeExpectedChange.toString()); + console.info("bridgeBalanceBefore", bridgeBalanceBefore.toString()); expect( bridgeBalanceBefore.sub(bridgeExpectedChange).eq(bridgeBalanceAfter) ).toBeTruthy(); @@ -542,15 +549,17 @@ describe("Bridge Tests", () => { mockBridgeIntegration, denom ); - const contractExpectedChange = new Int(amount); + // tax applied, so we expect less than the original amount + const contractBlanceAfterExpected = new Int("99900099"); expect( - contractBalanceBefore - .add(contractExpectedChange) - .eq(contractBalanceAfter) + contractBalanceAfter + .eq(contractBlanceAfterExpected) ).toBeTruthy(); - // cehck bridge balance change - const bridgeExpectedChange = new Int(amount); + // check bridge balance change + // the expected change is slightly less than the amount, due to + // a small rounding error in the tax calculation + const bridgeExpectedChange = new Int("99999999"); const bridgeBalanceAfter = await getNativeBalance( client, tokenBridge, From 608a4ed934c1373e1c52f4e5a9362cae366dbc20 Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Sun, 10 Dec 2023 19:39:33 +0000 Subject: [PATCH 11/12] terra/token-bridge: check first 12 bytes to determine native denoms --- terra/contracts/token-bridge/src/contract.rs | 38 ++++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/terra/contracts/token-bridge/src/contract.rs b/terra/contracts/token-bridge/src/contract.rs index 327dbba0eb..919bf7fad0 100644 --- a/terra/contracts/token-bridge/src/contract.rs +++ b/terra/contracts/token-bridge/src/contract.rs @@ -681,10 +681,9 @@ fn handle_complete_transfer( relayer_address: &HumanAddr, ) -> StdResult { let transfer_info = TransferInfo::deserialize(data)?; - let marker_byte = transfer_info.token_address.as_slice()[0]; if transfer_info.token_chain == CHAIN_ID { - match marker_byte { - 1 => handle_complete_transfer_token_native( + if is_native_id(transfer_info.token_address.as_slice()) { + handle_complete_transfer_token_native( deps, env, info, @@ -693,8 +692,9 @@ fn handle_complete_transfer( transfer_type, data, relayer_address, - ), - 0 => handle_complete_transfer_token( + ) + } else { + handle_complete_transfer_token( deps, env, info, @@ -703,8 +703,7 @@ fn handle_complete_transfer( transfer_type, data, relayer_address, - ), - b => Err(StdError::generic_err(format!("Unknown marker byte: {b}"))), + ) } } else { handle_complete_transfer_token( @@ -1204,6 +1203,15 @@ fn handle_initiate_transfer_token( } }; + // Ensure that the asset's address does not collide with the native + // address format. This is impossible for legacy CW20 addresses as they are + // 20 bytes long left padded with 0s, so their first byte can't be 1. + // However, it's theoretically possible for a new 32 byte CW20 address to have + // this format. The probability of this happening is 1 / 2^96 ≈ 1.2 * 10^-29, + // so it is negligible. Regardless, we block such addresses here + // for the sake of completeness and documentation. + assert!(!is_native_id(&asset_address)); + Ok(Response::new() .add_messages(messages) .add_submessages(submessages) @@ -1272,9 +1280,19 @@ fn handle_initiate_transfer_native_token( send_native(deps.storage, &asset_address, amount)?; // Mark the first byte of the address to distinguish it as native. + // NOTE: Since the asset's address 20 bytes long, it will get left padded + // with 12 bytes of zeros, meaning that after the marker byte adjustment, + // the address is [1] ++ [0; 11], i.e. a single 1 byte followed by eleven 0 + // bytes. We maintain the global invariant that only native bank denoms + // have the first 12 bytes in this format. Since there is a theoretical + // probability that a 32 byte CW20 address could collide with this format, + // we block such addresses on the way out. let mut asset_address = extend_address_to_32_array(&asset_address); asset_address[0] = 1; + // sanity check, this will always pass + assert!(is_native_id(&asset_address)); + let token_bridge_message: TokenBridgeMessage = match transfer_type { TransferType::WithoutPayload => { let transfer_info = TransferInfo { @@ -1423,6 +1441,12 @@ pub fn build_native_id(denom: &str) -> Vec { asset_address } +/// Check that the first byte of the address is 1 and the remaining 11 bytes are 0. +/// For more information, see the comment in [`handle_initiate_transfer_native_token`]. +fn is_native_id(address: &[u8]) -> bool { + address[0] == 1 && address[1..12].iter().all(|&x| x == 0) +} + fn is_governance_emitter(cfg: &ConfigInfo, emitter_chain: u16, emitter_address: &[u8]) -> bool { cfg.gov_chain == emitter_chain && cfg.gov_address == emitter_address } From 7b321ca895333100a63388a40a46227b28aa0a4a Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Sun, 10 Dec 2023 19:45:09 +0000 Subject: [PATCH 12/12] terra/token-bridge: simplify conditional --- terra/contracts/token-bridge/src/contract.rs | 36 +++++++------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/terra/contracts/token-bridge/src/contract.rs b/terra/contracts/token-bridge/src/contract.rs index 919bf7fad0..5dbe11abdd 100644 --- a/terra/contracts/token-bridge/src/contract.rs +++ b/terra/contracts/token-bridge/src/contract.rs @@ -681,30 +681,18 @@ fn handle_complete_transfer( relayer_address: &HumanAddr, ) -> StdResult { let transfer_info = TransferInfo::deserialize(data)?; - if transfer_info.token_chain == CHAIN_ID { - if is_native_id(transfer_info.token_address.as_slice()) { - handle_complete_transfer_token_native( - deps, - env, - info, - emitter_chain, - emitter_address, - transfer_type, - data, - relayer_address, - ) - } else { - handle_complete_transfer_token( - deps, - env, - info, - emitter_chain, - emitter_address, - transfer_type, - data, - relayer_address, - ) - } + if transfer_info.token_chain == CHAIN_ID && is_native_id(transfer_info.token_address.as_slice()) + { + handle_complete_transfer_token_native( + deps, + env, + info, + emitter_chain, + emitter_address, + transfer_type, + data, + relayer_address, + ) } else { handle_complete_transfer_token( deps,

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Ć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 literal 266211 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