diff --git a/terra/Cargo.lock b/terra/Cargo.lock index 0e7d6f6db..71c364d3c 100644 --- a/terra/Cargo.lock +++ b/terra/Cargo.lock @@ -8,7 +8,7 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03345e98af8f3d786b6d9f656ccfa6ac316d954e92bc4841f0bba20789d5fb5a" dependencies = [ - "gimli 0.24.0", + "gimli", ] [[package]] @@ -17,18 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "autocfg" version = "1.0.1" @@ -43,18 +31,18 @@ checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.24.0", "rustc-demangle", ] [[package]] name = "base64" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bigint" @@ -63,16 +51,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def" dependencies = [ "byteorder", - "crunchy", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", + "crunchy 0.1.6", ] [[package]] @@ -81,32 +60,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -[[package]] -name = "bitvec" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98fcd36dda4e17b7d7abc64cb549bf0201f4ab71e00700c798ca7e62ed3761fa" -dependencies = [ - "funty", - "radium", - "wyz", -] - -[[package]] -name = "blake3" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if 0.1.10", - "constant_time_eq", - "crypto-mac 0.8.0", - "digest 0.9.0", -] - [[package]] name = "block-buffer" version = "0.9.0" @@ -114,7 +67,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "block-padding", - "generic-array 0.14.4", + "generic-array", ] [[package]] @@ -135,12 +88,6 @@ version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -148,38 +95,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "clru" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "591ff76ca0691bd91c1b0b5b987e5cf93b21ec810ad96665c5a569c60846dd93" + +[[package]] +name = "const-oid" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdab415d6744056100f40250a66bc430c1a46f7a02e20bc11c94c79a0f0464df" + +[[package]] +name = "cosmwasm-crypto" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec9bdd1f4da5fc0d085251b0322661c5aaf773ab299e3e205fb18130b7f6ba3" dependencies = [ - "bitflags", + "digest", + "ed25519-zebra", + "k256", + "rand_core 0.5.1", + "thiserror", ] [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "cosmwasm-derive" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "5ac17a14b4ab09a5d89b5301218067acca33d9311376e5c34c9877f09e562395" +dependencies = [ + "syn", +] [[package]] name = "cosmwasm-std" -version = "0.10.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f85908a2696117c8f2c1b3ce201d34a1aa9a6b3c1583a65cfb794ec66e1cfde4" +checksum = "e47306c113f4d964c35a74a87ceb8ccfb5811e9810a9dc427101148b5b9134ca" dependencies = [ "base64", + "cosmwasm-crypto", + "cosmwasm-derive", "schemars", "serde", "serde-json-wasm", - "snafu", + "thiserror", + "uint", ] [[package]] name = "cosmwasm-storage" -version = "0.10.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e103531a2ce636e86b7639cec25d348c4d360832ab8e0e7f9a6e00f08aac1379" +checksum = "2e3472d8e0e7155c5f4d89674ad47adede4b1491ad14f4141610e1522028a6a7" dependencies = [ "cosmwasm-std", "serde", @@ -187,22 +156,23 @@ dependencies = [ [[package]] name = "cosmwasm-vm" -version = "0.10.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12d56a7ad7bbbf04b94a782f25fe50a9372067737f661931acf9d30668003efd" +checksum = "8d90f1d30e2d01d815c520dad2738f93188f2e64b3dda3e11609c13eb73109b8" dependencies = [ + "clru", + "cosmwasm-crypto", "cosmwasm-std", "hex", - "memmap", + "loupe", "parity-wasm", "schemars", "serde", "serde_json", "sha2", - "snafu", - "wasmer-clif-backend", - "wasmer-middleware-common", - "wasmer-runtime-core", + "thiserror", + "wasmer", + "wasmer-middlewares", ] [[package]] @@ -216,36 +186,35 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.59.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a9c21f8042b9857bda93f6c1910b9f9f24100187a3d3d52f214a34e3dc5818" +checksum = "c8ca3560686e7c9c7ed7e0fe77469f2410ba5d7781b1acaa9adc8d8deea28e3e" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.59.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7853f77a6e4a33c67a69c40f5e1bb982bd2dc5c4a22e17e67b65bbccf9b33b2e" +checksum = "baf9bf1ffffb6ce3d2e5ebc83549bd2436426c99b31cc550d521364cbe35d276" dependencies = [ - "byteorder", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-entity", - "gimli 0.20.0", + "gimli", "log", + "regalloc", "smallvec", "target-lexicon", - "thiserror", ] [[package]] name = "cranelift-codegen-meta" -version = "0.59.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084cd6d5fb0d1da28acd72c199471bfb09acc703ec8f3bf07b1699584272a3b9" +checksum = "4cc21936a5a6d07e23849ffe83e5c1f6f50305c074f4b2970ca50c13bf55b821" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -253,34 +222,44 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.59.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "701b599783305a58c25027a4d73f2d6b599b2d8ef3f26677275f480b4d51e05d" +checksum = "ca5b6ffaa87560bebe69a5446449da18090b126037920b0c1c6d5945f72faf6b" [[package]] name = "cranelift-entity" -version = "0.59.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88e792b28e1ebbc0187b72ba5ba880dad083abe9231a99d19604d10c9e73f38" +checksum = "7d6b4a8bef04f82e4296782646f733c641d09497df2fabf791323fefaa44c64c" [[package]] -name = "cranelift-native" -version = "0.59.0" +name = "cranelift-frontend" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32daf082da21c0c05d93394ff4842c2ab7c4991b1f3186a1d952f8ac660edd0b" +checksum = "c31b783b351f966fce33e3c03498cb116d16d97a8f9978164a60920bd0d3a99c" dependencies = [ "cranelift-codegen", - "raw-cpuid", + "log", + "smallvec", "target-lexicon", ] +[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] @@ -290,7 +269,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] @@ -301,7 +280,7 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", "lazy_static", "memoffset", @@ -315,7 +294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278" dependencies = [ "autocfg", - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] @@ -326,30 +305,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" [[package]] -name = "crypto-mac" -version = "0.8.0" +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d12477e115c0d570c12a2dfd859f80b55b60ddb5075df210d3af06d133a69f45" dependencies = [ - "generic-array 0.14.4", + "generic-array", + "rand_core 0.6.3", "subtle", + "zeroize", ] [[package]] name = "crypto-mac" -version = "0.9.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.4", + "generic-array", "subtle", ] [[package]] -name = "cw0" -version = "0.2.3" +name = "curve25519-dalek" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b469bb5d63a036339cbb3042fb1254016b5d4889b15f420fea1c1339497b19de" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cw-storage-plus" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e867b9972b83b32e00e878dfbff48299ba26618dabeb19b9c56fae176dc225" dependencies = [ "cosmwasm-std", "schemars", @@ -357,22 +357,34 @@ dependencies = [ ] [[package]] -name = "cw2" -version = "0.2.3" +name = "cw0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a5dd960277ae9180e0077fcc8769928da2d9c1c42cc8c8c734c625c6f2a90b" +checksum = "c497f885a40918a02df7d938c81809965fa05cfc21b3dc591e9950237b5de0a9" dependencies = [ "cosmwasm-std", - "cosmwasm-storage", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d48454f96494aa1018556cd457977375cc8c57ef3e5c767cfa2ea5ec24b0258" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus", "schemars", "serde", ] [[package]] name = "cw20" -version = "0.2.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffd85ddcac2bf5c1899dd13e52985d260dae02db21a618d9d4c2c36dab63a915" +checksum = "a11a2adbd52258f5b4ed5323f62bc6e559f2cefbe52ef0e58290016fde5bb083" dependencies = [ "cosmwasm-std", "cw0", @@ -382,18 +394,36 @@ dependencies = [ [[package]] name = "cw20-base" -version = "0.2.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09657718df5243810b10d49359a352eed197966f578366624198fe1740fb52" +checksum = "fe3791e0f6b4a0a82b86541d48dcc67c2d607da8e5691a91b40b2c06ddf09c52" dependencies = [ "cosmwasm-std", - "cosmwasm-storage", + "cw-storage-plus", "cw0", "cw2", "cw20", "schemars", "serde", - "snafu", + "thiserror", +] + +[[package]] +name = "cw20-legacy" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d27b11827323369993519abb494f3ae9b6aac4d716d058bea5e181b9b0074b7" +dependencies = [ + "cosmwasm-std", + "cosmwasm-storage", + "cw-storage-plus", + "cw0", + "cw2", + "cw20", + "cw20-base", + "schemars", + "serde", + "thiserror", ] [[package]] @@ -403,20 +433,57 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "cosmwasm-vm", + "cw-storage-plus", + "cw2", "cw20", - "cw20-base", + "cw20-legacy", "schemars", "serde", "thiserror", ] [[package]] -name = "digest" -version = "0.8.1" +name = "darling" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12" dependencies = [ - "generic-array 0.12.4", + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2adca118c71ecd9ae094d4b68257b3fdfcb711a612b9eec7b5a0d27a5a70a5b4" +dependencies = [ + "const-oid", ] [[package]] @@ -425,26 +492,67 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.4", + "generic-array", ] [[package]] -name = "doc-comment" -version = "0.3.3" +name = "dyn-clone" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" + +[[package]] +name = "dynasm" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc2d9a5e44da60059bd38db2d05cbb478619541b8c79890547861ec1e3194f0" +dependencies = [ + "bitflags", + "byteorder", + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dynasmrt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42276e3f205fe63887cca255aa9a65a63fb72764c30b9a6252a7c7e46994f689" +dependencies = [ + "byteorder", + "dynasm", + "memmap2", +] [[package]] name = "ecdsa" -version = "0.8.5" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87bf8bfb05ea8a6f74ddf48c7d1774851ba77bbe51ac984fdfa6c30310e1ff5f" +checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" dependencies = [ + "der", "elliptic-curve", "hmac", "signature", ] +[[package]] +name = "ed25519-zebra" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a128b76af6dd4b427e34a6fd43dc78dbfe73672ec41ff615a2414c1a0ad0409" +dependencies = [ + "curve25519-dalek", + "hex", + "rand_core 0.5.1", + "serde", + "sha2", + "thiserror", +] + [[package]] name = "either" version = "1.6.1" @@ -453,72 +561,62 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "elliptic-curve" -version = "0.6.6" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396db09c483e7fca5d4fdb9112685632b3e76c9a607a2649c1bf904404a01366" +checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b" dependencies = [ - "bitvec", - "digest 0.9.0", + "crypto-bigint", "ff", - "generic-array 0.14.4", + "generic-array", "group", - "rand_core", + "pkcs8", + "rand_core 0.6.3", "subtle", "zeroize", ] [[package]] -name = "errno" -version = "0.2.7" +name = "enumset" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe" +checksum = "7e76129da36102af021b8e5000dab2c1c30dbef85c1e482beeff8da5dde0e0b0" dependencies = [ - "errno-dragonfly", - "libc", - "winapi", + "enumset_derive", ] [[package]] -name = "errno-dragonfly" -version = "0.1.1" +name = "enumset_derive" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" +checksum = "6451128aa6655d880755345d085494cf7561a6bee7c8dc821e5d77e6d267ecd4" dependencies = [ - "gcc", - "libc", + "darling", + "proc-macro2", + "quote", + "syn", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "ff" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01646e077d4ebda82b73f1bca002ea1e91561a77df2431a9e79729bcc31950ef" +checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" dependencies = [ - "bitvec", - "rand_core", + "rand_core 0.6.3", "subtle", ] [[package]] -name = "funty" -version = "1.1.0" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "generic-array" @@ -531,13 +629,25 @@ dependencies = [ ] [[package]] -name = "gimli" -version = "0.20.0" +name = "getrandom" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dd6190aad0f05ddbbf3245c54ed14ca4aa6dd32f22312b70d8f168c3e3e633" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "byteorder", - "indexmap", + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -545,15 +655,20 @@ name = "gimli" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] [[package]] name = "group" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc11f9f5fbf1943b48ae7c2bf6846e7d827a512d1be4f23af708f5ca5d01dde1" +checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.3", "subtle", ] @@ -580,14 +695,20 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.9.1", - "digest 0.9.0", + "crypto-mac", + "digest", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "1.6.2" @@ -607,13 +728,14 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "k256" -version = "0.5.10" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3934640b1efbc660af5889d041854b6985d403771dc4d5fee984e13e8f82f313" +checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", + "sha2", ] [[package]] @@ -628,6 +750,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "leb128" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" + [[package]] name = "libc" version = "0.2.95" @@ -635,12 +763,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" [[package]] -name = "lock_api" -version = "0.3.4" +name = "libloading" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" dependencies = [ - "scopeguard", + "cfg-if", + "winapi", ] [[package]] @@ -649,17 +778,52 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] -name = "memmap" -version = "0.7.0" +name = "loupe" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" +dependencies = [ + "indexmap", + "loupe-derive", + "rustversion", +] + +[[package]] +name = "loupe-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memmap2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4" dependencies = [ "libc", - "winapi", ] [[package]] @@ -682,17 +846,10 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.15.0" +name = "more-asserts" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" -dependencies = [ - "bitflags", - "cc", - "cfg-if 0.1.10", - "libc", - "void", -] +checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" [[package]] name = "num_cpus" @@ -710,50 +867,73 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" +[[package]] +name = "object" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +dependencies = [ + "crc32fast", + "indexmap", + "memchr", +] + [[package]] name = "opaque-debug" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "page_size" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "parity-wasm" -version = "0.41.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" +checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" [[package]] -name = "parking_lot" -version = "0.10.2" +name = "pin-project-lite" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" + +[[package]] +name = "pkcs8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" dependencies = [ - "lock_api", - "parking_lot_core", + "der", + "spki", ] [[package]] -name = "parking_lot_core" -version = "0.7.2" +name = "ppv-lite86" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall", - "smallvec", - "winapi", + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", ] [[package]] @@ -765,6 +945,26 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "quote" version = "1.0.9" @@ -775,26 +975,52 @@ dependencies = [ ] [[package]] -name = "radium" -version = "0.3.0" +name = "rand" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.3", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] [[package]] -name = "raw-cpuid" -version = "7.0.4" +name = "rand_core" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb71f708fe39b2c5e98076204c3cc094ee5a4c12c4cdb119a2b72dc34164f41" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "bitflags", - "cc", - "rustc_version", + "getrandom 0.2.3", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core 0.6.3", ] [[package]] @@ -824,9 +1050,67 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.57" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regalloc" +version = "0.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" +dependencies = [ + "log", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "region" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" +dependencies = [ + "bitflags", + "libc", + "mach", + "winapi", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rkyv" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb135b3e5e3311f0a254bfb00333f4bac9ef1d89888b84242a89eb8722b09a07" +dependencies = [ + "memoffset", + "ptr_meta", + "rkyv_derive", + "seahash", +] + +[[package]] +name = "rkyv_derive" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8f489f6b6d8551bb15904293c1ad58a6abafa7d8390d15f7ed05a2afcd87d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "rustc-demangle" @@ -835,13 +1119,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce" [[package]] -name = "rustc_version" -version = "0.2.3" +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustversion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" [[package]] name = "ryu" @@ -851,10 +1138,11 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "schemars" -version = "0.7.6" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be77ed66abed6954aabf6a3e31a84706bedbf93750d267e92ef4a6d90bbd6a61" +checksum = "d7a48d098c2a7fdf5740b19deb1181b4fb8a9e68e03ae517c14cde04b5725409" dependencies = [ + "dyn-clone", "schemars_derive", "serde", "serde_json", @@ -862,9 +1150,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.7.6" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11af7a475c9ee266cfaa9e303a47c830ebe072bf3101ab907a7b7b9d816fa01d" +checksum = "4a9ea2a613fe4cd7118b2bb101a25d8ae6192e1975179b67b2f17afd11e70ac8" dependencies = [ "proc-macro2", "quote", @@ -879,19 +1167,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "semver" -version = "0.9.0" +name = "seahash" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "serde" @@ -902,21 +1181,11 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-bench" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" -dependencies = [ - "byteorder", - "serde", -] - [[package]] name = "serde-json-wasm" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120bad73306616e91acd7ceed522ba96032a51cffeef3cc813de7f367df71e37" +checksum = "50eef3672ec8fa45f3457fd423ba131117786784a895548021976117c1ded449" dependencies = [ "serde", ] @@ -970,9 +1239,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" dependencies = [ "block-buffer", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.9.0", + "digest", "opaque-debug", ] @@ -983,19 +1252,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ "block-buffer", - "digest 0.9.0", + "digest", "keccak", "opaque-debug", ] [[package]] name = "signature" -version = "1.2.2" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" +checksum = "c19772be3c4dd2ceaacf03cb41d5885f2a02c4d8804884918e3a258480803335" dependencies = [ - "digest 0.9.0", - "rand_core", + "digest", + "rand_core 0.6.3", ] [[package]] @@ -1005,26 +1274,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] -name = "snafu" -version = "0.6.10" +name = "spki" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" +checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" dependencies = [ - "backtrace", - "doc-comment", - "snafu-derive", + "der", ] [[package]] -name = "snafu-derive" -version = "0.6.10" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" @@ -1045,15 +1319,29 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.10.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" +checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff" + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] [[package]] name = "terra-cosmwasm" -version = "1.2.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d7275aacd385e4f41647634c35692b1982085917b4dcfc1fdfa3984ee4ce45d" +checksum = "552f18cba2b535d1f8c0e3b3f37696820b954bc7535d2e33909f2a6342302718" dependencies = [ "cosmwasm-std", "schemars", @@ -1062,9 +1350,9 @@ dependencies = [ [[package]] name = "terraswap" -version = "1.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02334ec5ad280fcc09c86467d40383ea1e4d977103345e53a4f03006c4be51c2" +checksum = "96f2c2a6371e9ddf2c942368e64645cc3e8fc2855da70c8c6bed238dcdd5522f" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -1105,7 +1393,7 @@ dependencies = [ "cw20", "cw20-base", "cw20-wrapped", - "generic-array 0.14.4", + "generic-array", "hex", "k256", "lazy_static", @@ -1118,12 +1406,56 @@ dependencies = [ "wormhole", ] +[[package]] +name = "tracing" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98863d0dd09fa59a1b79c6750ad80dbda6b75f4e71c437a6a1a8cb91a8bcbd77" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46125608c26121c81b0c6d693eab5a420e416da7e43c426d2e8f7df8da8a3acf" +dependencies = [ + "lazy_static", +] + [[package]] name = "typenum" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +[[package]] +name = "uint" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" +dependencies = [ + "byteorder", + "crunchy 0.2.2", + "hex", + "static_assertions", +] + [[package]] name = "unicode-xid" version = "0.2.2" @@ -1137,118 +1469,247 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] -name = "void" -version = "1.0.2" +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] -name = "wasmer-clif-backend" -version = "0.17.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691ea323652d540a10722066dbf049936f4367bb22a96f8992a262a942a8b11b" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasmer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f52e455a01d0fac439cd7a96ba9b519bdc84e923a5b96034054697ebb17cd75" +dependencies = [ + "cfg-if", + "indexmap", + "loupe", + "more-asserts", + "target-lexicon", + "thiserror", + "wasmer-compiler", + "wasmer-compiler-cranelift", + "wasmer-compiler-singlepass", + "wasmer-derive", + "wasmer-engine", + "wasmer-engine-dylib", + "wasmer-engine-universal", + "wasmer-types", + "wasmer-vm", + "winapi", +] + +[[package]] +name = "wasmer-compiler" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc86dda6f715f03104800be575a38382b35c3962953af9e9d8722dcf0bd2458f" +dependencies = [ + "enumset", + "loupe", + "rkyv", + "serde", + "serde_bytes", + "smallvec", + "target-lexicon", + "thiserror", + "wasmer-types", + "wasmer-vm", + "wasmparser", +] + +[[package]] +name = "wasmer-compiler-cranelift" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a570746cbec434179e2d53357973a34dfdb208043104e8fac3b7b0023015cf6" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "gimli", + "loupe", + "more-asserts", + "rayon", + "smallvec", + "tracing", + "wasmer-compiler", + "wasmer-types", + "wasmer-vm", +] + +[[package]] +name = "wasmer-compiler-singlepass" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9429b9f7708c582d855b1787f09c7029ff23fb692550d4a1cc351c8ea84c3014" dependencies = [ "byteorder", - "cranelift-codegen", - "cranelift-entity", - "cranelift-native", - "libc", - "nix", - "rayon", - "serde", - "serde-bench", - "serde_bytes", - "serde_derive", - "target-lexicon", - "wasmer-clif-fork-frontend", - "wasmer-clif-fork-wasm", - "wasmer-runtime-core", - "wasmer-win-exception-handler", - "wasmparser", - "winapi", -] - -[[package]] -name = "wasmer-clif-fork-frontend" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c23f2824f354a00a77e4b040eef6e1d4c595a8a3e9013bad65199cc8dade9a5a" -dependencies = [ - "cranelift-codegen", - "log", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "wasmer-clif-fork-wasm" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35e21d3aebc51cc6ebc0e830cf8458a9891c3482fb3c65ad18d408102929ae5" -dependencies = [ - "cranelift-codegen", - "cranelift-entity", - "log", - "thiserror", - "wasmer-clif-fork-frontend", - "wasmparser", -] - -[[package]] -name = "wasmer-middleware-common" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd94068186b25fbe5213442648ffe0fa65ee77389bed020404486fd22056cc87" -dependencies = [ - "wasmer-runtime-core", -] - -[[package]] -name = "wasmer-runtime-core" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45d4253f097502423d8b19d54cb18745f61b984b9dbce32424cba7945cfef367" -dependencies = [ - "bincode", - "blake3", - "cc", - "digest 0.8.1", - "errno", - "hex", - "indexmap", + "dynasm", + "dynasmrt", "lazy_static", - "libc", - "nix", - "page_size", - "parking_lot", - "rustc_version", - "serde", - "serde-bench", - "serde_bytes", - "serde_derive", + "loupe", + "more-asserts", + "rayon", "smallvec", + "wasmer-compiler", + "wasmer-types", + "wasmer-vm", +] + +[[package]] +name = "wasmer-derive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee7b351bcc1e782997c72dc0b5b328f3ddcad4813b8ce3cac3f25ae5a4ab56b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "wasmer-engine" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8454ead320a4017ba36ddd9ab4fbf7776fceea6ab0b79b5e53664a1682569fc3" +dependencies = [ + "backtrace", + "lazy_static", + "loupe", + "memmap2", + "more-asserts", + "rustc-demangle", + "serde", + "serde_bytes", "target-lexicon", - "wasmparser", + "thiserror", + "wasmer-compiler", + "wasmer-types", + "wasmer-vm", +] + +[[package]] +name = "wasmer-engine-dylib" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa390d123ebe23d5315c39f6063fcc18319661d03c8000f23d0fe1c011e8135" +dependencies = [ + "cfg-if", + "leb128", + "libloading", + "loupe", + "rkyv", + "serde", + "tempfile", + "tracing", + "wasmer-compiler", + "wasmer-engine", + "wasmer-object", + "wasmer-types", + "wasmer-vm", + "which", +] + +[[package]] +name = "wasmer-engine-universal" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dffe8015f08915eb4939ebc8e521cde8246f272f5197ea60d46214ac5aef285" +dependencies = [ + "cfg-if", + "leb128", + "loupe", + "region", + "rkyv", + "wasmer-compiler", + "wasmer-engine", + "wasmer-types", + "wasmer-vm", "winapi", ] [[package]] -name = "wasmer-win-exception-handler" -version = "0.17.0" +name = "wasmer-middlewares" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf22ce6dc66d893099aac853d451bf9443fa8f5443f5bf4fc63f3aebd7b592b1" +checksum = "95d2b4722d64c850893f7a7eab3ab76181efbafcd366827801d8bcd64bff525f" dependencies = [ + "loupe", + "wasmer", + "wasmer-types", + "wasmer-vm", +] + +[[package]] +name = "wasmer-object" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c541c985799fc1444702501c15d41becfb066c92d9673defc1c7417fd8739e15" +dependencies = [ + "object 0.25.3", + "thiserror", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-types" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91f75d3c31f8b1f8d818ff49624fc974220243cbc07a2252f408192e97c6b51" +dependencies = [ + "indexmap", + "loupe", + "rkyv", + "serde", + "thiserror", +] + +[[package]] +name = "wasmer-vm" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469a12346a4831e7dac639b9646d8c9b24c7d2cf0cf458b77f489edb35060c1f" +dependencies = [ + "backtrace", "cc", + "cfg-if", + "indexmap", "libc", - "wasmer-runtime-core", + "loupe", + "memoffset", + "more-asserts", + "region", + "rkyv", + "serde", + "thiserror", + "wasmer-types", "winapi", ] [[package]] name = "wasmparser" -version = "0.51.4" +version = "0.78.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb1956b19469d1c5e63e459d29e7b5aa0f558d9f16fcef09736f8a265e6c10a" +checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65" + +[[package]] +name = "which" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" +dependencies = [ + "either", + "lazy_static", + "libc", +] [[package]] name = "winapi" @@ -1282,7 +1743,8 @@ dependencies = [ "cw20", "cw20-base", "cw20-wrapped", - "generic-array 0.14.4", + "generic-array", + "getrandom 0.2.3", "hex", "k256", "lazy_static", @@ -1293,12 +1755,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - [[package]] name = "zeroize" version = "1.3.0" diff --git a/terra/Cargo.toml b/terra/Cargo.toml index 924e0591e..97a55debf 100644 --- a/terra/Cargo.toml +++ b/terra/Cargo.toml @@ -10,4 +10,4 @@ debug-assertions = false codegen-units = 1 panic = 'abort' incremental = false -overflow-checks = true \ No newline at end of file +overflow-checks = true diff --git a/terra/Dockerfile b/terra/Dockerfile index ab42d0fc6..7a2d47040 100644 --- a/terra/Dockerfile +++ b/terra/Dockerfile @@ -1,6 +1,6 @@ # This is a multi-stage docker file, first stage builds contracts # And the second one creates node.js environment to deploy them -FROM cosmwasm/workspace-optimizer:0.10.4@sha256:a976db4ee7add887a6af26724b804bbd9e9d534554506447e72ac57e65357db9 AS builder +FROM cosmwasm/workspace-optimizer:0.12.1@sha256:1508cf7545f4b656ecafa34e29c1acf200cdab47fced85c2bc076c0c158b1338 AS builder ADD Cargo.lock /code/ ADD Cargo.toml /code/ ADD contracts /code/contracts diff --git a/terra/artifacts/cw20_base.wasm b/terra/artifacts/cw20_base.wasm index ed4cd3fdc..a28e3f3a2 100644 Binary files a/terra/artifacts/cw20_base.wasm and b/terra/artifacts/cw20_base.wasm differ diff --git a/terra/contracts-5/README.md b/terra/contracts-5/README.md deleted file mode 100644 index 27ec9c8e1..000000000 --- a/terra/contracts-5/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Terra Wormhole Contracts - -The Wormhole Terra integration is developed and maintained by Everstake / @ysavchenko. diff --git a/terra/contracts-5/cw20-wrapped/.cargo/config b/terra/contracts-5/cw20-wrapped/.cargo/config deleted file mode 100644 index 2d5cce4ea..000000000 --- a/terra/contracts-5/cw20-wrapped/.cargo/config +++ /dev/null @@ -1,5 +0,0 @@ -[alias] -wasm = "build --release --target wasm32-unknown-unknown" -wasm-debug = "build --target wasm32-unknown-unknown" -unit-test = "test --lib --features backtraces" -integration-test = "test --test integration" \ No newline at end of file diff --git a/terra/contracts-5/cw20-wrapped/Cargo.toml b/terra/contracts-5/cw20-wrapped/Cargo.toml deleted file mode 100644 index f35f2042c..000000000 --- a/terra/contracts-5/cw20-wrapped/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "cw20-wrapped" -version = "0.1.0" -authors = ["Yuriy Savchenko "] -edition = "2018" -description = "Wrapped CW20 token contract" - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all init/handle/query exports -library = [] - -[dependencies] -cosmwasm-std = { version = "0.16.0" } -cosmwasm-storage = { version = "0.16.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"]} -cw-storage-plus = { version = "0.8.0" } -thiserror = { version = "1.0.20" } - -[dev-dependencies] -cosmwasm-vm = { version = "0.16.0", default-features = false } diff --git a/terra/contracts-5/cw20-wrapped/src/contract.rs b/terra/contracts-5/cw20-wrapped/src/contract.rs deleted file mode 100644 index 528af9554..000000000 --- a/terra/contracts-5/cw20-wrapped/src/contract.rs +++ /dev/null @@ -1,374 +0,0 @@ -use cosmwasm_std::{ - entry_point, - to_binary, - Binary, - CosmosMsg, - Deps, - DepsMut, - Env, - MessageInfo, - Response, - StdError, - StdResult, - Uint128, - WasmMsg, -}; - -use cw2::set_contract_version; -use cw20_legacy::{ - allowances::{ - execute_burn_from, - execute_decrease_allowance, - execute_increase_allowance, - execute_send_from, - execute_transfer_from, - query_allowance, - }, - contract::{ - execute_mint, - execute_send, - execute_transfer, - query_balance, - }, - state::{ - MinterData, - TokenInfo, - TOKEN_INFO, - }, - ContractError, -}; - -use crate::{ - msg::{ - ExecuteMsg, - InstantiateMsg, - QueryMsg, - WrappedAssetInfoResponse, - }, - state::{ - wrapped_asset_info, - wrapped_asset_info_read, - WrappedAssetInfo, - }, -}; -use cw20::TokenInfoResponse; -use std::string::String; - -type HumanAddr = String; - -// version info for migration info -const CONTRACT_NAME: &str = "crates.io:cw20-base"; -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: InstantiateMsg, -) -> StdResult { - set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - - // store token info using cw20-base format - let data = TokenInfo { - name: msg.name, - symbol: msg.symbol, - decimals: msg.decimals, - total_supply: Uint128::new(0), - // set creator as minter - mint: Some(MinterData { - minter: deps.api.addr_canonicalize(&info.sender.as_str())?, - cap: None, - }), - }; - TOKEN_INFO.save(deps.storage, &data)?; - - // save wrapped asset info - let data = WrappedAssetInfo { - asset_chain: msg.asset_chain, - asset_address: msg.asset_address, - bridge: deps.api.addr_canonicalize(&info.sender.as_str())?, - }; - wrapped_asset_info(deps.storage).save(&data)?; - - if let Some(mint_info) = msg.mint { - execute_mint(deps, env, info, mint_info.recipient, mint_info.amount) - .map_err(|e| StdError::generic_err(format!("{}", e)))?; - } - - if let Some(hook) = msg.init_hook { - Ok( - Response::new().add_message(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: hook.contract_addr, - msg: hook.msg, - funds: vec![], - })), - ) - } else { - Ok(Response::default()) - } -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: ExecuteMsg, -) -> Result { - match msg { - // these all come from cw20-base to implement the cw20 standard - ExecuteMsg::Transfer { recipient, amount } => { - Ok(execute_transfer(deps, env, info, recipient, amount)?) - } - ExecuteMsg::Burn { account, amount } => { - Ok(execute_burn_from(deps, env, info, account, amount)?) - } - ExecuteMsg::Send { - contract, - amount, - msg, - } => Ok(execute_send(deps, env, info, contract, amount, msg)?), - ExecuteMsg::Mint { recipient, amount } => { - execute_mint_wrapped(deps, env, info, recipient, amount) - } - ExecuteMsg::IncreaseAllowance { - spender, - amount, - expires, - } => Ok(execute_increase_allowance( - deps, env, info, spender, amount, expires, - )?), - ExecuteMsg::DecreaseAllowance { - spender, - amount, - expires, - } => Ok(execute_decrease_allowance( - deps, env, info, spender, amount, expires, - )?), - ExecuteMsg::TransferFrom { - owner, - recipient, - amount, - } => Ok(execute_transfer_from( - deps, env, info, owner, recipient, amount, - )?), - ExecuteMsg::BurnFrom { owner, amount } => { - Ok(execute_burn_from(deps, env, info, owner, amount)?) - } - ExecuteMsg::SendFrom { - owner, - contract, - amount, - msg, - } => Ok(execute_send_from( - deps, env, info, owner, contract, amount, msg, - )?), - } -} - -fn execute_mint_wrapped( - deps: DepsMut, - env: Env, - info: MessageInfo, - recipient: HumanAddr, - amount: Uint128, -) -> Result { - // Only bridge can mint - let wrapped_info = wrapped_asset_info_read(deps.storage).load()?; - if wrapped_info.bridge != deps.api.addr_canonicalize(&info.sender.as_str())? { - return Err(ContractError::Unauthorized {}); - } - - Ok(execute_mint(deps, env, info, recipient, amount)?) -} - -pub fn query(deps: Deps, msg: QueryMsg) -> StdResult { - match msg { - QueryMsg::WrappedAssetInfo {} => to_binary(&query_wrapped_asset_info(deps)?), - // inherited from cw20-base - QueryMsg::TokenInfo {} => to_binary(&query_token_info(deps)?), - QueryMsg::Balance { address } => to_binary(&query_balance(deps, address)?), - QueryMsg::Allowance { owner, spender } => { - to_binary(&query_allowance(deps, owner, spender)?) - } - } -} - -pub fn query_token_info(deps: Deps) -> StdResult { - let info = TOKEN_INFO.load(deps.storage)?; - Ok(TokenInfoResponse { - name: String::from("Wormhole:") + info.name.as_str(), - symbol: String::from("wh") + info.symbol.as_str(), - decimals: info.decimals, - total_supply: info.total_supply, - }) -} - -pub fn query_wrapped_asset_info(deps: Deps) -> StdResult { - let info = wrapped_asset_info_read(deps.storage).load()?; - Ok(WrappedAssetInfoResponse { - asset_chain: info.asset_chain, - asset_address: info.asset_address, - bridge: deps.api.addr_humanize(&info.bridge)?, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use cosmwasm_std::testing::{ - mock_dependencies, - mock_env, - mock_info, - }; - use cw20::TokenInfoResponse; - - const CANONICAL_LENGTH: usize = 20; - - fn get_balance(deps: Deps, address: HumanAddr) -> Uint128 { - query_balance(deps, address.into()).unwrap().balance - } - - fn do_init(mut deps: DepsMut, creator: &HumanAddr) { - let init_msg = InstantiateMsg { - name: "Integers".to_string(), - symbol: "INT".to_string(), - asset_chain: 1, - asset_address: vec![1; 32].into(), - decimals: 10, - mint: None, - init_hook: None, - }; - let env = mock_env(); - let info = mock_info(creator, &[]); - let res = instantiate(deps, env, info, init_msg).unwrap(); - assert_eq!(0, res.messages.len()); - - assert_eq!( - query_token_info(deps.as_ref()).unwrap(), - TokenInfoResponse { - name: "Wormhole Wrapped".to_string(), - symbol: "WWT".to_string(), - decimals: 10, - total_supply: Uint128::from(0u128), - } - ); - - assert_eq!( - query_wrapped_asset_info(deps.as_ref()).unwrap(), - WrappedAssetInfoResponse { - asset_chain: 1, - asset_address: vec![1; 32].into(), - bridge: deps.api.addr_validate(creator).unwrap(), - } - ); - } - - fn do_init_and_mint( - mut deps: DepsMut, - creator: &HumanAddr, - mint_to: &HumanAddr, - amount: Uint128, - ) { - do_init(deps, creator); - - let msg = ExecuteMsg::Mint { - recipient: mint_to.clone(), - amount, - }; - - let env = mock_env(); - let info = mock_info(creator, &[]); - let res = execute(deps.as_mut(), env, info, msg.clone()).unwrap(); - assert_eq!(0, res.messages.len()); - assert_eq!(get_balance(deps.as_ref(), mint_to.clone(),), amount); - - assert_eq!( - query_token_info(deps.as_ref()).unwrap(), - TokenInfoResponse { - name: "Wormhole Wrapped".to_string(), - symbol: "WWT".to_string(), - decimals: 10, - total_supply: amount, - } - ); - } - - #[test] - fn can_mint_by_minter() { - let mut deps = mock_dependencies(&[]); - let minter = HumanAddr::from("minter"); - let recipient = HumanAddr::from("recipient"); - let amount = Uint128::new(222_222_222); - do_init_and_mint(deps.as_mut(), &minter, &recipient, amount); - } - - #[test] - fn others_cannot_mint() { - let mut deps = mock_dependencies(&[]); - let minter = HumanAddr::from("minter"); - let recipient = HumanAddr::from("recipient"); - do_init(deps.as_mut(), &minter); - - let amount = Uint128::new(222_222_222); - let msg = ExecuteMsg::Mint { - recipient: recipient.clone(), - amount, - }; - - let other_address = HumanAddr::from("other"); - let env = mock_env(); - let info = mock_info(&other_address, &[]); - let res = execute(deps.as_mut(), env, info, msg); - assert_eq!( - format!("{}", res.unwrap_err()), - format!("{}", crate::error::ContractError::Unauthorized {}) - ); - } - - #[test] - fn transfer_balance_success() { - let mut deps = mock_dependencies(&[]); - let minter = HumanAddr::from("minter"); - let owner = HumanAddr::from("owner"); - let amount_initial = Uint128::new(222_222_222); - do_init_and_mint(deps.as_mut(), &minter, &owner, amount_initial); - - // Transfer - let recipient = HumanAddr::from("recipient"); - let amount_transfer = Uint128::new(222_222); - let msg = ExecuteMsg::Transfer { - recipient: recipient.clone(), - amount: amount_transfer, - }; - - let env = mock_env(); - let info = mock_info(&owner, &[]); - let res = execute(deps.as_mut(), env, info, msg.clone()).unwrap(); - assert_eq!(0, res.messages.len()); - assert_eq!(get_balance(deps.as_ref(), owner), Uint128::new(222_000_000)); - assert_eq!(get_balance(deps.as_ref(), recipient), amount_transfer); - } - - #[test] - fn transfer_balance_not_enough() { - let mut deps = mock_dependencies(&[]); - let minter = HumanAddr::from("minter"); - let owner = HumanAddr::from("owner"); - let amount_initial = Uint128::new(222_221); - do_init_and_mint(deps.as_mut(), &minter, &owner, amount_initial); - - // Transfer - let recipient = HumanAddr::from("recipient"); - let amount_transfer = Uint128::new(222_222); - let msg = ExecuteMsg::Transfer { - recipient: recipient.clone(), - amount: amount_transfer, - }; - - let env = mock_env(); - let info = mock_info(&owner, &[]); - let _ = execute(deps.as_mut(), env, info, msg.clone()).unwrap_err(); // Will panic if no error - } -} diff --git a/terra/contracts-5/cw20-wrapped/src/error.rs b/terra/contracts-5/cw20-wrapped/src/error.rs deleted file mode 100644 index 95eba93cb..000000000 --- a/terra/contracts-5/cw20-wrapped/src/error.rs +++ /dev/null @@ -1,27 +0,0 @@ -use cosmwasm_std::StdError; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum ContractError { - // CW20 errors - #[error("{0}")] - Std(#[from] StdError), - - #[error("Unauthorized")] - Unauthorized {}, - - #[error("Cannot set to own account")] - CannotSetOwnAccount {}, - - #[error("Invalid zero amount")] - InvalidZeroAmount {}, - - #[error("Allowance is expired")] - Expired {}, - - #[error("No allowance for this account")] - NoAllowance {}, - - #[error("Minting cannot exceed the cap")] - CannotExceedCap {}, -} diff --git a/terra/contracts-5/cw20-wrapped/src/lib.rs b/terra/contracts-5/cw20-wrapped/src/lib.rs deleted file mode 100644 index 6e2ebd886..000000000 --- a/terra/contracts-5/cw20-wrapped/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod error; - -pub mod contract; -pub mod msg; -pub mod state; - -pub use crate::error::ContractError; diff --git a/terra/contracts-5/cw20-wrapped/src/msg.rs b/terra/contracts-5/cw20-wrapped/src/msg.rs deleted file mode 100644 index 25ca6377b..000000000 --- a/terra/contracts-5/cw20-wrapped/src/msg.rs +++ /dev/null @@ -1,122 +0,0 @@ -#![allow(clippy::field_reassign_with_default)] -use schemars::JsonSchema; -use serde::{ - Deserialize, - Serialize, -}; - -use cosmwasm_std::{ - Addr, - Binary, - Uint128, -}; -use cw20::Expiration; - -type HumanAddr = String; - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InstantiateMsg { - pub name: String, - pub symbol: String, - pub asset_chain: u16, - pub asset_address: Binary, - pub decimals: u8, - pub mint: Option, - pub init_hook: Option, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InitHook { - pub msg: Binary, - pub contract_addr: HumanAddr, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InitMint { - pub recipient: HumanAddr, - pub amount: Uint128, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ExecuteMsg { - /// Implements CW20. Transfer is a base message to move tokens to another account without triggering actions - Transfer { - recipient: HumanAddr, - amount: Uint128, - }, - /// Slightly different than CW20. Burn is a base message to destroy tokens forever - Burn { account: HumanAddr, amount: Uint128 }, - /// Implements CW20. Send is a base message to transfer tokens to a contract and trigger an action - /// on the receiving contract. - Send { - contract: HumanAddr, - amount: Uint128, - msg: Binary, - }, - /// Implements CW20 "mintable" extension. If authorized, creates amount new tokens - /// and adds to the recipient balance. - Mint { - recipient: HumanAddr, - amount: Uint128, - }, - /// Implements CW20 "approval" extension. Allows spender to access an additional amount tokens - /// from the owner's (env.sender) account. If expires is Some(), overwrites current allowance - /// expiration with this one. - IncreaseAllowance { - spender: HumanAddr, - amount: Uint128, - expires: Option, - }, - /// Implements CW20 "approval" extension. Lowers the spender's access of tokens - /// from the owner's (env.sender) account by amount. If expires is Some(), overwrites current - /// allowance expiration with this one. - DecreaseAllowance { - spender: HumanAddr, - amount: Uint128, - expires: Option, - }, - /// Implements CW20 "approval" extension. Transfers amount tokens from owner -> recipient - /// if `env.sender` has sufficient pre-approval. - TransferFrom { - owner: HumanAddr, - recipient: HumanAddr, - amount: Uint128, - }, - /// Implements CW20 "approval" extension. Sends amount tokens from owner -> contract - /// if `env.sender` has sufficient pre-approval. - SendFrom { - owner: HumanAddr, - contract: HumanAddr, - amount: Uint128, - msg: Binary, - }, - /// Implements CW20 "approval" extension. Destroys tokens forever - BurnFrom { owner: HumanAddr, amount: Uint128 }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - // Generic information about the wrapped asset - WrappedAssetInfo {}, - /// Implements CW20. Returns the current balance of the given address, 0 if unset. - Balance { - address: HumanAddr, - }, - /// Implements CW20. Returns metadata on the contract - name, decimals, supply, etc. - TokenInfo {}, - /// Implements CW20 "allowance" extension. - /// Returns how much spender can use from owner account, 0 if unset. - Allowance { - owner: HumanAddr, - spender: HumanAddr, - }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct WrappedAssetInfoResponse { - pub asset_chain: u16, // Asset chain id - pub asset_address: Binary, // Asset smart contract address in the original chain - pub bridge: Addr, // Bridge address, authorized to mint and burn wrapped tokens -} diff --git a/terra/contracts-5/cw20-wrapped/src/state.rs b/terra/contracts-5/cw20-wrapped/src/state.rs deleted file mode 100644 index 2d9ba10ff..000000000 --- a/terra/contracts-5/cw20-wrapped/src/state.rs +++ /dev/null @@ -1,37 +0,0 @@ -use schemars::JsonSchema; -use serde::{ - Deserialize, - Serialize, -}; - -use cosmwasm_std::{ - Binary, - CanonicalAddr, - Storage, -}; -use cosmwasm_storage::{ - singleton, - singleton_read, - ReadonlySingleton, - Singleton, -}; - -pub const KEY_WRAPPED_ASSET: &[u8] = b"wrappedAsset"; - -// Created at initialization and reference original asset and bridge address -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct WrappedAssetInfo { - pub asset_chain: u16, // Asset chain id - pub asset_address: Binary, // Asset smart contract address on the original chain - pub bridge: CanonicalAddr, // Bridge address, authorized to mint and burn wrapped tokens -} - -pub fn wrapped_asset_info(storage: &mut dyn Storage) -> Singleton { - singleton(storage, KEY_WRAPPED_ASSET) -} - -pub fn wrapped_asset_info_read( - storage: &dyn Storage, -) -> ReadonlySingleton { - singleton_read(storage, KEY_WRAPPED_ASSET) -} diff --git a/terra/contracts-5/cw20-wrapped/tests/integration.rs b/terra/contracts-5/cw20-wrapped/tests/integration.rs deleted file mode 100644 index 141cbea50..000000000 --- a/terra/contracts-5/cw20-wrapped/tests/integration.rs +++ /dev/null @@ -1,253 +0,0 @@ -static WASM: &[u8] = - include_bytes!("../../../target/wasm32-unknown-unknown/release/cw20_wrapped.wasm"); - -use cosmwasm_std::{ - from_slice, - Binary, - Env, - HandleResponse, - HandleResult, - HumanAddr, - InitResponse, - Uint128, -}; -use cosmwasm_storage::to_length_prefixed; -use cosmwasm_vm::{ - testing::{ - handle, - init, - mock_env, - mock_instance, - query, - MockApi, - MockQuerier, - MockStorage, - }, - Api, - Instance, - Storage, -}; -use cw20_wrapped::{ - msg::{ - HandleMsg, - InitMsg, - QueryMsg, - }, - state::{ - WrappedAssetInfo, - KEY_WRAPPED_ASSET, - }, - ContractError, -}; - -enum TestAddress { - INITIALIZER, - RECIPIENT, - SENDER, -} - -impl TestAddress { - fn value(&self) -> HumanAddr { - match self { - TestAddress::INITIALIZER => HumanAddr::from("addr0000"), - TestAddress::RECIPIENT => HumanAddr::from("addr2222"), - TestAddress::SENDER => HumanAddr::from("addr3333"), - } - } -} - -fn mock_env_height(signer: &HumanAddr, height: u64, time: u64) -> Env { - let mut env = mock_env(signer, &[]); - env.block.height = height; - env.block.time = time; - env -} - -fn get_wrapped_asset_info(storage: &S) -> WrappedAssetInfo { - let key = to_length_prefixed(KEY_WRAPPED_ASSET); - let data = storage - .get(&key) - .0 - .expect("error getting data") - .expect("data should exist"); - from_slice(&data).expect("invalid data") -} - -fn do_init(height: u64) -> Instance { - let mut deps = mock_instance(WASM, &[]); - let init_msg = InitMsg { - asset_chain: 1, - asset_address: vec![1; 32].into(), - decimals: 10, - mint: None, - init_hook: None, - }; - let env = mock_env_height(&TestAddress::INITIALIZER.value(), height, 0); - let res: InitResponse = init(&mut deps, env, init_msg).unwrap(); - assert_eq!(0, res.messages.len()); - - // query the store directly - let api = deps.api; - deps.with_storage(|storage| { - assert_eq!( - get_wrapped_asset_info(storage), - WrappedAssetInfo { - asset_chain: 1, - asset_address: vec![1; 32].into(), - bridge: api.canonical_address(&TestAddress::INITIALIZER.value()).0?, - } - ); - Ok(()) - }) - .unwrap(); - deps -} - -fn do_mint( - deps: &mut Instance, - height: u64, - recipient: &HumanAddr, - amount: &Uint128, -) { - let mint_msg = HandleMsg::Mint { - recipient: recipient.clone(), - amount: amount.clone(), - }; - let env = mock_env_height(&TestAddress::INITIALIZER.value(), height, 0); - let handle_response: HandleResponse = handle(deps, env, mint_msg).unwrap(); - assert_eq!(0, handle_response.messages.len()); -} - -fn do_transfer( - deps: &mut Instance, - height: u64, - sender: &HumanAddr, - recipient: &HumanAddr, - amount: &Uint128, -) { - let transfer_msg = HandleMsg::Transfer { - recipient: recipient.clone(), - amount: amount.clone(), - }; - let env = mock_env_height(sender, height, 0); - let handle_response: HandleResponse = handle(deps, env, transfer_msg).unwrap(); - assert_eq!(0, handle_response.messages.len()); -} - -fn check_balance( - deps: &mut Instance, - address: &HumanAddr, - amount: &Uint128, -) { - let query_response = query( - deps, - QueryMsg::Balance { - address: address.clone(), - }, - ) - .unwrap(); - assert_eq!( - query_response.as_slice(), - format!("{{\"balance\":\"{}\"}}", amount.u128()).as_bytes() - ); -} - -fn check_token_details(deps: &mut Instance, supply: &Uint128) { - let query_response = query(deps, QueryMsg::TokenInfo {}).unwrap(); - assert_eq!( - query_response.as_slice(), - format!( - "{{\"name\":\"Wormhole Wrapped\",\ - \"symbol\":\"WWT\",\ - \"decimals\":10,\ - \"total_supply\":\"{}\"}}", - supply.u128() - ) - .as_bytes() - ); -} - -#[test] -fn init_works() { - let mut deps = do_init(111); - check_token_details(&mut deps, &Uint128(0)); -} - -#[test] -fn query_works() { - let mut deps = do_init(111); - - let query_response = query(&mut deps, QueryMsg::WrappedAssetInfo {}).unwrap(); - assert_eq!( - query_response.as_slice(), - format!( - "{{\"asset_chain\":1,\ - \"asset_address\":\"{}\",\ - \"bridge\":\"{}\"}}", - Binary::from(vec![1; 32]).to_base64(), - TestAddress::INITIALIZER.value().as_str() - ) - .as_bytes() - ); -} - -#[test] -fn mint_works() { - let mut deps = do_init(111); - - do_mint( - &mut deps, - 112, - &TestAddress::RECIPIENT.value(), - &Uint128(123_123_123), - ); - - check_balance( - &mut deps, - &TestAddress::RECIPIENT.value(), - &Uint128(123_123_123), - ); - check_token_details(&mut deps, &Uint128(123_123_123)); -} - -#[test] -fn others_cannot_mint() { - let mut deps = do_init(111); - - let mint_msg = HandleMsg::Mint { - recipient: TestAddress::RECIPIENT.value(), - amount: Uint128(123_123_123), - }; - let env = mock_env_height(&TestAddress::RECIPIENT.value(), 112, 0); - let handle_result: HandleResult = handle(&mut deps, env, mint_msg); - assert_eq!( - format!("{}", handle_result.unwrap_err()), - format!("{}", ContractError::Unauthorized {}) - ); -} - -#[test] -fn transfer_works() { - let mut deps = do_init(111); - - do_mint( - &mut deps, - 112, - &TestAddress::SENDER.value(), - &Uint128(123_123_123), - ); - do_transfer( - &mut deps, - 113, - &TestAddress::SENDER.value(), - &TestAddress::RECIPIENT.value(), - &Uint128(123_123_000), - ); - - check_balance(&mut deps, &TestAddress::SENDER.value(), &Uint128(123)); - check_balance( - &mut deps, - &TestAddress::RECIPIENT.value(), - &Uint128(123_123_000), - ); -} diff --git a/terra/contracts-5/token-bridge/.cargo/config b/terra/contracts-5/token-bridge/.cargo/config deleted file mode 100644 index 2d5cce4ea..000000000 --- a/terra/contracts-5/token-bridge/.cargo/config +++ /dev/null @@ -1,5 +0,0 @@ -[alias] -wasm = "build --release --target wasm32-unknown-unknown" -wasm-debug = "build --target wasm32-unknown-unknown" -unit-test = "test --lib --features backtraces" -integration-test = "test --test integration" \ No newline at end of file diff --git a/terra/contracts-5/token-bridge/Cargo.toml b/terra/contracts-5/token-bridge/Cargo.toml deleted file mode 100644 index 7465bd1d9..000000000 --- a/terra/contracts-5/token-bridge/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "token-bridge" -version = "0.1.0" -authors = ["Yuriy Savchenko "] -edition = "2018" -description = "Wormhole token bridge" - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all init/handle/query exports -library = [] - -[dependencies] -cosmwasm-std = { version = "0.16.0" } -cosmwasm-storage = { version = "0.16.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"] } -terraswap = "2.4.0" -wormhole = { path = "../wormhole", features = ["library"] } -thiserror = { version = "1.0.20" } -k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } -sha3 = { version = "0.9.1", default-features = false } -generic-array = { version = "0.14.4" } -hex = "0.4.2" -lazy_static = "1.4.0" -bigint = "4" - -[dev-dependencies] -cosmwasm-vm = { version = "0.16.0", default-features = false } -serde_json = "1.0" diff --git a/terra/contracts-5/token-bridge/src/contract.rs b/terra/contracts-5/token-bridge/src/contract.rs deleted file mode 100644 index d682ec3d5..000000000 --- a/terra/contracts-5/token-bridge/src/contract.rs +++ /dev/null @@ -1,733 +0,0 @@ -use crate::msg::WrappedRegistryResponse; -use cosmwasm_std::{ - entry_point, - to_binary, - Binary, - CanonicalAddr, - Coin, - CosmosMsg, - Deps, - DepsMut, - Empty, - Env, - MessageInfo, - QueryRequest, - Response, - StdError, - StdResult, - Uint128, - WasmMsg, - WasmQuery, -}; - -use crate::{ - msg::{ - ExecuteMsg, - InstantiateMsg, - QueryMsg, - }, - state::{ - bridge_contracts, - bridge_contracts_read, - config, - config_read, - receive_native, - send_native, - wrapped_asset, - wrapped_asset_address, - wrapped_asset_address_read, - wrapped_asset_read, - Action, - AssetMeta, - ConfigInfo, - RegisterChain, - TokenBridgeMessage, - TransferInfo, - }, -}; -use wormhole::{ - byte_utils::{ - extend_address_to_32, - extend_string_to_32, - get_string_from_32, - ByteUtils, - }, - error::ContractError, -}; - -use cw20_base::msg::{ - ExecuteMsg as TokenMsg, - QueryMsg as TokenQuery, -}; - -use wormhole::msg::{ - ExecuteMsg as WormholeExecuteMsg, - QueryMsg as WormholeQueryMsg, -}; - -use wormhole::state::{ - vaa_archive_add, - vaa_archive_check, - GovernancePacket, - ParsedVAA, -}; - -use cw20::TokenInfoResponse; - -use cw20_wrapped::msg::{ - ExecuteMsg as WrappedMsg, - InitHook, - InstantiateMsg as WrappedInit, - QueryMsg as WrappedQuery, - WrappedAssetInfoResponse, -}; -use terraswap::asset::{ - Asset, - AssetInfo, -}; - -use sha3::{ - Digest, - Keccak256, -}; -use std::cmp::{ - max, - min, -}; - -type HumanAddr = String; - -// Chain ID of Terra -const CHAIN_ID: u16 = 3; - -const WRAPPED_ASSET_UPDATING: &str = "updating"; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: InstantiateMsg, -) -> StdResult { - // Save general wormhole info - let state = ConfigInfo { - gov_chain: msg.gov_chain, - gov_address: msg.gov_address.as_slice().to_vec(), - wormhole_contract: msg.wormhole_contract, - wrapped_asset_code_id: msg.wrapped_asset_code_id, - }; - config(deps.storage).save(&state)?; - - Ok(Response::default()) -} - -pub fn coins_after_tax(deps: DepsMut, coins: Vec) -> StdResult> { - let mut res = vec![]; - for coin in coins { - let asset = Asset { - amount: coin.amount.clone(), - info: AssetInfo::NativeToken { - denom: coin.denom.clone(), - }, - }; - res.push(asset.deduct_tax(&deps.querier)?); - } - Ok(res) -} - -pub fn parse_vaa(deps: DepsMut, 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.clone(), - msg: to_binary(&WormholeQueryMsg::VerifyVAA { - vaa: data.clone(), - block_time, - })?, - }))?; - Ok(vaa) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -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()) - } - ExecuteMsg::InitiateTransfer { - asset, - amount, - recipient_chain, - recipient, - fee, - nonce, - } => handle_initiate_transfer( - deps, - env, - info, - asset, - amount, - recipient_chain, - recipient.as_slice().to_vec(), - fee, - nonce, - ), - ExecuteMsg::SubmitVaa { data } => submit_vaa(deps, env, info, &data), - ExecuteMsg::CreateAssetMeta { - asset_address, - nonce, - } => handle_create_asset_meta(deps, env, info, &asset_address, nonce), - } -} - -/// Handle wrapped asset registration messages -fn handle_register_asset( - deps: DepsMut, - _env: Env, - info: MessageInfo, - asset_id: &[u8], -) -> StdResult { - let mut bucket = wrapped_asset(deps.storage); - let result = bucket.load(asset_id); - let result = result.map_err(|_| ContractError::RegistrationForbidden.std())?; - if result != HumanAddr::from(WRAPPED_ASSET_UPDATING) { - return ContractError::AssetAlreadyRegistered.std_err(); - } - - bucket.save(asset_id, &info.sender.to_string())?; - - let contract_address: CanonicalAddr = deps.api.addr_canonicalize(&info.sender.as_str())?; - wrapped_asset_address(deps.storage).save(contract_address.as_slice(), &asset_id.to_vec())?; - - Ok(Response::new() - .add_attribute("action", "register_asset") - .add_attribute("asset_id", format!("{:?}", asset_id)) - .add_attribute("contract_addr", info.sender)) -} - -fn handle_attest_meta( - deps: DepsMut, - env: Env, - emitter_chain: u16, - emitter_address: Vec, - data: &Vec, -) -> StdResult { - let meta = AssetMeta::deserialize(data)?; - - let expected_contract = - bridge_contracts_read(deps.storage).load(&emitter_chain.to_be_bytes())?; - - // must be sent by a registered token bridge contract - if expected_contract != emitter_address { - return Err(StdError::generic_err("invalid emitter")); - } - - if CHAIN_ID == meta.token_chain { - return Err(StdError::generic_err( - "this asset is native to this chain and should not be attested", - )); - } - - let cfg = config_read(deps.storage).load()?; - let asset_id = build_asset_id(meta.token_chain, &meta.token_address.as_slice()); - - if wrapped_asset_read(deps.storage).load(&asset_id).is_ok() { - return Err(StdError::generic_err( - "this asset has already been attested", - )); - } - - wrapped_asset(deps.storage).save(&asset_id, &HumanAddr::from(WRAPPED_ASSET_UPDATING))?; - - Ok( - Response::new().add_message(CosmosMsg::Wasm(WasmMsg::Instantiate { - admin: None, - code_id: cfg.wrapped_asset_code_id, - msg: to_binary(&WrappedInit { - name: get_string_from_32(&meta.name)?, - symbol: get_string_from_32(&meta.symbol)?, - asset_chain: meta.token_chain, - asset_address: meta.token_address.to_vec().into(), - decimals: min(meta.decimals, 8u8), - mint: None, - init_hook: Some(InitHook { - contract_addr: env.contract.address.to_string(), - msg: to_binary(&ExecuteMsg::RegisterAssetHook { - asset_id: asset_id.to_vec().into(), - })?, - }), - })?, - funds: vec![], - label: String::new(), - })), - ) -} - -fn handle_create_asset_meta( - deps: DepsMut, - env: Env, - info: MessageInfo, - asset_address: &HumanAddr, - nonce: u32, -) -> StdResult { - let cfg = config_read(deps.storage).load()?; - - let request = QueryRequest::Wasm(WasmQuery::Smart { - contract_addr: asset_address.clone(), - msg: to_binary(&TokenQuery::TokenInfo {})?, - }); - - let asset_canonical = deps.api.addr_canonicalize(asset_address)?; - let token_info: TokenInfoResponse = deps.querier.query(&request)?; - - let meta: AssetMeta = AssetMeta { - token_chain: CHAIN_ID, - token_address: extend_address_to_32(&asset_canonical), - decimals: token_info.decimals, - symbol: extend_string_to_32(&token_info.symbol)?, - name: extend_string_to_32(&token_info.name)?, - }; - - let token_bridge_message = TokenBridgeMessage { - action: Action::ATTEST_META, - payload: meta.serialize().to_vec(), - }; - - Ok(Response::new() - .add_message(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: cfg.wormhole_contract, - msg: to_binary(&WormholeExecuteMsg::PostMessage { - message: Binary::from(token_bridge_message.serialize()), - nonce, - })?, - // forward coins sent to this message - funds: coins_after_tax(deps, info.funds.clone())?, - })) - .add_attribute("meta.token_chain", CHAIN_ID.to_string()) - .add_attribute("meta.token", asset_address) - .add_attribute("meta.nonce", nonce.to_string()) - .add_attribute("meta.block_time", env.block.time.seconds().to_string())) -} - -fn submit_vaa( - mut deps: DepsMut, - env: Env, - info: MessageInfo, - data: &Binary, -) -> StdResult { - let state = config_read(deps.storage).load()?; - - let vaa = parse_vaa(deps.branch(), env.block.time.seconds(), data)?; - let data = vaa.payload; - - if vaa_archive_check(deps.storage, vaa.hash.as_slice()) { - return ContractError::VaaAlreadyExecuted.std_err(); - } - vaa_archive_add(deps.storage, vaa.hash.as_slice())?; - - // check if vaa is from governance - if state.gov_chain == vaa.emitter_chain && state.gov_address == vaa.emitter_address { - return handle_governance_payload(deps, env, &data); - } - - let message = TokenBridgeMessage::deserialize(&data)?; - - match message.action { - Action::TRANSFER => handle_complete_transfer( - deps, - env, - info, - vaa.emitter_chain, - vaa.emitter_address, - &message.payload, - ), - Action::ATTEST_META => handle_attest_meta( - deps, - env, - vaa.emitter_chain, - vaa.emitter_address, - &message.payload, - ), - _ => ContractError::InvalidVAAAction.std_err(), - } -} - -fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec) -> StdResult { - let gov_packet = GovernancePacket::deserialize(&data)?; - let module = get_string_from_32(&gov_packet.module)?; - - if module != "TokenBridge" { - return Err(StdError::generic_err("this is not a valid module")); - } - - if gov_packet.chain != 0 && gov_packet.chain != CHAIN_ID { - return Err(StdError::generic_err( - "the governance VAA is for another chain", - )); - } - - match gov_packet.action { - 1u8 => handle_register_chain(deps, env, &gov_packet.payload), - _ => ContractError::InvalidVAAAction.std_err(), - } -} - -fn handle_register_chain(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { - let RegisterChain { - chain_id, - chain_address, - } = RegisterChain::deserialize(&data)?; - - let existing = bridge_contracts_read(deps.storage).load(&chain_id.to_be_bytes()); - if existing.is_ok() { - return Err(StdError::generic_err( - "bridge contract already exists for this chain", - )); - } - - let mut bucket = bridge_contracts(deps.storage); - bucket.save(&chain_id.to_be_bytes(), &chain_address)?; - - Ok(Response::new() - .add_attribute("chain_id", chain_id.to_string()) - .add_attribute("chain_address", hex::encode(chain_address))) -} - -fn handle_complete_transfer( - deps: DepsMut, - _env: Env, - info: MessageInfo, - emitter_chain: u16, - emitter_address: Vec, - data: &Vec, -) -> StdResult { - let transfer_info = TransferInfo::deserialize(&data)?; - - let expected_contract = - bridge_contracts_read(deps.storage).load(&emitter_chain.to_be_bytes())?; - - // must be sent by a registered token bridge contract - if expected_contract != emitter_address { - return Err(StdError::generic_err("invalid emitter")); - } - - if transfer_info.recipient_chain != CHAIN_ID { - return Err(StdError::generic_err( - "this transfer is not directed at this chain", - )); - } - - let token_chain = transfer_info.token_chain; - let target_address = (&transfer_info.recipient.as_slice()).get_address(0); - - let (not_supported_amount, mut amount) = transfer_info.amount; - let (not_supported_fee, mut fee) = transfer_info.fee; - - amount = amount.checked_sub(fee).unwrap(); - - // Check high 128 bit of amount value to be empty - if not_supported_amount != 0 || not_supported_fee != 0 { - return ContractError::AmountTooHigh.std_err(); - } - - if token_chain != CHAIN_ID { - let asset_address = transfer_info.token_address; - let asset_id = build_asset_id(token_chain, &asset_address); - - // Check if this asset is already deployed - let contract_addr = wrapped_asset_read(deps.storage).load(&asset_id).ok(); - - return if let Some(contract_addr) = contract_addr { - // Asset already deployed, just mint - - let recipient = deps - .api - .addr_humanize(&target_address) - .or_else(|_| ContractError::WrongTargetAddressFormat.std_err())?; - - let mut messages = vec![CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract_addr.clone(), - msg: to_binary(&WrappedMsg::Mint { - recipient: recipient.to_string(), - amount: Uint128::from(amount), - })?, - funds: vec![], - })]; - if fee != 0 { - messages.push(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract_addr.clone(), - msg: to_binary(&WrappedMsg::Mint { - recipient: info.sender.to_string(), - amount: Uint128::from(fee), - })?, - funds: vec![], - })) - } - - Ok(Response::new() - .add_messages(messages) - .add_attribute("action", "complete_transfer_wrapped") - .add_attribute("contract", contract_addr) - .add_attribute("recipient", recipient) - .add_attribute("amount", amount.to_string())) - } else { - Err(StdError::generic_err("Wrapped asset not deployed. To deploy, invoke CreateWrapped with the associated AssetMeta")) - }; - } else { - let token_address = transfer_info.token_address.as_slice().get_address(0); - - let recipient = deps.api.addr_humanize(&target_address)?; - let contract_addr = deps.api.addr_humanize(&token_address)?; - - // note -- here the amount is the amount the recipient will receive; - // amount + fee is the total sent - receive_native(deps.storage, &token_address, Uint128::new(amount + fee))?; - - // undo normalization to 8 decimals - let token_info: TokenInfoResponse = - deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { - contract_addr: contract_addr.to_string(), - msg: to_binary(&TokenQuery::TokenInfo {})?, - }))?; - - let decimals = token_info.decimals; - let multiplier = 10u128.pow((max(decimals, 8u8) - 8u8) as u32); - amount = amount.checked_mul(multiplier).unwrap(); - fee = fee.checked_mul(multiplier).unwrap(); - - let mut messages = vec![CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract_addr.to_string(), - msg: to_binary(&TokenMsg::Transfer { - recipient: recipient.to_string(), - amount: Uint128::from(amount), - })?, - funds: vec![], - })]; - - if fee != 0 { - messages.push(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract_addr.to_string(), - msg: to_binary(&TokenMsg::Transfer { - recipient: info.sender.to_string(), - amount: Uint128::from(fee), - })?, - funds: vec![], - })) - } - - Ok(Response::new() - .add_messages(messages) - .add_attribute("action", "complete_transfer_native") - .add_attribute("recipient", recipient) - .add_attribute("contract", contract_addr) - .add_attribute("amount", amount.to_string())) - } -} - -fn handle_initiate_transfer( - mut deps: DepsMut, - env: Env, - info: MessageInfo, - asset: HumanAddr, - mut amount: Uint128, - recipient_chain: u16, - recipient: Vec, - mut fee: Uint128, - nonce: u32, -) -> StdResult { - if recipient_chain == CHAIN_ID { - return ContractError::SameSourceAndTarget.std_err(); - } - - if amount.is_zero() { - return ContractError::AmountTooLow.std_err(); - } - - if fee > amount { - return Err(StdError::generic_err("fee greater than sent amount")); - } - - let asset_chain: u16; - let asset_address: Vec; - - let cfg: ConfigInfo = config_read(deps.storage).load()?; - let asset_canonical: CanonicalAddr = deps.api.addr_canonicalize(&asset)?; - - let mut messages: Vec = vec![]; - - match wrapped_asset_address_read(deps.storage).load(asset_canonical.as_slice()) { - Ok(_) => { - // This is a deployed wrapped asset, burn it - messages.push(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: asset.clone(), - msg: to_binary(&WrappedMsg::Burn { - account: info.sender.to_string(), - amount, - })?, - funds: vec![], - })); - let request = QueryRequest::::Wasm(WasmQuery::Smart { - contract_addr: asset, - msg: to_binary(&WrappedQuery::WrappedAssetInfo {})?, - }); - let wrapped_token_info: WrappedAssetInfoResponse = - deps.querier.custom_query(&request)?; - asset_chain = wrapped_token_info.asset_chain; - asset_address = wrapped_token_info.asset_address.as_slice().to_vec(); - } - Err(_) => { - // normalize amount to 8 decimals when it sent over the wormhole - let token_info: TokenInfoResponse = - deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { - contract_addr: asset.clone(), - msg: to_binary(&TokenQuery::TokenInfo {})?, - }))?; - - let decimals = token_info.decimals; - let multiplier = 10u128.pow((max(decimals, 8u8) - 8u8) as u32); - // chop off dust - amount = Uint128::new( - amount - .u128() - .checked_sub(amount.u128().checked_rem(multiplier).unwrap()) - .unwrap(), - ); - fee = Uint128::new( - fee.u128() - .checked_sub(fee.u128().checked_rem(multiplier).unwrap()) - .unwrap(), - ); - - // This is a regular asset, transfer its balance - messages.push(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: asset, - msg: to_binary(&TokenMsg::TransferFrom { - owner: info.sender.to_string(), - recipient: env.contract.address.to_string(), - amount, - })?, - funds: vec![], - })); - asset_address = extend_address_to_32(&asset_canonical); - asset_chain = CHAIN_ID; - - // convert to normalized amounts before recording & posting vaa - amount = Uint128::new(amount.u128().checked_div(multiplier).unwrap()); - fee = Uint128::new(fee.u128().checked_div(multiplier).unwrap()); - - send_native(deps.storage, &asset_canonical, amount)?; - } - }; - - let transfer_info = TransferInfo { - token_chain: asset_chain, - token_address: asset_address.clone(), - amount: (0, amount.u128()), - recipient_chain, - recipient: recipient.clone(), - fee: (0, fee.u128()), - }; - - let token_bridge_message = TokenBridgeMessage { - action: Action::TRANSFER, - payload: transfer_info.serialize(), - }; - - messages.push(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: cfg.wormhole_contract, - msg: to_binary(&WormholeExecuteMsg::PostMessage { - message: Binary::from(token_bridge_message.serialize()), - nonce, - })?, - // forward coins sent to this message - funds: coins_after_tax(deps.branch(), info.funds.clone())?, - })); - - Ok(Response::new() - .add_messages(messages) - .add_attribute("transfer.token_chain", asset_chain.to_string()) - .add_attribute("transfer.token", hex::encode(asset_address)) - .add_attribute( - "transfer.sender", - hex::encode(extend_address_to_32( - &deps.api.addr_canonicalize(&info.sender.as_str())?, - )), - ) - .add_attribute("transfer.recipient_chain", recipient_chain.to_string()) - .add_attribute("transfer.recipient", hex::encode(recipient)) - .add_attribute("transfer.amount", amount.to_string()) - .add_attribute("transfer.nonce", nonce.to_string()) - .add_attribute("transfer.block_time", env.block.time.seconds().to_string())) -} - -pub fn query(deps: Deps, msg: QueryMsg) -> StdResult { - match msg { - QueryMsg::WrappedRegistry { chain, address } => { - to_binary(&query_wrapped_registry(deps, chain, address.as_slice())?) - } - } -} - -pub fn query_wrapped_registry( - deps: Deps, - chain: u16, - address: &[u8], -) -> StdResult { - let asset_id = build_asset_id(chain, address); - // Check if this asset is already deployed - match wrapped_asset_read(deps.storage).load(&asset_id) { - Ok(address) => Ok(WrappedRegistryResponse { address }), - Err(_) => ContractError::AssetNotFound.std_err(), - } -} - -fn build_asset_id(chain: u16, address: &[u8]) -> Vec { - let mut asset_id: Vec = vec![]; - asset_id.extend_from_slice(&chain.to_be_bytes()); - asset_id.extend_from_slice(address); - - let mut hasher = Keccak256::new(); - hasher.update(asset_id); - hasher.finalize().to_vec() -} - -#[cfg(test)] -mod tests { - use cosmwasm_std::{ - to_binary, - Binary, - StdResult, - }; - - #[test] - fn test_me() -> StdResult<()> { - let x = vec![ - 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 96u8, 180u8, 94u8, 195u8, 0u8, 0u8, - 0u8, 1u8, 0u8, 3u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 38u8, - 229u8, 4u8, 215u8, 149u8, 163u8, 42u8, 54u8, 156u8, 236u8, 173u8, 168u8, 72u8, 220u8, - 100u8, 90u8, 154u8, 159u8, 160u8, 215u8, 0u8, 91u8, 48u8, 44u8, 48u8, 44u8, 51u8, 44u8, - 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, - 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 53u8, 55u8, 44u8, 52u8, - 54u8, 44u8, 50u8, 53u8, 53u8, 44u8, 53u8, 48u8, 44u8, 50u8, 52u8, 51u8, 44u8, 49u8, - 48u8, 54u8, 44u8, 49u8, 50u8, 50u8, 44u8, 49u8, 49u8, 48u8, 44u8, 49u8, 50u8, 53u8, - 44u8, 56u8, 56u8, 44u8, 55u8, 51u8, 44u8, 49u8, 56u8, 57u8, 44u8, 50u8, 48u8, 55u8, - 44u8, 49u8, 48u8, 52u8, 44u8, 56u8, 51u8, 44u8, 49u8, 49u8, 57u8, 44u8, 49u8, 50u8, - 55u8, 44u8, 49u8, 57u8, 50u8, 44u8, 49u8, 52u8, 55u8, 44u8, 56u8, 57u8, 44u8, 48u8, - 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, - 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, - 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, - 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, - 44u8, 48u8, 44u8, 51u8, 44u8, 50u8, 51u8, 50u8, 44u8, 48u8, 44u8, 51u8, 44u8, 48u8, - 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, - 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 53u8, 51u8, 44u8, 49u8, 49u8, - 54u8, 44u8, 52u8, 56u8, 44u8, 49u8, 49u8, 54u8, 44u8, 49u8, 52u8, 57u8, 44u8, 49u8, - 48u8, 56u8, 44u8, 49u8, 49u8, 51u8, 44u8, 56u8, 44u8, 48u8, 44u8, 50u8, 51u8, 50u8, - 44u8, 52u8, 57u8, 44u8, 49u8, 53u8, 50u8, 44u8, 49u8, 44u8, 50u8, 56u8, 44u8, 50u8, - 48u8, 51u8, 44u8, 50u8, 49u8, 50u8, 44u8, 50u8, 50u8, 49u8, 44u8, 50u8, 52u8, 49u8, - 44u8, 56u8, 53u8, 44u8, 49u8, 48u8, 57u8, 93u8, - ]; - let b = Binary::from(x.clone()); - let y = b.as_slice().to_vec(); - assert_eq!(x, y); - Ok(()) - } -} diff --git a/terra/contracts-5/token-bridge/src/lib.rs b/terra/contracts-5/token-bridge/src/lib.rs deleted file mode 100644 index 1d2cc8b37..000000000 --- a/terra/contracts-5/token-bridge/src/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[cfg(test)] -#[macro_use] -extern crate lazy_static; - -pub mod contract; -pub mod msg; -pub mod state; - -#[cfg(all(target_arch = "wasm32", not(feature = "library")))] -cosmwasm_std::create_entry_points!(contract); diff --git a/terra/contracts-5/token-bridge/src/msg.rs b/terra/contracts-5/token-bridge/src/msg.rs deleted file mode 100644 index fb2b0bd6d..000000000 --- a/terra/contracts-5/token-bridge/src/msg.rs +++ /dev/null @@ -1,71 +0,0 @@ -use cosmwasm_std::{ - Binary, - Uint128, -}; -use terraswap::asset::{Asset, AssetInfo}; -use schemars::JsonSchema; -use serde::{ - Deserialize, - Serialize, -}; - -type HumanAddr = String; - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InstantiateMsg { - // governance contract details - pub gov_chain: u16, - pub gov_address: Binary, - - pub wormhole_contract: HumanAddr, - pub wrapped_asset_code_id: u64, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ExecuteMsg { - RegisterAssetHook { - asset_id: Binary, - }, - - DepositTokens {}, - WithdrawTokens { - asset: AssetInfo, - }, - - - InitiateTransfer { - asset: Asset, - recipient_chain: u16, - recipient: Binary, - fee: Uint128, - nonce: u32, - }, - - SubmitVaa { - data: Binary, - }, - - CreateAssetMeta { - asset_info: AssetInfo, - nonce: u32, - }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - WrappedRegistry { chain: u16, address: Binary }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct WrappedRegistryResponse { - pub address: HumanAddr, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum WormholeQueryMsg { - VerifyVAA { vaa: Binary, block_time: u64 }, -} diff --git a/terra/contracts-5/token-bridge/src/state.rs b/terra/contracts-5/token-bridge/src/state.rs deleted file mode 100644 index a9a2364b5..000000000 --- a/terra/contracts-5/token-bridge/src/state.rs +++ /dev/null @@ -1,249 +0,0 @@ -use schemars::JsonSchema; -use serde::{ - Deserialize, - Serialize, -}; - -use cosmwasm_std::{ - CanonicalAddr, - StdError, - StdResult, - Storage, - Uint128, -}; -use cosmwasm_storage::{ - bucket, - bucket_read, - singleton, - singleton_read, - Bucket, - ReadonlyBucket, - ReadonlySingleton, - Singleton, -}; - -use wormhole::byte_utils::ByteUtils; - -type HumanAddr = String; - -pub static CONFIG_KEY: &[u8] = b"config"; -pub static WRAPPED_ASSET_KEY: &[u8] = b"wrapped_asset"; -pub static WRAPPED_ASSET_ADDRESS_KEY: &[u8] = b"wrapped_asset_address"; -pub static BRIDGE_CONTRACTS: &[u8] = b"bridge_contracts"; -pub static NATIVE_COUNTER: &[u8] = b"native_counter"; - -// Guardian set information -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ConfigInfo { - // governance contract details - pub gov_chain: u16, - pub gov_address: Vec, - - pub wormhole_contract: HumanAddr, - pub wrapped_asset_code_id: u64, -} - -pub fn config(storage: &mut dyn Storage) -> Singleton { - singleton(storage, CONFIG_KEY) -} - -pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton { - singleton_read(storage, CONFIG_KEY) -} - -pub fn bridge_contracts(storage: &mut dyn Storage) -> Bucket> { - bucket(storage, BRIDGE_CONTRACTS) -} - -pub fn bridge_contracts_read(storage: &dyn Storage) -> ReadonlyBucket> { - bucket_read(storage, BRIDGE_CONTRACTS) -} - -pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket { - bucket(storage, WRAPPED_ASSET_KEY) -} - -pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket { - bucket_read(storage, WRAPPED_ASSET_KEY) -} - -pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket> { - bucket(storage, WRAPPED_ASSET_ADDRESS_KEY) -} - -pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket> { - bucket_read(storage, WRAPPED_ASSET_ADDRESS_KEY) -} - -pub fn send_native( - storage: &mut dyn Storage, - asset_address: &CanonicalAddr, - amount: Uint128, -) -> StdResult<()> { - let mut counter_bucket = bucket(storage, NATIVE_COUNTER); - let new_total = amount - + counter_bucket - .load(asset_address.as_slice()) - .unwrap_or(Uint128::zero()); - if new_total > Uint128::new(u64::MAX as u128) { - return Err(StdError::generic_err( - "transfer exceeds max outstanding bridged token amount", - )); - } - counter_bucket.save(asset_address.as_slice(), &new_total) -} - -pub fn receive_native( - storage: &mut dyn Storage, - asset_address: &CanonicalAddr, - amount: Uint128, -) -> StdResult<()> { - let mut counter_bucket = bucket(storage, NATIVE_COUNTER); - let total: Uint128 = counter_bucket.load(asset_address.as_slice())?; - let result = total.checked_sub(amount)?; - counter_bucket.save(asset_address.as_slice(), &result) -} - -pub struct Action; - -impl Action { - pub const TRANSFER: u8 = 1; - pub const ATTEST_META: u8 = 2; -} - -// 0 u8 action -// 1 [u8] payload - -pub struct TokenBridgeMessage { - pub action: u8, - pub payload: Vec, -} - -impl TokenBridgeMessage { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let action = data.get_u8(0); - let payload = &data[1..]; - - Ok(TokenBridgeMessage { - action, - payload: payload.to_vec(), - }) - } - - pub fn serialize(&self) -> Vec { - [self.action.to_be_bytes().to_vec(), self.payload.clone()].concat() - } -} - -// 0 u256 amount -// 32 [u8; 32] token_address -// 64 u16 token_chain -// 66 [u8; 32] recipient -// 98 u16 recipient_chain -// 100 u256 fee - -pub struct TransferInfo { - pub amount: (u128, u128), - pub token_address: Vec, - pub token_chain: u16, - pub recipient: Vec, - pub recipient_chain: u16, - pub fee: (u128, u128), -} - -impl TransferInfo { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let amount = data.get_u256(0); - let token_address = data.get_bytes32(32).to_vec(); - let token_chain = data.get_u16(64); - let recipient = data.get_bytes32(66).to_vec(); - let recipient_chain = data.get_u16(98); - let fee = data.get_u256(100); - - Ok(TransferInfo { - amount, - token_address, - token_chain, - recipient, - recipient_chain, - fee, - }) - } - pub fn serialize(&self) -> Vec { - [ - self.amount.0.to_be_bytes().to_vec(), - self.amount.1.to_be_bytes().to_vec(), - self.token_address.clone(), - self.token_chain.to_be_bytes().to_vec(), - self.recipient.to_vec(), - self.recipient_chain.to_be_bytes().to_vec(), - self.fee.0.to_be_bytes().to_vec(), - self.fee.1.to_be_bytes().to_vec(), - ] - .concat() - } -} - -// 0 [32]uint8 TokenAddress -// 32 uint16 TokenChain -// 34 uint8 Decimals -// 35 [32]uint8 Symbol -// 67 [32]uint8 Name - -pub struct AssetMeta { - pub token_address: Vec, - pub token_chain: u16, - pub decimals: u8, - pub symbol: Vec, - pub name: Vec, -} - -impl AssetMeta { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let token_address = data.get_bytes32(0).to_vec(); - let token_chain = data.get_u16(32); - let decimals = data.get_u8(34); - let symbol = data.get_bytes32(35).to_vec(); - let name = data.get_bytes32(67).to_vec(); - - Ok(AssetMeta { - token_chain, - token_address, - decimals, - symbol, - name, - }) - } - - pub fn serialize(&self) -> Vec { - [ - self.token_address.clone(), - self.token_chain.to_be_bytes().to_vec(), - self.decimals.to_be_bytes().to_vec(), - self.symbol.clone(), - self.name.clone(), - ] - .concat() - } -} - -pub struct RegisterChain { - pub chain_id: u16, - pub chain_address: Vec, -} - -impl RegisterChain { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let chain_id = data.get_u16(0); - let chain_address = data[2..].to_vec(); - - Ok(RegisterChain { - chain_id, - chain_address, - }) - } -} diff --git a/terra/contracts-5/token-bridge/tests/integration.rs b/terra/contracts-5/token-bridge/tests/integration.rs deleted file mode 100644 index 88d0359ba..000000000 --- a/terra/contracts-5/token-bridge/tests/integration.rs +++ /dev/null @@ -1,114 +0,0 @@ -static WASM: &[u8] = include_bytes!("../../../target/wasm32-unknown-unknown/release/wormhole.wasm"); - -use cosmwasm_std::{ - from_slice, - Coin, - Env, - HumanAddr, - InitResponse, -}; -use cosmwasm_storage::to_length_prefixed; -use cosmwasm_vm::{ - testing::{ - init, - mock_env, - mock_instance, - MockApi, - MockQuerier, - MockStorage, - }, - Api, - Instance, - Storage, -}; - -use wormhole::{ - msg::InitMsg, - state::{ - ConfigInfo, - GuardianAddress, - GuardianSetInfo, - CONFIG_KEY, - }, -}; - -use hex; - -enum TestAddress { - INITIALIZER, -} - -impl TestAddress { - fn value(&self) -> HumanAddr { - match self { - TestAddress::INITIALIZER => HumanAddr::from("initializer"), - } - } -} - -fn mock_env_height(signer: &HumanAddr, height: u64, time: u64) -> Env { - let mut env = mock_env(signer, &[]); - env.block.height = height; - env.block.time = time; - env -} - -fn get_config_info(storage: &S) -> ConfigInfo { - let key = to_length_prefixed(CONFIG_KEY); - let data = storage - .get(&key) - .0 - .expect("error getting data") - .expect("data should exist"); - from_slice(&data).expect("invalid data") -} - -fn do_init( - height: u64, - guardians: &Vec, -) -> Instance { - let mut deps = mock_instance(WASM, &[]); - let init_msg = InitMsg { - initial_guardian_set: GuardianSetInfo { - addresses: guardians.clone(), - expiration_time: 100, - }, - guardian_set_expirity: 50, - wrapped_asset_code_id: 999, - }; - let env = mock_env_height(&TestAddress::INITIALIZER.value(), height, 0); - let owner = deps - .api - .canonical_address(&TestAddress::INITIALIZER.value()) - .0 - .unwrap(); - let res: InitResponse = init(&mut deps, env, init_msg).unwrap(); - assert_eq!(0, res.messages.len()); - - // query the store directly - deps.with_storage(|storage| { - assert_eq!( - get_config_info(storage), - ConfigInfo { - guardian_set_index: 0, - guardian_set_expirity: 50, - wrapped_asset_code_id: 999, - owner, - fee: Coin::new(10000, "uluna"), - } - ); - Ok(()) - }) - .unwrap(); - deps -} - -#[test] -fn init_works() { - let guardians = vec![GuardianAddress::from(GuardianAddress { - bytes: hex::decode("beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe") - .expect("Decoding failed") - .into(), - })]; - let _deps = do_init(111, &guardians); -} diff --git a/terra/contracts-5/wormhole/.cargo/config b/terra/contracts-5/wormhole/.cargo/config deleted file mode 100644 index 2d5cce4ea..000000000 --- a/terra/contracts-5/wormhole/.cargo/config +++ /dev/null @@ -1,5 +0,0 @@ -[alias] -wasm = "build --release --target wasm32-unknown-unknown" -wasm-debug = "build --target wasm32-unknown-unknown" -unit-test = "test --lib --features backtraces" -integration-test = "test --test integration" \ No newline at end of file diff --git a/terra/contracts-5/wormhole/Cargo.toml b/terra/contracts-5/wormhole/Cargo.toml deleted file mode 100644 index b7464e6d0..000000000 --- a/terra/contracts-5/wormhole/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "wormhole" -version = "0.1.0" -authors = ["Yuriy Savchenko "] -edition = "2018" -description = "Wormhole contract" - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all init/handle/query exports -library = [] - -[dependencies] -cosmwasm-std = { version = "0.16.0" } -cosmwasm-storage = { version = "0.16.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"] } -sha3 = { version = "0.9.1", default-features = false } -generic-array = { version = "0.14.4" } -hex = "0.4.2" -lazy_static = "1.4.0" - -[dev-dependencies] -cosmwasm-vm = { version = "0.10.0", default-features = false, features = ["default-cranelift"] } -serde_json = "1.0" diff --git a/terra/contracts-5/wormhole/src/byte_utils.rs b/terra/contracts-5/wormhole/src/byte_utils.rs deleted file mode 100644 index 9f3a0e636..000000000 --- a/terra/contracts-5/wormhole/src/byte_utils.rs +++ /dev/null @@ -1,76 +0,0 @@ -use cosmwasm_std::{ - CanonicalAddr, - StdError, - StdResult, -}; - -pub trait ByteUtils { - fn get_u8(&self, index: usize) -> u8; - fn get_u16(&self, index: usize) -> u16; - fn get_u32(&self, index: usize) -> u32; - fn get_u64(&self, index: usize) -> u64; - - fn get_u128_be(&self, index: usize) -> u128; - /// High 128 then low 128 - fn get_u256(&self, index: usize) -> (u128, u128); - fn get_address(&self, index: usize) -> CanonicalAddr; - fn get_bytes32(&self, index: usize) -> &[u8]; -} - -impl ByteUtils for &[u8] { - fn get_u8(&self, index: usize) -> u8 { - self[index] - } - fn get_u16(&self, index: usize) -> u16 { - let mut bytes: [u8; 16 / 8] = [0; 16 / 8]; - bytes.copy_from_slice(&self[index..index + 2]); - u16::from_be_bytes(bytes) - } - fn get_u32(&self, index: usize) -> u32 { - let mut bytes: [u8; 32 / 8] = [0; 32 / 8]; - bytes.copy_from_slice(&self[index..index + 4]); - u32::from_be_bytes(bytes) - } - fn get_u64(&self, index: usize) -> u64 { - let mut bytes: [u8; 64 / 8] = [0; 64 / 8]; - bytes.copy_from_slice(&self[index..index + 8]); - u64::from_be_bytes(bytes) - } - fn get_u128_be(&self, index: usize) -> u128 { - let mut bytes: [u8; 128 / 8] = [0; 128 / 8]; - bytes.copy_from_slice(&self[index..index + 128 / 8]); - u128::from_be_bytes(bytes) - } - 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 - CanonicalAddr::from(&self[index + 32 - 20..index + 32]) - } - fn get_bytes32(&self, index: usize) -> &[u8] { - &self[index..index + 32] - } -} - -pub fn extend_address_to_32(addr: &CanonicalAddr) -> Vec { - let mut result: Vec = vec![0; 12]; - result.extend(addr.as_slice()); - result -} - -pub fn extend_string_to_32(s: &String) -> StdResult> { - let bytes = s.as_bytes(); - if bytes.len() > 32 { - return Err(StdError::generic_err("string more than 32 ")); - } - - let result = vec![0; 32 - bytes.len()]; - Ok([bytes.to_vec(), result].concat()) -} - -pub fn get_string_from_32(v: &Vec) -> StdResult { - let s = String::from_utf8(v.clone()) - .or_else(|_| Err(StdError::generic_err("could not parse string")))?; - Ok(s.chars().filter(|c| c != &'\0').collect()) -} diff --git a/terra/contracts-5/wormhole/src/contract.rs b/terra/contracts-5/wormhole/src/contract.rs deleted file mode 100644 index 378cbb1ef..000000000 --- a/terra/contracts-5/wormhole/src/contract.rs +++ /dev/null @@ -1,387 +0,0 @@ -use cosmwasm_std::{ - entry_point, - has_coins, - to_binary, - BankMsg, - Binary, - Coin, - CosmosMsg, - Deps, - DepsMut, - Env, - MessageInfo, - Response, - StdError, - StdResult, - Storage, -}; - -use crate::{ - byte_utils::{ - extend_address_to_32, - ByteUtils, - }, - error::ContractError, - msg::{ - ExecuteMsg, - GetAddressHexResponse, - GetStateResponse, - GuardianSetInfoResponse, - InstantiateMsg, - QueryMsg, - }, - state::{ - config, - config_read, - guardian_set_get, - guardian_set_set, - sequence_read, - sequence_set, - vaa_archive_add, - vaa_archive_check, - ConfigInfo, - GovernancePacket, - GuardianAddress, - GuardianSetInfo, - GuardianSetUpgrade, - ParsedVAA, - SetFee, - TransferFee, - }, -}; - -use k256::{ - ecdsa::{ - recoverable::{ - Id as RecoverableId, - Signature as RecoverableSignature, - }, - Signature, - VerifyingKey, - }, - EncodedPoint, -}; -use sha3::{ - Digest, - Keccak256, -}; - -use generic_array::GenericArray; -use std::convert::TryFrom; - -type HumanAddr = String; - -// Chain ID of Terra -const CHAIN_ID: u16 = 3; - -// Lock assets fee amount and denomination -const FEE_AMOUNT: u128 = 10000; -pub const FEE_DENOMINATION: &str = "uluna"; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate(deps: DepsMut, _env: Env, msg: InstantiateMsg) -> StdResult { - // Save general wormhole info - let state = ConfigInfo { - gov_chain: msg.gov_chain, - gov_address: msg.gov_address.as_slice().to_vec(), - guardian_set_index: 0, - guardian_set_expirity: msg.guardian_set_expirity, - fee: Coin::new(FEE_AMOUNT, FEE_DENOMINATION), // 0.01 Luna (or 10000 uluna) fee by default - }; - config(deps.storage).save(&state)?; - - // Add initial guardian set to storage - guardian_set_set( - deps.storage, - state.guardian_set_index, - &msg.initial_guardian_set, - )?; - - Ok(Response::default()) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { - match msg { - ExecuteMsg::PostMessage { message, nonce } => { - handle_post_message(deps, env, info, &message.as_slice(), nonce) - } - ExecuteMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, info, vaa.as_slice()), - } -} - -/// Process VAA message signed by quardians -fn handle_submit_vaa( - deps: DepsMut, - env: Env, - _info: MessageInfo, - data: &[u8], -) -> StdResult { - let state = config_read(deps.storage).load()?; - - let vaa = parse_and_verify_vaa(deps.storage, data, env.block.time.seconds())?; - vaa_archive_add(deps.storage, vaa.hash.as_slice())?; - - if state.gov_chain == vaa.emitter_chain && state.gov_address == vaa.emitter_address { - if state.guardian_set_index != vaa.guardian_set_index { - return Err(StdError::generic_err( - "governance VAAs must be signed by the current guardian set", - )); - } - return handle_governance_payload(deps, env, &vaa.payload); - } - - ContractError::InvalidVAAAction.std_err() -} - -fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec) -> StdResult { - let gov_packet = GovernancePacket::deserialize(&data)?; - - let module = String::from_utf8(gov_packet.module).unwrap(); - let module: String = module.chars().filter(|c| c != &'\0').collect(); - - if module != "Core" { - return Err(StdError::generic_err("this is not a valid module")); - } - - if gov_packet.chain != 0 && gov_packet.chain != CHAIN_ID { - return Err(StdError::generic_err( - "the governance VAA is for another chain", - )); - } - - match gov_packet.action { - // 1 is reserved for upgrade / migration - 2u8 => vaa_update_guardian_set(deps, env, &gov_packet.payload), - 3u8 => handle_set_fee(deps, env, &gov_packet.payload), - 4u8 => handle_transfer_fee(deps, env, &gov_packet.payload), - _ => ContractError::InvalidVAAAction.std_err(), - } -} - -/// Parses raw VAA data into a struct and verifies whether it contains sufficient signatures of an -/// active guardian set i.e. is valid according to Wormhole consensus rules -fn parse_and_verify_vaa( - storage: &dyn Storage, - data: &[u8], - block_time: u64, -) -> StdResult { - let vaa = ParsedVAA::deserialize(data)?; - - if vaa.version != 1 { - return ContractError::InvalidVersion.std_err(); - } - - // Check if VAA with this hash was already accepted - if vaa_archive_check(storage, vaa.hash.as_slice()) { - return ContractError::VaaAlreadyExecuted.std_err(); - } - - // Load and check guardian set - let guardian_set = guardian_set_get(storage, vaa.guardian_set_index); - let guardian_set: GuardianSetInfo = - guardian_set.or_else(|_| ContractError::InvalidGuardianSetIndex.std_err())?; - - if guardian_set.expiration_time != 0 && guardian_set.expiration_time < block_time { - return ContractError::GuardianSetExpired.std_err(); - } - if (vaa.len_signers as usize) < guardian_set.quorum() { - return ContractError::NoQuorum.std_err(); - } - - // Verify guardian signatures - let mut last_index: i32 = -1; - let mut pos = ParsedVAA::HEADER_LEN; - - for _ in 0..vaa.len_signers { - if pos + ParsedVAA::SIGNATURE_LEN > data.len() { - return ContractError::InvalidVAA.std_err(); - } - let index = data.get_u8(pos) as i32; - if index <= last_index { - return ContractError::WrongGuardianIndexOrder.std_err(); - } - last_index = index; - - let signature = Signature::try_from( - &data[pos + ParsedVAA::SIG_DATA_POS - ..pos + ParsedVAA::SIG_DATA_POS + ParsedVAA::SIG_DATA_LEN], - ) - .or_else(|_| ContractError::CannotDecodeSignature.std_err())?; - let id = RecoverableId::new(data.get_u8(pos + ParsedVAA::SIG_RECOVERY_POS)) - .or_else(|_| ContractError::CannotDecodeSignature.std_err())?; - let recoverable_signature = RecoverableSignature::new(&signature, id) - .or_else(|_| ContractError::CannotDecodeSignature.std_err())?; - - let verify_key = recoverable_signature - .recover_verify_key_from_digest_bytes(GenericArray::from_slice(vaa.hash.as_slice())) - .or_else(|_| ContractError::CannotRecoverKey.std_err())?; - - let index = index as usize; - if index >= guardian_set.addresses.len() { - return ContractError::TooManySignatures.std_err(); - } - if !keys_equal(&verify_key, &guardian_set.addresses[index]) { - return ContractError::GuardianSignatureError.std_err(); - } - pos += ParsedVAA::SIGNATURE_LEN; - } - - Ok(vaa) -} - -fn vaa_update_guardian_set(deps: DepsMut, env: Env, data: &Vec) -> StdResult { - /* Payload format - 0 uint32 new_index - 4 uint8 len(keys) - 5 [][20]uint8 guardian addresses - */ - - let mut state = config_read(deps.storage).load()?; - - let GuardianSetUpgrade { - new_guardian_set_index, - new_guardian_set, - } = GuardianSetUpgrade::deserialize(&data)?; - - if new_guardian_set_index != state.guardian_set_index + 1 { - return ContractError::GuardianSetIndexIncreaseError.std_err(); - } - - let old_guardian_set_index = state.guardian_set_index; - - state.guardian_set_index = new_guardian_set_index; - - guardian_set_set(deps.storage, state.guardian_set_index, &new_guardian_set)?; - - config(deps.storage).save(&state)?; - - let mut old_guardian_set = guardian_set_get(deps.storage, old_guardian_set_index)?; - old_guardian_set.expiration_time = env.block.time.seconds() + state.guardian_set_expirity; - guardian_set_set(deps.storage, old_guardian_set_index, &old_guardian_set)?; - - Ok(Response::new() - .add_attribute("action", "guardian_set_change") - .add_attribute("old", old_guardian_set_index.to_string()) - .add_attribute("new", state.guardian_set_index.to_string())) -} - -pub fn handle_set_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { - let set_fee_msg = SetFee::deserialize(&data)?; - - // Save new fees - let mut state = config_read(deps.storage).load()?; - state.fee = set_fee_msg.fee; - config(deps.storage).save(&state)?; - - Ok(Response::new() - .add_attribute("action", "fee_change") - .add_attribute("new_fee.amount", state.fee.amount.to_string()) - .add_attribute("new_fee.denom", state.fee.denom.to_string())) -} - -pub fn handle_transfer_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { - let transfer_msg = TransferFee::deserialize(&data)?; - - Ok(Response::new().add_message(CosmosMsg::Bank(BankMsg::Send { - to_address: deps.api.addr_humanize(&transfer_msg.recipient)?.to_string(), - amount: vec![transfer_msg.amount], - }))) -} - -fn handle_post_message( - deps: DepsMut, - env: Env, - info: MessageInfo, - message: &[u8], - nonce: u32, -) -> StdResult { - let state = config_read(deps.storage).load()?; - let fee = state.fee; - - // Check fee - if !has_coins(info.funds.as_ref(), &fee) { - return ContractError::FeeTooLow.std_err(); - } - - let emitter = extend_address_to_32(&deps.api.addr_canonicalize(&info.sender.as_str())?); - let sequence = sequence_read(deps.storage, emitter.as_slice()); - sequence_set(deps.storage, emitter.as_slice(), sequence + 1)?; - - Ok(Response::new() - .add_attribute("message.message", hex::encode(message)) - .add_attribute("message.sender", hex::encode(emitter)) - .add_attribute("message.chain_id", CHAIN_ID.to_string()) - .add_attribute("message.nonce", nonce.to_string()) - .add_attribute("message.sequence", sequence.to_string()) - .add_attribute("message.block_time", env.block.time.seconds().to_string())) -} - -pub fn query(deps: Deps, msg: QueryMsg) -> StdResult { - match msg { - QueryMsg::GuardianSetInfo {} => to_binary(&query_guardian_set_info(deps)?), - QueryMsg::VerifyVAA { vaa, block_time } => to_binary(&query_parse_and_verify_vaa( - deps, - &vaa.as_slice(), - block_time, - )?), - QueryMsg::GetState {} => to_binary(&query_state(deps)?), - QueryMsg::QueryAddressHex { address } => to_binary(&query_address_hex(deps, &address)?), - } -} - -pub fn query_guardian_set_info(deps: Deps) -> StdResult { - let state = config_read(deps.storage).load()?; - let guardian_set = guardian_set_get(deps.storage, state.guardian_set_index)?; - let res = GuardianSetInfoResponse { - guardian_set_index: state.guardian_set_index, - addresses: guardian_set.addresses, - }; - Ok(res) -} - -pub fn query_parse_and_verify_vaa( - deps: Deps, - data: &[u8], - block_time: u64, -) -> StdResult { - parse_and_verify_vaa(deps.storage, data, block_time) -} - -// returns the hex of the 32 byte address we use for some address on this chain -pub fn query_address_hex(deps: Deps, address: &HumanAddr) -> StdResult { - Ok(GetAddressHexResponse { - hex: hex::encode(extend_address_to_32(&deps.api.addr_canonicalize(&address)?)), - }) -} - -pub fn query_state(deps: Deps) -> StdResult { - let state = config_read(deps.storage).load()?; - let res = GetStateResponse { fee: state.fee }; - Ok(res) -} - -fn keys_equal(a: &VerifyingKey, b: &GuardianAddress) -> bool { - let mut hasher = Keccak256::new(); - - let point: EncodedPoint = EncodedPoint::from(a); - let point = point.decompress(); - if bool::from(point.is_none()) { - return false; - } - let point = point.unwrap(); - - hasher.update(&point.as_bytes()[1..]); - let a = &hasher.finalize()[12..]; - - let b = &b.bytes; - if a.len() != b.len() { - return false; - } - for (ai, bi) in a.iter().zip(b.as_slice().iter()) { - if ai != bi { - return false; - } - } - true -} diff --git a/terra/contracts-5/wormhole/src/error.rs b/terra/contracts-5/wormhole/src/error.rs deleted file mode 100644 index 67603f5d9..000000000 --- a/terra/contracts-5/wormhole/src/error.rs +++ /dev/null @@ -1,113 +0,0 @@ -use cosmwasm_std::StdError; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum ContractError { - /// Invalid VAA version - #[error("InvalidVersion")] - InvalidVersion, - - /// Guardian set with this index does not exist - #[error("InvalidGuardianSetIndex")] - InvalidGuardianSetIndex, - - /// Guardian set expiration date is zero or in the past - #[error("GuardianSetExpired")] - GuardianSetExpired, - - /// Not enough signers on the VAA - #[error("NoQuorum")] - NoQuorum, - - /// Wrong guardian index order, order must be ascending - #[error("WrongGuardianIndexOrder")] - WrongGuardianIndexOrder, - - /// Some problem with signature decoding from bytes - #[error("CannotDecodeSignature")] - CannotDecodeSignature, - - /// Some problem with public key recovery from the signature - #[error("CannotRecoverKey")] - CannotRecoverKey, - - /// Recovered pubkey from signature does not match guardian address - #[error("GuardianSignatureError")] - GuardianSignatureError, - - /// VAA action code not recognized - #[error("InvalidVAAAction")] - InvalidVAAAction, - - /// VAA guardian set is not current - #[error("NotCurrentGuardianSet")] - NotCurrentGuardianSet, - - /// Only 128-bit amounts are supported - #[error("AmountTooHigh")] - AmountTooHigh, - - /// Amount should be higher than zero - #[error("AmountTooLow")] - AmountTooLow, - - /// Source and target chain ids must be different - #[error("SameSourceAndTarget")] - SameSourceAndTarget, - - /// Target chain id must be the same as the current CHAIN_ID - #[error("WrongTargetChain")] - WrongTargetChain, - - /// Wrapped asset init hook sent twice for the same asset id - #[error("AssetAlreadyRegistered")] - AssetAlreadyRegistered, - - /// Guardian set must increase in steps of 1 - #[error("GuardianSetIndexIncreaseError")] - GuardianSetIndexIncreaseError, - - /// VAA was already executed - #[error("VaaAlreadyExecuted")] - VaaAlreadyExecuted, - - /// Message sender not permitted to execute this operation - #[error("PermissionDenied")] - PermissionDenied, - - /// Could not decode target address from canonical to human-readable form - #[error("WrongTargetAddressFormat")] - WrongTargetAddressFormat, - - /// More signatures than active guardians found - #[error("TooManySignatures")] - TooManySignatures, - - /// Wrapped asset not found in the registry - #[error("AssetNotFound")] - AssetNotFound, - - /// Generic error when there is a problem with VAA structure - #[error("InvalidVAA")] - InvalidVAA, - - /// Thrown when fee is enabled for the action, but was not sent with the transaction - #[error("FeeTooLow")] - FeeTooLow, - - /// Registering asset outside of the wormhole - #[error("RegistrationForbidden")] - RegistrationForbidden, -} - -impl ContractError { - pub fn std(&self) -> StdError { - StdError::GenericErr { - msg: format!("{}", self), - } - } - - pub fn std_err(&self) -> Result { - Err(self.std()) - } -} diff --git a/terra/contracts-5/wormhole/src/lib.rs b/terra/contracts-5/wormhole/src/lib.rs deleted file mode 100644 index 610d16ed2..000000000 --- a/terra/contracts-5/wormhole/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod byte_utils; -pub mod contract; -pub mod error; -pub mod msg; -pub mod state; - -pub use crate::error::ContractError; diff --git a/terra/contracts-5/wormhole/src/msg.rs b/terra/contracts-5/wormhole/src/msg.rs deleted file mode 100644 index 810aa92b9..000000000 --- a/terra/contracts-5/wormhole/src/msg.rs +++ /dev/null @@ -1,66 +0,0 @@ -use cosmwasm_std::{ - Binary, - Coin, -}; -use schemars::JsonSchema; -use serde::{ - Deserialize, - Serialize, -}; - -use crate::state::{ - GuardianAddress, - GuardianSetInfo, -}; - -type HumanAddr = String; - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InstantiateMsg { - pub gov_chain: u16, - pub gov_address: Binary, - - pub initial_guardian_set: GuardianSetInfo, - pub guardian_set_expirity: u64, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ExecuteMsg { - SubmitVAA { vaa: Binary }, - PostMessage { message: Binary, nonce: u32 }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - GuardianSetInfo {}, - VerifyVAA { vaa: Binary, block_time: u64 }, - GetState {}, - QueryAddressHex { address: HumanAddr }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct GuardianSetInfoResponse { - pub guardian_set_index: u32, // Current guardian set index - pub addresses: Vec, // List of querdian addresses -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct WrappedRegistryResponse { - pub address: HumanAddr, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct GetStateResponse { - pub fee: Coin, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct GetAddressHexResponse { - pub hex: String, -} diff --git a/terra/contracts-5/wormhole/src/state.rs b/terra/contracts-5/wormhole/src/state.rs deleted file mode 100644 index c0ce806f6..000000000 --- a/terra/contracts-5/wormhole/src/state.rs +++ /dev/null @@ -1,444 +0,0 @@ -use schemars::{ - JsonSchema, -}; -use serde::{ - Deserialize, - Serialize, -}; - -use cosmwasm_std::{ - Binary, - CanonicalAddr, - Coin, - StdResult, - Storage, - Uint128, -}; -use cosmwasm_storage::{ - bucket, - bucket_read, - singleton, - singleton_read, - Bucket, - ReadonlyBucket, - ReadonlySingleton, - Singleton, -}; - -use crate::{ - byte_utils::ByteUtils, - error::ContractError, -}; - -use sha3::{ - Digest, - Keccak256, -}; - -type HumanAddr = String; - -pub static CONFIG_KEY: &[u8] = b"config"; -pub static GUARDIAN_SET_KEY: &[u8] = b"guardian_set"; -pub static SEQUENCE_KEY: &[u8] = b"sequence"; -pub static WRAPPED_ASSET_KEY: &[u8] = b"wrapped_asset"; -pub static WRAPPED_ASSET_ADDRESS_KEY: &[u8] = b"wrapped_asset_address"; - -// Guardian set information -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ConfigInfo { - // Current active guardian set - pub guardian_set_index: u32, - - // Period for which a guardian set stays active after it has been replaced - pub guardian_set_expirity: u64, - - // governance contract details - pub gov_chain: u16, - pub gov_address: Vec, - - // Message sending fee - pub fee: Coin, -} - -// Validator Action Approval(VAA) data -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ParsedVAA { - pub version: u8, - pub guardian_set_index: u32, - pub timestamp: u32, - pub nonce: u32, - pub len_signers: u8, - - pub emitter_chain: u16, - pub emitter_address: Vec, - pub sequence: u64, - pub consistency_level: u8, - pub payload: Vec, - - pub hash: Vec, -} - -impl ParsedVAA { - /* VAA format: - - header (length 6): - 0 uint8 version (0x01) - 1 uint32 guardian set index - 5 uint8 len signatures - - per signature (length 66): - 0 uint8 index of the signer (in guardian keys) - 1 [65]uint8 signature - - body: - 0 uint32 timestamp (unix in seconds) - 4 uint32 nonce - 8 uint16 emitter_chain - 10 [32]uint8 emitter_address - 42 uint64 sequence - 50 uint8 consistency_level - 51 []uint8 payload - */ - - pub const HEADER_LEN: usize = 6; - pub const SIGNATURE_LEN: usize = 66; - - pub const GUARDIAN_SET_INDEX_POS: usize = 1; - pub const LEN_SIGNER_POS: usize = 5; - - pub const VAA_NONCE_POS: usize = 4; - pub const VAA_EMITTER_CHAIN_POS: usize = 8; - pub const VAA_EMITTER_ADDRESS_POS: usize = 10; - pub const VAA_SEQUENCE_POS: usize = 42; - pub const VAA_CONSISTENCY_LEVEL_POS: usize = 50; - pub const VAA_PAYLOAD_POS: usize = 51; - - // Signature data offsets in the signature block - pub const SIG_DATA_POS: usize = 1; - // Signature length minus recovery id at the end - pub const SIG_DATA_LEN: usize = 64; - // Recovery byte is last after the main signature - pub const SIG_RECOVERY_POS: usize = Self::SIG_DATA_POS + Self::SIG_DATA_LEN; - - pub fn deserialize(data: &[u8]) -> StdResult { - let version = data.get_u8(0); - - // Load 4 bytes starting from index 1 - let guardian_set_index: u32 = data.get_u32(Self::GUARDIAN_SET_INDEX_POS); - let len_signers = data.get_u8(Self::LEN_SIGNER_POS) as usize; - let body_offset: usize = Self::HEADER_LEN + Self::SIGNATURE_LEN * len_signers as usize; - - // Hash the body - if body_offset >= data.len() { - return ContractError::InvalidVAA.std_err(); - } - let body = &data[body_offset..]; - let mut hasher = Keccak256::new(); - hasher.update(body); - let hash = hasher.finalize().to_vec(); - - // Rehash the hash - let mut hasher = Keccak256::new(); - hasher.update(hash); - let hash = hasher.finalize().to_vec(); - - // Signatures valid, apply VAA - if body_offset + Self::VAA_PAYLOAD_POS > data.len() { - return ContractError::InvalidVAA.std_err(); - } - - let timestamp = data.get_u32(body_offset); - let nonce = data.get_u32(body_offset + Self::VAA_NONCE_POS); - let emitter_chain = data.get_u16(body_offset + Self::VAA_EMITTER_CHAIN_POS); - let emitter_address = data - .get_bytes32(body_offset + Self::VAA_EMITTER_ADDRESS_POS) - .to_vec(); - let sequence = data.get_u64(body_offset + Self::VAA_SEQUENCE_POS); - let consistency_level = data.get_u8(body_offset + Self::VAA_CONSISTENCY_LEVEL_POS); - let payload = data[body_offset + Self::VAA_PAYLOAD_POS..].to_vec(); - - Ok(ParsedVAA { - version, - guardian_set_index, - timestamp, - nonce, - len_signers: len_signers as u8, - emitter_chain, - emitter_address, - sequence, - consistency_level, - payload, - hash, - }) - } -} - -// Guardian address -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct GuardianAddress { - pub bytes: Binary, // 20-byte addresses -} - -use crate::contract::FEE_DENOMINATION; -#[cfg(test)] -use hex; - -#[cfg(test)] -impl GuardianAddress { - pub fn from(string: &str) -> GuardianAddress { - GuardianAddress { - bytes: hex::decode(string).expect("Decoding failed").into(), - } - } -} - -// Guardian set information -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct GuardianSetInfo { - pub addresses: Vec, - // List of guardian addresses - pub expiration_time: u64, // Guardian set expiration time -} - -impl GuardianSetInfo { - pub fn quorum(&self) -> usize { - // allow quorum of 0 for testing purposes... - if self.addresses.len() == 0 { - return 0; - } - ((self.addresses.len() * 10 / 3) * 2) / 10 + 1 - } -} - -// Wormhole contract generic information -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct WormholeInfo { - // Period for which a guardian set stays active after it has been replaced - pub guardian_set_expirity: u64, -} - -pub fn config(storage: &mut dyn Storage) -> Singleton { - singleton(storage, CONFIG_KEY) -} - -pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton { - singleton_read(storage, CONFIG_KEY) -} - -pub fn guardian_set_set( - storage: &mut dyn Storage, - index: u32, - data: &GuardianSetInfo, -) -> StdResult<()> { - bucket(storage, GUARDIAN_SET_KEY).save(&index.to_be_bytes(), data) -} - -pub fn guardian_set_get(storage: &dyn Storage, index: u32) -> StdResult { - bucket_read(storage, GUARDIAN_SET_KEY).load(&index.to_be_bytes()) -} - -pub fn sequence_set(storage: &mut dyn Storage, emitter: &[u8], sequence: u64) -> StdResult<()> { - bucket(storage, SEQUENCE_KEY).save(emitter, &sequence) -} - -pub fn sequence_read(storage: &dyn Storage, emitter: &[u8]) -> u64 { - bucket_read(storage, SEQUENCE_KEY) - .load(&emitter) - .or::(Ok(0)) - .unwrap() -} - -pub fn vaa_archive_add(storage: &mut dyn Storage, hash: &[u8]) -> StdResult<()> { - bucket(storage, GUARDIAN_SET_KEY).save(hash, &true) -} - -pub fn vaa_archive_check(storage: &dyn Storage, hash: &[u8]) -> bool { - bucket_read(storage, GUARDIAN_SET_KEY) - .load(&hash) - .or::(Ok(false)) - .unwrap() -} - -pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket { - bucket(storage, WRAPPED_ASSET_KEY) -} - -pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket { - bucket_read(storage, WRAPPED_ASSET_KEY) -} - -pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket> { - bucket(storage, WRAPPED_ASSET_ADDRESS_KEY) -} - -pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket> { - bucket_read(storage, WRAPPED_ASSET_ADDRESS_KEY) -} - -pub struct GovernancePacket { - pub module: Vec, - pub action: u8, - pub chain: u16, - pub payload: Vec, -} - -impl GovernancePacket { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let module = data.get_bytes32(0).to_vec(); - let action = data.get_u8(32); - let chain = data.get_u16(33); - let payload = data[35..].to_vec(); - - Ok(GovernancePacket { - module, - action, - chain, - payload, - }) - } -} - -// action 2 -pub struct GuardianSetUpgrade { - pub new_guardian_set_index: u32, - pub new_guardian_set: GuardianSetInfo, -} - -impl GuardianSetUpgrade { - pub fn deserialize(data: &Vec) -> StdResult { - const ADDRESS_LEN: usize = 20; - - let data = data.as_slice(); - let new_guardian_set_index = data.get_u32(0); - - let n_guardians = data.get_u8(4); - - let mut addresses = vec![]; - - for i in 0..n_guardians { - let pos = 5 + (i as usize) * ADDRESS_LEN; - if pos + ADDRESS_LEN > data.len() { - return ContractError::InvalidVAA.std_err(); - } - - addresses.push(GuardianAddress { - bytes: data[pos..pos + ADDRESS_LEN].to_vec().into(), - }); - } - - let new_guardian_set = GuardianSetInfo { - addresses, - expiration_time: 0, - }; - - return Ok(GuardianSetUpgrade { - new_guardian_set_index, - new_guardian_set, - }); - } -} - -// action 3 -pub struct SetFee { - pub fee: Coin, -} - -impl SetFee { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - - let (_, amount) = data.get_u256(0); - let fee = Coin { - denom: String::from(FEE_DENOMINATION), - amount: Uint128::new(amount), - }; - Ok(SetFee { fee }) - } -} - -// action 4 -pub struct TransferFee { - pub amount: Coin, - pub recipient: CanonicalAddr, -} - -impl TransferFee { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let recipient = data.get_address(0); - - let (_, amount) = data.get_u256(32); - let amount = Coin { - denom: String::from(FEE_DENOMINATION), - amount: Uint128::new(amount), - }; - Ok(TransferFee { amount, recipient }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn build_guardian_set(length: usize) -> GuardianSetInfo { - let mut addresses: Vec = Vec::with_capacity(length); - for _ in 0..length { - addresses.push(GuardianAddress { - bytes: vec![].into(), - }); - } - - GuardianSetInfo { - addresses, - expiration_time: 0, - } - } - - #[test] - fn quardian_set_quorum() { - assert_eq!(build_guardian_set(1).quorum(), 1); - assert_eq!(build_guardian_set(2).quorum(), 2); - assert_eq!(build_guardian_set(3).quorum(), 3); - assert_eq!(build_guardian_set(4).quorum(), 3); - assert_eq!(build_guardian_set(5).quorum(), 4); - assert_eq!(build_guardian_set(6).quorum(), 5); - assert_eq!(build_guardian_set(7).quorum(), 5); - assert_eq!(build_guardian_set(8).quorum(), 6); - assert_eq!(build_guardian_set(9).quorum(), 7); - assert_eq!(build_guardian_set(10).quorum(), 7); - assert_eq!(build_guardian_set(11).quorum(), 8); - assert_eq!(build_guardian_set(12).quorum(), 9); - assert_eq!(build_guardian_set(20).quorum(), 14); - assert_eq!(build_guardian_set(25).quorum(), 17); - assert_eq!(build_guardian_set(100).quorum(), 67); - } - - #[test] - fn test_deserialize() { - let x = hex::decode("080000000901007bfa71192f886ab6819fa4862e34b4d178962958d9b2e3d9437338c9e5fde1443b809d2886eaa69e0f0158ea517675d96243c9209c3fe1d94d5b19866654c6980000000b150000000500020001020304000000000000000000000000000000000000000000000000000000000000000000000a0261626364").unwrap(); - let v = ParsedVAA::deserialize(x.as_slice()).unwrap(); - assert_eq!( - v, - ParsedVAA { - version: 8, - guardian_set_index: 9, - timestamp: 2837, - nonce: 5, - len_signers: 1, - emitter_chain: 2, - emitter_address: vec![ - 0, 1, 2, 3, 4, 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 - ], - sequence: 10, - consistency_level: 2, - payload: vec![97, 98, 99, 100], - hash: vec![ - 195, 10, 19, 96, 8, 61, 218, 69, 160, 238, 165, 142, 105, 119, 139, 121, 212, - 73, 238, 179, 13, 80, 245, 224, 75, 110, 163, 8, 185, 132, 55, 34 - ] - } - ); - } -} diff --git a/terra/contracts/cw20-wrapped/Cargo.toml b/terra/contracts/cw20-wrapped/Cargo.toml index 6b153b065..f35f2042c 100644 --- a/terra/contracts/cw20-wrapped/Cargo.toml +++ b/terra/contracts/cw20-wrapped/Cargo.toml @@ -14,13 +14,15 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.10.0" } -cosmwasm-storage = { version = "0.10.0" } -schemars = "0.7" +cosmwasm-std = { version = "0.16.0" } +cosmwasm-storage = { version = "0.16.0" } +schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -cw20 = "0.2.0" -cw20-base = { version = "0.2.0", features = ["library"] } +cw2 = { version = "0.8.0" } +cw20 = { version = "0.8.0" } +cw20-legacy = { version = "0.2.0", features = ["library"]} +cw-storage-plus = { version = "0.8.0" } thiserror = { version = "1.0.20" } [dev-dependencies] -cosmwasm-vm = { version = "0.10.0", default-features = false, features = ["default-cranelift"] } \ No newline at end of file +cosmwasm-vm = { version = "0.16.0", default-features = false } diff --git a/terra/contracts/cw20-wrapped/src/contract.rs b/terra/contracts/cw20-wrapped/src/contract.rs index 4c053b773..11ca72ae8 100644 --- a/terra/contracts/cw20-wrapped/src/contract.rs +++ b/terra/contracts/cw20-wrapped/src/contract.rs @@ -1,48 +1,47 @@ use cosmwasm_std::{ + entry_point, to_binary, - Api, Binary, CosmosMsg, + Deps, + DepsMut, Env, - Extern, - HandleResponse, - HumanAddr, - InitResponse, - Querier, + MessageInfo, + Response, StdError, StdResult, - Storage, Uint128, WasmMsg, }; -use cw20_base::{ +use cw2::set_contract_version; +use cw20_legacy::{ allowances::{ - handle_burn_from, - handle_decrease_allowance, - handle_increase_allowance, - handle_send_from, - handle_transfer_from, + execute_burn_from, + execute_decrease_allowance, + execute_increase_allowance, + execute_send_from, + execute_transfer_from, query_allowance, }, contract::{ - handle_mint, - handle_send, - handle_transfer, + execute_mint, + execute_send, + execute_transfer, query_balance, }, state::{ - token_info, - token_info_read, MinterData, TokenInfo, + TOKEN_INFO, }, + ContractError, }; use crate::{ msg::{ - HandleMsg, - InitMsg, + ExecuteMsg, + InstantiateMsg, QueryMsg, WrappedAssetInfoResponse, }, @@ -55,116 +54,137 @@ use crate::{ use cw20::TokenInfoResponse; use std::string::String; -pub fn init( - deps: &mut Extern, +type HumanAddr = String; + +// version info for migration info +const CONTRACT_NAME: &str = "crates.io:cw20-base"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, env: Env, - msg: InitMsg, -) -> StdResult { + info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + // store token info using cw20-base format let data = TokenInfo { name: msg.name, symbol: msg.symbol, decimals: msg.decimals, - total_supply: Uint128(0), + total_supply: Uint128::new(0), // set creator as minter mint: Some(MinterData { - minter: deps.api.canonical_address(&env.message.sender)?, + minter: deps.api.addr_canonicalize(&info.sender.as_str())?, cap: None, }), }; - token_info(&mut deps.storage).save(&data)?; + TOKEN_INFO.save(deps.storage, &data)?; // save wrapped asset info let data = WrappedAssetInfo { asset_chain: msg.asset_chain, asset_address: msg.asset_address, - bridge: deps.api.canonical_address(&env.message.sender)?, + bridge: deps.api.addr_canonicalize(&info.sender.as_str())?, }; - wrapped_asset_info(&mut deps.storage).save(&data)?; + wrapped_asset_info(deps.storage).save(&data)?; if let Some(mint_info) = msg.mint { - handle_mint(deps, env, mint_info.recipient, mint_info.amount)?; + execute_mint(deps, env, info, mint_info.recipient, mint_info.amount) + .map_err(|e| StdError::generic_err(format!("{}", e)))?; } if let Some(hook) = msg.init_hook { - Ok(InitResponse { - messages: vec![CosmosMsg::Wasm(WasmMsg::Execute { + Ok( + Response::new().add_message(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: hook.contract_addr, msg: hook.msg, - send: vec![], - })], - log: vec![], - }) + funds: vec![], + })), + ) } else { - Ok(InitResponse::default()) + Ok(Response::default()) } } -pub fn handle( - deps: &mut Extern, +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, env: Env, - msg: HandleMsg, -) -> StdResult { + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { match msg { // these all come from cw20-base to implement the cw20 standard - HandleMsg::Transfer { recipient, amount } => { - Ok(handle_transfer(deps, env, recipient, amount)?) + ExecuteMsg::Transfer { recipient, amount } => { + Ok(execute_transfer(deps, env, info, recipient, amount)?) } - HandleMsg::Burn { account, amount } => Ok(handle_burn_from(deps, env, account, amount)?), - HandleMsg::Send { + ExecuteMsg::Burn { account, amount } => { + Ok(execute_burn_from(deps, env, info, account, amount)?) + } + ExecuteMsg::Send { contract, amount, msg, - } => Ok(handle_send(deps, env, contract, amount, msg)?), - HandleMsg::Mint { recipient, amount } => handle_mint_wrapped(deps, env, recipient, amount), - HandleMsg::IncreaseAllowance { + } => Ok(execute_send(deps, env, info, contract, amount, msg)?), + ExecuteMsg::Mint { recipient, amount } => { + execute_mint_wrapped(deps, env, info, recipient, amount) + } + ExecuteMsg::IncreaseAllowance { spender, amount, expires, - } => Ok(handle_increase_allowance( - deps, env, spender, amount, expires, + } => Ok(execute_increase_allowance( + deps, env, info, spender, amount, expires, )?), - HandleMsg::DecreaseAllowance { + ExecuteMsg::DecreaseAllowance { spender, amount, expires, - } => Ok(handle_decrease_allowance( - deps, env, spender, amount, expires, + } => Ok(execute_decrease_allowance( + deps, env, info, spender, amount, expires, )?), - HandleMsg::TransferFrom { + ExecuteMsg::TransferFrom { owner, recipient, amount, - } => Ok(handle_transfer_from(deps, env, owner, recipient, amount)?), - HandleMsg::BurnFrom { owner, amount } => Ok(handle_burn_from(deps, env, owner, amount)?), - HandleMsg::SendFrom { + } => Ok(execute_transfer_from( + deps, env, info, owner, recipient, amount, + )?), + ExecuteMsg::BurnFrom { owner, amount } => { + Ok(execute_burn_from(deps, env, info, owner, amount)?) + } + ExecuteMsg::SendFrom { owner, contract, amount, msg, - } => Ok(handle_send_from(deps, env, owner, contract, amount, msg)?), + } => Ok(execute_send_from( + deps, env, info, owner, contract, amount, msg, + )?), } } -fn handle_mint_wrapped( - deps: &mut Extern, +fn execute_mint_wrapped( + deps: DepsMut, env: Env, + info: MessageInfo, recipient: HumanAddr, amount: Uint128, -) -> StdResult { +) -> Result { // Only bridge can mint - let wrapped_info = wrapped_asset_info_read(&deps.storage).load()?; - if wrapped_info.bridge != deps.api.canonical_address(&env.message.sender)? { - return Err(StdError::unauthorized()); + let wrapped_info = wrapped_asset_info_read(deps.storage).load()?; + if wrapped_info.bridge != deps.api.addr_canonicalize(&info.sender.as_str())? { + return Err(ContractError::Unauthorized {}); } - Ok(handle_mint(deps, env, recipient, amount)?) + Ok(execute_mint(deps, env, info, recipient, amount)?) } -pub fn query( - deps: &Extern, - msg: QueryMsg, -) -> StdResult { +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::WrappedAssetInfo {} => to_binary(&query_wrapped_asset_info(deps)?), // inherited from cw20-base @@ -176,66 +196,58 @@ pub fn query( } } -pub fn query_token_info( - deps: &Extern, -) -> StdResult { - let info = token_info_read(&deps.storage).load()?; - let res = TokenInfoResponse { +pub fn query_token_info(deps: Deps) -> StdResult { + let info = TOKEN_INFO.load(deps.storage)?; + Ok(TokenInfoResponse { name: String::from("Wormhole:") + info.name.as_str(), symbol: String::from("wh") + info.symbol.as_str(), decimals: info.decimals, total_supply: info.total_supply, - }; - Ok(res) + }) } -pub fn query_wrapped_asset_info( - deps: &Extern, -) -> StdResult { - let info = wrapped_asset_info_read(&deps.storage).load()?; - let res = WrappedAssetInfoResponse { +pub fn query_wrapped_asset_info(deps: Deps) -> StdResult { + let info = wrapped_asset_info_read(deps.storage).load()?; + Ok(WrappedAssetInfoResponse { asset_chain: info.asset_chain, asset_address: info.asset_address, - bridge: deps.api.human_address(&info.bridge)?, - }; - Ok(res) + bridge: deps.api.addr_humanize(&info.bridge)?, + }) } #[cfg(test)] mod tests { use super::*; - use cosmwasm_std::{ - testing::{ - mock_dependencies, - mock_env, - }, - HumanAddr, + use cosmwasm_std::testing::{ + mock_dependencies, + mock_env, + mock_info, }; use cw20::TokenInfoResponse; const CANONICAL_LENGTH: usize = 20; - fn get_balance>( - deps: &Extern, - address: T, - ) -> Uint128 { - query_balance(&deps, address.into()).unwrap().balance + fn get_balance(deps: Deps, address: HumanAddr) -> Uint128 { + query_balance(deps, address.into()).unwrap().balance } - fn do_init(deps: &mut Extern, creator: &HumanAddr) { - let init_msg = InitMsg { + fn do_init(mut deps: DepsMut, creator: &HumanAddr) { + let init_msg = InstantiateMsg { + name: "Integers".to_string(), + symbol: "INT".to_string(), asset_chain: 1, asset_address: vec![1; 32].into(), decimals: 10, mint: None, init_hook: None, }; - let env = mock_env(creator, &[]); - let res = init(deps, env, init_msg).unwrap(); + let env = mock_env(); + let info = mock_info(creator, &[]); + let res = instantiate(deps, env, info, init_msg).unwrap(); assert_eq!(0, res.messages.len()); assert_eq!( - query_token_info(&deps).unwrap(), + query_token_info(deps.as_ref()).unwrap(), TokenInfoResponse { name: "Wormhole Wrapped".to_string(), symbol: "WWT".to_string(), @@ -245,35 +257,36 @@ mod tests { ); assert_eq!( - query_wrapped_asset_info(&deps).unwrap(), + query_wrapped_asset_info(deps.as_ref()).unwrap(), WrappedAssetInfoResponse { asset_chain: 1, asset_address: vec![1; 32].into(), - bridge: creator.clone(), + bridge: deps.api.addr_validate(creator).unwrap(), } ); } - fn do_init_and_mint( - deps: &mut Extern, + fn do_init_and_mint( + mut deps: DepsMut, creator: &HumanAddr, mint_to: &HumanAddr, amount: Uint128, ) { do_init(deps, creator); - let msg = HandleMsg::Mint { + let msg = ExecuteMsg::Mint { recipient: mint_to.clone(), amount, }; - let env = mock_env(&creator, &[]); - let res = handle(deps, env, msg.clone()).unwrap(); + let env = mock_env(); + let info = mock_info(creator, &[]); + let res = execute(deps.as_mut(), env, info, msg.clone()).unwrap(); assert_eq!(0, res.messages.len()); - assert_eq!(get_balance(deps, mint_to), amount); + assert_eq!(get_balance(deps.as_ref(), mint_to.clone(),), amount); assert_eq!( - query_token_info(&deps).unwrap(), + query_token_info(deps.as_ref()).unwrap(), TokenInfoResponse { name: "Wormhole Wrapped".to_string(), symbol: "WWT".to_string(), @@ -285,29 +298,30 @@ mod tests { #[test] fn can_mint_by_minter() { - let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]); + let mut deps = mock_dependencies(&[]); let minter = HumanAddr::from("minter"); let recipient = HumanAddr::from("recipient"); - let amount = Uint128(222_222_222); - do_init_and_mint(&mut deps, &minter, &recipient, amount); + let amount = Uint128::new(222_222_222); + do_init_and_mint(deps.as_mut(), &minter, &recipient, amount); } #[test] fn others_cannot_mint() { - let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]); + let mut deps = mock_dependencies(&[]); let minter = HumanAddr::from("minter"); let recipient = HumanAddr::from("recipient"); - do_init(&mut deps, &minter); + do_init(deps.as_mut(), &minter); - let amount = Uint128(222_222_222); - let msg = HandleMsg::Mint { + let amount = Uint128::new(222_222_222); + let msg = ExecuteMsg::Mint { recipient: recipient.clone(), amount, }; let other_address = HumanAddr::from("other"); - let env = mock_env(&other_address, &[]); - let res = handle(&mut deps, env, msg); + let env = mock_env(); + let info = mock_info(&other_address, &[]); + let res = execute(deps.as_mut(), env, info, msg); assert_eq!( format!("{}", res.unwrap_err()), format!("{}", crate::error::ContractError::Unauthorized {}) @@ -316,44 +330,46 @@ mod tests { #[test] fn transfer_balance_success() { - let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]); + let mut deps = mock_dependencies(&[]); let minter = HumanAddr::from("minter"); let owner = HumanAddr::from("owner"); - let amount_initial = Uint128(222_222_222); - do_init_and_mint(&mut deps, &minter, &owner, amount_initial); + let amount_initial = Uint128::new(222_222_222); + do_init_and_mint(deps.as_mut(), &minter, &owner, amount_initial); // Transfer let recipient = HumanAddr::from("recipient"); - let amount_transfer = Uint128(222_222); - let msg = HandleMsg::Transfer { + let amount_transfer = Uint128::new(222_222); + let msg = ExecuteMsg::Transfer { recipient: recipient.clone(), amount: amount_transfer, }; - let env = mock_env(&owner, &[]); - let res = handle(&mut deps, env, msg.clone()).unwrap(); + let env = mock_env(); + let info = mock_info(&owner, &[]); + let res = execute(deps.as_mut(), env, info, msg.clone()).unwrap(); assert_eq!(0, res.messages.len()); - assert_eq!(get_balance(&deps, owner), Uint128(222_000_000)); - assert_eq!(get_balance(&deps, recipient), amount_transfer); + assert_eq!(get_balance(deps.as_ref(), owner), Uint128::new(222_000_000)); + assert_eq!(get_balance(deps.as_ref(), recipient), amount_transfer); } #[test] fn transfer_balance_not_enough() { - let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]); + let mut deps = mock_dependencies(&[]); let minter = HumanAddr::from("minter"); let owner = HumanAddr::from("owner"); - let amount_initial = Uint128(222_221); - do_init_and_mint(&mut deps, &minter, &owner, amount_initial); + let amount_initial = Uint128::new(222_221); + do_init_and_mint(deps.as_mut(), &minter, &owner, amount_initial); // Transfer let recipient = HumanAddr::from("recipient"); - let amount_transfer = Uint128(222_222); - let msg = HandleMsg::Transfer { + let amount_transfer = Uint128::new(222_222); + let msg = ExecuteMsg::Transfer { recipient: recipient.clone(), amount: amount_transfer, }; - let env = mock_env(&owner, &[]); - let _ = handle(&mut deps, env, msg.clone()).unwrap_err(); // Will panic if no error + let env = mock_env(); + let info = mock_info(&owner, &[]); + let _ = execute(deps.as_mut(), env, info, msg.clone()).unwrap_err(); // Will panic if no error } } diff --git a/terra/contracts/cw20-wrapped/src/lib.rs b/terra/contracts/cw20-wrapped/src/lib.rs index e8a832763..6e2ebd886 100644 --- a/terra/contracts/cw20-wrapped/src/lib.rs +++ b/terra/contracts/cw20-wrapped/src/lib.rs @@ -1,9 +1,7 @@ -pub mod contract; mod error; + +pub mod contract; pub mod msg; pub mod state; pub use crate::error::ContractError; - -#[cfg(all(target_arch = "wasm32", not(feature = "library")))] -cosmwasm_std::create_entry_points!(contract); diff --git a/terra/contracts/cw20-wrapped/src/msg.rs b/terra/contracts/cw20-wrapped/src/msg.rs index 31c8cd6e0..25ca6377b 100644 --- a/terra/contracts/cw20-wrapped/src/msg.rs +++ b/terra/contracts/cw20-wrapped/src/msg.rs @@ -6,14 +6,16 @@ use serde::{ }; use cosmwasm_std::{ + Addr, Binary, - HumanAddr, Uint128, }; use cw20::Expiration; +type HumanAddr = String; + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InitMsg { +pub struct InstantiateMsg { pub name: String, pub symbol: String, pub asset_chain: u16, @@ -37,7 +39,7 @@ pub struct InitMint { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub enum HandleMsg { +pub enum ExecuteMsg { /// Implements CW20. Transfer is a base message to move tokens to another account without triggering actions Transfer { recipient: HumanAddr, @@ -50,7 +52,7 @@ pub enum HandleMsg { Send { contract: HumanAddr, amount: Uint128, - msg: Option, + msg: Binary, }, /// Implements CW20 "mintable" extension. If authorized, creates amount new tokens /// and adds to the recipient balance. @@ -87,7 +89,7 @@ pub enum HandleMsg { owner: HumanAddr, contract: HumanAddr, amount: Uint128, - msg: Option, + msg: Binary, }, /// Implements CW20 "approval" extension. Destroys tokens forever BurnFrom { owner: HumanAddr, amount: Uint128 }, @@ -116,5 +118,5 @@ pub enum QueryMsg { pub struct WrappedAssetInfoResponse { pub asset_chain: u16, // Asset chain id pub asset_address: Binary, // Asset smart contract address in the original chain - pub bridge: HumanAddr, // Bridge address, authorized to mint and burn wrapped tokens + pub bridge: Addr, // Bridge address, authorized to mint and burn wrapped tokens } diff --git a/terra/contracts/cw20-wrapped/src/state.rs b/terra/contracts/cw20-wrapped/src/state.rs index 382f7d83c..2d9ba10ff 100644 --- a/terra/contracts/cw20-wrapped/src/state.rs +++ b/terra/contracts/cw20-wrapped/src/state.rs @@ -7,7 +7,6 @@ use serde::{ use cosmwasm_std::{ Binary, CanonicalAddr, - ReadonlyStorage, Storage, }; use cosmwasm_storage::{ @@ -27,12 +26,12 @@ pub struct WrappedAssetInfo { pub bridge: CanonicalAddr, // Bridge address, authorized to mint and burn wrapped tokens } -pub fn wrapped_asset_info(storage: &mut S) -> Singleton { +pub fn wrapped_asset_info(storage: &mut dyn Storage) -> Singleton { singleton(storage, KEY_WRAPPED_ASSET) } -pub fn wrapped_asset_info_read( - storage: &S, -) -> ReadonlySingleton { +pub fn wrapped_asset_info_read( + storage: &dyn Storage, +) -> ReadonlySingleton { singleton_read(storage, KEY_WRAPPED_ASSET) } diff --git a/terra/contracts/token-bridge/Cargo.toml b/terra/contracts/token-bridge/Cargo.toml index a0df81ecf..7465bd1d9 100644 --- a/terra/contracts/token-bridge/Cargo.toml +++ b/terra/contracts/token-bridge/Cargo.toml @@ -14,18 +14,17 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.10.0" } -cosmwasm-storage = { version = "0.10.0" } -schemars = "0.7" +cosmwasm-std = { version = "0.16.0" } +cosmwasm-storage = { version = "0.16.0" } +schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -cw20 = "0.2.2" -cw20-base = { version = "0.2.2", features = ["library"] } +cw20 = "0.8.0" +cw20-base = { version = "0.8.0", features = ["library"] } cw20-wrapped = { path = "../cw20-wrapped", features = ["library"] } -terraswap = "1.1.0" +terraswap = "2.4.0" wormhole = { path = "../wormhole", features = ["library"] } - thiserror = { version = "1.0.20" } -k256 = { version = "0.5.9", default-features = false, features = ["ecdsa"] } +k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } sha3 = { version = "0.9.1", default-features = false } generic-array = { version = "0.14.4" } hex = "0.4.2" @@ -33,5 +32,5 @@ lazy_static = "1.4.0" bigint = "4" [dev-dependencies] -cosmwasm-vm = { version = "0.10.0", default-features = false, features = ["default-cranelift"] } -serde_json = "1.0" \ No newline at end of file +cosmwasm-vm = { version = "0.16.0", default-features = false } +serde_json = "1.0" diff --git a/terra/contracts/token-bridge/src/contract.rs b/terra/contracts/token-bridge/src/contract.rs index 3ee6de0e2..298f3ba74 100644 --- a/terra/contracts/token-bridge/src/contract.rs +++ b/terra/contracts/token-bridge/src/contract.rs @@ -1,24 +1,22 @@ use crate::msg::WrappedRegistryResponse; use cosmwasm_std::{ coin, - log, + entry_point, to_binary, - Api, BankMsg, Binary, CanonicalAddr, Coin, CosmosMsg, + Deps, + DepsMut, + Empty, Env, - Extern, - HandleResponse, - HumanAddr, - InitResponse, - Querier, + MessageInfo, QueryRequest, + Response, StdError, StdResult, - Storage, Uint128, WasmMsg, WasmQuery, @@ -26,16 +24,16 @@ use cosmwasm_std::{ use crate::{ msg::{ - HandleMsg, - InitMsg, + ExecuteMsg, + InstantiateMsg, QueryMsg, }, state::{ bridge_contracts, bridge_contracts_read, + bridge_deposit, config, config_read, - bridge_deposit, receive_native, send_native, wrapped_asset, @@ -61,12 +59,12 @@ use wormhole::{ }; use cw20_base::msg::{ - HandleMsg as TokenMsg, + ExecuteMsg as TokenMsg, QueryMsg as TokenQuery, }; use wormhole::msg::{ - HandleMsg as WormholeHandleMsg, + ExecuteMsg as WormholeExecuteMsg, QueryMsg as WormholeQueryMsg, }; @@ -80,9 +78,9 @@ use wormhole::state::{ use cw20::TokenInfoResponse; use cw20_wrapped::msg::{ - HandleMsg as WrappedMsg, + ExecuteMsg as WrappedMsg, InitHook, - InitMsg as WrappedInit, + InstantiateMsg as WrappedInit, QueryMsg as WrappedQuery, WrappedAssetInfoResponse, }; @@ -100,16 +98,20 @@ use std::cmp::{ min, }; +type HumanAddr = String; + // Chain ID of Terra const CHAIN_ID: u16 = 3; const WRAPPED_ASSET_UPDATING: &str = "updating"; -pub fn init( - deps: &mut Extern, +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, _env: Env, - msg: InitMsg, -) -> StdResult { + _info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { // Save general wormhole info let state = ConfigInfo { gov_chain: msg.gov_chain, @@ -117,15 +119,12 @@ pub fn init( wormhole_contract: msg.wormhole_contract, wrapped_asset_code_id: msg.wrapped_asset_code_id, }; - config(&mut deps.storage).save(&state)?; + config(deps.storage).save(&state)?; - Ok(InitResponse::default()) + Ok(Response::default()) } -pub fn coins_after_tax( - deps: &mut Extern, - coins: Vec, -) -> StdResult> { +pub fn coins_after_tax(deps: DepsMut, coins: Vec) -> StdResult> { let mut res = vec![]; for coin in coins { let asset = Asset { @@ -134,17 +133,13 @@ pub fn coins_after_tax( denom: coin.denom.clone(), }, }; - res.push(asset.deduct_tax(&deps)?); + res.push(asset.deduct_tax(&deps.querier)?); } Ok(res) } -pub fn parse_vaa( - deps: &mut Extern, - block_time: u64, - data: &Binary, -) -> StdResult { - let cfg = config_read(&deps.storage).load()?; +pub fn parse_vaa(deps: DepsMut, 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.clone(), msg: to_binary(&WormholeQueryMsg::VerifyVAA { @@ -155,16 +150,13 @@ pub fn parse_vaa( Ok(vaa) } -pub fn handle( - deps: &mut Extern, - env: Env, - msg: HandleMsg, -) -> StdResult { +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { match msg { - HandleMsg::RegisterAssetHook { asset_id } => { - handle_register_asset(deps, env, &asset_id.as_slice()) + ExecuteMsg::RegisterAssetHook { asset_id } => { + handle_register_asset(deps, env, info, &asset_id.as_slice()) } - HandleMsg::InitiateTransfer { + ExecuteMsg::InitiateTransfer { asset, recipient_chain, recipient, @@ -173,126 +165,110 @@ pub fn handle( } => handle_initiate_transfer( deps, env, + info, asset, recipient_chain, recipient.as_slice().to_vec(), fee, nonce, ), - HandleMsg::DepositTokens {} => deposit_tokens(deps, env), - HandleMsg::WithdrawTokens { asset } => withdraw_tokens(deps, env, asset), - HandleMsg::SubmitVaa { data } => submit_vaa(deps, env, &data), - HandleMsg::CreateAssetMeta { - asset_info, - nonce, - } => handle_create_asset_meta(deps, env, asset_info, nonce), + ExecuteMsg::DepositTokens {} => deposit_tokens(deps, env, info), + ExecuteMsg::WithdrawTokens { asset } => withdraw_tokens(deps, env, info, asset), + ExecuteMsg::SubmitVaa { data } => submit_vaa(deps, env, info, &data), + ExecuteMsg::CreateAssetMeta { asset_info, nonce } => { + handle_create_asset_meta(deps, env, info, asset_info, nonce) + } } } -fn deposit_tokens( - deps: &mut Extern, - env: Env, -) -> StdResult { - for coin in env.message.sent_funds { +fn deposit_tokens(deps: DepsMut, _env: Env, info: MessageInfo) -> StdResult { + for coin in info.funds { let asset = Asset { amount: coin.amount.clone(), info: AssetInfo::NativeToken { denom: coin.denom.clone(), }, }; - let deducted_amount = asset.deduct_tax(&deps)?.amount; - let deposit_key = format!("{}:{}", env.message.sender, coin.denom); - bridge_deposit(&mut deps.storage).update(deposit_key.as_bytes(), |amount: Option| - Ok(amount.unwrap_or(Uint128(0)) + deducted_amount) + let deducted_amount = asset.deduct_tax(&deps.querier)?.amount; + let deposit_key = format!("{}:{}", info.sender, coin.denom); + bridge_deposit(deps.storage).update( + deposit_key.as_bytes(), + |amount: Option| -> StdResult { + Ok(amount.unwrap_or(Uint128::new(0)) + deducted_amount) + }, )?; } - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("action", "deposit_tokens"), - ], - data: None, - }) + Ok(Response::new().add_attribute("action", "deposit_tokens")) } -fn withdraw_tokens( - deps: &mut Extern, - env: Env, +fn withdraw_tokens( + deps: DepsMut, + _env: Env, + info: MessageInfo, data: AssetInfo, -) -> StdResult { +) -> StdResult { let mut messages: Vec = vec![]; if let AssetInfo::NativeToken { denom } = data { - let deposit_key = format!("{}:{}", env.message.sender, denom); - bridge_deposit(&mut deps.storage).update(deposit_key.as_bytes(), |current: Option| { - match current { + let deposit_key = format!("{}:{}", info.sender, denom); + bridge_deposit(deps.storage).update( + deposit_key.as_bytes(), + |current: Option| match current { Some(v) => { messages.push(CosmosMsg::Bank(BankMsg::Send { - from_address: env.contract.address.clone(), - to_address: env.message.sender.clone(), + to_address: info.sender.to_string(), amount: vec![coin(v.u128(), &denom)], })); - Ok(Uint128(0)) + Ok(Uint128::new(0)) } - None => Err(StdError::generic_err("no deposit found to withdraw")) - } - })?; + None => Err(StdError::generic_err("no deposit found to withdraw")), + }, + )?; } - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("action", "withdraw_tokens"), - ], - data: None, - }) + Ok(Response::new().add_attribute("action", "withdraw_tokens")) } /// Handle wrapped asset registration messages -fn handle_register_asset( - deps: &mut Extern, - env: Env, +fn handle_register_asset( + deps: DepsMut, + _env: Env, + info: MessageInfo, asset_id: &[u8], -) -> StdResult { - let mut bucket = wrapped_asset(&mut deps.storage); +) -> StdResult { + let mut bucket = wrapped_asset(deps.storage); let result = bucket.load(asset_id); let result = result.map_err(|_| ContractError::RegistrationForbidden.std())?; if result != HumanAddr::from(WRAPPED_ASSET_UPDATING) { return ContractError::AssetAlreadyRegistered.std_err(); } - bucket.save(asset_id, &env.message.sender)?; + bucket.save(asset_id, &info.sender.to_string())?; - let contract_address: CanonicalAddr = deps.api.canonical_address(&env.message.sender)?; - wrapped_asset_address(&mut deps.storage) - .save(contract_address.as_slice(), &asset_id.to_vec())?; + let contract_address: CanonicalAddr = deps.api.addr_canonicalize(&info.sender.as_str())?; + wrapped_asset_address(deps.storage).save(contract_address.as_slice(), &asset_id.to_vec())?; - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("action", "register_asset"), - log("asset_id", format!("{:?}", asset_id)), - log("contract_addr", env.message.sender), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("action", "register_asset") + .add_attribute("asset_id", format!("{:?}", asset_id)) + .add_attribute("contract_addr", info.sender)) } -fn handle_attest_meta( - deps: &mut Extern, +fn handle_attest_meta( + deps: DepsMut, env: Env, emitter_chain: u16, emitter_address: Vec, data: &Vec, -) -> StdResult { +) -> StdResult { let meta = AssetMeta::deserialize(data)?; let expected_contract = - bridge_contracts_read(&deps.storage).load(&emitter_chain.to_be_bytes())?; + bridge_contracts_read(deps.storage).load(&emitter_chain.to_be_bytes())?; // must be sent by a registered token bridge contract if expected_contract != emitter_address { - return Err(StdError::unauthorized()); + return Err(StdError::generic_err("invalid emitter")); } if CHAIN_ID == meta.token_chain { @@ -301,22 +277,20 @@ fn handle_attest_meta( )); } - let cfg = config_read(&deps.storage).load()?; + let cfg = config_read(deps.storage).load()?; let asset_id = build_asset_id(meta.token_chain, &meta.token_address.as_slice()); - if wrapped_asset_read(&mut deps.storage) - .load(&asset_id) - .is_ok() - { + if wrapped_asset_read(deps.storage).load(&asset_id).is_ok() { return Err(StdError::generic_err( "this asset has already been attested", )); } - wrapped_asset(&mut deps.storage).save(&asset_id, &HumanAddr::from(WRAPPED_ASSET_UPDATING))?; + wrapped_asset(deps.storage).save(&asset_id, &HumanAddr::from(WRAPPED_ASSET_UPDATING))?; - Ok(HandleResponse { - messages: vec![CosmosMsg::Wasm(WasmMsg::Instantiate { + Ok( + Response::new().add_message(CosmosMsg::Wasm(WasmMsg::Instantiate { + admin: None, code_id: cfg.wrapped_asset_code_id, msg: to_binary(&WrappedInit { name: get_string_from_32(&meta.name)?, @@ -326,56 +300,50 @@ fn handle_attest_meta( decimals: min(meta.decimals, 8u8), mint: None, init_hook: Some(InitHook { - contract_addr: env.contract.address, - msg: to_binary(&HandleMsg::RegisterAssetHook { + contract_addr: env.contract.address.to_string(), + msg: to_binary(&ExecuteMsg::RegisterAssetHook { asset_id: asset_id.to_vec().into(), })?, }), })?, - send: vec![], - label: None, - })], - log: vec![], - data: None, - }) + funds: vec![], + label: String::new(), + })), + ) } -fn handle_create_asset_meta( - deps: &mut Extern, +fn handle_create_asset_meta( + deps: DepsMut, env: Env, + info: MessageInfo, asset_info: AssetInfo, nonce: u32, -) -> StdResult { +) -> StdResult { match asset_info { - AssetInfo::Token { contract_addr } => handle_create_asset_meta_token( - deps, - env, - contract_addr, - nonce, - ), - AssetInfo::NativeToken { ref denom } => handle_create_asset_meta_native_token( - deps, - env, - denom.clone(), - nonce, - ) + AssetInfo::Token { contract_addr } => { + handle_create_asset_meta_token(deps, env, info, contract_addr, nonce) + } + AssetInfo::NativeToken { ref denom } => { + handle_create_asset_meta_native_token(deps, env, info, denom.clone(), nonce) + } } } -fn handle_create_asset_meta_token( - deps: &mut Extern, +fn handle_create_asset_meta_token( + deps: DepsMut, env: Env, + info: MessageInfo, asset_address: HumanAddr, nonce: u32, -) -> StdResult { - let cfg = config_read(&deps.storage).load()?; +) -> StdResult { + let cfg = config_read(deps.storage).load()?; let request = QueryRequest::Wasm(WasmQuery::Smart { contract_addr: asset_address.clone(), msg: to_binary(&TokenQuery::TokenInfo {})?, }); - let asset_canonical = deps.api.canonical_address(&asset_address)?; + let asset_canonical = deps.api.addr_canonicalize(&asset_address)?; let token_info: TokenInfoResponse = deps.querier.query(&request)?; let meta: AssetMeta = AssetMeta { @@ -391,49 +359,33 @@ fn handle_create_asset_meta_token( payload: meta.serialize().to_vec(), }; - Ok(HandleResponse { - messages: vec![CosmosMsg::Wasm(WasmMsg::Execute { + Ok(Response::new() + .add_message(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: cfg.wormhole_contract, - msg: to_binary(&WormholeHandleMsg::PostMessage { + msg: to_binary(&WormholeExecuteMsg::PostMessage { message: Binary::from(token_bridge_message.serialize()), nonce, })?, // forward coins sent to this message - send: coins_after_tax(deps, env.message.sent_funds.clone())?, - })], - log: vec![ - log("meta.token_chain", CHAIN_ID), - log("meta.token", asset_address), - log("meta.nonce", nonce), - log("meta.block_time", env.block.time), - ], - data: None, - }) + funds: coins_after_tax(deps, info.funds.clone())?, + })) + .add_attribute("meta.token_chain", CHAIN_ID.to_string()) + .add_attribute("meta.token", asset_address) + .add_attribute("meta.nonce", nonce.to_string()) + .add_attribute("meta.block_time", env.block.time.seconds().to_string())) } -/// All ISO-4217 currency codes are 3 letters, so we can safely slice anything that is not ULUNA. -/// https://www.xe.com/iso4217.php -fn format_native_denom_symbol(denom: &str) -> String { - if denom == "uluna" { - return "LUNA".to_string(); - } - // UUSD -> US -> UST - denom.to_uppercase()[1..3].to_string() + "T" -} - -fn handle_create_asset_meta_native_token( - deps: &mut Extern, +fn handle_create_asset_meta_native_token( + deps: DepsMut, env: Env, + info: MessageInfo, denom: String, nonce: u32, -) -> StdResult { - let cfg = config_read(&deps.storage).load()?; - +) -> StdResult { + let cfg = config_read(deps.storage).load()?; let mut asset_id = extend_address_to_32(&build_native_id(&denom).into()); asset_id[0] = 1; - let symbol = format_native_denom_symbol(&denom); - let meta: AssetMeta = AssetMeta { token_chain: CHAIN_ID, token_address: asset_id.clone(), @@ -441,47 +393,42 @@ fn handle_create_asset_meta_native_token( symbol: extend_string_to_32(&symbol)?, name: extend_string_to_32(&symbol)?, }; - let token_bridge_message = TokenBridgeMessage { action: Action::ATTEST_META, payload: meta.serialize().to_vec(), }; - - Ok(HandleResponse { - messages: vec![CosmosMsg::Wasm(WasmMsg::Execute { + Ok(Response::new() + .add_message(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: cfg.wormhole_contract, - msg: to_binary(&WormholeHandleMsg::PostMessage { + msg: to_binary(&WormholeExecuteMsg::PostMessage { message: Binary::from(token_bridge_message.serialize()), nonce, })?, // forward coins sent to this message - send: coins_after_tax(deps, env.message.sent_funds.clone())?, - })], - log: vec![ - log("meta.token_chain", CHAIN_ID), - log("meta.symbol", symbol), - log("meta.asset_id", hex::encode(asset_id)), - log("meta.nonce", nonce), - log("meta.block_time", env.block.time), - ], - data: None, - }) + funds: coins_after_tax(deps, info.funds.clone())?, + })) + .add_attribute("meta.token_chain", CHAIN_ID.to_string()) + .add_attribute("meta.symbol", symbol) + .add_attribute("meta.asset_id", hex::encode(asset_id)) + .add_attribute("meta.nonce", nonce.to_string()) + .add_attribute("meta.block_time", env.block.time.seconds().to_string())) } -fn submit_vaa( - deps: &mut Extern, +fn submit_vaa( + mut deps: DepsMut, env: Env, + info: MessageInfo, data: &Binary, -) -> StdResult { - let state = config_read(&deps.storage).load()?; +) -> StdResult { + let state = config_read(deps.storage).load()?; - let vaa = parse_vaa(deps, env.block.time, data)?; + let vaa = parse_vaa(deps.branch(), env.block.time.seconds(), data)?; let data = vaa.payload; - if vaa_archive_check(&deps.storage, vaa.hash.as_slice()) { + if vaa_archive_check(deps.storage, vaa.hash.as_slice()) { return ContractError::VaaAlreadyExecuted.std_err(); } - vaa_archive_add(&mut deps.storage, vaa.hash.as_slice())?; + vaa_archive_add(deps.storage, vaa.hash.as_slice())?; // check if vaa is from governance if state.gov_chain == vaa.emitter_chain && state.gov_address == vaa.emitter_address { @@ -490,10 +437,11 @@ fn submit_vaa( let message = TokenBridgeMessage::deserialize(&data)?; - let result = match message.action { + match message.action { Action::TRANSFER => handle_complete_transfer( deps, env, + info, vaa.emitter_chain, vaa.emitter_address, &message.payload, @@ -506,15 +454,10 @@ fn submit_vaa( &message.payload, ), _ => ContractError::InvalidVAAAction.std_err(), - }; - return result; + } } -fn handle_governance_payload( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec) -> StdResult { let gov_packet = GovernancePacket::deserialize(&data)?; let module = get_string_from_32(&gov_packet.module)?; @@ -534,77 +477,67 @@ fn handle_governance_payload( } } -fn handle_register_chain( - deps: &mut Extern, - _env: Env, - data: &Vec, -) -> StdResult { +fn handle_register_chain(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { let RegisterChain { chain_id, chain_address, } = RegisterChain::deserialize(&data)?; - let existing = bridge_contracts_read(&deps.storage).load(&chain_id.to_be_bytes()); + let existing = bridge_contracts_read(deps.storage).load(&chain_id.to_be_bytes()); if existing.is_ok() { return Err(StdError::generic_err( "bridge contract already exists for this chain", )); } - let mut bucket = bridge_contracts(&mut deps.storage); + let mut bucket = bridge_contracts(deps.storage); bucket.save(&chain_id.to_be_bytes(), &chain_address)?; - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("chain_id", chain_id), - log("chain_address", hex::encode(chain_address)), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("chain_id", chain_id.to_string()) + .add_attribute("chain_address", hex::encode(chain_address))) } -fn handle_complete_transfer( - deps: &mut Extern, +fn handle_complete_transfer( + deps: DepsMut, env: Env, + info: MessageInfo, emitter_chain: u16, emitter_address: Vec, data: &Vec, -) -> StdResult { +) -> StdResult { let transfer_info = TransferInfo::deserialize(&data)?; - - // All terra token addresses are 20 bytes, and so start with 12 0's, if the address begins with - // a 1 we can identify it as a fully native token. match transfer_info.token_address.as_slice()[0] { - 1 => handle_complete_transfer_token_native(deps, env, emitter_chain, emitter_address, data), - _ => handle_complete_transfer_token(deps, env, emitter_chain, emitter_address, data), + 1 => handle_complete_transfer_token_native(deps, env, info, emitter_chain, emitter_address, data), + _ => handle_complete_transfer_token(deps, env, info, emitter_chain, emitter_address, data), } } -fn handle_complete_transfer_token( - deps: &mut Extern, - env: Env, +fn handle_complete_transfer_token( + deps: DepsMut, + _env: Env, + info: MessageInfo, emitter_chain: u16, emitter_address: Vec, data: &Vec, -) -> StdResult { +) -> StdResult { let transfer_info = TransferInfo::deserialize(&data)?; - let expected_contract = - bridge_contracts_read(&deps.storage).load(&emitter_chain.to_be_bytes())?; + bridge_contracts_read(deps.storage).load(&emitter_chain.to_be_bytes())?; // must be sent by a registered token bridge contract if expected_contract != emitter_address { - return Err(StdError::unauthorized()); + return Err(StdError::generic_err("invalid emitter")); } + if transfer_info.recipient_chain != CHAIN_ID { return Err(StdError::generic_err( "this transfer is not directed at this chain", )); } - let target_address = (&transfer_info.recipient.as_slice()).get_address(0); let token_chain = transfer_info.token_chain; + let target_address = (&transfer_info.recipient.as_slice()).get_address(0); let (not_supported_amount, mut amount) = transfer_info.amount; let (not_supported_fee, mut fee) = transfer_info.fee; @@ -621,62 +554,58 @@ fn handle_complete_transfer_token( let asset_id = build_asset_id(token_chain, &asset_address); // Check if this asset is already deployed - let contract_addr = wrapped_asset_read(&deps.storage).load(&asset_id).ok(); + let contract_addr = wrapped_asset_read(deps.storage).load(&asset_id).ok(); return if let Some(contract_addr) = contract_addr { // Asset already deployed, just mint let recipient = deps .api - .human_address(&target_address) + .addr_humanize(&target_address) .or_else(|_| ContractError::WrongTargetAddressFormat.std_err())?; let mut messages = vec![CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: contract_addr.clone(), msg: to_binary(&WrappedMsg::Mint { - recipient: recipient.clone(), + recipient: recipient.to_string(), amount: Uint128::from(amount), })?, - send: vec![], + funds: vec![], })]; if fee != 0 { messages.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: contract_addr.clone(), msg: to_binary(&WrappedMsg::Mint { - recipient: env.message.sender.clone(), + recipient: info.sender.to_string(), amount: Uint128::from(fee), })?, - send: vec![], + funds: vec![], })) } - Ok(HandleResponse { - messages, - log: vec![ - log("action", "complete_transfer_wrapped"), - log("contract", contract_addr), - log("recipient", recipient), - log("amount", amount), - ], - data: None, - }) + Ok(Response::new() + .add_messages(messages) + .add_attribute("action", "complete_transfer_wrapped") + .add_attribute("contract", contract_addr) + .add_attribute("recipient", recipient) + .add_attribute("amount", amount.to_string())) } else { Err(StdError::generic_err("Wrapped asset not deployed. To deploy, invoke CreateWrapped with the associated AssetMeta")) }; } else { let token_address = transfer_info.token_address.as_slice().get_address(0); - let recipient = deps.api.human_address(&target_address)?; - let contract_addr = deps.api.human_address(&token_address)?; + let recipient = deps.api.addr_humanize(&target_address)?; + let contract_addr = deps.api.addr_humanize(&token_address)?; // note -- here the amount is the amount the recipient will receive; // amount + fee is the total sent - receive_native(&mut deps.storage, &token_address, Uint128(amount + fee))?; + receive_native(deps.storage, &token_address, Uint128::new(amount + fee))?; // undo normalization to 8 decimals let token_info: TokenInfoResponse = deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { - contract_addr: contract_addr.clone(), + contract_addr: contract_addr.to_string(), msg: to_binary(&TokenQuery::TokenInfo {})?, }))?; @@ -686,54 +615,55 @@ fn handle_complete_transfer_token( fee = fee.checked_mul(multiplier).unwrap(); let mut messages = vec![CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract_addr.clone(), + contract_addr: contract_addr.to_string(), msg: to_binary(&TokenMsg::Transfer { - recipient: recipient.clone(), + recipient: recipient.to_string(), amount: Uint128::from(amount), })?, - send: vec![], + funds: vec![], })]; if fee != 0 { messages.push(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract_addr.clone(), + contract_addr: contract_addr.to_string(), msg: to_binary(&TokenMsg::Transfer { - recipient: env.message.sender.clone(), + recipient: info.sender.to_string(), amount: Uint128::from(fee), })?, - send: vec![], + funds: vec![], })) } - Ok(HandleResponse { - messages, - log: vec![ - log("action", "complete_transfer_token"), - log("recipient", recipient), - log("contract", contract_addr), - log("amount", amount), - ], - data: None, - }) + Ok(Response::new() + .add_messages(messages) + .add_attribute("action", "complete_transfer_native") + .add_attribute("recipient", recipient) + .add_attribute("contract", contract_addr) + .add_attribute("amount", amount.to_string())) } } -fn handle_complete_transfer_token_native( - deps: &mut Extern, - env: Env, + +fn handle_complete_transfer_token_native( + deps: DepsMut, + _env: Env, + info: MessageInfo, emitter_chain: u16, emitter_address: Vec, data: &Vec, -) -> StdResult { +) -> StdResult { let transfer_info = TransferInfo::deserialize(&data)?; let expected_contract = - bridge_contracts_read(&deps.storage).load(&emitter_chain.to_be_bytes())?; + bridge_contracts_read(deps.storage).load(&emitter_chain.to_be_bytes())?; // must be sent by a registered token bridge contract if expected_contract != emitter_address { - return Err(StdError::unauthorized()); + return Err(StdError::generic_err( + "invalid emitter", + )); } + if transfer_info.recipient_chain != CHAIN_ID { return Err(StdError::generic_err( "this transfer is not directed at this chain", @@ -763,49 +693,46 @@ fn handle_complete_transfer_token_native( // note -- here the amount is the amount the recipient will receive; // amount + fee is the total sent - let recipient = deps.api.human_address(&target_address)?; + let recipient = deps.api.addr_humanize(&target_address)?; let token_address = (&*token_address).get_address(0); - receive_native(&mut deps.storage, &token_address, Uint128(amount + fee))?; + receive_native(deps.storage, &token_address, Uint128::new(amount + fee))?; let mut messages = vec![CosmosMsg::Bank(BankMsg::Send { - from_address: env.contract.address.clone(), - to_address: recipient.clone(), + to_address: recipient.to_string(), amount: vec![coin(amount, &denom)], })]; if fee != 0 { messages.push(CosmosMsg::Bank(BankMsg::Send { - from_address: env.contract.address.clone(), - to_address: recipient.clone(), + to_address: recipient.to_string(), amount: vec![coin(fee, &denom)], })); } - Ok(HandleResponse { - messages, - log: vec![ - log("action", "complete_transfer_token_native"), - log("recipient", recipient), - log("denom", denom), - log("amount", amount), - ], - data: None, - }) + Ok(Response::new() + .add_messages(messages) + .add_attribute("action", "complete_transfer_terra_native") + .add_attribute("recipient", recipient) + .add_attribute("denom", denom) + .add_attribute("amount", amount.to_string())) } -fn handle_initiate_transfer( - deps: &mut Extern, + +fn handle_initiate_transfer( + deps: DepsMut, env: Env, + info: MessageInfo, asset: Asset, recipient_chain: u16, recipient: Vec, fee: Uint128, nonce: u32, -) -> StdResult { +) -> StdResult { match asset.info { AssetInfo::Token { contract_addr } => handle_initiate_transfer_token( deps, env, + info, contract_addr, asset.amount, recipient_chain, @@ -813,31 +740,31 @@ fn handle_initiate_transfer( fee, nonce, ), - AssetInfo::NativeToken { ref denom } => { - handle_initiate_transfer_native_token( - deps, - env, - denom.clone(), - asset.amount, - recipient_chain, - recipient, - fee, - nonce, - ) - } + AssetInfo::NativeToken { ref denom } => handle_initiate_transfer_native_token( + deps, + env, + info, + denom.clone(), + asset.amount, + recipient_chain, + recipient, + fee, + nonce, + ), } } -fn handle_initiate_transfer_token( - deps: &mut Extern, +fn handle_initiate_transfer_token( + mut deps: DepsMut, env: Env, + info: MessageInfo, asset: HumanAddr, mut amount: Uint128, recipient_chain: u16, recipient: Vec, mut fee: Uint128, nonce: u32, -) -> StdResult { +) -> StdResult { if recipient_chain == CHAIN_ID { return ContractError::SameSourceAndTarget.std_err(); } @@ -851,23 +778,23 @@ fn handle_initiate_transfer_token( let asset_chain: u16; let asset_address: Vec; - let cfg: ConfigInfo = config_read(&deps.storage).load()?; - let asset_canonical: CanonicalAddr = deps.api.canonical_address(&asset)?; + let cfg: ConfigInfo = config_read(deps.storage).load()?; + let asset_canonical: CanonicalAddr = deps.api.addr_canonicalize(&asset)?; let mut messages: Vec = vec![]; - match wrapped_asset_address_read(&deps.storage).load(asset_canonical.as_slice()) { + match wrapped_asset_address_read(deps.storage).load(asset_canonical.as_slice()) { Ok(_) => { // This is a deployed wrapped asset, burn it messages.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: asset.clone(), msg: to_binary(&WrappedMsg::Burn { - account: env.message.sender.clone(), + account: info.sender.to_string(), amount, })?, - send: vec![], + funds: vec![], })); - let request = QueryRequest::<()>::Wasm(WasmQuery::Smart { + let request = QueryRequest::::Wasm(WasmQuery::Smart { contract_addr: asset, msg: to_binary(&WrappedQuery::WrappedAssetInfo {})?, }); @@ -887,13 +814,13 @@ fn handle_initiate_transfer_token( let decimals = token_info.decimals; let multiplier = 10u128.pow((max(decimals, 8u8) - 8u8) as u32); // chop off dust - amount = Uint128( + amount = Uint128::new( amount .u128() .checked_sub(amount.u128().checked_rem(multiplier).unwrap()) .unwrap(), ); - fee = Uint128( + fee = Uint128::new( fee.u128() .checked_sub(fee.u128().checked_rem(multiplier).unwrap()) .unwrap(), @@ -903,20 +830,20 @@ fn handle_initiate_transfer_token( messages.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: asset, msg: to_binary(&TokenMsg::TransferFrom { - owner: env.message.sender.clone(), - recipient: env.contract.address.clone(), + owner: info.sender.to_string(), + recipient: env.contract.address.to_string(), amount, })?, - send: vec![], + funds: vec![], })); asset_address = extend_address_to_32(&asset_canonical); asset_chain = CHAIN_ID; // convert to normalized amounts before recording & posting vaa - amount = Uint128(amount.u128().checked_div(multiplier).unwrap()); - fee = Uint128(fee.u128().checked_div(multiplier).unwrap()); + amount = Uint128::new(amount.u128().checked_div(multiplier).unwrap()); + fee = Uint128::new(fee.u128().checked_div(multiplier).unwrap()); - send_native(&mut deps.storage, &asset_canonical, amount)?; + send_native(deps.storage, &asset_canonical, amount)?; } }; @@ -936,45 +863,52 @@ fn handle_initiate_transfer_token( messages.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: cfg.wormhole_contract, - msg: to_binary(&WormholeHandleMsg::PostMessage { + msg: to_binary(&WormholeExecuteMsg::PostMessage { message: Binary::from(token_bridge_message.serialize()), nonce, })?, // forward coins sent to this message - send: coins_after_tax(deps, env.message.sent_funds.clone())?, + funds: coins_after_tax(deps.branch(), info.funds.clone())?, })); - Ok(HandleResponse { - messages, - log: vec![ - log("transfer.token_chain", asset_chain), - log("transfer.token", hex::encode(asset_address)), - log( - "transfer.sender", - hex::encode(extend_address_to_32( - &deps.api.canonical_address(&env.message.sender)?, - )), - ), - log("transfer.recipient_chain", recipient_chain), - log("transfer.recipient", hex::encode(recipient)), - log("transfer.amount", amount), - log("transfer.nonce", nonce), - log("transfer.block_time", env.block.time), - ], - data: None, - }) + Ok(Response::new() + .add_messages(messages) + .add_attribute("transfer.token_chain", asset_chain.to_string()) + .add_attribute("transfer.token", hex::encode(asset_address)) + .add_attribute( + "transfer.sender", + hex::encode(extend_address_to_32( + &deps.api.addr_canonicalize(&info.sender.as_str())?, + )), + ) + .add_attribute("transfer.recipient_chain", recipient_chain.to_string()) + .add_attribute("transfer.recipient", hex::encode(recipient)) + .add_attribute("transfer.amount", amount.to_string()) + .add_attribute("transfer.nonce", nonce.to_string()) + .add_attribute("transfer.block_time", env.block.time.seconds().to_string())) } -fn handle_initiate_transfer_native_token( - deps: &mut Extern, +/// All ISO-4217 currency codes are 3 letters, so we can safely slice anything that is not ULUNA. +/// https://www.xe.com/iso4217.php +fn format_native_denom_symbol(denom: &str) -> String { + if denom == "uluna" { + return "LUNA".to_string(); + } + // UUSD -> US -> UST + denom.to_uppercase()[1..3].to_string() + "T" +} + +fn handle_initiate_transfer_native_token( + deps: DepsMut, env: Env, + info: MessageInfo, denom: String, amount: Uint128, recipient_chain: u16, recipient: Vec, fee: Uint128, nonce: u32, -) -> StdResult { +) -> StdResult { if recipient_chain == CHAIN_ID { return ContractError::SameSourceAndTarget.std_err(); } @@ -985,21 +919,21 @@ fn handle_initiate_transfer_native_token( return Err(StdError::generic_err("fee greater than sent amount")); } - let deposit_key = format!("{}:{}", env.message.sender, denom); - bridge_deposit(&mut deps.storage).update(deposit_key.as_bytes(), |current: Option| { + let deposit_key = format!("{}:{}", info.sender, denom); + bridge_deposit(deps.storage).update(deposit_key.as_bytes(), |current: Option| { match current { - Some(v) => Ok((v - amount)?), - None => Err(StdError::generic_err("no deposit found to transfer")) + Some(v) => Ok(v.checked_sub(amount)?), + None => Err(StdError::generic_err("no deposit found to transfer")), } })?; - let cfg: ConfigInfo = config_read(&deps.storage).load()?; + let cfg: ConfigInfo = config_read(deps.storage).load()?; let mut messages: Vec = vec![]; let asset_chain: u16 = CHAIN_ID; let mut asset_address: Vec = build_native_id(&denom); - send_native(&mut deps.storage, &asset_address[..].into(), amount)?; + send_native(deps.storage, &asset_address[..].into(), amount)?; // Mark the first byte of the address to distinguish it as native. asset_address = extend_address_to_32(&asset_address.into()); @@ -1019,40 +953,33 @@ fn handle_initiate_transfer_native_token( payload: transfer_info.serialize(), }; + let sender = deps.api.addr_canonicalize(&info.sender.as_str())?; messages.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: cfg.wormhole_contract, - msg: to_binary(&WormholeHandleMsg::PostMessage { + msg: to_binary(&WormholeExecuteMsg::PostMessage { message: Binary::from(token_bridge_message.serialize()), nonce, })?, - send: coins_after_tax(deps, env.message.sent_funds.clone())?, + funds: coins_after_tax(deps, info.funds.clone())?, })); - Ok(HandleResponse { - messages, - log: vec![ - log("transfer.token_chain", asset_chain), - log("transfer.token", hex::encode(asset_address)), - log( - "transfer.sender", - hex::encode(extend_address_to_32( - &deps.api.canonical_address(&env.message.sender)?, - )), - ), - log("transfer.recipient_chain", recipient_chain), - log("transfer.recipient", hex::encode(recipient)), - log("transfer.amount", amount), - log("transfer.nonce", nonce), - log("transfer.block_time", env.block.time), - ], - data: None, - }) + Ok(Response::new() + .add_messages(messages) + .add_attribute("transfer.token_chain", asset_chain.to_string()) + .add_attribute("transfer.token", hex::encode(asset_address)) + .add_attribute( + "transfer.sender", + hex::encode(extend_address_to_32(&sender)), + ) + .add_attribute("transfer.recipient_chain", recipient_chain.to_string()) + .add_attribute("transfer.recipient", hex::encode(recipient)) + .add_attribute("transfer.amount", amount.to_string()) + .add_attribute("transfer.nonce", nonce.to_string()) + .add_attribute("transfer.block_time", env.block.time.seconds().to_string())) } -pub fn query( - deps: &Extern, - msg: QueryMsg, -) -> StdResult { +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::WrappedRegistry { chain, address } => { to_binary(&query_wrapped_registry(deps, chain, address.as_slice())?) @@ -1060,14 +987,14 @@ pub fn query( } } -pub fn query_wrapped_registry( - deps: &Extern, +pub fn query_wrapped_registry( + deps: Deps, chain: u16, address: &[u8], ) -> StdResult { let asset_id = build_asset_id(chain, address); // Check if this asset is already deployed - match wrapped_asset_read(&deps.storage).load(&asset_id) { + match wrapped_asset_read(deps.storage).load(&asset_id) { Ok(address) => Ok(WrappedRegistryResponse { address }), Err(_) => ContractError::AssetNotFound.std_err(), } diff --git a/terra/contracts/token-bridge/src/lib.rs b/terra/contracts/token-bridge/src/lib.rs index 1d2cc8b37..f67a6e5e3 100644 --- a/terra/contracts/token-bridge/src/lib.rs +++ b/terra/contracts/token-bridge/src/lib.rs @@ -1,10 +1,6 @@ #[cfg(test)] -#[macro_use] extern crate lazy_static; pub mod contract; pub mod msg; pub mod state; - -#[cfg(all(target_arch = "wasm32", not(feature = "library")))] -cosmwasm_std::create_entry_points!(contract); diff --git a/terra/contracts/token-bridge/src/msg.rs b/terra/contracts/token-bridge/src/msg.rs index 06b4f44fb..fb2b0bd6d 100644 --- a/terra/contracts/token-bridge/src/msg.rs +++ b/terra/contracts/token-bridge/src/msg.rs @@ -1,13 +1,18 @@ -use cosmwasm_std::{Binary, HumanAddr, Uint128}; -use schemars::JsonSchema; +use cosmwasm_std::{ + Binary, + Uint128, +}; use terraswap::asset::{Asset, AssetInfo}; +use schemars::JsonSchema; use serde::{ Deserialize, Serialize, }; +type HumanAddr = String; + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InitMsg { +pub struct InstantiateMsg { // governance contract details pub gov_chain: u16, pub gov_address: Binary, @@ -18,7 +23,7 @@ pub struct InitMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub enum HandleMsg { +pub enum ExecuteMsg { RegisterAssetHook { asset_id: Binary, }, @@ -28,6 +33,7 @@ pub enum HandleMsg { asset: AssetInfo, }, + InitiateTransfer { asset: Asset, recipient_chain: u16, diff --git a/terra/contracts/token-bridge/src/state.rs b/terra/contracts/token-bridge/src/state.rs index bbab0ee54..ef3d9daef 100644 --- a/terra/contracts/token-bridge/src/state.rs +++ b/terra/contracts/token-bridge/src/state.rs @@ -6,7 +6,6 @@ use serde::{ use cosmwasm_std::{ CanonicalAddr, - HumanAddr, StdError, StdResult, Storage, @@ -25,6 +24,8 @@ use cosmwasm_storage::{ use wormhole::byte_utils::ByteUtils; +type HumanAddr = String; + pub static CONFIG_KEY: &[u8] = b"config"; pub static WRAPPED_ASSET_KEY: &[u8] = b"wrapped_asset"; pub static WRAPPED_ASSET_ADDRESS_KEY: &[u8] = b"wrapped_asset_address"; @@ -43,57 +44,57 @@ pub struct ConfigInfo { pub wrapped_asset_code_id: u64, } -pub fn config(storage: &mut S) -> Singleton { +pub fn config(storage: &mut dyn Storage) -> Singleton { singleton(storage, CONFIG_KEY) } -pub fn config_read(storage: &S) -> ReadonlySingleton { +pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton { singleton_read(storage, CONFIG_KEY) } -pub fn bridge_deposit(storage: &mut S) -> Bucket { - bucket(BRIDGE_DEPOSITS, storage) +pub fn bridge_deposit(storage: &mut dyn Storage) -> Bucket { + bucket(storage, BRIDGE_DEPOSITS) } -pub fn bridge_deposit_read(storage: &S) -> ReadonlyBucket { - bucket_read(BRIDGE_DEPOSITS, storage) +pub fn bridge_deposit_read(storage: &dyn Storage) -> ReadonlyBucket { + bucket_read(storage, BRIDGE_DEPOSITS) } -pub fn bridge_contracts(storage: &mut S) -> Bucket> { - bucket(BRIDGE_CONTRACTS, storage) +pub fn bridge_contracts(storage: &mut dyn Storage) -> Bucket> { + bucket(storage, BRIDGE_CONTRACTS) } -pub fn bridge_contracts_read(storage: &S) -> ReadonlyBucket> { - bucket_read(BRIDGE_CONTRACTS, storage) +pub fn bridge_contracts_read(storage: &dyn Storage) -> ReadonlyBucket> { + bucket_read(storage, BRIDGE_CONTRACTS) } -pub fn wrapped_asset(storage: &mut S) -> Bucket { - bucket(WRAPPED_ASSET_KEY, storage) +pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket { + bucket(storage, WRAPPED_ASSET_KEY) } -pub fn wrapped_asset_read(storage: &S) -> ReadonlyBucket { - bucket_read(WRAPPED_ASSET_KEY, storage) +pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket { + bucket_read(storage, WRAPPED_ASSET_KEY) } -pub fn wrapped_asset_address(storage: &mut S) -> Bucket> { - bucket(WRAPPED_ASSET_ADDRESS_KEY, storage) +pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket> { + bucket(storage, WRAPPED_ASSET_ADDRESS_KEY) } -pub fn wrapped_asset_address_read(storage: &S) -> ReadonlyBucket> { - bucket_read(WRAPPED_ASSET_ADDRESS_KEY, storage) +pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket> { + bucket_read(storage, WRAPPED_ASSET_ADDRESS_KEY) } -pub fn send_native( - storage: &mut S, +pub fn send_native( + storage: &mut dyn Storage, asset_address: &CanonicalAddr, amount: Uint128, ) -> StdResult<()> { - let mut counter_bucket = bucket(NATIVE_COUNTER, storage); + let mut counter_bucket = bucket(storage, NATIVE_COUNTER); let new_total = amount + counter_bucket .load(asset_address.as_slice()) .unwrap_or(Uint128::zero()); - if new_total > Uint128(u64::MAX as u128) { + if new_total > Uint128::new(u64::MAX as u128) { return Err(StdError::generic_err( "transfer exceeds max outstanding bridged token amount", )); @@ -101,14 +102,15 @@ pub fn send_native( counter_bucket.save(asset_address.as_slice(), &new_total) } -pub fn receive_native( - storage: &mut S, +pub fn receive_native( + storage: &mut dyn Storage, asset_address: &CanonicalAddr, amount: Uint128, ) -> StdResult<()> { - let mut counter_bucket = bucket(NATIVE_COUNTER, storage); + let mut counter_bucket = bucket(storage, NATIVE_COUNTER); let total: Uint128 = counter_bucket.load(asset_address.as_slice())?; - counter_bucket.save(asset_address.as_slice(), &(total - amount)?) + let result = total.checked_sub(amount)?; + counter_bucket.save(asset_address.as_slice(), &result) } pub struct Action; diff --git a/terra/contracts/wormhole/Cargo.toml b/terra/contracts/wormhole/Cargo.toml index 391fdd4ca..c8c9996e6 100644 --- a/terra/contracts/wormhole/Cargo.toml +++ b/terra/contracts/wormhole/Cargo.toml @@ -14,20 +14,21 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.10.0" } -cosmwasm-storage = { version = "0.10.0" } -schemars = "0.7" +cosmwasm-std = { version = "0.16.0" } +cosmwasm-storage = { version = "0.16.0" } +schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -cw20 = "0.2.2" -cw20-base = { version = "0.2.2", features = ["library"] } +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.5.9", default-features = false, features = ["ecdsa"] } +k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } +getrandom = { version = "0.2", features = ["custom"] } sha3 = { version = "0.9.1", default-features = false } generic-array = { version = "0.14.4" } hex = "0.4.2" lazy_static = "1.4.0" [dev-dependencies] -cosmwasm-vm = { version = "0.10.0", default-features = false, features = ["default-cranelift"] } -serde_json = "1.0" \ No newline at end of file +cosmwasm-vm = { version = "0.16.0", default-features = false } +serde_json = "1.0" diff --git a/terra/contracts/wormhole/src/contract.rs b/terra/contracts/wormhole/src/contract.rs index c1859594a..f7a53bf40 100644 --- a/terra/contracts/wormhole/src/contract.rs +++ b/terra/contracts/wormhole/src/contract.rs @@ -1,21 +1,20 @@ use cosmwasm_std::{ + entry_point, has_coins, - log, to_binary, - Api, BankMsg, Binary, Coin, CosmosMsg, + Deps, + DepsMut, Env, - Extern, - HandleResponse, - HumanAddr, - InitResponse, - Querier, + MessageInfo, + Response, StdError, StdResult, Storage, + WasmMsg, }; use crate::{ @@ -25,11 +24,12 @@ use crate::{ }, error::ContractError, msg::{ + ExecuteMsg, GetAddressHexResponse, GetStateResponse, GuardianSetInfoResponse, - HandleMsg, - InitMsg, + InstantiateMsg, + MigrateMsg, QueryMsg, }, state::{ @@ -42,6 +42,7 @@ use crate::{ vaa_archive_add, vaa_archive_check, ConfigInfo, + ContractUpgrade, GovernancePacket, GuardianAddress, GuardianSetInfo, @@ -59,7 +60,7 @@ use k256::{ Signature as RecoverableSignature, }, Signature, - VerifyKey, + VerifyingKey, }, EncodedPoint, }; @@ -71,6 +72,8 @@ use sha3::{ use generic_array::GenericArray; use std::convert::TryFrom; +type HumanAddr = String; + // Chain ID of Terra const CHAIN_ID: u16 = 3; @@ -78,11 +81,18 @@ const CHAIN_ID: u16 = 3; const FEE_AMOUNT: u128 = 10000; pub const FEE_DENOMINATION: &str = "uluna"; -pub fn init( - deps: &mut Extern, +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, _env: Env, - msg: InitMsg, -) -> StdResult { + _info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { // Save general wormhole info let state = ConfigInfo { gov_chain: msg.gov_chain, @@ -91,41 +101,39 @@ pub fn init( guardian_set_expirity: msg.guardian_set_expirity, fee: Coin::new(FEE_AMOUNT, FEE_DENOMINATION), // 0.01 Luna (or 10000 uluna) fee by default }; - config(&mut deps.storage).save(&state)?; + config(deps.storage).save(&state)?; // Add initial guardian set to storage guardian_set_set( - &mut deps.storage, + deps.storage, state.guardian_set_index, &msg.initial_guardian_set, )?; - Ok(InitResponse::default()) + Ok(Response::default()) } -pub fn handle( - deps: &mut Extern, - env: Env, - msg: HandleMsg, -) -> StdResult { +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { match msg { - HandleMsg::PostMessage { message, nonce } => { - handle_post_message(deps, env, &message.as_slice(), nonce) + ExecuteMsg::PostMessage { message, nonce } => { + handle_post_message(deps, env, info, &message.as_slice(), nonce) } - HandleMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, vaa.as_slice()), + ExecuteMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, info, vaa.as_slice()), } } /// Process VAA message signed by quardians -fn handle_submit_vaa( - deps: &mut Extern, +fn handle_submit_vaa( + deps: DepsMut, env: Env, + _info: MessageInfo, data: &[u8], -) -> StdResult { - let state = config_read(&deps.storage).load()?; +) -> StdResult { + let state = config_read(deps.storage).load()?; - let vaa = parse_and_verify_vaa(&deps.storage, data, env.block.time)?; - vaa_archive_add(&mut deps.storage, vaa.hash.as_slice())?; + let vaa = parse_and_verify_vaa(deps.storage, data, env.block.time.seconds())?; + vaa_archive_add(deps.storage, vaa.hash.as_slice())?; if state.gov_chain == vaa.emitter_chain && state.gov_address == vaa.emitter_address { if state.guardian_set_index != vaa.guardian_set_index { @@ -139,11 +147,7 @@ fn handle_submit_vaa( ContractError::InvalidVAAAction.std_err() } -fn handle_governance_payload( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec) -> StdResult { let gov_packet = GovernancePacket::deserialize(&data)?; let module = String::from_utf8(gov_packet.module).unwrap(); @@ -160,7 +164,7 @@ fn handle_governance_payload( } match gov_packet.action { - // 1 is reserved for upgrade / migration + 1u8 => vaa_update_contract(deps, env, &gov_packet.payload), 2u8 => vaa_update_guardian_set(deps, env, &gov_packet.payload), 3u8 => handle_set_fee(deps, env, &gov_packet.payload), 4u8 => handle_transfer_fee(deps, env, &gov_packet.payload), @@ -170,8 +174,8 @@ fn handle_governance_payload( /// Parses raw VAA data into a struct and verifies whether it contains sufficient signatures of an /// active guardian set i.e. is valid according to Wormhole consensus rules -fn parse_and_verify_vaa( - storage: &S, +fn parse_and_verify_vaa( + storage: &dyn Storage, data: &[u8], block_time: u64, ) -> StdResult { @@ -239,18 +243,14 @@ fn parse_and_verify_vaa( Ok(vaa) } -fn vaa_update_guardian_set( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +fn vaa_update_guardian_set(deps: DepsMut, env: Env, data: &Vec) -> StdResult { /* Payload format 0 uint32 new_index 4 uint8 len(keys) 5 [][20]uint8 guardian addresses */ - let mut state = config_read(&deps.storage).load()?; + let mut state = config_read(deps.storage).load()?; let GuardianSetUpgrade { new_guardian_set_index, @@ -265,107 +265,89 @@ fn vaa_update_guardian_set( state.guardian_set_index = new_guardian_set_index; - guardian_set_set( - &mut deps.storage, - state.guardian_set_index, - &new_guardian_set, - )?; + guardian_set_set(deps.storage, state.guardian_set_index, &new_guardian_set)?; - config(&mut deps.storage).save(&state)?; + config(deps.storage).save(&state)?; - let mut old_guardian_set = guardian_set_get(&deps.storage, old_guardian_set_index)?; - old_guardian_set.expiration_time = env.block.time + state.guardian_set_expirity; - guardian_set_set(&mut deps.storage, old_guardian_set_index, &old_guardian_set)?; + let mut old_guardian_set = guardian_set_get(deps.storage, old_guardian_set_index)?; + old_guardian_set.expiration_time = env.block.time.seconds() + state.guardian_set_expirity; + guardian_set_set(deps.storage, old_guardian_set_index, &old_guardian_set)?; - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("action", "guardian_set_change"), - log("old", old_guardian_set_index), - log("new", state.guardian_set_index), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("action", "guardian_set_change") + .add_attribute("old", old_guardian_set_index.to_string()) + .add_attribute("new", state.guardian_set_index.to_string())) } -pub fn handle_set_fee( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +fn vaa_update_contract(_deps: DepsMut, env: Env, data: &Vec) -> StdResult { + /* Payload format + 0 [][32]uint8 new_contract + */ + + let ContractUpgrade { new_contract } = ContractUpgrade::deserialize(&data)?; + + Ok(Response::new() + .add_message(CosmosMsg::Wasm(WasmMsg::Migrate { + contract_addr: env.contract.address.to_string(), + new_code_id: new_contract, + msg: to_binary(&MigrateMsg {})?, + })) + .add_attribute("action", "contract_upgrade")) +} + +pub fn handle_set_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { let set_fee_msg = SetFee::deserialize(&data)?; // Save new fees - let mut state = config_read(&mut deps.storage).load()?; + let mut state = config_read(deps.storage).load()?; state.fee = set_fee_msg.fee; - config(&mut deps.storage).save(&state)?; + config(deps.storage).save(&state)?; - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("action", "fee_change"), - log("new_fee.amount", state.fee.amount), - log("new_fee.denom", state.fee.denom), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("action", "fee_change") + .add_attribute("new_fee.amount", state.fee.amount.to_string()) + .add_attribute("new_fee.denom", state.fee.denom.to_string())) } -pub fn handle_transfer_fee( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +pub fn handle_transfer_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { let transfer_msg = TransferFee::deserialize(&data)?; - Ok(HandleResponse { - messages: vec![CosmosMsg::Bank(BankMsg::Send { - from_address: env.contract.address, - to_address: deps.api.human_address(&transfer_msg.recipient)?, - amount: vec![transfer_msg.amount], - })], - log: vec![], - data: None, - }) + Ok(Response::new().add_message(CosmosMsg::Bank(BankMsg::Send { + to_address: deps.api.addr_humanize(&transfer_msg.recipient)?.to_string(), + amount: vec![transfer_msg.amount], + }))) } -fn handle_post_message( - deps: &mut Extern, +fn handle_post_message( + deps: DepsMut, env: Env, + info: MessageInfo, message: &[u8], nonce: u32, -) -> StdResult { - let state = config_read(&deps.storage).load()?; +) -> StdResult { + let state = config_read(deps.storage).load()?; let fee = state.fee; // Check fee - if !has_coins(env.message.sent_funds.as_ref(), &fee) { + if !has_coins(info.funds.as_ref(), &fee) { return ContractError::FeeTooLow.std_err(); } - let emitter = extend_address_to_32(&deps.api.canonical_address(&env.message.sender)?); + let emitter = extend_address_to_32(&deps.api.addr_canonicalize(&info.sender.as_str())?); + let sequence = sequence_read(deps.storage, emitter.as_slice()); + sequence_set(deps.storage, emitter.as_slice(), sequence + 1)?; - let sequence = sequence_read(&deps.storage, emitter.as_slice()); - sequence_set(&mut deps.storage, emitter.as_slice(), sequence + 1)?; - - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("message.message", hex::encode(message)), - log("message.sender", hex::encode(emitter)), - log("message.chain_id", CHAIN_ID), - log("message.nonce", nonce), - log("message.sequence", sequence), - log("message.block_time", env.block.time), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("message.message", hex::encode(message)) + .add_attribute("message.sender", hex::encode(emitter)) + .add_attribute("message.chain_id", CHAIN_ID.to_string()) + .add_attribute("message.nonce", nonce.to_string()) + .add_attribute("message.sequence", sequence.to_string()) + .add_attribute("message.block_time", env.block.time.seconds().to_string())) } -pub fn query( - deps: &Extern, - msg: QueryMsg, -) -> StdResult { +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::GuardianSetInfo {} => to_binary(&query_guardian_set_info(deps)?), QueryMsg::VerifyVAA { vaa, block_time } => to_binary(&query_parse_and_verify_vaa( @@ -378,11 +360,9 @@ pub fn query( } } -pub fn query_guardian_set_info( - deps: &Extern, -) -> StdResult { - let state = config_read(&deps.storage).load()?; - let guardian_set = guardian_set_get(&deps.storage, state.guardian_set_index)?; +pub fn query_guardian_set_info(deps: Deps) -> StdResult { + let state = config_read(deps.storage).load()?; + let guardian_set = guardian_set_get(deps.storage, state.guardian_set_index)?; let res = GuardianSetInfoResponse { guardian_set_index: state.guardian_set_index, addresses: guardian_set.addresses, @@ -390,33 +370,28 @@ pub fn query_guardian_set_info( Ok(res) } -pub fn query_parse_and_verify_vaa( - deps: &Extern, +pub fn query_parse_and_verify_vaa( + deps: Deps, data: &[u8], block_time: u64, ) -> StdResult { - parse_and_verify_vaa(&deps.storage, data, block_time) + parse_and_verify_vaa(deps.storage, data, block_time) } // returns the hex of the 32 byte address we use for some address on this chain -pub fn query_address_hex( - deps: &Extern, - address: &HumanAddr, -) -> StdResult { +pub fn query_address_hex(deps: Deps, address: &HumanAddr) -> StdResult { Ok(GetAddressHexResponse { - hex: hex::encode(extend_address_to_32(&deps.api.canonical_address(&address)?)), + hex: hex::encode(extend_address_to_32(&deps.api.addr_canonicalize(&address)?)), }) } -pub fn query_state( - deps: &Extern, -) -> StdResult { - let state = config_read(&deps.storage).load()?; +pub fn query_state(deps: Deps) -> StdResult { + let state = config_read(deps.storage).load()?; let res = GetStateResponse { fee: state.fee }; Ok(res) } -fn keys_equal(a: &VerifyKey, b: &GuardianAddress) -> bool { +fn keys_equal(a: &VerifyingKey, b: &GuardianAddress) -> bool { let mut hasher = Keccak256::new(); let point: EncodedPoint = EncodedPoint::from(a); diff --git a/terra/contracts/wormhole/src/error.rs b/terra/contracts/wormhole/src/error.rs index 2975eafc4..67603f5d9 100644 --- a/terra/contracts/wormhole/src/error.rs +++ b/terra/contracts/wormhole/src/error.rs @@ -104,7 +104,6 @@ impl ContractError { pub fn std(&self) -> StdError { StdError::GenericErr { msg: format!("{}", self), - backtrace: None, } } diff --git a/terra/contracts/wormhole/src/lib.rs b/terra/contracts/wormhole/src/lib.rs index 9117b3f19..610d16ed2 100644 --- a/terra/contracts/wormhole/src/lib.rs +++ b/terra/contracts/wormhole/src/lib.rs @@ -5,6 +5,3 @@ pub mod msg; pub mod state; pub use crate::error::ContractError; - -#[cfg(all(target_arch = "wasm32", not(feature = "library")))] -cosmwasm_std::create_entry_points!(contract); diff --git a/terra/contracts/wormhole/src/msg.rs b/terra/contracts/wormhole/src/msg.rs index 0bfc5c13f..9653c052c 100644 --- a/terra/contracts/wormhole/src/msg.rs +++ b/terra/contracts/wormhole/src/msg.rs @@ -1,7 +1,6 @@ use cosmwasm_std::{ Binary, Coin, - HumanAddr, }; use schemars::JsonSchema; use serde::{ @@ -14,8 +13,10 @@ use crate::state::{ GuardianSetInfo, }; +type HumanAddr = String; + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InitMsg { +pub struct InstantiateMsg { pub gov_chain: u16, pub gov_address: Binary, @@ -25,11 +26,16 @@ pub struct InitMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub enum HandleMsg { +pub enum ExecuteMsg { SubmitVAA { vaa: Binary }, PostMessage { message: Binary, nonce: u32 }, } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct MigrateMsg { +} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { diff --git a/terra/contracts/wormhole/src/state.rs b/terra/contracts/wormhole/src/state.rs index e8abe94e7..43cacbff2 100644 --- a/terra/contracts/wormhole/src/state.rs +++ b/terra/contracts/wormhole/src/state.rs @@ -1,6 +1,5 @@ use schemars::{ JsonSchema, - Set, }; use serde::{ Deserialize, @@ -11,7 +10,6 @@ use cosmwasm_std::{ Binary, CanonicalAddr, Coin, - HumanAddr, StdResult, Storage, Uint128, @@ -37,6 +35,8 @@ use sha3::{ Keccak256, }; +type HumanAddr = String; + pub static CONFIG_KEY: &[u8] = b"config"; pub static GUARDIAN_SET_KEY: &[u8] = b"guardian_set"; pub static SEQUENCE_KEY: &[u8] = b"sequence"; @@ -217,62 +217,62 @@ pub struct WormholeInfo { pub guardian_set_expirity: u64, } -pub fn config(storage: &mut S) -> Singleton { +pub fn config(storage: &mut dyn Storage) -> Singleton { singleton(storage, CONFIG_KEY) } -pub fn config_read(storage: &S) -> ReadonlySingleton { +pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton { singleton_read(storage, CONFIG_KEY) } -pub fn guardian_set_set( - storage: &mut S, +pub fn guardian_set_set( + storage: &mut dyn Storage, index: u32, data: &GuardianSetInfo, ) -> StdResult<()> { - bucket(GUARDIAN_SET_KEY, storage).save(&index.to_be_bytes(), data) + bucket(storage, GUARDIAN_SET_KEY).save(&index.to_be_bytes(), data) } -pub fn guardian_set_get(storage: &S, index: u32) -> StdResult { - bucket_read(GUARDIAN_SET_KEY, storage).load(&index.to_be_bytes()) +pub fn guardian_set_get(storage: &dyn Storage, index: u32) -> StdResult { + bucket_read(storage, GUARDIAN_SET_KEY).load(&index.to_be_bytes()) } -pub fn sequence_set(storage: &mut S, emitter: &[u8], sequence: u64) -> StdResult<()> { - bucket(SEQUENCE_KEY, storage).save(emitter, &sequence) +pub fn sequence_set(storage: &mut dyn Storage, emitter: &[u8], sequence: u64) -> StdResult<()> { + bucket(storage, SEQUENCE_KEY).save(emitter, &sequence) } -pub fn sequence_read(storage: &S, emitter: &[u8]) -> u64 { - bucket_read(SEQUENCE_KEY, storage) +pub fn sequence_read(storage: &dyn Storage, emitter: &[u8]) -> u64 { + bucket_read(storage, SEQUENCE_KEY) .load(&emitter) .or::(Ok(0)) .unwrap() } -pub fn vaa_archive_add(storage: &mut S, hash: &[u8]) -> StdResult<()> { - bucket(GUARDIAN_SET_KEY, storage).save(hash, &true) +pub fn vaa_archive_add(storage: &mut dyn Storage, hash: &[u8]) -> StdResult<()> { + bucket(storage, GUARDIAN_SET_KEY).save(hash, &true) } -pub fn vaa_archive_check(storage: &S, hash: &[u8]) -> bool { - bucket_read(GUARDIAN_SET_KEY, storage) +pub fn vaa_archive_check(storage: &dyn Storage, hash: &[u8]) -> bool { + bucket_read(storage, GUARDIAN_SET_KEY) .load(&hash) .or::(Ok(false)) .unwrap() } -pub fn wrapped_asset(storage: &mut S) -> Bucket { - bucket(WRAPPED_ASSET_KEY, storage) +pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket { + bucket(storage, WRAPPED_ASSET_KEY) } -pub fn wrapped_asset_read(storage: &S) -> ReadonlyBucket { - bucket_read(WRAPPED_ASSET_KEY, storage) +pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket { + bucket_read(storage, WRAPPED_ASSET_KEY) } -pub fn wrapped_asset_address(storage: &mut S) -> Bucket> { - bucket(WRAPPED_ASSET_ADDRESS_KEY, storage) +pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket> { + bucket(storage, WRAPPED_ASSET_ADDRESS_KEY) } -pub fn wrapped_asset_address_read(storage: &S) -> ReadonlyBucket> { - bucket_read(WRAPPED_ASSET_ADDRESS_KEY, storage) +pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket> { + bucket_read(storage, WRAPPED_ASSET_ADDRESS_KEY) } pub struct GovernancePacket { @@ -299,12 +299,27 @@ impl GovernancePacket { } } +// action 1 +pub struct ContractUpgrade { + pub new_contract: u64, +} + // action 2 pub struct GuardianSetUpgrade { pub new_guardian_set_index: u32, pub new_guardian_set: GuardianSetInfo, } +impl ContractUpgrade { + pub fn deserialize(data: &Vec) -> StdResult { + let data = data.as_slice(); + let new_contract = data.get_u64(24); + Ok(ContractUpgrade { + new_contract, + }) + } +} + impl GuardianSetUpgrade { pub fn deserialize(data: &Vec) -> StdResult { const ADDRESS_LEN: usize = 20; @@ -351,7 +366,7 @@ impl SetFee { let (_, amount) = data.get_u256(0); let fee = Coin { denom: String::from(FEE_DENOMINATION), - amount: Uint128(amount), + amount: Uint128::new(amount), }; Ok(SetFee { fee }) } @@ -371,7 +386,7 @@ impl TransferFee { let (_, amount) = data.get_u256(32); let amount = Coin { denom: String::from(FEE_DENOMINATION), - amount: Uint128(amount), + amount: Uint128::new(amount), }; Ok(TransferFee { amount, recipient }) } diff --git a/terra/tools/deploy.js b/terra/tools/deploy.js index 92f66a51d..95a2f3156 100644 --- a/terra/tools/deploy.js +++ b/terra/tools/deploy.js @@ -1,5 +1,10 @@ import { Wallet, LCDClient, MnemonicKey } from "@terra-money/terra.js"; -import { StdFee, MsgInstantiateContract, MsgExecuteContract, MsgStoreCode } from "@terra-money/terra.js"; +import { + StdFee, + MsgInstantiateContract, + MsgExecuteContract, + MsgStoreCode, +} from "@terra-money/terra.js"; import { readFileSync, readdirSync } from "fs"; // TODO: Workaround /tx/estimate_fee errors. @@ -37,139 +42,191 @@ async function main() { await wallet.sequence(); // Deploy WASM blobs. - const artifacts = readdirSync('../artifacts/'); + // Read a list of files from directory containing compiled contracts. + const artifacts = readdirSync("../artifacts/"); + + // Sort them to get a determinstic list for consecutive code ids. artifacts.sort(); + artifacts.reverse(); + + const hardcodedGas = { + "cw20_base.wasm": 4000000, + "cw20_wrapped.wasm": 4000000, + "wormhole.wasm": 5000000, + "token_bridge.wasm": 6000000, + }; + + // Deploy all found WASM files and assign Code IDs. + const codeIds = {}; for (const artifact in artifacts) { - console.log(artifact); - console.log(artifacts.hasOwnProperty(artifact)); - if(artifacts.hasOwnProperty(artifact) && artifacts[artifact].includes('.wasm')) { - const file = artifacts[artifact]; - const contract_bytes = readFileSync(`../artifacts/${file}`); - console.log(`Storing Bytes, ${contract_bytes.length}, for ${file}`); - const store_code = new MsgStoreCode( - wallet.key.accAddress, - contract_bytes.toString('base64'), - ); + if ( + artifacts.hasOwnProperty(artifact) && + artifacts[artifact].includes(".wasm") + ) { + const file = artifacts[artifact]; + const contract_bytes = readFileSync(`../artifacts/${file}`); - try { - const tx = await wallet.createAndSignTx({ - msgs: [store_code], - memo: '', - fee: new StdFee( - 3000000, - { uluna: "100000" } - ) - }); + console.log(`Storing WASM: ${file} (${contract_bytes.length} bytes)`); - const rs = await terra.tx.broadcast(tx); + const store_code = new MsgStoreCode( + wallet.key.accAddress, + contract_bytes.toString("base64") + ); - console.log(JSON.stringify(rs, null, 2)); - await wallet.sequence(); - } catch (e) { - console.log('Failed to Execute'); - } + try { + const tx = await wallet.createAndSignTx({ + msgs: [store_code], + memo: "", + fee: new StdFee(hardcodedGas[artifacts[artifact]], { + uluna: "100000", + }), + }); + + const rs = await terra.tx.broadcast(tx); + const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1]; + codeIds[file] = parseInt(ci); + } catch (e) { + console.log("Failed to Execute"); + } } } + console.log(codeIds); + + // Governance constants defined by the Wormhole spec. const govChain = 1; - const govAddress = "0000000000000000000000000000000000000000000000000000000000000004"; + const govAddress = + "0000000000000000000000000000000000000000000000000000000000000004"; + const addresses = {}; - //Instantiate Contracts - wallet.createAndSignTx({ + // Instantiate Wormhole + console.log("Instantiating Wormhole"); + await wallet + .createAndSignTx({ msgs: [ new MsgInstantiateContract( - wallet.key.accAddress, - undefined, - 2, - { - gov_chain: govChain, - gov_address: Buffer.from(govAddress, 'hex').toString('base64'), - guardian_set_expirity: 86400, - initial_guardian_set: { - addresses: [ - { - bytes: Buffer.from('beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe', 'hex').toString('base64'), - } - ], - expiration_time: 0 + wallet.key.accAddress, + wallet.key.accAddress, + codeIds["wormhole.wasm"], + { + gov_chain: govChain, + gov_address: Buffer.from(govAddress, "hex").toString("base64"), + guardian_set_expirity: 86400, + initial_guardian_set: { + addresses: [ + { + bytes: Buffer.from( + "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe", + "hex" + ).toString("base64"), }, + ], + expiration_time: 0, }, - ) - ], - memo:'', - }) - .then(tx => terra.tx.broadcast(tx)) - .then(rs => console.log(rs)); + } + ), + ], + memo: "", + }) + .then((tx) => terra.tx.broadcast(tx)) + .then((rs) => { + const address = /"contract_address","value":"([^"]+)/gm.exec( + rs.raw_log + )[1]; + addresses["wormhole.wasm"] = address; + }); - wallet.createAndSignTx({ + console.log("Instantiating Token Bridge"); + await wallet + .createAndSignTx({ msgs: [ new MsgInstantiateContract( - wallet.key.accAddress, - undefined, - 4, - { - owner: deployer.key.accAddress, - gov_chain: govChain, - gov_address: Buffer.from(govAddress, 'hex').toString('base64'), - wormhole_contract: "", - wrapped_asset_code_id: 2, - }, - ) - ], - memo:'', - }) - .then(tx => terra.tx.broadcast(tx)) - .then(rs => console.log(rs)); + wallet.key.accAddress, + wallet.key.accAddress, + codeIds["token_bridge.wasm"], + { + owner: wallet.key.accAddress, + gov_chain: govChain, + gov_address: Buffer.from(govAddress, "hex").toString("base64"), + wormhole_contract: addresses["wormhole.wasm"], + wrapped_asset_code_id: 2, + } + ), + ], + memo: "", + }) + .then((tx) => terra.tx.broadcast(tx)) + .then((rs) => { + const address = /"contract_address","value":"([^"]+)/gm.exec( + rs.raw_log + )[1]; + addresses["token_bridge.wasm"] = address; + }); - wallet.createAndSignTx({ + await wallet + .createAndSignTx({ msgs: [ new MsgInstantiateContract( - wallet.key.accAddress, - undefined, - 3, - { - name: "MOCK", - symbol: "MCK", - decimals: 6, - initial_balances: [ - { - "address": deployer.key.acc_address, - "amount": "100000000" - } - ], - mint: null, - }, - ) - ], - memo:'', - }) - .then(tx => terra.tx.broadcast(tx)) - .then(rs => console.log(rs)); + wallet.key.accAddress, + undefined, + codeIds["cw20_base.wasm"], + { + name: "MOCK", + symbol: "MCK", + decimals: 6, + initial_balances: [ + { + address: wallet.key.accAddress, + amount: "100000000", + }, + ], + mint: null, + } + ), + ], + memo: "", + }) + .then((tx) => terra.tx.broadcast(tx)) + .then((rs) => { + const address = /"contract_address","value":"([^"]+)/gm.exec( + rs.raw_log + )[1]; + addresses["mock.wasm"] = address; + }); + + console.log(addresses); const registrations = [ - '01000000000100c9f4230109e378f7efc0605fb40f0e1869f2d82fda5b1dfad8a5a2dafee85e033d155c18641165a77a2db6a7afbf2745b458616cb59347e89ae0c7aa3e7cc2d400000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e4272696467650100000001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f', - '01000000000100e2e1975d14734206e7a23d90db48a6b5b6696df72675443293c6057dcb936bf224b5df67d32967adeb220d4fe3cb28be515be5608c74aab6adb31099a478db5c01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e42726964676501000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16' + "01000000000100c9f4230109e378f7efc0605fb40f0e1869f2d82fda5b1dfad8a5a2dafee85e033d155c18641165a77a2db6a7afbf2745b458616cb59347e89ae0c7aa3e7cc2d400000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e4272696467650100000001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f", + "01000000000100e2e1975d14734206e7a23d90db48a6b5b6696df72675443293c6057dcb936bf224b5df67d32967adeb220d4fe3cb28be515be5608c74aab6adb31099a478db5c01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e42726964676501000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16", ]; - registrations.forEach(registration => { - wallet.createAndSignTx({ - msgs: [ - new MsgExecuteContract( + for (const registration in registrations) { + if (registrations.hasOwnProperty(registration)) { + console.log('Registering'); + await wallet + .createAndSignTx({ + msgs: [ + new MsgExecuteContract( wallet.key.accAddress, - "", + addresses["token_bridge.wasm"], { - submit_vaa: { - data: Buffer.from(registration, 'hex'), - }, + submit_vaa: { + data: Buffer.from(registrations[registration], "hex").toString('base64'), + }, }, { uluna: 1000 } - ), - ], - memo: '', - }) - .then(tx => terra.tx.broadcast(tx)) - .then(rs => console.log(rs)); - }); + ), + ], + memo: "", + fee: new StdFee(2000000, { + uluna: "100000", + }), + }) + .then((tx) => terra.tx.broadcast(tx)) + .then((rs) => console.log(rs)); + } + } } -main() +main(); diff --git a/terra/tools/deploy.sh b/terra/tools/deploy.sh index c125d49da..103079782 100644 --- a/terra/tools/deploy.sh +++ b/terra/tools/deploy.sh @@ -11,5 +11,6 @@ done sleep 2 npm ci && node deploy.js + echo "Going to sleep, interrupt if running manually" sleep infinity diff --git a/terra/tools/migrate.js b/terra/tools/migrate.js new file mode 100644 index 000000000..575b7c695 --- /dev/null +++ b/terra/tools/migrate.js @@ -0,0 +1,133 @@ +import { Wallet, LCDClient, MnemonicKey } from "@terra-money/terra.js"; +import { + StdFee, + MsgExecuteContract, + MsgInstantiateContract, + MsgMigrateContract, + MsgStoreCode, + MsgUpdateContractAdmin, +} from "@terra-money/terra.js"; +import { readFileSync, readdirSync } from "fs"; + +async function main() { + const terra = new LCDClient({ + URL: "http://localhost:1317", + chainID: "localterra", + }); + + const wallet = terra.wallet( + new MnemonicKey({ + 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", + }) + ); + + const hardcodedGas = { + "wormhole.wasm": 5000000, + }; + + // Deploy Wormhole alone. + const file = "wormhole.wasm"; + const contract_bytes = readFileSync(`../artifacts/${file}`); + console.log(`Storing WASM: ${file} (${contract_bytes.length} bytes)`); + + // Get new code id. + const store_code = new MsgStoreCode( + wallet.key.accAddress, + contract_bytes.toString("base64") + ); + + const codeIds = {}; + try { + const tx = await wallet.createAndSignTx({ + msgs: [store_code], + memo: "", + fee: new StdFee(hardcodedGas["wormhole.wasm"], { + uluna: "100000", + }), + }); + + const rs = await terra.tx.broadcast(tx); + const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1]; + codeIds[file] = parseInt(ci); + } catch (e) { + console.log("Failed to Execute"); + } + + // Perform a Centralised update. + await wallet + .createAndSignTx({ + msgs: [ + new MsgMigrateContract( + wallet.key.accAddress, + "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5", + codeIds["wormhole.wasm"], + { + "action": "" + }, + { uluna: 1000 } + ), + ], + memo: "", + }) + .then((tx) => terra.tx.broadcast(tx)) + .then((rs) => console.log(rs)); + + // Set the Admin to the contract. + await wallet + .createAndSignTx({ + msgs: [ + new MsgUpdateContractAdmin( + wallet.key.accAddress, + "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5", + "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5" + ), + ], + memo: "", + }) + .then((tx) => terra.tx.broadcast(tx)) + .then((rs) => console.log(rs)); + + // Deploy a new CodeID. + try { + const tx = await wallet.createAndSignTx({ + msgs: [store_code], + memo: "", + fee: new StdFee(hardcodedGas["wormhole.wasm"], { + uluna: "100000", + }), + }); + + const rs = await terra.tx.broadcast(tx); + const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1]; + codeIds[file] = parseInt(ci); + } catch (e) { + console.log("Failed to Execute"); + } + + const upgradeVAA = '010000000001008928c70a029a924d334a24587e9d2ddbcfa7250d7ba61200e86b16966ef2bbd675fb759aa7a47c6392482ef073e9a6d7c4980dc53ed6f90fc84331486e284912000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000004e78c580000000000000000000000000000000000000000000000000000000000436f72650100030000000000000000000000000000000000000000000000000000000000000005'; + + // Perform a decentralised update with a signed VAA. + await wallet + .createAndSignTx({ + msgs: [ + new MsgExecuteContract( + wallet.key.accAddress, + "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5", + { + submit_v_a_a: { + vaa: Buffer.from(upgradeVAA, "hex").toString( + "base64" + ), + }, + }, + { uluna: 1000 } + ), + ], + memo: "", + }) + .then((tx) => terra.tx.broadcast(tx)) + .then((rs) => console.log(rs)); +} + +main();