From 0ebc458bc1492511277cf541bd9b3e613543bc36 Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 13 Dec 2023 11:24:58 +0100 Subject: [PATCH 01/40] use creator for withdraw address --- Cargo.lock | 200 +++++++++++------- Cargo.toml | 4 +- contracts/cw721-tester/src/lib.rs | 1 + packages/ics721/src/execute.rs | 12 +- .../ics721/src/testing/integration_tests.rs | 79 ++++--- 5 files changed, 183 insertions(+), 113 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49c4a4a6..bd6d6182 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ dependencies = [ [[package]] name = "bnum" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128a44527fc0d6abf05f9eda748b9027536e12dff93f5acc8449f51583309350" +checksum = "ab9008b6bb9fc80b5277f2fe481c09e828743d9151203e804583eb4c9e15b31d" [[package]] name = "byteorder" @@ -233,16 +233,16 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e2c2f2c0877b839c5cad85e67811074e854a50c1ff3085eb8290b1c27809c" +checksum = "6a710459f7cd15dc322db4ecd7ab6c8fda6ffbe06faf1843cc63023f9c190b76" dependencies = [ "anyhow", "cosmwasm-std", "cw-storage-plus 1.2.0", - "cw-utils 1.0.2", + "cw-utils 1.0.3", "derivative", - "itertools", + "itertools 0.12.0", "prost", "schemars", "serde", @@ -261,7 +261,7 @@ dependencies = [ "cw-address-like", "cw-ownable-derive", "cw-storage-plus 1.2.0", - "cw-utils 1.0.2", + "cw-utils 1.0.3", "thiserror", ] @@ -279,7 +279,7 @@ dependencies = [ [[package]] name = "cw-paginate-storage" version = "2.3.0" -source = "git+https://github.com/DA0-DA0/dao-contracts.git#1187dbac2729bc0504a3d39b7f617773a8a5b6ad" +source = "git+https://github.com/DA0-DA0/dao-contracts.git#4cc8cc4afdd74e12ba7e69daf5a17caa333f72be" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -294,7 +294,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", - "cw-utils 1.0.2", + "cw-utils 1.0.3", "thiserror", ] @@ -350,13 +350,13 @@ dependencies = [ [[package]] name = "cw-utils" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9f351a4e4d81ef7c890e44d903f8c0bdcdc00f094fd3a181eaf70c0eec7a3a" +checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2 1.1.1", + "cw2 1.1.2", "schemars", "semver", "serde", @@ -378,14 +378,15 @@ dependencies = [ [[package]] name = "cw2" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9431d14f64f49e41c6ef5561ed11a5391c417d0cb16455dea8cdcb9037a8d197" +checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", "schemars", + "semver", "serde", "thiserror", ] @@ -411,7 +412,19 @@ checksum = "e3c4d286625ccadc957fe480dd3bdc54ada19e0e6b5b9325379db3130569e914" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils 1.0.2", + "cw-utils 1.0.3", + "schemars", + "serde", +] + +[[package]] +name = "cw721" +version = "0.18.0" +source = "git+https://github.com/arkprotocol/cw-nfts?branch=fee_share#1c081d84cbeaec28cae62f4f82ea8ff86a92259d" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 1.0.3", "schemars", "serde", ] @@ -443,9 +456,27 @@ dependencies = [ "cosmwasm-std", "cw-ownable", "cw-storage-plus 1.2.0", - "cw-utils 1.0.2", - "cw2 1.1.1", - "cw721 0.18.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.16.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw721-base" +version = "0.18.0" +source = "git+https://github.com/arkprotocol/cw-nfts?branch=fee_share#1c081d84cbeaec28cae62f4f82ea8ff86a92259d" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ownable", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", "cw721-base 0.16.0", "schemars", "serde", @@ -460,7 +491,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", - "cw721 0.18.0", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721-proxy-derive", "thiserror", ] @@ -470,7 +501,7 @@ name = "cw721-proxy-derive" version = "0.0.1" source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.0.7#a433953f4d4f605a7b472f9cb31b5068dcad3e28" dependencies = [ - "cw721 0.18.0", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", "quote", "syn 1.0.109", @@ -485,8 +516,8 @@ dependencies = [ "cosmwasm-std", "cw-rate-limiter", "cw-storage-plus 1.2.0", - "cw2 1.1.1", - "cw721 0.18.0", + "cw2 1.1.2", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721-proxy", "cw721-proxy-derive", "serde", @@ -500,8 +531,8 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", - "cw2 1.1.1", - "cw721-base 0.18.0", + "cw2 1.1.2", + "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", "thiserror", ] @@ -590,9 +621,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" -version = "0.13.7" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9775b22bc152ad86a0cf23f0f348b884b26add12bf741e7ffc4d4ab2ab4d205" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", @@ -619,9 +650,9 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -703,12 +734,12 @@ dependencies = [ "cw-paginate-storage", "cw-pause-once", "cw-storage-plus 1.2.0", - "cw-utils 1.0.2", - "cw2 1.1.1", + "cw-utils 1.0.3", + "cw2 1.1.2", "cw721 0.16.0", - "cw721 0.18.0", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", "cw721-base 0.16.0", - "cw721-base 0.18.0", + "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", "cw721-proxy-derive", "cw721-rate-limited-proxy", "serde", @@ -722,7 +753,7 @@ name = "ics721-base" version = "0.1.0" dependencies = [ "cosmwasm-std", - "cw2 1.1.1", + "cw2 1.1.2", "ics721", ] @@ -734,17 +765,17 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "cw-storage-plus 1.2.0", - "cw2 1.1.1", - "cw721 0.18.0", + "cw2 1.1.2", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", "ics721", "thiserror", ] [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -759,11 +790,20 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "k256" @@ -781,15 +821,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -799,9 +839,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pkcs8" @@ -815,18 +855,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5a410fc7882af66deb8d01d01737353cf3ad6204c408177ba494291a626312" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" dependencies = [ "bytes", "prost-derive", @@ -834,15 +874,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065717a5dfaca4a83d2fe57db3487b311365200000551d7a364e715dbf4346bc" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -881,9 +921,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "schemars" @@ -931,9 +971,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -949,13 +989,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -992,9 +1032,9 @@ dependencies = [ "cw-multi-test", "cw-pause-once", "cw-storage-plus 1.2.0", - "cw2 1.1.1", - "cw721 0.18.0", - "cw721-base 0.18.0", + "cw2 1.1.2", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", + "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", "cw721-rate-limited-proxy", "ics721", "sg-std", @@ -1011,8 +1051,8 @@ checksum = "4db53aebc2b4f981dc20a51213544adde8beaace6880345627f4babe2e1bc3ab" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils 1.0.2", - "cw721 0.18.0", + "cw-utils 1.0.3", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "schemars", "serde", "thiserror", @@ -1027,8 +1067,8 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-ownable", - "cw-utils 1.0.2", - "cw721-base 0.18.0", + "cw-utils 1.0.3", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "thiserror", ] @@ -1043,10 +1083,10 @@ dependencies = [ "cosmwasm-std", "cw-ownable", "cw-storage-plus 1.2.0", - "cw-utils 1.0.2", - "cw2 1.1.1", - "cw721 0.18.0", - "cw721-base 0.18.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "sg-std", "sg721", @@ -1090,9 +1130,9 @@ dependencies = [ [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -1123,9 +1163,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -1149,7 +1189,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -1175,9 +1215,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-ident" @@ -1196,9 +1236,9 @@ dependencies = [ [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", diff --git a/Cargo.toml b/Cargo.toml index 2a8f4f1d..1dcd86e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,9 @@ cw-ownable = "0.5.0" cw-paginate-storage = { version = "2.2.0", git = "https://github.com/DA0-DA0/dao-contracts.git" } cw-storage-plus = "1.1" cw2 = "1.1" -cw721 = "0.18" +cw721 = { git = "https://github.com/arkprotocol/cw-nfts", branch = "fee_share"} cw721-016 = { version = "0.16.0", package = "cw721" } -cw721-base = "0.18" +cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "fee_share"} cw721-base-016 = { version = "0.16.0", package = "cw721-base" } cw721-proxy-derive = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } cw721-rate-limited-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } diff --git a/contracts/cw721-tester/src/lib.rs b/contracts/cw721-tester/src/lib.rs index e793ca10..ed686b1e 100644 --- a/contracts/cw721-tester/src/lib.rs +++ b/contracts/cw721-tester/src/lib.rs @@ -40,6 +40,7 @@ pub fn instantiate( name: msg.name, symbol: msg.symbol, minter: msg.minter, + withdraw_address: None, }, )?; TARGET.save(deps.storage, &deps.api.addr_validate(&msg.target)?)?; diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 990ae8ec..e8a3ff3e 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -1,8 +1,8 @@ use std::fmt::Debug; use cosmwasm_std::{ - from_json, to_json_binary, Addr, Binary, Deps, DepsMut, Empty, Env, IbcMsg, MessageInfo, - Response, StdResult, SubMsg, WasmMsg, + from_json, to_json_binary, Addr, Binary, ContractInfoResponse, Deps, DepsMut, Empty, Env, + IbcMsg, MessageInfo, Response, StdResult, SubMsg, WasmMsg, }; use serde::{de::DeserializeOwned, Serialize}; use sha2::{Digest, Sha256}; @@ -325,12 +325,18 @@ where } /// Default implementation using `cw721_base::msg::InstantiateMsg` - fn init_msg(&self, _deps: Deps, env: &Env, class: &Class) -> StdResult { + fn init_msg(&self, deps: Deps, env: &Env, class: &Class) -> StdResult { + // use ics721 creator for withdraw address + let ContractInfoResponse { creator, .. } = deps + .querier + .query_wasm_contract_info(env.contract.address.to_string())?; + // use by default ClassId, in case there's no class data with name and symbol let mut instantiate_msg = cw721_base::msg::InstantiateMsg { name: class.id.clone().into(), symbol: class.id.clone().into(), minter: env.contract.address.to_string(), + withdraw_address: Some(creator), }; // use collection data for setting name and symbol diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index c5dcd607..57a6fb33 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -284,6 +284,7 @@ impl Test { proxy: bool, admin_and_pauser: Option, cw721_code: Box>, + is_cw721_018: bool, ) -> Self { let mut app = AppBuilder::new() .with_wasm::>( @@ -331,20 +332,37 @@ impl Test { .unwrap(); let source_cw721_owner = app.api().addr_make(COLLECTION_OWNER_SOURCE_CHAIN); - let source_cw721 = app - .instantiate_contract( - source_cw721_id, - source_cw721_owner.clone(), - &Cw721InstantiateMsg { - name: "name".to_string(), - symbol: "symbol".to_string(), - minter: source_cw721_owner.to_string(), - }, - &[], - "cw721-base", - None, - ) - .unwrap(); + let source_cw721 = match is_cw721_018 { + true => app + .instantiate_contract( + source_cw721_id, + source_cw721_owner.clone(), + &Cw721InstantiateMsg { + name: "name".to_string(), + symbol: "symbol".to_string(), + minter: source_cw721_owner.to_string(), + withdraw_address: None, + }, + &[], + "cw721-base", + None, + ) + .unwrap(), + false => app + .instantiate_contract( + source_cw721_id, + source_cw721_owner.clone(), + &cw721_base_016::msg::InstantiateMsg { + name: "name".to_string(), + symbol: "symbol".to_string(), + minter: source_cw721_owner.to_string(), + }, + &[], + "cw721-base", + None, + ) + .unwrap(), + }; Self { app, @@ -509,7 +527,7 @@ fn proxy_contract() -> Box> { #[test] fn test_instantiate() { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); // check stores are properly initialized let cw721_id = test.query_cw721_id(); @@ -524,7 +542,7 @@ fn test_instantiate() { #[test] fn test_do_instantiate_and_mint_weird_data() { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -575,7 +593,7 @@ fn test_do_instantiate_and_mint_weird_data() { fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with no ClassData (without owner, name, and symbol) { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -714,7 +732,7 @@ fn test_do_instantiate_and_mint() { } // test case: instantiate cw721 with ClassData containing owner, name, and symbol { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -869,7 +887,7 @@ fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with CustomClassData (includes name, but without owner and symbol) // results in nft contract using class id for name and symbol { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1023,7 +1041,7 @@ fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with PartialCustomCollectionData (includes name and symbol) // results in nft contract using name and symbol { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1183,7 +1201,7 @@ fn test_do_instantiate_and_mint() { fn test_do_instantiate_and_mint_2_different_collections() { // test case: instantiate two cw721 contracts with different class id and make sure instantiate2 creates 2 different, predictable contracts { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain_1 = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id_1 = format!( @@ -1450,7 +1468,7 @@ fn test_do_instantiate_and_mint_2_different_collections() { #[test] fn test_do_instantiate_and_mint_no_instantiate() { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1558,7 +1576,7 @@ fn test_do_instantiate_and_mint_no_instantiate() { #[test] fn test_do_instantiate_and_mint_permissions() { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1612,7 +1630,7 @@ fn test_do_instantiate_and_mint_permissions() { /// Tests that we can not proxy NFTs if no proxy is configured. #[test] fn test_no_proxy_unauthorized() { - let mut test = Test::new(false, None, cw721_base_contract()); + let mut test = Test::new(false, None, cw721_base_contract(), true); let err: ContractError = test .app .execute_contract( @@ -1636,7 +1654,7 @@ fn test_no_proxy_unauthorized() { #[test] fn test_proxy_authorized() { - let mut test = Test::new(true, None, cw721_base_contract()); + let mut test = Test::new(true, None, cw721_base_contract(), true); let proxy_address: Option = test .app .wrap() @@ -1660,6 +1678,7 @@ fn test_proxy_authorized() { .api() .addr_make(COLLECTION_OWNER_SOURCE_CHAIN) .to_string(), + withdraw_address: None, }, &[], "label cw721", @@ -1719,7 +1738,9 @@ fn test_proxy_authorized() { fn test_receive_nft() { // test case: receive nft from cw721-base { - let mut test = Test::new(false, None, cw721_base_contract()); + println!(">>>>>>>>>>>>1"); + let mut test = Test::new(false, None, cw721_base_contract(), true); + println!(">>>>>>>>>>>>2"); // simplify: mint and escrowed/owned by ics721, as a precondition for receive nft let token_id = test.execute_cw721_mint(test.ics721.clone()).unwrap(); // ics721 receives NFT from sender/collection contract, @@ -1787,7 +1808,7 @@ fn test_receive_nft() { } // test case: backward compatibility - receive nft also works for old/v016 cw721-base { - let mut test = Test::new(false, None, cw721_v016_base_contract()); + let mut test = Test::new(false, None, cw721_v016_base_contract(), false); // simplify: mint and escrowed/owned by ics721, as a precondition for receive nft let token_id = test.execute_cw721_mint(test.ics721.clone()).unwrap(); // ics721 receives NFT from sender/collection contract, @@ -1861,7 +1882,7 @@ fn test_receive_nft() { /// In case proxy for ICS721 is defined, ICS721 only accepts receival from proxy - not from nft contract! #[test] fn test_no_receive_with_proxy() { - let mut test = Test::new(true, None, cw721_base_contract()); + let mut test = Test::new(true, None, cw721_base_contract(), true); // unauthorized to receive nft from nft contract let err: ContractError = test .app @@ -1897,6 +1918,7 @@ fn test_pause() { true, Some(ICS721_ADMIN_AND_PAUSER.to_string()), cw721_base_contract(), + true, ); // Should start unpaused. let (paused, pauser) = test.query_pause_info(); @@ -1979,6 +2001,7 @@ fn test_migration() { true, Some(ICS721_ADMIN_AND_PAUSER.to_string()), cw721_base_contract(), + true, ); // assert instantiation worked let (_, pauser) = test.query_pause_info(); From 659c87ecbdb6c0148d8f287641f6a5428247eaa4 Mon Sep 17 00:00:00 2001 From: mr-t Date: Thu, 28 Dec 2023 14:49:43 +0100 Subject: [PATCH 02/40] update branch --- Cargo.lock | 52 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 4 ++-- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd6d6182..51009dbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" [[package]] name = "base16ct" @@ -87,9 +87,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cosmwasm-crypto" @@ -278,8 +278,8 @@ dependencies = [ [[package]] name = "cw-paginate-storage" -version = "2.3.0" -source = "git+https://github.com/DA0-DA0/dao-contracts.git#4cc8cc4afdd74e12ba7e69daf5a17caa333f72be" +version = "2.4.0" +source = "git+https://github.com/DA0-DA0/dao-contracts.git#3ead037e9366d922c862614974b16b4dc732b329" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -420,7 +420,7 @@ dependencies = [ [[package]] name = "cw721" version = "0.18.0" -source = "git+https://github.com/arkprotocol/cw-nfts?branch=fee_share#1c081d84cbeaec28cae62f4f82ea8ff86a92259d" +source = "git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address#8691baf71422448b50d98bc5e516b9115dc13336" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -468,7 +468,7 @@ dependencies = [ [[package]] name = "cw721-base" version = "0.18.0" -source = "git+https://github.com/arkprotocol/cw-nfts?branch=fee_share#1c081d84cbeaec28cae62f4f82ea8ff86a92259d" +source = "git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address#8691baf71422448b50d98bc5e516b9115dc13336" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -476,7 +476,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "cw721-base 0.16.0", "schemars", "serde", @@ -532,7 +532,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", + "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "thiserror", ] @@ -737,9 +737,9 @@ dependencies = [ "cw-utils 1.0.3", "cw2 1.1.2", "cw721 0.16.0", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "cw721-base 0.16.0", - "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", + "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "cw721-proxy-derive", "cw721-rate-limited-proxy", "serde", @@ -766,7 +766,7 @@ dependencies = [ "cosmwasm-storage", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "ics721", "thiserror", ] @@ -855,9 +855,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" dependencies = [ "unicode-ident", ] @@ -882,7 +882,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.43", ] [[package]] @@ -995,7 +995,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.43", ] [[package]] @@ -1033,8 +1033,8 @@ dependencies = [ "cw-pause-once", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", - "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=fee_share)", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "cw721-rate-limited-proxy", "ics721", "sg-std", @@ -1163,9 +1163,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" dependencies = [ "proc-macro2", "quote", @@ -1174,22 +1174,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.43", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1dcd86e3..92c694df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,9 @@ cw-ownable = "0.5.0" cw-paginate-storage = { version = "2.2.0", git = "https://github.com/DA0-DA0/dao-contracts.git" } cw-storage-plus = "1.1" cw2 = "1.1" -cw721 = { git = "https://github.com/arkprotocol/cw-nfts", branch = "fee_share"} +cw721 = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdrawal_address"} # TODO switch to official repo, once merged cw721-016 = { version = "0.16.0", package = "cw721" } -cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "fee_share"} +cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdrawal_address"} # TODO switch to official repo, once merged cw721-base-016 = { version = "0.16.0", package = "cw721-base" } cw721-proxy-derive = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } cw721-rate-limited-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } From d74b39df52978807011ab609487182794c00a02a Mon Sep 17 00:00:00 2001 From: mr-t Date: Thu, 28 Dec 2023 15:48:57 +0100 Subject: [PATCH 03/40] use cw721-base with withdraw address --- e2e/callback_test.go | 2 ++ e2e/suite_test.go | 2 ++ e2e/types.go | 1 + external-wasms/cw721_base_v0.18.0.wasm | Bin 307271 -> 327759 bytes 4 files changed, 5 insertions(+) diff --git a/e2e/callback_test.go b/e2e/callback_test.go index d0520b55..f3f9a087 100644 --- a/e2e/callback_test.go +++ b/e2e/callback_test.go @@ -70,6 +70,7 @@ func (suite *CbTestSuite) SetupTest() { "bad/kids", "bad/kids", suite.chainA.SenderAccount.GetAddress().String(), + nil, } instantiateRaw, err := json.Marshal(cw721Instantiate) require.NoError(suite.T(), err) @@ -133,6 +134,7 @@ func (suite *CbTestSuite) SetupTest() { "bad/kids", "bad/kids", suite.chainA.SenderAccount.GetAddress().String(), + nil, } instantiateRaw, err := json.Marshal(cw721Instantiate) require.NoError(suite.T(), err) diff --git a/e2e/suite_test.go b/e2e/suite_test.go index 32140034..5f578fa4 100644 --- a/e2e/suite_test.go +++ b/e2e/suite_test.go @@ -114,6 +114,7 @@ func (suite *TransferTestSuite) TestIBCSendNFT() { "bad/kids", "bad/kids", suite.chainA.SenderAccount.GetAddress().String(), + nil, } instantiateRaw, err := json.Marshal(cw721Instantiate) require.NoError(suite.T(), err) @@ -280,6 +281,7 @@ func instantiateCw721(t *testing.T, chain *wasmibctesting.TestChain) sdk.AccAddr "bad/kids", "bad/kids", chain.SenderAccount.GetAddress().String(), + nil, } instantiateRaw, err := json.Marshal(cw721Instantiate) require.NoError(t, err) diff --git a/e2e/types.go b/e2e/types.go index c69776c6..da4d44c1 100644 --- a/e2e/types.go +++ b/e2e/types.go @@ -33,6 +33,7 @@ type InstantiateCw721 struct { Name string `json:"name"` Symbol string `json:"symbol"` Minter string `json:"minter"` + WithdrawAddress *string `json:"withdraw_address"` } type InstantiateBridgeTester struct { diff --git a/external-wasms/cw721_base_v0.18.0.wasm b/external-wasms/cw721_base_v0.18.0.wasm index 74fba98ca0ac692e98ee46d1d4839a9157a04358..86f066963d17797150c0623ff47d3a6aa8817a20 100644 GIT binary patch literal 327759 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
l3#U7 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 Xh$#GW8Ac36SUE- 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%0AmrJM1c$I_igx*q_o7yJH>Er?b)#%`}=X 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 From 3a06220b02de4a9b49a829459fb2478ad57f878e Mon Sep 17 00:00:00 2001 From: mr-t Date: Thu, 28 Dec 2023 15:59:32 +0100 Subject: [PATCH 04/40] fix tests --- e2e/adversarial_test.go | 4 ++-- e2e/suite_test.go | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/adversarial_test.go b/e2e/adversarial_test.go index c4ce761a..57d95ac9 100644 --- a/e2e/adversarial_test.go +++ b/e2e/adversarial_test.go @@ -244,7 +244,7 @@ func (suite *AdversarialTestSuite) TestInvalidOnMineValidOnTheirs() { ics721Nft(suite.T(), suite.chainA, suite.pathAC, suite.coordinator, chainACw721, "bad kid 1", suite.bridgeA, suite.chainA.SenderAccount.GetAddress(), suite.chainC.SenderAccount.GetAddress(), "") err = suite.chainA.SmartQuery(chainACw721, OwnerOfQuery{OwnerOf: OwnerOfQueryData{TokenID: suite.tokenIdA}}, &OwnerOfResponse{}) - require.ErrorContains(suite.T(), err, "cw721_base::state::TokenInfo> not found") + require.ErrorContains(suite.T(), err, "cw721_base::state::TokenInfo>; key: [00, 06, 74, 6F, 6B, 65, 6E, 73, 62, 61, 64, 20, 6B, 69, 64, 20, 31] not found") // Send the NFT back, this time setting new metadata for the // class ID. @@ -477,7 +477,7 @@ func (suite *AdversarialTestSuite) TestMetadataForwarding() { require.ErrorContains( suite.T(), err, - "cw721_base::state::TokenInfo> not found", + "cw721_base::state::TokenInfo>; key: [00, 06, 74, 6F, 6B, 65, 6E, 73, 62, 61, 64, 20, 6B, 69, 64, 20, 31] not found", ) // Check that token metadata was cleared. diff --git a/e2e/suite_test.go b/e2e/suite_test.go index 5f578fa4..77d6b2d2 100644 --- a/e2e/suite_test.go +++ b/e2e/suite_test.go @@ -487,7 +487,7 @@ func TestSendBetweenThreeIdenticalChains(t *testing.T) { // contract "is this burned" so we just query and make sure it // now errors with a storage load failure. err := chainA.SmartQuery(chainANftDerivative, OwnerOfQuery{OwnerOf: OwnerOfQueryData{TokenID: "bad kid 1"}}, &OwnerOfResponse{}) - require.ErrorContains(t, err, "cw721_base::state::TokenInfo> not found") + require.ErrorContains(t, err, "cw721_base::state::TokenInfo>; key: [00, 06, 74, 6F, 6B, 65, 6E, 73, 62, 61, 64, 20, 6B, 69, 64, 20, 31] not found") // NFT should belong to chainC sender on chain C. ownerC = queryGetOwnerOf(t, chainC, chainCNft, "bad kid 1") @@ -503,7 +503,7 @@ func TestSendBetweenThreeIdenticalChains(t *testing.T) { // Burned on C. err = chainC.SmartQuery(chainCNft, OwnerOfQuery{OwnerOf: OwnerOfQueryData{TokenID: "bad kid 1"}}, &OwnerOfResponse{}) - require.ErrorContains(t, err, "cw721_base::state::TokenInfo> not found") + require.ErrorContains(t, err, "cw721_base::state::TokenInfo>; key: [00, 06, 74, 6F, 6B, 65, 6E, 73, 62, 61, 64, 20, 6B, 69, 64, 20, 31] not found") // B -> A path = getPath(1, 0) @@ -515,7 +515,7 @@ func TestSendBetweenThreeIdenticalChains(t *testing.T) { // Burned on chain B. err = chainB.SmartQuery(chainBNft, OwnerOfQuery{OwnerOf: OwnerOfQueryData{TokenID: "bad kid 1"}}, &OwnerOfResponse{}) - require.ErrorContains(t, err, "cw721_base::state::TokenInfo> not found") + require.ErrorContains(t, err, "cw721_base::state::TokenInfo>; key: [00, 06, 74, 6F, 6B, 65, 6E, 73, 62, 61, 64, 20, 6B, 69, 64, 20, 31] not found") // Hooray! We have completed the journey between three // identical blockchains using our ICS721 contract. @@ -571,7 +571,7 @@ func (suite *TransferTestSuite) TestMultipleAddressesInvolved() { // Make sure the NFT was burned on chain B err = suite.chainB.SmartQuery(chainBNft, OwnerOfQuery{OwnerOf: OwnerOfQueryData{TokenID: "bad kid 1"}}, &OwnerOfResponse{}) - require.ErrorContains(suite.T(), err, "cw721_base::state::TokenInfo> not found") + require.ErrorContains(suite.T(), err, "cw721_base::state::TokenInfo>; key: [00, 06, 74, 6F, 6B, 65, 6E, 73, 62, 61, 64, 20, 6B, 69, 64, 20, 31] not found") // Make another account on chain B and transfer to the new account. anotherAcount := CreateAndFundAccount(suite.T(), suite.chainB, 19) @@ -589,7 +589,7 @@ func (suite *TransferTestSuite) TestMultipleAddressesInvolved() { // Make sure it was burned on B. err = suite.chainB.SmartQuery(chainBNft, OwnerOfQuery{OwnerOf: OwnerOfQueryData{TokenID: "bad kid 1"}}, &OwnerOfResponse{}) - require.ErrorContains(suite.T(), err, "cw721_base::state::TokenInfo> not found") + require.ErrorContains(suite.T(), err, "cw721_base::state::TokenInfo>; key: [00, 06, 74, 6F, 6B, 65, 6E, 73, 62, 61, 64, 20, 6B, 69, 64, 20, 31] not found") // Make sure it is owned by the correct address on A. resp := OwnerOfResponse{} From 3b6aac10d46a108c3c97a6d87e7f9af1c1d96ca3 Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 12 Dec 2023 12:34:49 +0100 Subject: [PATCH 05/40] rename proxy > outgoing proxy --- .../src/testing/integration_tests.rs | 2 +- packages/ics721/src/execute.rs | 29 +++++++++++-------- packages/ics721/src/ibc.rs | 12 ++++---- packages/ics721/src/msg.rs | 2 +- packages/ics721/src/query.rs | 4 +-- packages/ics721/src/state.rs | 2 +- packages/ics721/src/testing/ibc_tests.rs | 2 +- .../ics721/src/testing/integration_tests.rs | 2 +- 8 files changed, 30 insertions(+), 25 deletions(-) diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index f77f1094..a1051502 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -319,7 +319,7 @@ impl Test { app.api().addr_make(ICS721_CREATOR), &InstantiateMsg { cw721_base_code_id: source_cw721_id, - proxy, + outgoing_proxy: proxy, pauser: admin_and_pauser .clone() .map(|p| app.api().addr_make(&p).to_string()), diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index e8a3ff3e..cb7a37b4 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -9,12 +9,14 @@ use sha2::{Digest, Sha256}; use crate::{ helpers::get_instantiate2_address, - ibc::{NonFungibleTokenPacketData, INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_PROXY_REPLY_ID}, + ibc::{ + NonFungibleTokenPacketData, INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, + }, msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg}, state::{ CollectionData, UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, - CW721_CODE_ID, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO, PROXY, - TOKEN_METADATA, + CW721_CODE_ID, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, + PO, TOKEN_METADATA, }, token_types::{Class, ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}, ContractError, @@ -34,13 +36,13 @@ where msg: InstantiateMsg, ) -> StdResult> { CW721_CODE_ID.save(deps.storage, &msg.cw721_base_code_id)?; - PROXY.save(deps.storage, &None)?; + OUTGOING_PROXY.save(deps.storage, &None)?; PO.set_pauser(deps.storage, deps.api, msg.pauser.as_deref())?; let proxy_instantiate = msg - .proxy + .outgoing_proxy .map(|m| m.into_wasm_msg(env.contract.address)) - .map(|wasm| SubMsg::reply_on_success(wasm, INSTANTIATE_PROXY_REPLY_ID)) + .map(|wasm| SubMsg::reply_on_success(wasm, INSTANTIATE_OUTGOING_PROXY_REPLY_ID)) .map_or(vec![], |s| vec![s]); Ok(Response::default() @@ -80,7 +82,7 @@ where sender: String, msg: Binary, ) -> Result, ContractError> { - if PROXY.load(deps.storage)?.is_some() { + if OUTGOING_PROXY.load(deps.storage)?.is_some() { Err(ContractError::Unauthorized {}) } else { self.receive_nft(deps, env, info, TokenId::new(token_id), sender, msg) @@ -95,7 +97,7 @@ where eyeball: String, msg: cw721::Cw721ReceiveMsg, ) -> Result, ContractError> { - if PROXY + if OUTGOING_PROXY .load(deps.storage)? .map_or(true, |proxy| info.sender != proxy) { @@ -429,12 +431,12 @@ where match msg { MigrateMsg::WithUpdate { pauser, - proxy, + proxy: outgoing_proxy, cw721_base_code_id, } => { - PROXY.save( + OUTGOING_PROXY.save( deps.storage, - &proxy + &outgoing_proxy .as_ref() .map(|h| deps.api.addr_validate(h)) .transpose()?, @@ -446,7 +448,10 @@ where Ok(Response::default() .add_attribute("method", "migrate") .add_attribute("pauser", pauser.map_or_else(|| "none".to_string(), |or| or)) - .add_attribute("proxy", proxy.map_or_else(|| "none".to_string(), |or| or)) + .add_attribute( + "outgoing_proxy", + outgoing_proxy.map_or_else(|| "none".to_string(), |or| or), + ) .add_attribute( "cw721_base_code_id", cw721_base_code_id.map_or_else(|| "none".to_string(), |or| or.to_string()), diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index 4365bea5..5b0701f5 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -14,7 +14,7 @@ use crate::{ ibc_packet_receive::receive_ibc_packet, state::{ CLASS_ID_TO_NFT_CONTRACT, INCOMING_CLASS_TOKEN_TO_CHANNEL, NFT_CONTRACT_TO_CLASS_ID, - OUTGOING_CLASS_TOKEN_TO_CHANNEL, PROXY, TOKEN_METADATA, + OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, TOKEN_METADATA, }, token_types::{ClassId, TokenId}, types::Ics721Status, @@ -24,7 +24,7 @@ use crate::{ /// Submessage reply ID used for instantiating cw721 contracts. pub(crate) const INSTANTIATE_CW721_REPLY_ID: u64 = 0; /// Submessage reply ID used for instantiating the proxy contract. -pub(crate) const INSTANTIATE_PROXY_REPLY_ID: u64 = 1; +pub(crate) const INSTANTIATE_OUTGOING_PROXY_REPLY_ID: u64 = 1; /// Submessages dispatched with this reply ID will set the ack on the /// response depending on if the submessage execution succeded or /// failed. @@ -286,14 +286,14 @@ where .add_attribute("class_id", class_id) .add_attribute("cw721_addr", cw721_addr)) } - INSTANTIATE_PROXY_REPLY_ID => { + INSTANTIATE_OUTGOING_PROXY_REPLY_ID => { let res = parse_reply_instantiate_data(reply)?; let proxy_addr = deps.api.addr_validate(&res.contract_address)?; - PROXY.save(deps.storage, &Some(proxy_addr))?; + OUTGOING_PROXY.save(deps.storage, &Some(proxy_addr))?; Ok(Response::default() - .add_attribute("method", "instantiate_proxy_reply_id") - .add_attribute("proxy", res.contract_address)) + .add_attribute("method", "instantiate_outgoing_proxy_reply_id") + .add_attribute("outgoing_proxy", res.contract_address)) } // These messages don't need to do any state changes in the // reply - just need to commit an ack. diff --git a/packages/ics721/src/msg.rs b/packages/ics721/src/msg.rs index 4f84ba69..f2ee89a4 100644 --- a/packages/ics721/src/msg.rs +++ b/packages/ics721/src/msg.rs @@ -19,7 +19,7 @@ pub struct InstantiateMsg { /// will only accept NFTs from that proxy. The proxy is expected /// to implement the cw721 proxy interface defined in the /// cw721-proxy crate. - pub proxy: Option, + pub outgoing_proxy: Option, /// Address that may pause the contract. PAUSER may pause the /// contract a single time; in pausing the contract they burn the /// right to do so again. A new pauser may be later nominated by diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index 408220c9..b48b64d8 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -6,7 +6,7 @@ use crate::{ state::{ UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, - PO, PROXY, TOKEN_METADATA, + OUTGOING_PROXY, PO, TOKEN_METADATA, }, token_types::{Class, ClassId, Token, TokenId}, }; @@ -31,7 +31,7 @@ pub trait Ics721Query { } QueryMsg::Pauser {} => to_json_binary(&PO.query_pauser(deps.storage)?), QueryMsg::Paused {} => to_json_binary(&PO.query_paused(deps.storage)?), - QueryMsg::Proxy {} => to_json_binary(&PROXY.load(deps.storage)?), + QueryMsg::Proxy {} => to_json_binary(&OUTGOING_PROXY.load(deps.storage)?), QueryMsg::Cw721CodeId {} => to_json_binary(&self.query_cw721_code_id(deps)?), QueryMsg::NftContracts { start_after, limit } => { to_json_binary(&self.query_nft_contracts(deps, start_after, limit)?) diff --git a/packages/ics721/src/state.rs b/packages/ics721/src/state.rs index 8a17b4a1..d41d6493 100644 --- a/packages/ics721/src/state.rs +++ b/packages/ics721/src/state.rs @@ -9,7 +9,7 @@ use crate::token_types::{Class, ClassId, TokenId}; /// The code ID we will use for instantiating new cw721s. pub const CW721_CODE_ID: Item = Item::new("a"); /// The proxy that this contract is receiving NFTs from, if any. -pub const PROXY: Item> = Item::new("b"); +pub const OUTGOING_PROXY: Item> = Item::new("b"); /// Manages contract pauses. pub const PO: PauseOrchestrator = PauseOrchestrator::new("c", "d"); diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index b8092f48..686b9ce6 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -105,7 +105,7 @@ fn add_channel(mut deps: DepsMut, env: Env, channel_id: &str) { fn do_instantiate(deps: DepsMut, env: Env, sender: &str) -> StdResult { let msg = InstantiateMsg { cw721_base_code_id: CW721_CODE_ID, - proxy: None, + outgoing_proxy: None, pauser: None, }; Ics721Contract::default().instantiate(deps, env, mock_info(sender, &[]), msg) diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 57a6fb33..731c3fa8 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -320,7 +320,7 @@ impl Test { app.api().addr_make(ICS721_CREATOR), &InstantiateMsg { cw721_base_code_id: source_cw721_id, - proxy, + outgoing_proxy: proxy, pauser: admin_and_pauser .clone() .map(|p| app.api().addr_make(&p).to_string()), From de167a33e818a830367ff922edf9aa06dae31c96 Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 12 Dec 2023 12:44:09 +0100 Subject: [PATCH 06/40] fix test --- e2e/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/types.go b/e2e/types.go index da4d44c1..3d6cb37a 100644 --- a/e2e/types.go +++ b/e2e/types.go @@ -25,7 +25,7 @@ type ModuleInstantiateInfo struct { type InstantiateICS721Bridge struct { CW721CodeID uint64 `json:"cw721_base_code_id"` - Proxy *ModuleInstantiateInfo `json:"proxy"` + Proxy *ModuleInstantiateInfo `json:"outgoing_proxy"` Pauser *string `json:"pauser"` } From 26ee9147ebaff1ff6397066129c3d413befcc59a Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 12 Dec 2023 13:53:14 +0100 Subject: [PATCH 07/40] update libs --- Cargo.lock | 5 +- Cargo.toml | 22 +- contracts/cw721-tester/Cargo.lock | 738 ------------------ contracts/ics721-base-tester/Cargo.lock | 738 ------------------ contracts/ics721-base/Cargo.lock | 738 ------------------ contracts/sg-ics721/Cargo.lock | 738 ------------------ .../src/testing/integration_tests.rs | 3 +- .../ics721/src/testing/integration_tests.rs | 3 +- 8 files changed, 18 insertions(+), 2967 deletions(-) delete mode 100644 contracts/cw721-tester/Cargo.lock delete mode 100644 contracts/ics721-base-tester/Cargo.lock delete mode 100644 contracts/ics721-base/Cargo.lock delete mode 100644 contracts/sg-ics721/Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index 51009dbd..9863b06c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -233,11 +233,12 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.18.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a710459f7cd15dc322db4ecd7ab6c8fda6ffbe06faf1843cc63023f9c190b76" +checksum = "67fff029689ae89127cf6d7655809a68d712f3edbdb9686c70b018ba438b26ca" dependencies = [ "anyhow", + "bech32", "cosmwasm-std", "cw-storage-plus 1.2.0", "cw-utils 1.0.3", diff --git a/Cargo.toml b/Cargo.toml index 92c694df..033a5ce0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,12 +7,12 @@ edition = "2021" [workspace.dependencies] # common libs -anyhow = "1.0" +anyhow = "^1.0" bech32 = "^0.9" -cosmwasm-std = "1.2" -cosmwasm-schema = "1.2" -cosmwasm-storage = "1.2" -cw-ownable = "0.5.0" +cosmwasm-std = "^1.5" +cosmwasm-schema = "^1.5" +cosmwasm-storage = "^1.5" +cw-ownable = "^0.5" cw-paginate-storage = { version = "2.2.0", git = "https://github.com/DA0-DA0/dao-contracts.git" } cw-storage-plus = "1.1" cw2 = "1.1" @@ -22,16 +22,16 @@ cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdra cw721-base-016 = { version = "0.16.0", package = "cw721-base" } cw721-proxy-derive = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } cw721-rate-limited-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } -cw-multi-test = { version = "0.18", features = ["cosmwasm_1_2"] } -cw-utils = "1.0" +cw-multi-test = { version = "^0.20", features = ["cosmwasm_1_2"] } +cw-utils = "^1.0" sha2 = "^0.10" -serde = "1.0" -thiserror = "1" +serde = "^1.0" +thiserror = "^1.0" # Stargaze libs sg-std = "^3.2" sg-multi-test = "^3.1" -sg721 = "^3.1" -sg721-base = "^3.1" +sg721 = "^3.3" +sg721-base = "^3.3" # packages and contracts cw-cii = { path = "./packages/cw-cii" } cw-pause-once = { path = "./packages/cw-pause-once" } diff --git a/contracts/cw721-tester/Cargo.lock b/contracts/cw721-tester/Cargo.lock deleted file mode 100644 index 91fb09ff..00000000 --- a/contracts/cw721-tester/Cargo.lock +++ /dev/null @@ -1,738 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "base64ct" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "const-oid" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" - -[[package]] -name = "cosmwasm-crypto" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd" -dependencies = [ - "digest", - "ed25519-zebra", - "k256", - "rand_core 0.6.3", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" -dependencies = [ - "syn", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772e80bbad231a47a2068812b723a1ff81dd4a0d56c9391ac748177bea3a61da" -dependencies = [ - "schemars", - "serde_json", -] - -[[package]] -name = "cosmwasm-std" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195" -dependencies = [ - "base64", - "cosmwasm-crypto", - "cosmwasm-derive", - "forward_ref", - "schemars", - "serde", - "serde-json-wasm", - "thiserror", - "uint", -] - -[[package]] -name = "cosmwasm-storage" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5" -dependencies = [ - "cosmwasm-std", - "serde", -] - -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" -dependencies = [ - "generic-array", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "cw-multi-test" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbea57e5be4a682268a5eca1a57efece57a54ff216bfd87603d5e864aad40e12" -dependencies = [ - "anyhow", - "cosmwasm-std", - "cosmwasm-storage", - "cw-storage-plus", - "cw-utils", - "derivative", - "itertools", - "prost", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-storage-plus" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-utils" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babd2c090f39d07ce5bf2556962305e795daa048ce20a93709eb591476e4a29e" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993df11574f29574dd443eb0c189484bb91bc0638b6de3e32ab7f9319c92122d" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - -[[package]] -name = "der" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" -dependencies = [ - "const-oid", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "dyn-clone" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" - -[[package]] -name = "ecdsa" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", -] - -[[package]] -name = "ed25519-zebra" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" -dependencies = [ - "curve25519-dalek", - "hex", - "rand_core 0.6.3", - "serde", - "sha2", - "thiserror", - "zeroize", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "elliptic-curve" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" -dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "ff", - "generic-array", - "group", - "rand_core 0.6.3", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ff" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" -dependencies = [ - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "forward_ref" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "group" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" -dependencies = [ - "ff", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" - -[[package]] -name = "k256" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sec1", - "sha2", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "pkcs8" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" -dependencies = [ - "der", - "spki", - "zeroize", -] - -[[package]] -name = "proc-macro2" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[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 = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.6", -] - -[[package]] -name = "rfc6979" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" -dependencies = [ - "crypto-bigint", - "hmac", - "zeroize", -] - -[[package]] -name = "ryu" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" - -[[package]] -name = "schemars" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d21ecb263bf75fc69d5e74b0f2a60b6dd80cfd9fb0eba15c4b9d1104ceffc77" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219b924f5b39f25b7d7c9203873a2698fdac8db2b396aaea6fa099b699cc40e9" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn", -] - -[[package]] -name = "sec1" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" -dependencies = [ - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "serde" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-json-wasm" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer", - "cfg-if", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "signature" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" -dependencies = [ - "digest", - "rand_core 0.6.3", -] - -[[package]] -name = "spki" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "testgen-local" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cosmwasm-storage", - "cw-multi-test", - "cw-storage-plus", - "cw2", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "thiserror" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "uint" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-ident" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "zeroize" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" diff --git a/contracts/ics721-base-tester/Cargo.lock b/contracts/ics721-base-tester/Cargo.lock deleted file mode 100644 index 42783426..00000000 --- a/contracts/ics721-base-tester/Cargo.lock +++ /dev/null @@ -1,738 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "base64ct" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "const-oid" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" - -[[package]] -name = "cosmwasm-crypto" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd" -dependencies = [ - "digest", - "ed25519-zebra", - "k256", - "rand_core 0.6.3", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" -dependencies = [ - "syn", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772e80bbad231a47a2068812b723a1ff81dd4a0d56c9391ac748177bea3a61da" -dependencies = [ - "schemars", - "serde_json", -] - -[[package]] -name = "cosmwasm-std" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195" -dependencies = [ - "base64", - "cosmwasm-crypto", - "cosmwasm-derive", - "forward_ref", - "schemars", - "serde", - "serde-json-wasm", - "thiserror", - "uint", -] - -[[package]] -name = "cosmwasm-storage" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5" -dependencies = [ - "cosmwasm-std", - "serde", -] - -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" -dependencies = [ - "generic-array", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "cw-ibc-example" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cosmwasm-storage", - "cw-multi-test", - "cw-storage-plus", - "cw2", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-multi-test" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbea57e5be4a682268a5eca1a57efece57a54ff216bfd87603d5e864aad40e12" -dependencies = [ - "anyhow", - "cosmwasm-std", - "cosmwasm-storage", - "cw-storage-plus", - "cw-utils", - "derivative", - "itertools", - "prost", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-storage-plus" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-utils" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babd2c090f39d07ce5bf2556962305e795daa048ce20a93709eb591476e4a29e" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993df11574f29574dd443eb0c189484bb91bc0638b6de3e32ab7f9319c92122d" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - -[[package]] -name = "der" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" -dependencies = [ - "const-oid", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "dyn-clone" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" - -[[package]] -name = "ecdsa" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", -] - -[[package]] -name = "ed25519-zebra" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" -dependencies = [ - "curve25519-dalek", - "hex", - "rand_core 0.6.3", - "serde", - "sha2", - "thiserror", - "zeroize", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "elliptic-curve" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" -dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "ff", - "generic-array", - "group", - "rand_core 0.6.3", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ff" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" -dependencies = [ - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "forward_ref" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "group" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" -dependencies = [ - "ff", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" - -[[package]] -name = "k256" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sec1", - "sha2", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "pkcs8" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" -dependencies = [ - "der", - "spki", - "zeroize", -] - -[[package]] -name = "proc-macro2" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[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 = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.6", -] - -[[package]] -name = "rfc6979" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" -dependencies = [ - "crypto-bigint", - "hmac", - "zeroize", -] - -[[package]] -name = "ryu" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" - -[[package]] -name = "schemars" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d21ecb263bf75fc69d5e74b0f2a60b6dd80cfd9fb0eba15c4b9d1104ceffc77" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219b924f5b39f25b7d7c9203873a2698fdac8db2b396aaea6fa099b699cc40e9" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn", -] - -[[package]] -name = "sec1" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" -dependencies = [ - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "serde" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-json-wasm" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer", - "cfg-if", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "signature" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" -dependencies = [ - "digest", - "rand_core 0.6.3", -] - -[[package]] -name = "spki" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "uint" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-ident" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "zeroize" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" diff --git a/contracts/ics721-base/Cargo.lock b/contracts/ics721-base/Cargo.lock deleted file mode 100644 index f3f526cb..00000000 --- a/contracts/ics721-base/Cargo.lock +++ /dev/null @@ -1,738 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "base64ct" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "const-oid" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" - -[[package]] -name = "cosmwasm-crypto" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd" -dependencies = [ - "digest", - "ed25519-zebra", - "k256", - "rand_core 0.6.3", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" -dependencies = [ - "syn", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772e80bbad231a47a2068812b723a1ff81dd4a0d56c9391ac748177bea3a61da" -dependencies = [ - "schemars", - "serde_json", -] - -[[package]] -name = "cosmwasm-std" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195" -dependencies = [ - "base64", - "cosmwasm-crypto", - "cosmwasm-derive", - "forward_ref", - "schemars", - "serde", - "serde-json-wasm", - "thiserror", - "uint", -] - -[[package]] -name = "cosmwasm-storage" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5" -dependencies = [ - "cosmwasm-std", - "serde", -] - -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" -dependencies = [ - "generic-array", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "cw-ics721" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cosmwasm-storage", - "cw-multi-test", - "cw-storage-plus", - "cw2", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-multi-test" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbea57e5be4a682268a5eca1a57efece57a54ff216bfd87603d5e864aad40e12" -dependencies = [ - "anyhow", - "cosmwasm-std", - "cosmwasm-storage", - "cw-storage-plus", - "cw-utils", - "derivative", - "itertools", - "prost", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-storage-plus" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-utils" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babd2c090f39d07ce5bf2556962305e795daa048ce20a93709eb591476e4a29e" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993df11574f29574dd443eb0c189484bb91bc0638b6de3e32ab7f9319c92122d" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - -[[package]] -name = "der" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" -dependencies = [ - "const-oid", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "dyn-clone" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" - -[[package]] -name = "ecdsa" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", -] - -[[package]] -name = "ed25519-zebra" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" -dependencies = [ - "curve25519-dalek", - "hex", - "rand_core 0.6.3", - "serde", - "sha2", - "thiserror", - "zeroize", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "elliptic-curve" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" -dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "ff", - "generic-array", - "group", - "rand_core 0.6.3", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ff" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" -dependencies = [ - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "forward_ref" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "group" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" -dependencies = [ - "ff", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" - -[[package]] -name = "k256" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sec1", - "sha2", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "pkcs8" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" -dependencies = [ - "der", - "spki", - "zeroize", -] - -[[package]] -name = "proc-macro2" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[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 = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.6", -] - -[[package]] -name = "rfc6979" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" -dependencies = [ - "crypto-bigint", - "hmac", - "zeroize", -] - -[[package]] -name = "ryu" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" - -[[package]] -name = "schemars" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d21ecb263bf75fc69d5e74b0f2a60b6dd80cfd9fb0eba15c4b9d1104ceffc77" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219b924f5b39f25b7d7c9203873a2698fdac8db2b396aaea6fa099b699cc40e9" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn", -] - -[[package]] -name = "sec1" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" -dependencies = [ - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "serde" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-json-wasm" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer", - "cfg-if", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "signature" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" -dependencies = [ - "digest", - "rand_core 0.6.3", -] - -[[package]] -name = "spki" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "uint" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-ident" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "zeroize" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" diff --git a/contracts/sg-ics721/Cargo.lock b/contracts/sg-ics721/Cargo.lock deleted file mode 100644 index f3f526cb..00000000 --- a/contracts/sg-ics721/Cargo.lock +++ /dev/null @@ -1,738 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "base64ct" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "const-oid" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" - -[[package]] -name = "cosmwasm-crypto" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd" -dependencies = [ - "digest", - "ed25519-zebra", - "k256", - "rand_core 0.6.3", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" -dependencies = [ - "syn", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772e80bbad231a47a2068812b723a1ff81dd4a0d56c9391ac748177bea3a61da" -dependencies = [ - "schemars", - "serde_json", -] - -[[package]] -name = "cosmwasm-std" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195" -dependencies = [ - "base64", - "cosmwasm-crypto", - "cosmwasm-derive", - "forward_ref", - "schemars", - "serde", - "serde-json-wasm", - "thiserror", - "uint", -] - -[[package]] -name = "cosmwasm-storage" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5" -dependencies = [ - "cosmwasm-std", - "serde", -] - -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" -dependencies = [ - "generic-array", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "cw-ics721" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cosmwasm-storage", - "cw-multi-test", - "cw-storage-plus", - "cw2", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-multi-test" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbea57e5be4a682268a5eca1a57efece57a54ff216bfd87603d5e864aad40e12" -dependencies = [ - "anyhow", - "cosmwasm-std", - "cosmwasm-storage", - "cw-storage-plus", - "cw-utils", - "derivative", - "itertools", - "prost", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-storage-plus" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-utils" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babd2c090f39d07ce5bf2556962305e795daa048ce20a93709eb591476e4a29e" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993df11574f29574dd443eb0c189484bb91bc0638b6de3e32ab7f9319c92122d" -dependencies = [ - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - -[[package]] -name = "der" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" -dependencies = [ - "const-oid", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "dyn-clone" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" - -[[package]] -name = "ecdsa" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", -] - -[[package]] -name = "ed25519-zebra" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" -dependencies = [ - "curve25519-dalek", - "hex", - "rand_core 0.6.3", - "serde", - "sha2", - "thiserror", - "zeroize", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "elliptic-curve" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" -dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "ff", - "generic-array", - "group", - "rand_core 0.6.3", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ff" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" -dependencies = [ - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "forward_ref" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "group" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" -dependencies = [ - "ff", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest", -] - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" - -[[package]] -name = "k256" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "sec1", - "sha2", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "pkcs8" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" -dependencies = [ - "der", - "spki", - "zeroize", -] - -[[package]] -name = "proc-macro2" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[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 = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.6", -] - -[[package]] -name = "rfc6979" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" -dependencies = [ - "crypto-bigint", - "hmac", - "zeroize", -] - -[[package]] -name = "ryu" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" - -[[package]] -name = "schemars" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d21ecb263bf75fc69d5e74b0f2a60b6dd80cfd9fb0eba15c4b9d1104ceffc77" -dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219b924f5b39f25b7d7c9203873a2698fdac8db2b396aaea6fa099b699cc40e9" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn", -] - -[[package]] -name = "sec1" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" -dependencies = [ - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "serde" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-json-wasm" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer", - "cfg-if", - "cpufeatures", - "digest", - "opaque-debug", -] - -[[package]] -name = "signature" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" -dependencies = [ - "digest", - "rand_core 0.6.3", -] - -[[package]] -name = "spki" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "uint" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-ident" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "zeroize" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index a1051502..ce51c72a 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -11,7 +11,7 @@ use cw721_base::msg::QueryMsg as Cw721QueryMsg; use cw_cii::{Admin, ContractInstantiateInfo}; use cw_multi_test::{ AddressGenerator, App, AppBuilder, BankKeeper, Contract, ContractWrapper, DistributionKeeper, - Executor, FailingModule, IbcAcceptingModule, Router, StakeKeeper, WasmKeeper, + Executor, FailingModule, IbcAcceptingModule, Router, StakeKeeper, StargateFailing, WasmKeeper, }; use cw_pause_once::PauseError; use ics721::{ @@ -49,6 +49,7 @@ type MockRouter = Router< DistributionKeeper, IbcAcceptingModule, FailingModule, + StargateFailing, >; type MockApp = App< diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 731c3fa8..c4193191 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -11,7 +11,7 @@ use cw721_base::msg::{InstantiateMsg as Cw721InstantiateMsg, QueryMsg as Cw721Qu use cw_cii::{Admin, ContractInstantiateInfo}; use cw_multi_test::{ AddressGenerator, App, AppBuilder, BankKeeper, Contract, ContractWrapper, DistributionKeeper, - Executor, FailingModule, IbcAcceptingModule, Router, StakeKeeper, WasmKeeper, + Executor, FailingModule, IbcAcceptingModule, Router, StakeKeeper, StargateFailing, WasmKeeper, }; use cw_pause_once::PauseError; use sha2::{digest::Update, Digest, Sha256}; @@ -49,6 +49,7 @@ type MockRouter = Router< DistributionKeeper, IbcAcceptingModule, FailingModule, + StargateFailing, >; type MockApp = App< From 8b808ee3efdc9e4bda35cc53edcd4a1a65392531 Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 14:24:27 +0100 Subject: [PATCH 08/40] optional incoming proxy --- Cargo.lock | 87 ++- Cargo.toml | 7 +- contracts/sg-ics721/Cargo.toml | 3 +- .../src/testing/integration_tests.rs | 118 ++-- e2e/adversarial_test.go | 1 + e2e/callback_test.go | 1 + e2e/suite_test.go | 3 + e2e/test.sh | 2 +- e2e/types.go | 3 +- external-wasms/cw721_incoming_proxy.wasm | Bin 0 -> 181642 bytes packages/cw-pause-once/src/lib.rs | 4 +- packages/ics721/Cargo.toml | 5 +- packages/ics721/schema/ics721.json | 157 ++++- packages/ics721/schema/raw/execute.json | 56 +- packages/ics721/schema/raw/instantiate.json | 25 +- packages/ics721/schema/raw/query.json | 20 +- .../raw/response_to_incoming_proxy.json | 18 + .../raw/response_to_outgoing_proxy.json | 18 + packages/ics721/src/execute.rs | 35 +- packages/ics721/src/ibc.rs | 13 +- packages/ics721/src/ibc_packet_receive.rs | 31 +- packages/ics721/src/msg.rs | 27 +- packages/ics721/src/query.rs | 5 +- packages/ics721/src/state.rs | 6 +- packages/ics721/src/testing/contract.rs | 79 ++- packages/ics721/src/testing/ibc_tests.rs | 3 +- .../ics721/src/testing/integration_tests.rs | 120 ++-- packages/ics721/src/types.rs | 8 +- ts-relayer-tests/build.sh | 2 +- ts-relayer-tests/package-lock.json | 585 +++++++++++------- ts-relayer-tests/package.json | 2 +- ts-relayer-tests/src/controller.ts | 5 +- ts-relayer-tests/src/ics721-utils.ts | 22 + ts-relayer-tests/src/ics721.spec.ts | 72 ++- ts-relayer-tests/src/utils.ts | 19 +- 35 files changed, 1148 insertions(+), 414 deletions(-) create mode 100644 external-wasms/cw721_incoming_proxy.wasm create mode 100644 packages/ics721/schema/raw/response_to_incoming_proxy.json create mode 100644 packages/ics721/schema/raw/response_to_outgoing_proxy.json create mode 100644 ts-relayer-tests/src/ics721-utils.ts diff --git a/Cargo.lock b/Cargo.lock index 9863b06c..33a6edac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,6 +231,34 @@ dependencies = [ "cosmwasm-std", ] +[[package]] +name = "cw-incoming-proxy" +version = "0.0.1" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-incoming-proxy-derive", + "cw-paginate-storage", + "cw-storage-plus 1.2.0", + "ics721-types", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw-incoming-proxy-derive" +version = "0.0.1" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +dependencies = [ + "cosmwasm-std", + "ics721-types", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "cw-multi-test" version = "0.20.0" @@ -302,7 +330,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.0.7#a433953f4d4f605a7b472f9cb31b5068dcad3e28" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -485,22 +513,41 @@ dependencies = [ ] [[package]] -name = "cw721-proxy" +name = "cw721-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.0.7#a433953f4d4f605a7b472f9cb31b5068dcad3e28" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", + "cw-incoming-proxy", + "cw-incoming-proxy-derive", "cw-storage-plus 1.2.0", + "cw2 1.1.2", "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw721-proxy-derive", + "cw721-outgoing-proxy", + "cw721-outgoing-proxy-derive", + "ics721-types", + "serde", + "thiserror", +] + +[[package]] +name = "cw721-outgoing-proxy" +version = "0.0.1" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-outgoing-proxy-derive", "thiserror", ] [[package]] -name = "cw721-proxy-derive" +name = "cw721-outgoing-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.0.7#a433953f4d4f605a7b472f9cb31b5068dcad3e28" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -509,9 +556,9 @@ dependencies = [ ] [[package]] -name = "cw721-rate-limited-proxy" +name = "cw721-outgoing-proxy-rate-limit" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.0.7#a433953f4d4f605a7b472f9cb31b5068dcad3e28" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -519,8 +566,8 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw2 1.1.2", "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw721-proxy", - "cw721-proxy-derive", + "cw721-outgoing-proxy", + "cw721-outgoing-proxy-derive", "serde", "thiserror", ] @@ -741,8 +788,9 @@ dependencies = [ "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "cw721-base 0.16.0", "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", - "cw721-proxy-derive", - "cw721-rate-limited-proxy", + "cw721-incoming-proxy", + "cw721-outgoing-proxy-derive", + "cw721-outgoing-proxy-rate-limit", "serde", "sha2 0.10.8", "thiserror", @@ -772,6 +820,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ics721-types" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#f112d264cdcd81a41a17a5a1ee8617f707a97966" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "serde", + "thiserror", +] + [[package]] name = "idna" version = "0.5.0" @@ -1036,7 +1096,8 @@ dependencies = [ "cw2 1.1.2", "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", - "cw721-rate-limited-proxy", + "cw721-incoming-proxy", + "cw721-outgoing-proxy-rate-limit", "ics721", "sg-std", "sg721", diff --git a/Cargo.toml b/Cargo.toml index 033a5ce0..67ed106f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,15 +13,16 @@ cosmwasm-std = "^1.5" cosmwasm-schema = "^1.5" cosmwasm-storage = "^1.5" cw-ownable = "^0.5" -cw-paginate-storage = { version = "2.2.0", git = "https://github.com/DA0-DA0/dao-contracts.git" } +cw-paginate-storage = { version = "^2.4", git = "https://github.com/DA0-DA0/dao-contracts.git" } cw-storage-plus = "1.1" cw2 = "1.1" cw721 = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdrawal_address"} # TODO switch to official repo, once merged cw721-016 = { version = "0.16.0", package = "cw721" } cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdrawal_address"} # TODO switch to official repo, once merged cw721-base-016 = { version = "0.16.0", package = "cw721-base" } -cw721-proxy-derive = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } -cw721-rate-limited-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.0.7" } +cw721-incoming-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git" } +cw721-outgoing-proxy-derive = { git = "https://github.com/arkprotocol/cw721-proxy.git" } +cw721-outgoing-proxy-rate-limit = { git = "https://github.com/arkprotocol/cw721-proxy.git" } cw-multi-test = { version = "^0.20", features = ["cosmwasm_1_2"] } cw-utils = "^1.0" sha2 = "^0.10" diff --git a/contracts/sg-ics721/Cargo.toml b/contracts/sg-ics721/Cargo.toml index 3bf2602e..d0654bb1 100644 --- a/contracts/sg-ics721/Cargo.toml +++ b/contracts/sg-ics721/Cargo.toml @@ -30,6 +30,7 @@ cw-multi-test = { workspace = true } cw-pause-once = { workspace = true } cw-storage-plus = { workspace = true } cw721 = { workspace = true} -cw721-rate-limited-proxy = { workspace = true } +cw721-incoming-proxy = { workspace = true } +cw721-outgoing-proxy-rate-limit = { workspace = true } cw721-base = { workspace = true} sha2 = { workspace = true } diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index ce51c72a..3427210d 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -282,7 +282,9 @@ struct Test { impl Test { fn new( - proxy: bool, + outgoing_proxy: bool, + incoming_proxy: bool, + source_channels: Option>, admin_and_pauser: Option, cw721_code: Box>, ) -> Self { @@ -296,19 +298,35 @@ impl Test { let source_cw721_id = app.store_code(cw721_code); let ics721_id = app.store_code(ics721_contract()); - use cw721_rate_limited_proxy as rlp; - let proxy = match proxy { + let outgoing_proxy = match outgoing_proxy { true => { - let proxy_id = app.store_code(proxy_contract()); + let proxy_id = app.store_code(outgoing_proxy_contract()); Some(ContractInstantiateInfo { code_id: proxy_id, - msg: to_json_binary(&rlp::msg::InstantiateMsg { - rate_limit: rlp::Rate::PerBlock(10), + msg: to_json_binary(&cw721_outgoing_proxy_rate_limit::msg::InstantiateMsg { + rate_limit: cw721_outgoing_proxy_rate_limit::Rate::PerBlock(10), origin: None, }) .unwrap(), admin: Some(Admin::Instantiator {}), - label: "rate limited proxy".to_string(), + label: "outgoing proxy rate limit".to_string(), + }) + } + false => None, + }; + + let incoming_proxy = match incoming_proxy { + true => { + let proxy_id = app.store_code(incoming_proxy_contract()); + Some(ContractInstantiateInfo { + code_id: proxy_id, + msg: to_json_binary(&cw721_incoming_proxy::msg::InstantiateMsg { + origin: None, + source_channels, + }) + .unwrap(), + admin: Some(Admin::Instantiator {}), + label: "incoming proxy".to_string(), }) } false => None, @@ -320,7 +338,8 @@ impl Test { app.api().addr_make(ICS721_CREATOR), &InstantiateMsg { cw721_base_code_id: source_cw721_id, - outgoing_proxy: proxy, + incoming_proxy, + outgoing_proxy, pauser: admin_and_pauser .clone() .map(|p| app.api().addr_make(&p).to_string()), @@ -406,10 +425,17 @@ impl Test { (paused, pauser) } - fn query_proxy(&mut self) -> Option { + fn query_outgoing_proxy(&mut self) -> Option { + self.app + .wrap() + .query_wasm_smart(self.ics721.clone(), &QueryMsg::OutgoingProxy {}) + .unwrap() + } + + fn query_incoming_proxy(&mut self) -> Option { self.app .wrap() - .query_wasm_smart(self.ics721.clone(), &QueryMsg::Proxy {}) + .query_wasm_smart(self.ics721.clone(), &QueryMsg::IncomingProxy {}) .unwrap() } @@ -514,20 +540,27 @@ fn ics721_contract() -> Box> { Box::new(contract) } -fn proxy_contract() -> Box> { - let execute_fn = cw721_rate_limited_proxy::contract::execute::; - let instatiate_fn = cw721_rate_limited_proxy::contract::instantiate::; +fn incoming_proxy_contract() -> Box> { + let contract = ContractWrapper::new( + cw721_incoming_proxy::contract::execute, + cw721_incoming_proxy::contract::instantiate, + cw721_incoming_proxy::contract::query, + ); + Box::new(contract) +} + +fn outgoing_proxy_contract() -> Box> { let contract = ContractWrapper::new( - execute_fn, - instatiate_fn, - cw721_rate_limited_proxy::contract::query, + cw721_outgoing_proxy_rate_limit::contract::execute, + cw721_outgoing_proxy_rate_limit::contract::instantiate, + cw721_outgoing_proxy_rate_limit::contract::query, ); Box::new(contract) } #[test] fn test_instantiate() { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(true, true, None, None, sg721_base_contract()); // check stores are properly initialized let cw721_id = test.query_cw721_id(); @@ -538,11 +571,15 @@ fn test_instantiate() { assert_eq!(outgoing_channels, []); let incoming_channels = test.query_incoming_channels(); assert_eq!(incoming_channels, []); + let outgoing_proxy = test.query_outgoing_proxy(); + assert!(outgoing_proxy.is_some()); + let incoming_proxy = test.query_incoming_proxy(); + assert!(incoming_proxy.is_some()); } #[test] fn test_do_instantiate_and_mint_weird_data() { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -594,7 +631,7 @@ fn test_do_instantiate_and_mint_weird_data() { fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with no ClassData (without owner, name, and symbol) { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -754,7 +791,7 @@ fn test_do_instantiate_and_mint() { } // test case: instantiate cw721 with ClassData containing owner, name, and symbol { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -931,7 +968,7 @@ fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with CustomClassData (includes name, but without owner and symbol) // results in nft contract using class id for name and symbol { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1106,7 +1143,7 @@ fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with PartialCustomCollectionData (includes name and symbol) // results in nft contract using name and symbol { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1284,7 +1321,7 @@ fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with PartialCustomCollectionData (includes name and symbol) // results in nft contract using name and symbol { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1465,7 +1502,7 @@ fn test_do_instantiate_and_mint() { fn test_do_instantiate_and_mint_2_different_collections() { // test case: instantiate two cw721 contracts with different class id and make sure instantiate2 creates 2 different, predictable contracts { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain_1 = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id_1 = format!( @@ -1770,7 +1807,7 @@ fn test_do_instantiate_and_mint_2_different_collections() { #[test] fn test_do_instantiate_and_mint_no_instantiate() { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1899,7 +1936,7 @@ fn test_do_instantiate_and_mint_no_instantiate() { #[test] fn test_do_instantiate_and_mint_permissions() { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1953,7 +1990,7 @@ fn test_do_instantiate_and_mint_permissions() { /// Tests that we can not proxy NFTs if no proxy is configured. #[test] fn test_no_proxy_unauthorized() { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); let err: ContractError = test .app .execute_contract( @@ -1977,11 +2014,11 @@ fn test_no_proxy_unauthorized() { #[test] fn test_proxy_authorized() { - let mut test = Test::new(true, None, sg721_base_contract()); + let mut test = Test::new(true, false, None, None, sg721_base_contract()); let proxy_address: Option = test .app .wrap() - .query_wasm_smart(&test.ics721, &QueryMsg::Proxy {}) + .query_wasm_smart(&test.ics721, &QueryMsg::OutgoingProxy {}) .unwrap(); // check proxy is set let proxy_address = proxy_address.expect("expected a proxy"); @@ -2071,7 +2108,7 @@ fn test_proxy_authorized() { #[test] fn test_receive_nft() { - let mut test = Test::new(false, None, sg721_base_contract()); + let mut test = Test::new(false, false, None, None, sg721_base_contract()); // simplify: mint and escrowed/owned by ics721, as a precondition for receive nft let token_id = test.execute_cw721_mint(test.ics721.clone()).unwrap(); // ics721 receives NFT from sender/collection contract, @@ -2150,7 +2187,7 @@ fn test_receive_nft() { /// In case proxy for ICS721 is defined, ICS721 only accepts receival from proxy - not from nft contract! #[test] fn test_no_receive_with_proxy() { - let mut test = Test::new(true, None, sg721_base_contract()); + let mut test = Test::new(true, false, None, None, sg721_base_contract()); // unauthorized to receive nft from nft contract let err: ContractError = test .app @@ -2184,6 +2221,8 @@ fn test_no_receive_with_proxy() { fn test_pause() { let mut test = Test::new( true, + false, + None, Some(ICS721_ADMIN_AND_PAUSER.to_string()), sg721_base_contract(), ); @@ -2240,7 +2279,8 @@ fn test_pause() { new_code_id: ics721_id, msg: to_json_binary(&MigrateMsg::WithUpdate { pauser: Some(test.app.api().addr_make("new_pauser").to_string()), - proxy: None, + incoming_proxy: None, + outgoing_proxy: None, cw721_base_code_id: None, }) .unwrap(), @@ -2266,6 +2306,8 @@ fn test_pause() { fn test_migration() { let mut test = Test::new( true, + false, + None, Some(ICS721_ADMIN_AND_PAUSER.to_string()), sg721_base_contract(), ); @@ -2275,7 +2317,7 @@ fn test_migration() { pauser, Some(test.app.api().addr_make(ICS721_ADMIN_AND_PAUSER)) ); - let proxy = test.query_proxy(); + let proxy = test.query_outgoing_proxy(); assert!(proxy.is_some()); let cw721_code_id = test.query_cw721_id(); assert_eq!(cw721_code_id, test.source_cw721_id); @@ -2289,7 +2331,8 @@ fn test_migration() { new_code_id: test.ics721_id, msg: to_json_binary(&MigrateMsg::WithUpdate { pauser: None, - proxy: None, + incoming_proxy: None, + outgoing_proxy: None, cw721_base_code_id: Some(12345678), }) .unwrap(), @@ -2300,7 +2343,7 @@ fn test_migration() { // assert migration worked let (_, pauser) = test.query_pause_info(); assert_eq!(pauser, None); - let proxy = test.query_proxy(); + let proxy = test.query_outgoing_proxy(); assert!(proxy.is_none()); let cw721_code_id = test.query_cw721_id(); assert_eq!(cw721_code_id, 12345678); @@ -2314,7 +2357,8 @@ fn test_migration() { new_code_id: test.ics721_id, msg: to_json_binary(&MigrateMsg::WithUpdate { pauser: None, - proxy: None, + incoming_proxy: None, + outgoing_proxy: None, cw721_base_code_id: None, }) .unwrap(), @@ -2325,7 +2369,7 @@ fn test_migration() { // assert migration worked let (_, pauser) = test.query_pause_info(); assert_eq!(pauser, None); - let proxy = test.query_proxy(); + let proxy = test.query_outgoing_proxy(); assert!(proxy.is_none()); let cw721_code_id = test.query_cw721_id(); assert_eq!(cw721_code_id, 12345678); diff --git a/e2e/adversarial_test.go b/e2e/adversarial_test.go index 57d95ac9..139a0b16 100644 --- a/e2e/adversarial_test.go +++ b/e2e/adversarial_test.go @@ -77,6 +77,7 @@ func (suite *AdversarialTestSuite) SetupTest() { 2, nil, nil, + nil, } instantiateBridgeRaw, err := json.Marshal(instantiateBridge) require.NoError(suite.T(), err) diff --git a/e2e/callback_test.go b/e2e/callback_test.go index f3f9a087..8ecf69c1 100644 --- a/e2e/callback_test.go +++ b/e2e/callback_test.go @@ -83,6 +83,7 @@ func (suite *CbTestSuite) SetupTest() { 2, nil, nil, + nil, } instantiateBridgeRaw, err := json.Marshal(instantiateBridge) require.NoError(suite.T(), err) diff --git a/e2e/suite_test.go b/e2e/suite_test.go index 77d6b2d2..3524ad8d 100644 --- a/e2e/suite_test.go +++ b/e2e/suite_test.go @@ -53,6 +53,7 @@ func (suite *TransferTestSuite) SetupTest() { // no pauser nor proxy by default. nil, nil, + nil, } instantiateICS721Raw, err := json.Marshal(instantiateICS721) require.NoError(suite.T(), err) @@ -269,6 +270,7 @@ func instantiateBridge(t *testing.T, chain *wasmibctesting.TestChain) sdk.AccAdd cw721resp.CodeID, nil, nil, + nil, } instantiateICS721Raw, err := json.Marshal(instantiateICS721) require.NoError(t, err) @@ -620,6 +622,7 @@ func TestCloseRejected(t *testing.T) { 2, nil, nil, + nil, } instantiateICS721Raw, err := json.Marshal(instantiateICS721) require.NoError(t, err) diff --git a/e2e/test.sh b/e2e/test.sh index c5f5b7fb..92a9fb72 100755 --- a/e2e/test.sh +++ b/e2e/test.sh @@ -1,7 +1,7 @@ #!/bin/bash SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # source: https://stackoverflow.com/a/246128/3437868 WORKSPACE_DIR=$(cd $SCRIPT_DIR/.. && pwd) -echo "!!! NOTE: for a clean test it is recommended to delete wasm files: sudo rm -rf $WORKSPACE_DIR/artifacts) !!!" +sudo rm -rf $WORKSPACE_DIR/artifacts $WORKSPACE_DIR/ts-relayer-tests/build.sh echo "running tests..." go test $SCRIPT_DIR \ No newline at end of file diff --git a/e2e/types.go b/e2e/types.go index 3d6cb37a..42baaa35 100644 --- a/e2e/types.go +++ b/e2e/types.go @@ -25,7 +25,8 @@ type ModuleInstantiateInfo struct { type InstantiateICS721Bridge struct { CW721CodeID uint64 `json:"cw721_base_code_id"` - Proxy *ModuleInstantiateInfo `json:"outgoing_proxy"` + OutgoingProxy *ModuleInstantiateInfo `json:"outgoing_proxy"` + IncomingProxy *ModuleInstantiateInfo `json:"incoming_proxy"` Pauser *string `json:"pauser"` } diff --git a/external-wasms/cw721_incoming_proxy.wasm b/external-wasms/cw721_incoming_proxy.wasm new file mode 100644 index 0000000000000000000000000000000000000000..e07d7308de8e9debecb4112366e5e99274749608 GIT binary patch literal 181642 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

B29eyO7K@mKuxaD^bM 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 { - pauser: Item<'a, Option>, - paused: Item<'a, bool>, + pub pauser: Item<'a, Option>, + pub paused: Item<'a, bool>, } impl<'a> PauseOrchestrator<'a> { diff --git a/packages/ics721/Cargo.toml b/packages/ics721/Cargo.toml index 3f9d7519..563b6646 100644 --- a/packages/ics721/Cargo.toml +++ b/packages/ics721/Cargo.toml @@ -18,7 +18,8 @@ cw721-base-016 = { workspace = true, features = ["library"] } thiserror = { workspace = true } serde = { workspace = true } cw-paginate-storage = { workspace = true } -cw721-proxy-derive = { workspace = true } +cw721-incoming-proxy = { workspace = true } +cw721-outgoing-proxy-derive = { workspace = true } cw-pause-once = { workspace = true } cw-cii = { workspace = true } sha2 = { workspace = true } @@ -29,4 +30,4 @@ anyhow = { workspace = true } cw-multi-test = { workspace = true } cw2 = { workspace = true } cw721-016 = { workspace = true } -cw721-rate-limited-proxy = { workspace = true } +cw721-outgoing-proxy-rate-limit = { workspace = true } diff --git a/packages/ics721/schema/ics721.json b/packages/ics721/schema/ics721.json index 2efdfd0c..863f9db2 100644 --- a/packages/ics721/schema/ics721.json +++ b/packages/ics721/schema/ics721.json @@ -1,6 +1,6 @@ { "contract_name": "ics721", - "contract_version": "0.0.1", + "contract_version": "0.1.0", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", @@ -16,15 +16,19 @@ "format": "uint64", "minimum": 0.0 }, - "pauser": { - "description": "Address that may pause the contract. PAUSER may pause the contract a single time; in pausing the contract they burn the right to do so again. A new pauser may be later nominated by the CosmWasm level admin via a migration.", - "type": [ - "string", - "null" + "incoming_proxy": { + "description": "An optional proxy contract. If an incoming proxy is set, the contract will call it and pass IbcPacket. The proxy is expected to implement the Ics721ReceiveIbcPacketMsg for message execution.", + "anyOf": [ + { + "$ref": "#/definitions/ContractInstantiateInfo" + }, + { + "type": "null" + } ] }, - "proxy": { - "description": "An optional proxy contract. If a proxy is set the contract will only accept NFTs from that proxy. The proxy is expected to implement the cw721 proxy interface defined in the cw721-proxy crate.", + "outgoing_proxy": { + "description": "An optional proxy contract. If an outging proxy is set, the contract will only accept NFTs from that proxy. The proxy is expected to implement the cw721 proxy interface defined in the cw721-outgoing-proxy crate.", "anyOf": [ { "$ref": "#/definitions/ContractInstantiateInfo" @@ -33,6 +37,13 @@ "type": "null" } ] + }, + "pauser": { + "description": "Address that may pause the contract. PAUSER may pause the contract a single time; in pausing the contract they burn the right to do so again. A new pauser may be later nominated by the CosmWasm level admin via a migration.", + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, @@ -562,7 +573,58 @@ } }, "label": { - "description": "A human-readbale label for the contract", + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", + "type": "string" + }, + "msg": { + "description": "msg is the JSON-encoded InstantiateMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Instantiates a new contracts from previously uploaded Wasm code using a predictable address derivation algorithm implemented in [`cosmwasm_std::instantiate2_address`].\n\nThis is translated to a [MsgInstantiateContract2](https://github.com/CosmWasm/wasmd/blob/v0.29.2/proto/cosmwasm/wasm/v1/tx.proto#L73-L96). `sender` is automatically filled with the current contract's address. `fix_msg` is automatically set to false.", + "type": "object", + "required": [ + "instantiate2" + ], + "properties": { + "instantiate2": { + "type": "object", + "required": [ + "code_id", + "funds", + "label", + "msg", + "salt" + ], + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "label": { + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", "type": "string" }, "msg": { @@ -572,6 +634,9 @@ "$ref": "#/definitions/Binary" } ] + }, + "salt": { + "$ref": "#/definitions/Binary" } } } @@ -815,13 +880,27 @@ "additionalProperties": false }, { - "description": "Gets this contract's cw721-proxy if one is set.", + "description": "Gets this contract's outgoing cw721-outgoing-proxy if one is set.", + "type": "object", + "required": [ + "outgoing_proxy" + ], + "properties": { + "outgoing_proxy": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Gets this contract's incoming cw721-outgoing-proxy if one is set.", "type": "object", "required": [ - "proxy" + "incoming_proxy" ], "properties": { - "proxy": { + "incoming_proxy": { "type": "object", "additionalProperties": false } @@ -1095,6 +1174,24 @@ } } }, + "incoming_proxy": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Addr", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + }, "nft_contract": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Nullable_Addr", @@ -1179,6 +1276,24 @@ } } }, + "outgoing_proxy": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Addr", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + }, "owner": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "OwnerOfResponse", @@ -1308,24 +1423,6 @@ } } }, - "proxy": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Nullable_Addr", - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ], - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - } - } - }, "token_metadata": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Nullable_Token", diff --git a/packages/ics721/schema/raw/execute.json b/packages/ics721/schema/raw/execute.json index 87023eee..6e99d45c 100644 --- a/packages/ics721/schema/raw/execute.json +++ b/packages/ics721/schema/raw/execute.json @@ -447,7 +447,7 @@ } }, "label": { - "description": "A human-readbale label for the contract", + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", "type": "string" }, "msg": { @@ -463,6 +463,60 @@ }, "additionalProperties": false }, + { + "description": "Instantiates a new contracts from previously uploaded Wasm code using a predictable address derivation algorithm implemented in [`cosmwasm_std::instantiate2_address`].\n\nThis is translated to a [MsgInstantiateContract2](https://github.com/CosmWasm/wasmd/blob/v0.29.2/proto/cosmwasm/wasm/v1/tx.proto#L73-L96). `sender` is automatically filled with the current contract's address. `fix_msg` is automatically set to false.", + "type": "object", + "required": [ + "instantiate2" + ], + "properties": { + "instantiate2": { + "type": "object", + "required": [ + "code_id", + "funds", + "label", + "msg", + "salt" + ], + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "label": { + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", + "type": "string" + }, + "msg": { + "description": "msg is the JSON-encoded InstantiateMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + }, + "salt": { + "$ref": "#/definitions/Binary" + } + } + } + }, + "additionalProperties": false + }, { "description": "Migrates a given contracts to use new wasm code. Passes a MigrateMsg to allow us to customize behavior.\n\nOnly the contract admin (as defined in wasmd), if any, is able to make this call.\n\nThis is translated to a [MsgMigrateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L86-L96). `sender` is automatically filled with the current contract's address.", "type": "object", diff --git a/packages/ics721/schema/raw/instantiate.json b/packages/ics721/schema/raw/instantiate.json index cbc071c4..f431f451 100644 --- a/packages/ics721/schema/raw/instantiate.json +++ b/packages/ics721/schema/raw/instantiate.json @@ -12,15 +12,19 @@ "format": "uint64", "minimum": 0.0 }, - "pauser": { - "description": "Address that may pause the contract. PAUSER may pause the contract a single time; in pausing the contract they burn the right to do so again. A new pauser may be later nominated by the CosmWasm level admin via a migration.", - "type": [ - "string", - "null" + "incoming_proxy": { + "description": "An optional proxy contract. If an incoming proxy is set, the contract will call it and pass IbcPacket. The proxy is expected to implement the Ics721ReceiveIbcPacketMsg for message execution.", + "anyOf": [ + { + "$ref": "#/definitions/ContractInstantiateInfo" + }, + { + "type": "null" + } ] }, - "proxy": { - "description": "An optional proxy contract. If a proxy is set the contract will only accept NFTs from that proxy. The proxy is expected to implement the cw721 proxy interface defined in the cw721-proxy crate.", + "outgoing_proxy": { + "description": "An optional proxy contract. If an outging proxy is set, the contract will only accept NFTs from that proxy. The proxy is expected to implement the cw721 proxy interface defined in the cw721-outgoing-proxy crate.", "anyOf": [ { "$ref": "#/definitions/ContractInstantiateInfo" @@ -29,6 +33,13 @@ "type": "null" } ] + }, + "pauser": { + "description": "Address that may pause the contract. PAUSER may pause the contract a single time; in pausing the contract they burn the right to do so again. A new pauser may be later nominated by the CosmWasm level admin via a migration.", + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, diff --git a/packages/ics721/schema/raw/query.json b/packages/ics721/schema/raw/query.json index 0af38314..9a6d14f2 100644 --- a/packages/ics721/schema/raw/query.json +++ b/packages/ics721/schema/raw/query.json @@ -148,13 +148,27 @@ "additionalProperties": false }, { - "description": "Gets this contract's cw721-proxy if one is set.", + "description": "Gets this contract's outgoing cw721-outgoing-proxy if one is set.", "type": "object", "required": [ - "proxy" + "outgoing_proxy" ], "properties": { - "proxy": { + "outgoing_proxy": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Gets this contract's incoming cw721-outgoing-proxy if one is set.", + "type": "object", + "required": [ + "incoming_proxy" + ], + "properties": { + "incoming_proxy": { "type": "object", "additionalProperties": false } diff --git a/packages/ics721/schema/raw/response_to_incoming_proxy.json b/packages/ics721/schema/raw/response_to_incoming_proxy.json new file mode 100644 index 00000000..970164b3 --- /dev/null +++ b/packages/ics721/schema/raw/response_to_incoming_proxy.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Addr", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/packages/ics721/schema/raw/response_to_outgoing_proxy.json b/packages/ics721/schema/raw/response_to_outgoing_proxy.json new file mode 100644 index 00000000..970164b3 --- /dev/null +++ b/packages/ics721/schema/raw/response_to_outgoing_proxy.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Addr", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index cb7a37b4..ca941fc6 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -10,13 +10,13 @@ use sha2::{Digest, Sha256}; use crate::{ helpers::get_instantiate2_address, ibc::{ - NonFungibleTokenPacketData, INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, + NonFungibleTokenPacketData, INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, INSTANTIATE_INCOMING_PROXY_REPLY_ID, }, msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg}, state::{ CollectionData, UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, - PO, TOKEN_METADATA, + PO, TOKEN_METADATA, INCOMING_PROXY, }, token_types::{Class, ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}, ContractError, @@ -37,16 +37,25 @@ where ) -> StdResult> { CW721_CODE_ID.save(deps.storage, &msg.cw721_base_code_id)?; OUTGOING_PROXY.save(deps.storage, &None)?; + INCOMING_PROXY.save(deps.storage, &None)?; PO.set_pauser(deps.storage, deps.api, msg.pauser.as_deref())?; - let proxy_instantiate = msg - .outgoing_proxy - .map(|m| m.into_wasm_msg(env.contract.address)) - .map(|wasm| SubMsg::reply_on_success(wasm, INSTANTIATE_OUTGOING_PROXY_REPLY_ID)) - .map_or(vec![], |s| vec![s]); + let mut proxies_instantiate: Vec> = Vec::new(); + if let Some(cii) = msg.incoming_proxy { + proxies_instantiate.push(SubMsg::reply_on_success( + cii.into_wasm_msg(env.clone().contract.address), + INSTANTIATE_INCOMING_PROXY_REPLY_ID, + )); + } + if let Some(cii) = msg.outgoing_proxy { + proxies_instantiate.push(SubMsg::reply_on_success( + cii.into_wasm_msg(env.contract.address), + INSTANTIATE_OUTGOING_PROXY_REPLY_ID, + )); + } Ok(Response::default() - .add_submessages(proxy_instantiate) + .add_submessages(proxies_instantiate) .add_attribute("method", "instantiate") .add_attribute("cw721_code_id", msg.cw721_base_code_id.to_string())) } @@ -431,9 +440,17 @@ where match msg { MigrateMsg::WithUpdate { pauser, - proxy: outgoing_proxy, + incoming_proxy, + outgoing_proxy, cw721_base_code_id, } => { + INCOMING_PROXY.save( + deps.storage, + &incoming_proxy + .as_ref() + .map(|h| deps.api.addr_validate(h)) + .transpose()?, + )?; OUTGOING_PROXY.save( deps.storage, &outgoing_proxy diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index 5b0701f5..350abf15 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -14,7 +14,7 @@ use crate::{ ibc_packet_receive::receive_ibc_packet, state::{ CLASS_ID_TO_NFT_CONTRACT, INCOMING_CLASS_TOKEN_TO_CHANNEL, NFT_CONTRACT_TO_CLASS_ID, - OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, TOKEN_METADATA, + OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, TOKEN_METADATA, INCOMING_PROXY, }, token_types::{ClassId, TokenId}, types::Ics721Status, @@ -24,6 +24,8 @@ use crate::{ /// Submessage reply ID used for instantiating cw721 contracts. pub(crate) const INSTANTIATE_CW721_REPLY_ID: u64 = 0; /// Submessage reply ID used for instantiating the proxy contract. +pub(crate) const INSTANTIATE_INCOMING_PROXY_REPLY_ID: u64 = 4; +/// Submessage reply ID used for instantiating the proxy contract. pub(crate) const INSTANTIATE_OUTGOING_PROXY_REPLY_ID: u64 = 1; /// Submessages dispatched with this reply ID will set the ack on the /// response depending on if the submessage execution succeded or @@ -295,6 +297,15 @@ where .add_attribute("method", "instantiate_outgoing_proxy_reply_id") .add_attribute("outgoing_proxy", res.contract_address)) } + INSTANTIATE_INCOMING_PROXY_REPLY_ID => { + let res = parse_reply_instantiate_data(reply)?; + let proxy_addr = deps.api.addr_validate(&res.contract_address)?; + INCOMING_PROXY.save(deps.storage, &Some(proxy_addr))?; + + Ok(Response::default() + .add_attribute("method", "instantiate_incoming_proxy_reply_id") + .add_attribute("incoming_proxy", res.contract_address)) + } // These messages don't need to do any state changes in the // reply - just need to commit an ack. ACK_AND_DO_NOTHING => { diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index bdc84f0c..61a7a978 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -11,10 +11,11 @@ use crate::{ ibc_helpers::{get_endpoint_prefix, try_pop_source_prefix}, msg::{CallbackMsg, ExecuteMsg}, state::{ - CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, + CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO, }, token_types::{Class, ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}, + types::Ics721ReceiveIbcPacketMsg, ContractError, }; @@ -52,10 +53,24 @@ pub(crate) fn receive_ibc_packet( packet: IbcPacket, ) -> Result { PO.error_if_paused(deps.storage)?; - let data: NonFungibleTokenPacketData = from_json(&packet.data)?; data.validate()?; + let incoming_proxy_msg = match INCOMING_PROXY.load(deps.storage).ok().flatten() { + Some(incoming_proxy) => { + let msg = Ics721ReceiveIbcPacketMsg { + packet: packet.clone(), + data: data.clone(), + }; + Some(WasmMsg::Execute { + contract_addr: incoming_proxy.to_string(), + msg: to_json_binary(&msg)?, + funds: vec![], + }) + } + None => None, + }; + let cloned_data = data.clone(); let receiver = deps.api.addr_validate(&data.receiver)?; let token_count = data.token_ids.len(); @@ -173,8 +188,12 @@ pub(crate) fn receive_ibc_packet( None }; - let submessage = - action_aggregator.into_submessage(env.contract.address, receiver, callback_msg)?; + let submessage = action_aggregator.into_submessage( + env.contract.address, + receiver, + callback_msg, + incoming_proxy_msg, + )?; let response = if let Some(memo) = data.memo { IbcReceiveResponse::default().add_attribute("ics721_memo", memo) @@ -297,8 +316,12 @@ impl ActionAggregator { contract: Addr, receiver: Addr, callback_msg: Option, + incoming_proxy_msg: Option, ) -> StdResult> { let mut m = Vec::with_capacity(2); + if let Some(incoming_proxy_msg) = incoming_proxy_msg { + m.push(incoming_proxy_msg) + } if let Some(redeem) = self.redemption { m.push(redeem.into_wasm_msg(contract.clone(), receiver.to_string())?) } diff --git a/packages/ics721/src/msg.rs b/packages/ics721/src/msg.rs index f2ee89a4..9ff087ad 100644 --- a/packages/ics721/src/msg.rs +++ b/packages/ics721/src/msg.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Addr, IbcTimeout, WasmMsg}; -use cw721_proxy_derive::cw721_proxy; +use cw721_outgoing_proxy_derive::cw721_outgoing_proxy; use cw_cii::ContractInstantiateInfo; use crate::token_types::{ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}; @@ -15,10 +15,14 @@ pub struct InstantiateMsg { /// this contract to stop working, and IBCd away NFTs to be /// unreturnable as cw721 does not have a mint method in the spec. pub cw721_base_code_id: u64, - /// An optional proxy contract. If a proxy is set the contract + /// An optional proxy contract. If an incoming proxy is set, the contract + /// will call it and pass IbcPacket. The proxy is expected + /// to implement the Ics721ReceiveIbcPacketMsg for message execution. + pub incoming_proxy: Option, + /// An optional proxy contract. If an outging proxy is set, the contract /// will only accept NFTs from that proxy. The proxy is expected /// to implement the cw721 proxy interface defined in the - /// cw721-proxy crate. + /// cw721-outgoing-proxy crate. pub outgoing_proxy: Option, /// Address that may pause the contract. PAUSER may pause the /// contract a single time; in pausing the contract they burn the @@ -27,7 +31,7 @@ pub struct InstantiateMsg { pub pauser: Option, } -#[cw721_proxy] +#[cw721_outgoing_proxy] #[cw_serde] pub enum ExecuteMsg { /// Receives a NFT to be IBC transfered away. The `msg` field must @@ -132,9 +136,13 @@ pub enum QueryMsg { #[returns(bool)] Paused {}, - /// Gets this contract's cw721-proxy if one is set. + /// Gets this contract's outgoing cw721-outgoing-proxy if one is set. #[returns(Option<::cosmwasm_std::Addr>)] - Proxy {}, + OutgoingProxy {}, + + /// Gets this contract's incoming cw721-outgoing-proxy if one is set. + #[returns(Option<::cosmwasm_std::Addr>)] + IncomingProxy {}, /// Gets the code used for instantiating new cw721s. #[returns(u64)] @@ -180,9 +188,12 @@ pub enum MigrateMsg { /// The address that may pause the contract. If `None` is /// provided the current pauser will be removed. pauser: Option, - /// The cw721-proxy for this contract. If `None` is provided + /// The cw721-outgoing-proxy for this contract. If `None` is provided + /// the current proxy will be removed. + outgoing_proxy: Option, + /// The cw721-outgoing-proxy for this contract. If `None` is provided /// the current proxy will be removed. - proxy: Option, + incoming_proxy: Option, /// Code ID of cw721-ics contract. A new cw721-ics will be /// instantiated for each new IBCd NFT classID. /// diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index b48b64d8..9683b09f 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -6,7 +6,7 @@ use crate::{ state::{ UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, - OUTGOING_PROXY, PO, TOKEN_METADATA, + OUTGOING_PROXY, PO, TOKEN_METADATA, INCOMING_PROXY, }, token_types::{Class, ClassId, Token, TokenId}, }; @@ -31,7 +31,8 @@ pub trait Ics721Query { } QueryMsg::Pauser {} => to_json_binary(&PO.query_pauser(deps.storage)?), QueryMsg::Paused {} => to_json_binary(&PO.query_paused(deps.storage)?), - QueryMsg::Proxy {} => to_json_binary(&OUTGOING_PROXY.load(deps.storage)?), + QueryMsg::OutgoingProxy {} => to_json_binary(&OUTGOING_PROXY.load(deps.storage)?), + QueryMsg::IncomingProxy {} => to_json_binary(&INCOMING_PROXY.load(deps.storage)?), QueryMsg::Cw721CodeId {} => to_json_binary(&self.query_cw721_code_id(deps)?), QueryMsg::NftContracts { start_after, limit } => { to_json_binary(&self.query_nft_contracts(deps, start_after, limit)?) diff --git a/packages/ics721/src/state.rs b/packages/ics721/src/state.rs index d41d6493..b631010e 100644 --- a/packages/ics721/src/state.rs +++ b/packages/ics721/src/state.rs @@ -8,8 +8,12 @@ use crate::token_types::{Class, ClassId, TokenId}; /// The code ID we will use for instantiating new cw721s. pub const CW721_CODE_ID: Item = Item::new("a"); -/// The proxy that this contract is receiving NFTs from, if any. + +/// The incoming proxy that this contract is handling incoming IbcPackets from, if any. +pub const INCOMING_PROXY: Item> = Item::new("k"); +/// The outgoing proxy that this contract is receiving NFTs from, if any. pub const OUTGOING_PROXY: Item> = Item::new("b"); + /// Manages contract pauses. pub const PO: PauseOrchestrator = PauseOrchestrator::new("c", "d"); diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index 0d271810..4252cc72 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -3,24 +3,30 @@ use cosmwasm_std::{ from_json, testing::{mock_dependencies, mock_env, mock_info, MockQuerier, MOCK_CONTRACT_ADDR}, to_json_binary, Addr, ContractResult, CosmosMsg, DepsMut, Empty, IbcMsg, IbcTimeout, Order, - QuerierResult, StdResult, SubMsg, Timestamp, WasmQuery, + QuerierResult, Response, StdResult, SubMsg, Timestamp, WasmQuery, }; use cw721::{AllNftInfoResponse, NftInfoResponse, NumTokensResponse}; use cw721_base::QueryMsg; +use cw_cii::ContractInstantiateInfo; use cw_ownable::Ownership; use crate::{ execute::Ics721Execute, - ibc::{Ics721Ibc, NonFungibleTokenPacketData}, - msg::IbcOutgoingMsg, + ibc::{Ics721Ibc, NonFungibleTokenPacketData, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, INSTANTIATE_INCOMING_PROXY_REPLY_ID}, + msg::{IbcOutgoingMsg, InstantiateMsg}, query::Ics721Query, - state::{CollectionData, CLASS_ID_TO_CLASS, OUTGOING_CLASS_TOKEN_TO_CHANNEL}, + state::{ + CollectionData, CLASS_ID_TO_CLASS, CW721_CODE_ID, INCOMING_PROXY, + OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, + }, token_types::{ClassId, TokenId}, utils::get_collection_data, }; const NFT_ADDR: &str = "nft"; -const OWNER: &str = "owner"; +const OWNER_ADDR: &str = "owner"; +const ADMIN_ADDR: &str = "admin"; +const PAUSER_ADDR: &str = "pauser"; #[derive(Default)] pub struct Ics721Contract {} @@ -72,7 +78,7 @@ fn mock_querier(query: &WasmQuery) -> QuerierResult { } => match from_json::>(&msg).unwrap() { QueryMsg::Ownership {} => QuerierResult::Ok(ContractResult::Ok( to_json_binary(&Ownership:: { - owner: Some(Addr::unchecked(OWNER)), + owner: Some(Addr::unchecked(OWNER_ADDR)), pending_owner: None, pending_expiry: None, }) @@ -128,7 +134,7 @@ fn mock_querier_v016(query: &WasmQuery) -> QuerierResult { to_json_binary( // return v016 response &cw721_base_016::msg::MinterResponse { - minter: OWNER.to_string(), + minter: OWNER_ADDR.to_string(), }, ) .unwrap(), @@ -231,7 +237,7 @@ fn test_receive_nft() { class_uri: None, class_data: Some( to_json_binary(&CollectionData { - owner: Some(OWNER.to_string()), + owner: Some(OWNER_ADDR.to_string()), contract_info: Some(expected_contract_info.clone()), name: "name".to_string(), symbol: "symbol".to_string(), @@ -312,7 +318,7 @@ fn test_receive_nft() { class_uri: None, class_data: Some( to_json_binary(&CollectionData { - owner: Some(OWNER.to_string()), + owner: Some(OWNER_ADDR.to_string()), contract_info: Some(expected_contract_info), name: "name".to_string(), symbol: "symbol".to_string(), @@ -467,7 +473,7 @@ fn test_receive_sets_uri() { class.data, Some( to_json_binary(&CollectionData { - owner: Some(OWNER.to_string()), + owner: Some(OWNER_ADDR.to_string()), contract_info: Some(expected_contract_info), name: "name".to_string(), symbol: "symbol".to_string(), @@ -477,3 +483,56 @@ fn test_receive_sets_uri() { ), ); } + +#[test] +fn test_instantiate() { + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = mock_info(OWNER_ADDR, &[]); + let incoming_proxy_init_msg = ContractInstantiateInfo { + code_id: 0, + msg: to_json_binary("incoming").unwrap(), + admin: Some(cw_cii::Admin::Address { + addr: ADMIN_ADDR.to_string(), + }), + label: "incoming".to_string(), + }; + let outgoing_proxy_init_msg = ContractInstantiateInfo { + code_id: 0, + msg: to_json_binary("outgoing").unwrap(), + admin: Some(cw_cii::Admin::Address { + addr: ADMIN_ADDR.to_string(), + }), + label: "outgoing".to_string(), + }; + let msg = InstantiateMsg { + cw721_base_code_id: 0, + incoming_proxy: Some(incoming_proxy_init_msg.clone()), + outgoing_proxy: Some(outgoing_proxy_init_msg.clone()), + pauser: Some(PAUSER_ADDR.to_string()), + }; + let response = Ics721Contract {} + .instantiate(deps.as_mut(), env.clone(), info, msg.clone()) + .unwrap(); + + let expected_incoming_proxy_msg = incoming_proxy_init_msg.into_wasm_msg(env.clone().contract.address); + let expected_outgoing_proxy_msg = outgoing_proxy_init_msg.into_wasm_msg(env.contract.address); + let expected_response = Response::::default() + .add_submessage(SubMsg::reply_on_success( + expected_incoming_proxy_msg, + INSTANTIATE_INCOMING_PROXY_REPLY_ID, + )) + .add_submessage(SubMsg::reply_on_success( + expected_outgoing_proxy_msg, + INSTANTIATE_OUTGOING_PROXY_REPLY_ID, + )) + .add_attribute("method", "instantiate") + .add_attribute("cw721_code_id", msg.cw721_base_code_id.to_string()); + assert_eq!(response, expected_response); + assert_eq!(CW721_CODE_ID.load(&deps.storage).unwrap(), 0); + // incoming and outgoing proxy initially set to None and set later in sub msg + assert_eq!(OUTGOING_PROXY.load(&deps.storage).unwrap(), None); + assert_eq!(INCOMING_PROXY.load(&deps.storage).unwrap(), None); + assert_eq!(PO.pauser.load(&deps.storage).unwrap(), Some(Addr::unchecked(PAUSER_ADDR))); + assert_eq!(PO.paused.load(&deps.storage).unwrap(), false); +} diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index 686b9ce6..2fc2ddaa 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -105,6 +105,7 @@ fn add_channel(mut deps: DepsMut, env: Env, channel_id: &str) { fn do_instantiate(deps: DepsMut, env: Env, sender: &str) -> StdResult { let msg = InstantiateMsg { cw721_base_code_id: CW721_CODE_ID, + incoming_proxy: None, outgoing_proxy: None, pauser: None, }; @@ -476,7 +477,7 @@ fn test_ibc_packet_receive() { #[test] fn test_ibc_packet_receive_invalid_packet_data() { // the actual message used here is unimportant. this just - // constructs a valud JSON blob that is not a valid ICS-721 + // constructs a valid JSON blob that is not a valid ICS-721 // packet. let data = to_json_binary(&QueryMsg::ClassMetadata { class_id: "foobar".to_string(), diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index c4193191..8dd4ca97 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -282,7 +282,9 @@ struct Test { impl Test { fn new( - proxy: bool, + outgoing_proxy: bool, + incoming_proxy: bool, + source_channels: Option>, admin_and_pauser: Option, cw721_code: Box>, is_cw721_018: bool, @@ -297,19 +299,35 @@ impl Test { let source_cw721_id = app.store_code(cw721_code); let ics721_id = app.store_code(ics721_contract()); - use cw721_rate_limited_proxy as rlp; - let proxy = match proxy { + let outgoing_proxy = match outgoing_proxy { true => { - let proxy_id = app.store_code(proxy_contract()); + let proxy_id = app.store_code(outgoing_proxy_contract()); Some(ContractInstantiateInfo { code_id: proxy_id, - msg: to_json_binary(&rlp::msg::InstantiateMsg { - rate_limit: rlp::Rate::PerBlock(10), + msg: to_json_binary(&cw721_outgoing_proxy_rate_limit::msg::InstantiateMsg { + rate_limit: cw721_outgoing_proxy_rate_limit::Rate::PerBlock(10), origin: None, }) .unwrap(), admin: Some(Admin::Instantiator {}), - label: "rate limited proxy".to_string(), + label: "outgoing proxy rate limit".to_string(), + }) + } + false => None, + }; + + let incoming_proxy = match incoming_proxy { + true => { + let proxy_id = app.store_code(incoming_proxy_contract()); + Some(ContractInstantiateInfo { + code_id: proxy_id, + msg: to_json_binary(&cw721_incoming_proxy::msg::InstantiateMsg { + origin: None, + source_channels, + }) + .unwrap(), + admin: Some(Admin::Instantiator {}), + label: "incoming proxy".to_string(), }) } false => None, @@ -321,7 +339,8 @@ impl Test { app.api().addr_make(ICS721_CREATOR), &InstantiateMsg { cw721_base_code_id: source_cw721_id, - outgoing_proxy: proxy, + incoming_proxy, + outgoing_proxy, pauser: admin_and_pauser .clone() .map(|p| app.api().addr_make(&p).to_string()), @@ -414,10 +433,17 @@ impl Test { (paused, pauser) } - fn query_proxy(&mut self) -> Option { + fn query_outgoing_proxy(&mut self) -> Option { + self.app + .wrap() + .query_wasm_smart(self.ics721.clone(), &QueryMsg::OutgoingProxy {}) + .unwrap() + } + + fn query_incoming_proxy(&mut self) -> Option { self.app .wrap() - .query_wasm_smart(self.ics721.clone(), &QueryMsg::Proxy {}) + .query_wasm_smart(self.ics721.clone(), &QueryMsg::IncomingProxy {}) .unwrap() } @@ -517,18 +543,27 @@ fn ics721_contract() -> Box> { Box::new(contract) } -fn proxy_contract() -> Box> { +fn incoming_proxy_contract() -> Box> { + let contract = ContractWrapper::new( + cw721_incoming_proxy::contract::execute, + cw721_incoming_proxy::contract::instantiate, + cw721_incoming_proxy::contract::query, + ); + Box::new(contract) +} + +fn outgoing_proxy_contract() -> Box> { let contract = ContractWrapper::new( - cw721_rate_limited_proxy::contract::execute::, - cw721_rate_limited_proxy::contract::instantiate, - cw721_rate_limited_proxy::contract::query, + cw721_outgoing_proxy_rate_limit::contract::execute, + cw721_outgoing_proxy_rate_limit::contract::instantiate, + cw721_outgoing_proxy_rate_limit::contract::query, ); Box::new(contract) } #[test] fn test_instantiate() { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(true, true, None, None, cw721_base_contract(), true); // check stores are properly initialized let cw721_id = test.query_cw721_id(); @@ -539,11 +574,15 @@ fn test_instantiate() { assert_eq!(outgoing_channels, []); let incoming_channels = test.query_incoming_channels(); assert_eq!(incoming_channels, []); + let outgoing_proxy = test.query_outgoing_proxy(); + assert!(outgoing_proxy.is_some()); + let incoming_proxy = test.query_incoming_proxy(); + assert!(incoming_proxy.is_some()); } #[test] fn test_do_instantiate_and_mint_weird_data() { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -594,7 +633,7 @@ fn test_do_instantiate_and_mint_weird_data() { fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with no ClassData (without owner, name, and symbol) { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -733,7 +772,7 @@ fn test_do_instantiate_and_mint() { } // test case: instantiate cw721 with ClassData containing owner, name, and symbol { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -888,7 +927,7 @@ fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with CustomClassData (includes name, but without owner and symbol) // results in nft contract using class id for name and symbol { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1042,7 +1081,7 @@ fn test_do_instantiate_and_mint() { // test case: instantiate cw721 with PartialCustomCollectionData (includes name and symbol) // results in nft contract using name and symbol { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1202,7 +1241,7 @@ fn test_do_instantiate_and_mint() { fn test_do_instantiate_and_mint_2_different_collections() { // test case: instantiate two cw721 contracts with different class id and make sure instantiate2 creates 2 different, predictable contracts { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain_1 = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id_1 = format!( @@ -1469,7 +1508,7 @@ fn test_do_instantiate_and_mint_2_different_collections() { #[test] fn test_do_instantiate_and_mint_no_instantiate() { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1577,7 +1616,7 @@ fn test_do_instantiate_and_mint_no_instantiate() { #[test] fn test_do_instantiate_and_mint_permissions() { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let collection_contract_source_chain = ClassId::new(test.app.api().addr_make(COLLECTION_CONTRACT_SOURCE_CHAIN)); let class_id = format!( @@ -1631,7 +1670,7 @@ fn test_do_instantiate_and_mint_permissions() { /// Tests that we can not proxy NFTs if no proxy is configured. #[test] fn test_no_proxy_unauthorized() { - let mut test = Test::new(false, None, cw721_base_contract(), true); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); let err: ContractError = test .app .execute_contract( @@ -1655,11 +1694,11 @@ fn test_no_proxy_unauthorized() { #[test] fn test_proxy_authorized() { - let mut test = Test::new(true, None, cw721_base_contract(), true); + let mut test = Test::new(true, false, None, None, cw721_base_contract(), true); let proxy_address: Option = test .app .wrap() - .query_wasm_smart(&test.ics721, &QueryMsg::Proxy {}) + .query_wasm_smart(&test.ics721, &QueryMsg::OutgoingProxy {}) .unwrap(); // check proxy is set let proxy_address = proxy_address.expect("expected a proxy"); @@ -1739,9 +1778,7 @@ fn test_proxy_authorized() { fn test_receive_nft() { // test case: receive nft from cw721-base { - println!(">>>>>>>>>>>>1"); - let mut test = Test::new(false, None, cw721_base_contract(), true); - println!(">>>>>>>>>>>>2"); + let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); // simplify: mint and escrowed/owned by ics721, as a precondition for receive nft let token_id = test.execute_cw721_mint(test.ics721.clone()).unwrap(); // ics721 receives NFT from sender/collection contract, @@ -1809,7 +1846,7 @@ fn test_receive_nft() { } // test case: backward compatibility - receive nft also works for old/v016 cw721-base { - let mut test = Test::new(false, None, cw721_v016_base_contract(), false); + let mut test = Test::new(false, false, None, None, cw721_v016_base_contract(), false); // simplify: mint and escrowed/owned by ics721, as a precondition for receive nft let token_id = test.execute_cw721_mint(test.ics721.clone()).unwrap(); // ics721 receives NFT from sender/collection contract, @@ -1883,7 +1920,7 @@ fn test_receive_nft() { /// In case proxy for ICS721 is defined, ICS721 only accepts receival from proxy - not from nft contract! #[test] fn test_no_receive_with_proxy() { - let mut test = Test::new(true, None, cw721_base_contract(), true); + let mut test = Test::new(true, false, None, None, cw721_base_contract(), true); // unauthorized to receive nft from nft contract let err: ContractError = test .app @@ -1917,6 +1954,8 @@ fn test_no_receive_with_proxy() { fn test_pause() { let mut test = Test::new( true, + false, + None, Some(ICS721_ADMIN_AND_PAUSER.to_string()), cw721_base_contract(), true, @@ -1974,7 +2013,8 @@ fn test_pause() { new_code_id: ics721_id, msg: to_json_binary(&MigrateMsg::WithUpdate { pauser: Some(test.app.api().addr_make("new_pauser").to_string()), - proxy: None, + incoming_proxy: None, + outgoing_proxy: None, cw721_base_code_id: None, }) .unwrap(), @@ -2000,6 +2040,8 @@ fn test_pause() { fn test_migration() { let mut test = Test::new( true, + false, + None, Some(ICS721_ADMIN_AND_PAUSER.to_string()), cw721_base_contract(), true, @@ -2010,8 +2052,8 @@ fn test_migration() { pauser, Some(test.app.api().addr_make(ICS721_ADMIN_AND_PAUSER)) ); - let proxy = test.query_proxy(); - assert!(proxy.is_some()); + let outgoing_proxy = test.query_outgoing_proxy(); + assert!(outgoing_proxy.is_some()); let cw721_code_id = test.query_cw721_id(); assert_eq!(cw721_code_id, test.source_cw721_id); @@ -2024,7 +2066,8 @@ fn test_migration() { new_code_id: test.ics721_id, msg: to_json_binary(&MigrateMsg::WithUpdate { pauser: None, - proxy: None, + incoming_proxy: None, + outgoing_proxy: None, cw721_base_code_id: Some(12345678), }) .unwrap(), @@ -2035,7 +2078,7 @@ fn test_migration() { // assert migration worked let (_, pauser) = test.query_pause_info(); assert_eq!(pauser, None); - let proxy = test.query_proxy(); + let proxy = test.query_outgoing_proxy(); assert!(proxy.is_none()); let cw721_code_id = test.query_cw721_id(); assert_eq!(cw721_code_id, 12345678); @@ -2049,7 +2092,8 @@ fn test_migration() { new_code_id: test.ics721_id, msg: to_json_binary(&MigrateMsg::WithUpdate { pauser: None, - proxy: None, + incoming_proxy: None, + outgoing_proxy: None, cw721_base_code_id: None, }) .unwrap(), @@ -2060,7 +2104,7 @@ fn test_migration() { // assert migration worked let (_, pauser) = test.query_pause_info(); assert_eq!(pauser, None); - let proxy = test.query_proxy(); + let proxy = test.query_outgoing_proxy(); assert!(proxy.is_none()); let cw721_code_id = test.query_cw721_id(); assert_eq!(cw721_code_id, 12345678); diff --git a/packages/ics721/src/types.rs b/packages/ics721/src/types.rs index e181e04f..11f01cda 100644 --- a/packages/ics721/src/types.rs +++ b/packages/ics721/src/types.rs @@ -1,9 +1,15 @@ use cosmwasm_schema::{cw_serde, schemars::JsonSchema}; -use cosmwasm_std::Binary; +use cosmwasm_std::{Binary, IbcPacket}; use serde::{Deserialize, Serialize}; use crate::ibc::NonFungibleTokenPacketData; +#[cw_serde] +pub struct Ics721ReceiveIbcPacketMsg { + pub packet: IbcPacket, + pub data: NonFungibleTokenPacketData, +} + #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug, PartialEq)] #[allow(clippy::derive_partial_eq_without_eq)] #[schemars(crate = "cosmwasm_schema::schemars")] diff --git a/ts-relayer-tests/build.sh b/ts-relayer-tests/build.sh index e58de99d..bcef98c7 100755 --- a/ts-relayer-tests/build.sh +++ b/ts-relayer-tests/build.sh @@ -11,7 +11,7 @@ cd "$(git rev-parse --show-toplevel)" docker run --rm -v "$(pwd)":/code --platform linux/amd64 \ --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ - cosmwasm/workspace-optimizer:0.14.0 + cosmwasm/workspace-optimizer:0.15.0 mkdir -p ./ts-relayer-tests/internal cp ./artifacts/*.wasm ./ts-relayer-tests/internal diff --git a/ts-relayer-tests/package-lock.json b/ts-relayer-tests/package-lock.json index 50588877..986325cc 100644 --- a/ts-relayer-tests/package-lock.json +++ b/ts-relayer-tests/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "license": "Apache-2.0", "dependencies": { - "@confio/relayer": "^0.10" + "@confio/relayer": "^0.11" }, "devDependencies": { "@ava/typescript": "^3.0.1", @@ -449,24 +449,24 @@ } }, "node_modules/@confio/relayer": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@confio/relayer/-/relayer-0.10.0.tgz", - "integrity": "sha512-/WW5Eyfgylby9u0wz6XakA7yo5hamdWh6pxkOYHPz0ls7ikd7Ld+c2fpRbL0Qg5wZn9+9P+Uhfj4l0pVl3WPgw==", - "dependencies": { - "@cosmjs/cosmwasm-stargate": "^0.31.0", - "@cosmjs/crypto": "^0.31.0", - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/faucet-client": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/proto-signing": "^0.31.0", - "@cosmjs/stargate": "^0.31.0", - "@cosmjs/stream": "^0.31.0", - "@cosmjs/tendermint-rpc": "^0.31.0", - "@cosmjs/utils": "^0.31.0", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@confio/relayer/-/relayer-0.11.2.tgz", + "integrity": "sha512-xzTtY1HaV7qX5lsrWBAzaktzEc43Q2Q/bq7rard79JSyGKDfkR2GlFXZoSxYZ4j4L4ZXO50wf9gz5WcUbBl2kA==", + "dependencies": { + "@cosmjs/cosmwasm-stargate": "^0.32.1", + "@cosmjs/crypto": "^0.32.1", + "@cosmjs/encoding": "^0.32.1", + "@cosmjs/faucet-client": "^0.32.1", + "@cosmjs/math": "^0.32.1", + "@cosmjs/proto-signing": "^0.32.1", + "@cosmjs/stargate": "^0.32.1", + "@cosmjs/stream": "^0.32.1", + "@cosmjs/tendermint-rpc": "^0.32.1", + "@cosmjs/utils": "^0.32.1", "ajv": "7.1.1", "axios": "0.21.4", "commander": "7.1.0", - "cosmjs-types": "^0.8.0", + "cosmjs-types": "^0.9.0", "fast-safe-stringify": "2.0.4", "js-yaml": "4.0.0", "lodash": "4.17.21", @@ -485,42 +485,41 @@ } }, "node_modules/@cosmjs/amino": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.31.3.tgz", - "integrity": "sha512-36emtUq895sPRX8PTSOnG+lhJDCVyIcE0Tr5ct59sUbgQiI14y43vj/4WAlJ/utSOxy+Zhj9wxcs4AZfu0BHsw==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.32.2.tgz", + "integrity": "sha512-lcK5RCVm4OfdAooxKcF2+NwaDVVpghOq6o/A40c2mHXDUzUoRZ33VAHjVJ9Me6vOFxshrw/XEFn1f4KObntjYA==", "dependencies": { - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/utils": "^0.31.3" + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/utils": "^0.32.2" } }, "node_modules/@cosmjs/cosmwasm-stargate": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.31.3.tgz", - "integrity": "sha512-Uv9TmCn3650gdFeZm7SEfUZF3uX3lfJfFhXOk6I2ZLr/FrKximnlb+vwAfZaZnWYvlA7qrKtHIjeRNHvT23zcw==", - "dependencies": { - "@cosmjs/amino": "^0.31.3", - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/proto-signing": "^0.31.3", - "@cosmjs/stargate": "^0.31.3", - "@cosmjs/tendermint-rpc": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.32.2.tgz", + "integrity": "sha512-OwJHzIx2CoJS6AULxOpNR6m+CI0GXxy8z9svHA1ZawzNM3ZGlL0GvHdhmF0WkpX4E7UdrYlJSLpKcgg5Fo6i7Q==", + "dependencies": { + "@cosmjs/amino": "^0.32.2", + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/proto-signing": "^0.32.2", + "@cosmjs/stargate": "^0.32.2", + "@cosmjs/tendermint-rpc": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "cosmjs-types": "^0.9.0", "pako": "^2.0.2" } }, "node_modules/@cosmjs/crypto": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.31.3.tgz", - "integrity": "sha512-vRbvM9ZKR2017TO73dtJ50KxoGcFzKtKI7C8iO302BQ5p+DuB+AirUg1952UpSoLfv5ki9O416MFANNg8UN/EQ==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.32.2.tgz", + "integrity": "sha512-RuxrYKzhrPF9g6NmU7VEq++Hn1vZJjqqJpZ9Tmw9lOYOV8BUsv+j/0BE86kmWi7xVJ7EwxiuxYsKuM8IR18CIA==", "dependencies": { - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/utils": "^0.31.3", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/utils": "^0.32.2", "@noble/hashes": "^1", "bn.js": "^5.2.0", "elliptic": "^6.5.4", @@ -528,9 +527,9 @@ } }, "node_modules/@cosmjs/encoding": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.31.3.tgz", - "integrity": "sha512-6IRtG0fiVYwyP7n+8e54uTx2pLYijO48V3t9TLiROERm5aUAIzIlz6Wp0NYaI5he9nh1lcEGJ1lkquVKFw3sUg==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.32.2.tgz", + "integrity": "sha512-WX7m1wLpA9V/zH0zRcz4EmgZdAv1F44g4dbXOgNj1eXZw1PIGR12p58OEkLN51Ha3S4DKRtCv5CkhK1KHEvQtg==", "dependencies": { "base64-js": "^1.3.0", "bech32": "^1.1.4", @@ -538,103 +537,120 @@ } }, "node_modules/@cosmjs/faucet-client": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/faucet-client/-/faucet-client-0.31.3.tgz", - "integrity": "sha512-gsVD/UD1R2k00iRVcBwXRgTkwzsnapfw8n1eWfc7o44xg0aVG8YL84ntj2YmjC9+NHCp2rmK9xndQeUOFIszOA==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/faucet-client/-/faucet-client-0.32.2.tgz", + "integrity": "sha512-tRumHGAURhCV7xvxPltwqiMX2bwJYR6M8Im586hnwVC+Ww2+TwH9c0QjZiUmWzZgCDUPkaSwVswUgucB7H59xA==", "dependencies": { - "axios": "^0.21.2" + "axios": "^1.6.0" + } + }, + "node_modules/@cosmjs/faucet-client/node_modules/axios": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", + "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/@cosmjs/json-rpc": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.31.3.tgz", - "integrity": "sha512-7LVYerXjnm69qqYR3uA6LGCrBW2EO5/F7lfJxAmY+iII2C7xO3a0vAjMSt5zBBh29PXrJVS6c2qRP22W1Le2Wg==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.32.2.tgz", + "integrity": "sha512-lan2lOgmz4yVE/HR8eCOSiII/1OudIulk8836koyIDCsPEpt6eKBuctnAD168vABGArKccLAo7Mr2gy9nrKrOQ==", "dependencies": { - "@cosmjs/stream": "^0.31.3", + "@cosmjs/stream": "^0.32.2", "xstream": "^11.14.0" } }, "node_modules/@cosmjs/math": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.31.3.tgz", - "integrity": "sha512-kZ2C6glA5HDb9hLz1WrftAjqdTBb3fWQsRR+Us2HsjAYdeE6M3VdXMsYCP5M3yiihal1WDwAY2U7HmfJw7Uh4A==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.32.2.tgz", + "integrity": "sha512-b8+ruAAY8aKtVKWSft2IvtCVCUH1LigIlf9ALIiY8n9jtM4kMASiaRbQ/27etnSAInV88IaezKK9rQZrtxTjcw==", "dependencies": { "bn.js": "^5.2.0" } }, "node_modules/@cosmjs/proto-signing": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.31.3.tgz", - "integrity": "sha512-24+10/cGl6lLS4VCrGTCJeDRPQTn1K5JfknzXzDIHOx8THR31JxA7/HV5eWGHqWgAbudA7ccdSvEK08lEHHtLA==", - "dependencies": { - "@cosmjs/amino": "^0.31.3", - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0" + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.32.2.tgz", + "integrity": "sha512-UV4WwkE3W3G3s7wwU9rizNcUEz2g0W8jQZS5J6/3fiN0mRPwtPKQ6EinPN9ASqcAJ7/VQH4/9EPOw7d6XQGnqw==", + "dependencies": { + "@cosmjs/amino": "^0.32.2", + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "cosmjs-types": "^0.9.0" } }, "node_modules/@cosmjs/socket": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.31.3.tgz", - "integrity": "sha512-aqrDGGi7os/hsz5p++avI4L0ZushJ+ItnzbqA7C6hamFSCJwgOkXaOUs+K9hXZdX4rhY7rXO4PH9IH8q09JkTw==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.32.2.tgz", + "integrity": "sha512-Qc8jaw4uSBJm09UwPgkqe3g9TBFx4ZR9HkXpwT6Z9I+6kbLerXPR0Gy3NSJFSUgxIfTpO8O1yqoWAyf0Ay17Mw==", "dependencies": { - "@cosmjs/stream": "^0.31.3", + "@cosmjs/stream": "^0.32.2", "isomorphic-ws": "^4.0.1", "ws": "^7", "xstream": "^11.14.0" } }, "node_modules/@cosmjs/stargate": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.31.3.tgz", - "integrity": "sha512-53NxnzmB9FfXpG4KjOUAYAvWLYKdEmZKsutcat/u2BrDXNZ7BN8jim/ENcpwXfs9/Og0K24lEIdvA4gsq3JDQw==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.32.2.tgz", + "integrity": "sha512-AsJa29fT7Jd4xt9Ai+HMqhyj7UQu7fyYKdXj/8+/9PD74xe6lZSYhQPcitUmMLJ1ckKPgXSk5Dd2LbsQT0IhZg==", "dependencies": { "@confio/ics23": "^0.6.8", - "@cosmjs/amino": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/proto-signing": "^0.31.3", - "@cosmjs/stream": "^0.31.3", - "@cosmjs/tendermint-rpc": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0", - "protobufjs": "~6.11.3", + "@cosmjs/amino": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/proto-signing": "^0.32.2", + "@cosmjs/stream": "^0.32.2", + "@cosmjs/tendermint-rpc": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "cosmjs-types": "^0.9.0", "xstream": "^11.14.0" } }, "node_modules/@cosmjs/stream": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.31.3.tgz", - "integrity": "sha512-8keYyI7X0RjsLyVcZuBeNjSv5FA4IHwbFKx7H60NHFXszN8/MvXL6aZbNIvxtcIHHsW7K9QSQos26eoEWlAd+w==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.32.2.tgz", + "integrity": "sha512-gpCufLfHAD8Zp1ZKge7AHbDf4RA0TZp66wZY6JaQR5bSiEF2Drjtp4mwXZPGejtaUMnaAgff3LrUzPJfKYdQwg==", "dependencies": { "xstream": "^11.14.0" } }, "node_modules/@cosmjs/tendermint-rpc": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.31.3.tgz", - "integrity": "sha512-s3TiWkPCW4QceTQjpYqn4xttUJH36mTPqplMl+qyocdqk5+X5mergzExU/pHZRWQ4pbby8bnR7kMvG4OC1aZ8g==", - "dependencies": { - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/json-rpc": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/socket": "^0.31.3", - "@cosmjs/stream": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "axios": "^0.21.2", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.32.2.tgz", + "integrity": "sha512-DXyJHDmcAfCix4H/7/dKR0UMdshP01KxJOXHdHxBCbLIpck94BsWD3B2ZTXwfA6sv98so9wOzhp7qGQa5malxg==", + "dependencies": { + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/json-rpc": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/socket": "^0.32.2", + "@cosmjs/stream": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "axios": "^1.6.0", "readonly-date": "^1.0.0", "xstream": "^11.14.0" } }, + "node_modules/@cosmjs/tendermint-rpc/node_modules/axios": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", + "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/@cosmjs/utils": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.31.3.tgz", - "integrity": "sha512-VBhAgzrrYdIe0O5IbKRqwszbQa7ZyQLx9nEQuHQ3HUplQW7P44COG/ye2n6AzCudtqxmwdX7nyX8ta1J07GoqA==" + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.32.2.tgz", + "integrity": "sha512-Gg5t+eR7vPJMAmhkFt6CZrzPd0EKpAslWwk5rFVYZpJsM8JG5KT9XQ99hgNM3Ov6ScNoIWbXkpX27F6A9cXR4Q==" }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", @@ -909,9 +925,9 @@ } }, "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", "engines": { "node": ">= 16" }, @@ -1474,6 +1490,11 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/ava": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.1.tgz", @@ -1989,6 +2010,17 @@ "text-hex": "1.0.x" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", @@ -2053,13 +2085,9 @@ } }, "node_modules/cosmjs-types": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.8.0.tgz", - "integrity": "sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg==", - "dependencies": { - "long": "^4.0.0", - "protobufjs": "~6.11.2" - } + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.9.0.tgz", + "integrity": "sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==" }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -2232,6 +2260,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/diff": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", @@ -3103,6 +3139,19 @@ "node": ">=8.0.0" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fromentries": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", @@ -4328,6 +4377,25 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -5544,6 +5612,11 @@ "pbts": "bin/pbts" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -7317,24 +7390,24 @@ } }, "@confio/relayer": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@confio/relayer/-/relayer-0.10.0.tgz", - "integrity": "sha512-/WW5Eyfgylby9u0wz6XakA7yo5hamdWh6pxkOYHPz0ls7ikd7Ld+c2fpRbL0Qg5wZn9+9P+Uhfj4l0pVl3WPgw==", - "requires": { - "@cosmjs/cosmwasm-stargate": "^0.31.0", - "@cosmjs/crypto": "^0.31.0", - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/faucet-client": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/proto-signing": "^0.31.0", - "@cosmjs/stargate": "^0.31.0", - "@cosmjs/stream": "^0.31.0", - "@cosmjs/tendermint-rpc": "^0.31.0", - "@cosmjs/utils": "^0.31.0", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@confio/relayer/-/relayer-0.11.2.tgz", + "integrity": "sha512-xzTtY1HaV7qX5lsrWBAzaktzEc43Q2Q/bq7rard79JSyGKDfkR2GlFXZoSxYZ4j4L4ZXO50wf9gz5WcUbBl2kA==", + "requires": { + "@cosmjs/cosmwasm-stargate": "^0.32.1", + "@cosmjs/crypto": "^0.32.1", + "@cosmjs/encoding": "^0.32.1", + "@cosmjs/faucet-client": "^0.32.1", + "@cosmjs/math": "^0.32.1", + "@cosmjs/proto-signing": "^0.32.1", + "@cosmjs/stargate": "^0.32.1", + "@cosmjs/stream": "^0.32.1", + "@cosmjs/tendermint-rpc": "^0.32.1", + "@cosmjs/utils": "^0.32.1", "ajv": "7.1.1", "axios": "0.21.4", "commander": "7.1.0", - "cosmjs-types": "^0.8.0", + "cosmjs-types": "^0.9.0", "fast-safe-stringify": "2.0.4", "js-yaml": "4.0.0", "lodash": "4.17.21", @@ -7346,42 +7419,41 @@ } }, "@cosmjs/amino": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.31.3.tgz", - "integrity": "sha512-36emtUq895sPRX8PTSOnG+lhJDCVyIcE0Tr5ct59sUbgQiI14y43vj/4WAlJ/utSOxy+Zhj9wxcs4AZfu0BHsw==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.32.2.tgz", + "integrity": "sha512-lcK5RCVm4OfdAooxKcF2+NwaDVVpghOq6o/A40c2mHXDUzUoRZ33VAHjVJ9Me6vOFxshrw/XEFn1f4KObntjYA==", "requires": { - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/utils": "^0.31.3" + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/utils": "^0.32.2" } }, "@cosmjs/cosmwasm-stargate": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.31.3.tgz", - "integrity": "sha512-Uv9TmCn3650gdFeZm7SEfUZF3uX3lfJfFhXOk6I2ZLr/FrKximnlb+vwAfZaZnWYvlA7qrKtHIjeRNHvT23zcw==", - "requires": { - "@cosmjs/amino": "^0.31.3", - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/proto-signing": "^0.31.3", - "@cosmjs/stargate": "^0.31.3", - "@cosmjs/tendermint-rpc": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.32.2.tgz", + "integrity": "sha512-OwJHzIx2CoJS6AULxOpNR6m+CI0GXxy8z9svHA1ZawzNM3ZGlL0GvHdhmF0WkpX4E7UdrYlJSLpKcgg5Fo6i7Q==", + "requires": { + "@cosmjs/amino": "^0.32.2", + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/proto-signing": "^0.32.2", + "@cosmjs/stargate": "^0.32.2", + "@cosmjs/tendermint-rpc": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "cosmjs-types": "^0.9.0", "pako": "^2.0.2" } }, "@cosmjs/crypto": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.31.3.tgz", - "integrity": "sha512-vRbvM9ZKR2017TO73dtJ50KxoGcFzKtKI7C8iO302BQ5p+DuB+AirUg1952UpSoLfv5ki9O416MFANNg8UN/EQ==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.32.2.tgz", + "integrity": "sha512-RuxrYKzhrPF9g6NmU7VEq++Hn1vZJjqqJpZ9Tmw9lOYOV8BUsv+j/0BE86kmWi7xVJ7EwxiuxYsKuM8IR18CIA==", "requires": { - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/utils": "^0.31.3", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/utils": "^0.32.2", "@noble/hashes": "^1", "bn.js": "^5.2.0", "elliptic": "^6.5.4", @@ -7389,9 +7461,9 @@ } }, "@cosmjs/encoding": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.31.3.tgz", - "integrity": "sha512-6IRtG0fiVYwyP7n+8e54uTx2pLYijO48V3t9TLiROERm5aUAIzIlz6Wp0NYaI5he9nh1lcEGJ1lkquVKFw3sUg==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.32.2.tgz", + "integrity": "sha512-WX7m1wLpA9V/zH0zRcz4EmgZdAv1F44g4dbXOgNj1eXZw1PIGR12p58OEkLN51Ha3S4DKRtCv5CkhK1KHEvQtg==", "requires": { "base64-js": "^1.3.0", "bech32": "^1.1.4", @@ -7399,103 +7471,124 @@ } }, "@cosmjs/faucet-client": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/faucet-client/-/faucet-client-0.31.3.tgz", - "integrity": "sha512-gsVD/UD1R2k00iRVcBwXRgTkwzsnapfw8n1eWfc7o44xg0aVG8YL84ntj2YmjC9+NHCp2rmK9xndQeUOFIszOA==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/faucet-client/-/faucet-client-0.32.2.tgz", + "integrity": "sha512-tRumHGAURhCV7xvxPltwqiMX2bwJYR6M8Im586hnwVC+Ww2+TwH9c0QjZiUmWzZgCDUPkaSwVswUgucB7H59xA==", "requires": { - "axios": "^0.21.2" + "axios": "^1.6.0" + }, + "dependencies": { + "axios": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", + "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + } } }, "@cosmjs/json-rpc": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.31.3.tgz", - "integrity": "sha512-7LVYerXjnm69qqYR3uA6LGCrBW2EO5/F7lfJxAmY+iII2C7xO3a0vAjMSt5zBBh29PXrJVS6c2qRP22W1Le2Wg==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.32.2.tgz", + "integrity": "sha512-lan2lOgmz4yVE/HR8eCOSiII/1OudIulk8836koyIDCsPEpt6eKBuctnAD168vABGArKccLAo7Mr2gy9nrKrOQ==", "requires": { - "@cosmjs/stream": "^0.31.3", + "@cosmjs/stream": "^0.32.2", "xstream": "^11.14.0" } }, "@cosmjs/math": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.31.3.tgz", - "integrity": "sha512-kZ2C6glA5HDb9hLz1WrftAjqdTBb3fWQsRR+Us2HsjAYdeE6M3VdXMsYCP5M3yiihal1WDwAY2U7HmfJw7Uh4A==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.32.2.tgz", + "integrity": "sha512-b8+ruAAY8aKtVKWSft2IvtCVCUH1LigIlf9ALIiY8n9jtM4kMASiaRbQ/27etnSAInV88IaezKK9rQZrtxTjcw==", "requires": { "bn.js": "^5.2.0" } }, "@cosmjs/proto-signing": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.31.3.tgz", - "integrity": "sha512-24+10/cGl6lLS4VCrGTCJeDRPQTn1K5JfknzXzDIHOx8THR31JxA7/HV5eWGHqWgAbudA7ccdSvEK08lEHHtLA==", - "requires": { - "@cosmjs/amino": "^0.31.3", - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0" + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.32.2.tgz", + "integrity": "sha512-UV4WwkE3W3G3s7wwU9rizNcUEz2g0W8jQZS5J6/3fiN0mRPwtPKQ6EinPN9ASqcAJ7/VQH4/9EPOw7d6XQGnqw==", + "requires": { + "@cosmjs/amino": "^0.32.2", + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "cosmjs-types": "^0.9.0" } }, "@cosmjs/socket": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.31.3.tgz", - "integrity": "sha512-aqrDGGi7os/hsz5p++avI4L0ZushJ+ItnzbqA7C6hamFSCJwgOkXaOUs+K9hXZdX4rhY7rXO4PH9IH8q09JkTw==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.32.2.tgz", + "integrity": "sha512-Qc8jaw4uSBJm09UwPgkqe3g9TBFx4ZR9HkXpwT6Z9I+6kbLerXPR0Gy3NSJFSUgxIfTpO8O1yqoWAyf0Ay17Mw==", "requires": { - "@cosmjs/stream": "^0.31.3", + "@cosmjs/stream": "^0.32.2", "isomorphic-ws": "^4.0.1", "ws": "^7", "xstream": "^11.14.0" } }, "@cosmjs/stargate": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.31.3.tgz", - "integrity": "sha512-53NxnzmB9FfXpG4KjOUAYAvWLYKdEmZKsutcat/u2BrDXNZ7BN8jim/ENcpwXfs9/Og0K24lEIdvA4gsq3JDQw==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.32.2.tgz", + "integrity": "sha512-AsJa29fT7Jd4xt9Ai+HMqhyj7UQu7fyYKdXj/8+/9PD74xe6lZSYhQPcitUmMLJ1ckKPgXSk5Dd2LbsQT0IhZg==", "requires": { "@confio/ics23": "^0.6.8", - "@cosmjs/amino": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/proto-signing": "^0.31.3", - "@cosmjs/stream": "^0.31.3", - "@cosmjs/tendermint-rpc": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0", - "protobufjs": "~6.11.3", + "@cosmjs/amino": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/proto-signing": "^0.32.2", + "@cosmjs/stream": "^0.32.2", + "@cosmjs/tendermint-rpc": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "cosmjs-types": "^0.9.0", "xstream": "^11.14.0" } }, "@cosmjs/stream": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.31.3.tgz", - "integrity": "sha512-8keYyI7X0RjsLyVcZuBeNjSv5FA4IHwbFKx7H60NHFXszN8/MvXL6aZbNIvxtcIHHsW7K9QSQos26eoEWlAd+w==", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.32.2.tgz", + "integrity": "sha512-gpCufLfHAD8Zp1ZKge7AHbDf4RA0TZp66wZY6JaQR5bSiEF2Drjtp4mwXZPGejtaUMnaAgff3LrUzPJfKYdQwg==", "requires": { "xstream": "^11.14.0" } }, "@cosmjs/tendermint-rpc": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.31.3.tgz", - "integrity": "sha512-s3TiWkPCW4QceTQjpYqn4xttUJH36mTPqplMl+qyocdqk5+X5mergzExU/pHZRWQ4pbby8bnR7kMvG4OC1aZ8g==", - "requires": { - "@cosmjs/crypto": "^0.31.3", - "@cosmjs/encoding": "^0.31.3", - "@cosmjs/json-rpc": "^0.31.3", - "@cosmjs/math": "^0.31.3", - "@cosmjs/socket": "^0.31.3", - "@cosmjs/stream": "^0.31.3", - "@cosmjs/utils": "^0.31.3", - "axios": "^0.21.2", + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.32.2.tgz", + "integrity": "sha512-DXyJHDmcAfCix4H/7/dKR0UMdshP01KxJOXHdHxBCbLIpck94BsWD3B2ZTXwfA6sv98so9wOzhp7qGQa5malxg==", + "requires": { + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", + "@cosmjs/json-rpc": "^0.32.2", + "@cosmjs/math": "^0.32.2", + "@cosmjs/socket": "^0.32.2", + "@cosmjs/stream": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "axios": "^1.6.0", "readonly-date": "^1.0.0", "xstream": "^11.14.0" + }, + "dependencies": { + "axios": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", + "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + } } }, "@cosmjs/utils": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.31.3.tgz", - "integrity": "sha512-VBhAgzrrYdIe0O5IbKRqwszbQa7ZyQLx9nEQuHQ3HUplQW7P44COG/ye2n6AzCudtqxmwdX7nyX8ta1J07GoqA==" + "version": "0.32.2", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.32.2.tgz", + "integrity": "sha512-Gg5t+eR7vPJMAmhkFt6CZrzPd0EKpAslWwk5rFVYZpJsM8JG5KT9XQ99hgNM3Ov6ScNoIWbXkpX27F6A9cXR4Q==" }, "@dabh/diagnostics": { "version": "2.0.3", @@ -7713,9 +7806,9 @@ } }, "@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==" }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -8105,6 +8198,11 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "ava": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.1.tgz", @@ -8491,6 +8589,14 @@ "text-hex": "1.0.x" } }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", @@ -8546,13 +8652,9 @@ "dev": true }, "cosmjs-types": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.8.0.tgz", - "integrity": "sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg==", - "requires": { - "long": "^4.0.0", - "protobufjs": "~6.11.2" - } + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.9.0.tgz", + "integrity": "sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==" }, "cross-spawn": { "version": "7.0.3", @@ -8679,6 +8781,11 @@ } } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "diff": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", @@ -9357,6 +9464,16 @@ "signal-exit": "^3.0.2" } }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fromentries": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", @@ -10237,6 +10354,19 @@ "picomatch": "^2.3.1" } }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, "mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -11136,6 +11266,11 @@ "long": "^4.0.0" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", diff --git a/ts-relayer-tests/package.json b/ts-relayer-tests/package.json index 2718a8a3..0fc49f0f 100644 --- a/ts-relayer-tests/package.json +++ b/ts-relayer-tests/package.json @@ -20,7 +20,7 @@ "test:unit": "nyc --silent ava --serial" }, "dependencies": { - "@confio/relayer": "^0.10" + "@confio/relayer": "^0.11" }, "devDependencies": { "@ava/typescript": "^3.0.1", diff --git a/ts-relayer-tests/src/controller.ts b/ts-relayer-tests/src/controller.ts index 05af7ec8..12af6e6c 100644 --- a/ts-relayer-tests/src/controller.ts +++ b/ts-relayer-tests/src/controller.ts @@ -13,7 +13,10 @@ export async function instantiateContract( codeId, msg, label, - "auto" + "auto", + { + admin: client.senderAddress, + } ); assert(result.contractAddress); return result; diff --git a/ts-relayer-tests/src/ics721-utils.ts b/ts-relayer-tests/src/ics721-utils.ts new file mode 100644 index 00000000..6bf96371 --- /dev/null +++ b/ts-relayer-tests/src/ics721-utils.ts @@ -0,0 +1,22 @@ +import { CosmWasmSigner } from "@confio/relayer"; + +// ######### execute + +export function migrate( + client: CosmWasmSigner, + contractAddress: string, + codeId: number, + incoming_proxy: string +) { + const msg = { + with_update: { incoming_proxy }, + }; + return client.sign.migrate( + client.senderAddress, + contractAddress, + codeId, + msg, + "auto", + undefined + ); +} diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index 223e13d1..8f276f82 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -4,10 +4,12 @@ import { Order } from "cosmjs-types/ibc/core/channel/v1/channel"; import { instantiateContract } from "./controller"; import { mint, ownerOf, sendNft } from "./cw721-utils"; +import { migrate } from "./ics721-utils"; import { assertAckErrors, assertAckSuccess, - ChannelInfo, + bigIntReplacer, + ChannelAndLinkInfo, ContractMsg, createIbcConnectionAndChannel, MNEMONIC, @@ -26,15 +28,20 @@ interface TestContext { wasmCw721: string; wasmIcs721: string; + wasmCw721IncomingProxy: string; + osmoCw721: string; osmoIcs721: string; - channel: ChannelInfo; + channel: ChannelAndLinkInfo; + + otherChannel: ChannelAndLinkInfo; } const test = anyTest as TestFn; const WASM_FILE_CW721 = "./internal/cw721_base_v0.18.0.wasm"; +const WASM_FILE_CW721_INCOMING_PROXY = "./internal/cw721_incoming_proxy.wasm"; const WASM_FILE_CW_ICS721_ICS721 = "./internal/ics721_base.wasm"; const MALICIOUS_CW721 = "./internal/cw721_tester.wasm"; @@ -56,6 +63,10 @@ const standardSetup = async (t: ExecutionContext) => { minter: wasmClient.senderAddress, }, }, + cw721IncomingProxy: { + path: WASM_FILE_CW721_INCOMING_PROXY, + instantiateMsg: undefined, + }, ics721: { path: WASM_FILE_CW_ICS721_ICS721, instantiateMsg: undefined, @@ -64,7 +75,11 @@ const standardSetup = async (t: ExecutionContext) => { const osmoContracts: Record = { cw721: { path: WASM_FILE_CW721, - instantiateMsg: undefined, + instantiateMsg: { + name: "ark", + symbol: "ark", + minter: osmoClient.senderAddress, + }, }, ics721: { path: WASM_FILE_CW_ICS721_ICS721, @@ -80,33 +95,39 @@ const standardSetup = async (t: ExecutionContext) => { ); const wasmCw721Id = info.wasmContractInfos.cw721.codeId; + const wasmCw721IncomingProxyId = + info.wasmContractInfos.cw721IncomingProxy.codeId; const osmoCw721Id = info.osmoContractInfos.cw721.codeId; const wasmIcs721Id = info.wasmContractInfos.ics721.codeId; const osmoIcs721Id = info.osmoContractInfos.ics721.codeId; t.context.wasmCw721 = info.wasmContractInfos.cw721.address as string; + t.context.osmoCw721 = info.osmoContractInfos.cw721.address as string; t.log(`instantiating wasm ICS721 contract (${wasmIcs721Id})`); - const { contractAddress: wasmIcs721 } = await instantiateContract( wasmClient, wasmIcs721Id, { cw721_base_code_id: wasmCw721Id }, "label ics721" ); + t.log(`- wasm ICS721 contract address: ${wasmIcs721}`); t.context.wasmIcs721 = wasmIcs721; t.log(`instantiating osmo ICS721 contract (${osmoIcs721Id})`); - const { contractAddress: osmoIcs721 } = await instantiateContract( osmoClient, osmoIcs721Id, { cw721_base_code_id: osmoCw721Id }, "label ics721" ); + t.log(`- osmo ICS721 contract address: ${osmoIcs721}`); t.context.osmoIcs721 = osmoIcs721; + t.log( + `creating IBC connection and channel between ${wasmIcs721} <-> ${osmoIcs721}` + ); const channelInfo = await createIbcConnectionAndChannel( wasmClient, osmoClient, @@ -115,9 +136,48 @@ const standardSetup = async (t: ExecutionContext) => { Order.ORDER_UNORDERED, "ics721-1" ); - + t.log(`- channel: ${JSON.stringify(channelInfo, bigIntReplacer, 2)}`); t.context.channel = channelInfo; + t.log( + `instantiating wasm cw721-incoming-proxy (${wasmCw721IncomingProxyId}) for channel ${channelInfo.channel.src.channelId}` + ); + const { contractAddress: wasmCw721IncomingProxy } = await instantiateContract( + wasmClient, + wasmCw721IncomingProxyId, + { + origin: wasmIcs721, + source_channels: [channelInfo.channel.src.channelId], + }, + "label incoming proxy" + ); + t.log(`- wasm cw721-incoming-proxy address: ${wasmCw721IncomingProxy}`); + t.context.wasmCw721IncomingProxy = wasmCw721IncomingProxy; + + t.log(`migrate ${wasmIcs721} contract to use incoming proxy`); + const migrateResult = await migrate( + wasmClient, + wasmIcs721, + wasmIcs721Id, + wasmCw721IncomingProxy + ); + t.log( + `- migrate result: ${JSON.stringify(migrateResult, bigIntReplacer, 2)}` + ); + + t.log( + `creating another IBC connection and channel between wasm and osmo (${wasmIcs721} <-> ${osmoIcs721})` + ); + const otherChannelInfo = await createIbcConnectionAndChannel( + wasmClient, + osmoClient, + wasmIcs721, + osmoIcs721, + Order.ORDER_UNORDERED, + "ics721-1" + ); + t.context.otherChannel = otherChannelInfo; + t.pass(); }; diff --git a/ts-relayer-tests/src/utils.ts b/ts-relayer-tests/src/utils.ts index e3551cbf..d965be95 100644 --- a/ts-relayer-tests/src/utils.ts +++ b/ts-relayer-tests/src/utils.ts @@ -26,6 +26,13 @@ const { const osmosis = { ...oldOsmo, minFee: "0.025uosmo" }; +export function bigIntReplacer(_key: string, value: any) { + if (typeof value === "bigint") { + return value.toString(); + } + return value; +} + export const MNEMONIC = "harsh adult scrub stadium solution impulse company agree tomorrow poem dirt innocent coyote slight nice digital scissors cool pact person item moon double wagon"; @@ -46,7 +53,7 @@ export interface ContractInfo { address: string | undefined; } -export interface ChannelInfo { +export interface ChannelAndLinkInfo { channel: ChannelPair; link: Link; } @@ -118,7 +125,7 @@ export async function createIbcConnectionAndChannel( osmoContractAddress: string, ordering: Order, version: string -): Promise { +): Promise { const { ibcPortId: wasmContractIbcPortId } = await wasmClient.sign.getContract(wasmContractAddress); assert(wasmContractIbcPortId); @@ -126,7 +133,7 @@ export async function createIbcConnectionAndChannel( await osmoClient.sign.getContract(osmoContractAddress); assert(osmoContractIbcPortId); // create a connection and channel - const [src, dest] = await setup(wasmd, osmosis); + const [srcIbcClient, destIbcClient] = await setup(wasmd, osmosis); const logger: Logger = { debug(message: string, meta?: Record): Logger { const logMsg = meta ? message + ": " + JSON.stringify(meta) : message; @@ -158,7 +165,11 @@ export async function createIbcConnectionAndChannel( return this; }, }; - const link = await Link.createWithNewConnections(src, dest, logger); + const link = await Link.createWithNewConnections( + srcIbcClient, + destIbcClient, + logger + ); const channel = await link.createChannel( "A", wasmContractIbcPortId, From e8f22b49d5c04b8d0e4e176a7071d1d6a91a66b3 Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 14:26:01 +0100 Subject: [PATCH 09/40] cargo clippy and fmt --- packages/ics721/src/execute.rs | 7 ++++--- packages/ics721/src/ibc.rs | 4 ++-- packages/ics721/src/query.rs | 4 ++-- packages/ics721/src/testing/contract.rs | 15 +++++++++++---- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index ca941fc6..2aa4266a 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -10,13 +10,14 @@ use sha2::{Digest, Sha256}; use crate::{ helpers::get_instantiate2_address, ibc::{ - NonFungibleTokenPacketData, INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, INSTANTIATE_INCOMING_PROXY_REPLY_ID, + NonFungibleTokenPacketData, INSTANTIATE_CW721_REPLY_ID, + INSTANTIATE_INCOMING_PROXY_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, }, msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg}, state::{ CollectionData, UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, - CW721_CODE_ID, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, - PO, TOKEN_METADATA, INCOMING_PROXY, + CW721_CODE_ID, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, + OUTGOING_PROXY, PO, TOKEN_METADATA, }, token_types::{Class, ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}, ContractError, diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index 350abf15..30c96615 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -13,8 +13,8 @@ use crate::{ ibc_helpers::{ack_fail, ack_success, try_get_ack_error, validate_order_and_version}, ibc_packet_receive::receive_ibc_packet, state::{ - CLASS_ID_TO_NFT_CONTRACT, INCOMING_CLASS_TOKEN_TO_CHANNEL, NFT_CONTRACT_TO_CLASS_ID, - OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, TOKEN_METADATA, INCOMING_PROXY, + CLASS_ID_TO_NFT_CONTRACT, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, + NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, TOKEN_METADATA, }, token_types::{ClassId, TokenId}, types::Ics721Status, diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index 9683b09f..404c5ea5 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -5,8 +5,8 @@ use crate::{ msg::{ClassToken, QueryMsg}, state::{ UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, - INCOMING_CLASS_TOKEN_TO_CHANNEL, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, - OUTGOING_PROXY, PO, TOKEN_METADATA, INCOMING_PROXY, + INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, + OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA, }, token_types::{Class, ClassId, Token, TokenId}, }; diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index 4252cc72..5881976e 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -12,7 +12,10 @@ use cw_ownable::Ownership; use crate::{ execute::Ics721Execute, - ibc::{Ics721Ibc, NonFungibleTokenPacketData, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, INSTANTIATE_INCOMING_PROXY_REPLY_ID}, + ibc::{ + Ics721Ibc, NonFungibleTokenPacketData, INSTANTIATE_INCOMING_PROXY_REPLY_ID, + INSTANTIATE_OUTGOING_PROXY_REPLY_ID, + }, msg::{IbcOutgoingMsg, InstantiateMsg}, query::Ics721Query, state::{ @@ -515,7 +518,8 @@ fn test_instantiate() { .instantiate(deps.as_mut(), env.clone(), info, msg.clone()) .unwrap(); - let expected_incoming_proxy_msg = incoming_proxy_init_msg.into_wasm_msg(env.clone().contract.address); + let expected_incoming_proxy_msg = + incoming_proxy_init_msg.into_wasm_msg(env.clone().contract.address); let expected_outgoing_proxy_msg = outgoing_proxy_init_msg.into_wasm_msg(env.contract.address); let expected_response = Response::::default() .add_submessage(SubMsg::reply_on_success( @@ -533,6 +537,9 @@ fn test_instantiate() { // incoming and outgoing proxy initially set to None and set later in sub msg assert_eq!(OUTGOING_PROXY.load(&deps.storage).unwrap(), None); assert_eq!(INCOMING_PROXY.load(&deps.storage).unwrap(), None); - assert_eq!(PO.pauser.load(&deps.storage).unwrap(), Some(Addr::unchecked(PAUSER_ADDR))); - assert_eq!(PO.paused.load(&deps.storage).unwrap(), false); + assert_eq!( + PO.pauser.load(&deps.storage).unwrap(), + Some(Addr::unchecked(PAUSER_ADDR)) + ); + assert!(!PO.paused.load(&deps.storage).unwrap()); } From 7c5e9c3b7e2e8fb0bb740e75eee2d92f27521bde Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 17:13:50 +0100 Subject: [PATCH 10/40] move types to dedicated package --- Cargo.lock | 20 ++- Cargo.toml | 1 + contracts/ics721-base-tester/Cargo.toml | 1 + contracts/ics721-base-tester/src/contract.rs | 4 +- contracts/ics721-base-tester/src/msg.rs | 6 +- contracts/sg-ics721/Cargo.toml | 1 + contracts/sg-ics721/src/execute.rs | 4 +- .../src/testing/integration_tests.rs | 3 +- packages/ics721-types/Cargo.toml | 13 ++ packages/ics721-types/src/error.rs | 17 ++ packages/ics721-types/src/ibc.rs | 160 ++++++++++++++++++ packages/ics721-types/src/lib.rs | 4 + packages/ics721-types/src/token_types.rs | 145 ++++++++++++++++ .../{ics721 => ics721-types}/src/types.rs | 0 packages/ics721/Cargo.toml | 1 + packages/ics721/src/error.rs | 16 +- packages/ics721/src/execute.rs | 5 +- packages/ics721/src/helpers.rs | 10 +- packages/ics721/src/ibc.rs | 41 +---- packages/ics721/src/ibc_helpers.rs | 120 +------------ packages/ics721/src/ibc_packet_receive.rs | 6 +- packages/ics721/src/lib.rs | 3 +- packages/ics721/src/msg.rs | 9 +- packages/ics721/src/query.rs | 2 +- packages/ics721/src/state.rs | 2 +- packages/ics721/src/testing/contract.rs | 4 +- packages/ics721/src/testing/ibc_tests.rs | 11 +- .../ics721/src/testing/integration_tests.rs | 3 +- packages/ics721/src/token_types.rs | 148 +--------------- 29 files changed, 410 insertions(+), 350 deletions(-) create mode 100644 packages/ics721-types/Cargo.toml create mode 100644 packages/ics721-types/src/error.rs create mode 100644 packages/ics721-types/src/ibc.rs create mode 100644 packages/ics721-types/src/lib.rs create mode 100644 packages/ics721-types/src/token_types.rs rename packages/{ics721 => ics721-types}/src/types.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 33a6edac..0d80bd6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -241,7 +241,7 @@ dependencies = [ "cw-incoming-proxy-derive", "cw-paginate-storage", "cw-storage-plus 1.2.0", - "ics721-types", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", "schemars", "serde", "thiserror", @@ -253,7 +253,7 @@ version = "0.0.1" source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" dependencies = [ "cosmwasm-std", - "ics721-types", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", "proc-macro2", "quote", "syn 1.0.109", @@ -526,7 +526,7 @@ dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721-outgoing-proxy", "cw721-outgoing-proxy-derive", - "ics721-types", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", "serde", "thiserror", ] @@ -791,6 +791,7 @@ dependencies = [ "cw721-incoming-proxy", "cw721-outgoing-proxy-derive", "cw721-outgoing-proxy-rate-limit", + "ics721-types 0.1.0", "serde", "sha2 0.10.8", "thiserror", @@ -817,6 +818,18 @@ dependencies = [ "cw2 1.1.2", "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "ics721", + "ics721-types 0.1.0", + "thiserror", +] + +[[package]] +name = "ics721-types" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "serde", "thiserror", ] @@ -1099,6 +1112,7 @@ dependencies = [ "cw721-incoming-proxy", "cw721-outgoing-proxy-rate-limit", "ics721", + "ics721-types 0.1.0", "sg-std", "sg721", "sg721-base", diff --git a/Cargo.toml b/Cargo.toml index 67ed106f..8866c042 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ sg721-base = "^3.3" cw-cii = { path = "./packages/cw-cii" } cw-pause-once = { path = "./packages/cw-pause-once" } ics721 = { path = "./packages/ics721" } +ics721-types = { path = "./packages/ics721-types" } zip-optional = { path = "./packages/zip-optional" } ics721-base = { path = "./contracts/ics721-base"} ics721-base-tester = { path = "./contracts/cw-ics721-base-tester"} diff --git a/contracts/ics721-base-tester/Cargo.toml b/contracts/ics721-base-tester/Cargo.toml index 1c266320..2d30479c 100644 --- a/contracts/ics721-base-tester/Cargo.toml +++ b/contracts/ics721-base-tester/Cargo.toml @@ -19,5 +19,6 @@ cosmwasm-storage = { workspace = true } cw-storage-plus = { workspace = true } cw2 = { workspace = true } ics721 = { workspace = true } +ics721-types = { workspace = true } thiserror = { workspace = true } cw721 = { workspace = true } diff --git a/contracts/ics721-base-tester/src/contract.rs b/contracts/ics721-base-tester/src/contract.rs index 94410133..82218e67 100644 --- a/contracts/ics721-base-tester/src/contract.rs +++ b/contracts/ics721-base-tester/src/contract.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{ StdResult, WasmMsg, }; use cw2::set_contract_version; -use ics721::ibc::NonFungibleTokenPacketData; +use ics721_types::ibc::NonFungibleTokenPacketData; use crate::{ error::ContractError, @@ -64,7 +64,7 @@ pub fn execute( mod receive_callbacks { use cosmwasm_std::{ensure_eq, from_json, DepsMut, MessageInfo, Response}; - use ics721::{ + use ics721_types::{ ibc::NonFungibleTokenPacketData, types::{Ics721AckCallbackMsg, Ics721ReceiveCallbackMsg, Ics721Status}, }; diff --git a/contracts/ics721-base-tester/src/msg.rs b/contracts/ics721-base-tester/src/msg.rs index 3038279c..d84c3186 100644 --- a/contracts/ics721-base-tester/src/msg.rs +++ b/contracts/ics721-base-tester/src/msg.rs @@ -43,8 +43,8 @@ pub struct InstantiateMsg { // for clippy's taste. pub enum ExecuteMsg { ReceiveNft(cw721::Cw721ReceiveMsg), - Ics721ReceiveCallback(ics721::types::Ics721ReceiveCallbackMsg), - Ics721AckCallback(ics721::types::Ics721AckCallbackMsg), + Ics721ReceiveCallback(ics721_types::types::Ics721ReceiveCallbackMsg), + Ics721AckCallback(ics721_types::types::Ics721AckCallbackMsg), SendNft { cw721: String, ics721: String, @@ -60,7 +60,7 @@ pub enum ExecuteMsg { channel_id: String, timeout: IbcTimeout, - data: ics721::ibc::NonFungibleTokenPacketData, + data: ics721_types::ibc::NonFungibleTokenPacketData, }, SetAckMode { ack_mode: AckMode, diff --git a/contracts/sg-ics721/Cargo.toml b/contracts/sg-ics721/Cargo.toml index d0654bb1..cf98d0fa 100644 --- a/contracts/sg-ics721/Cargo.toml +++ b/contracts/sg-ics721/Cargo.toml @@ -17,6 +17,7 @@ cosmwasm-std = { workspace = true, features = ["ibc3"] } cosmwasm-schema = { workspace = true } cw2 = { workspace = true } ics721 = { workspace = true } +ics721-types = { workspace = true } sg-std = { workspace = true} sg721 = { workspace = true } sg721-base = { workspace = true, features = ["library"] } diff --git a/contracts/sg-ics721/src/execute.rs b/contracts/sg-ics721/src/execute.rs index 2605a99a..98088abb 100644 --- a/contracts/sg-ics721/src/execute.rs +++ b/contracts/sg-ics721/src/execute.rs @@ -1,7 +1,9 @@ use cosmwasm_std::{from_json, to_json_binary, Addr, Binary, Deps, DepsMut, Env, StdResult}; use ics721::{ - execute::Ics721Execute, state::CollectionData, token_types::Class, utils::get_collection_data, + execute::Ics721Execute, state::CollectionData, utils::get_collection_data, }; +use ics721_types::token_types::{Class}; + use sg721_base::msg::{CollectionInfoResponse, QueryMsg}; use crate::state::{SgCollectionData, SgIcs721Contract}; diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index 3427210d..b671807e 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -20,8 +20,9 @@ use ics721::{ msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg, QueryMsg}, query::Ics721Query, state::CollectionData, - token_types::{Class, ClassId, Token, TokenId, VoucherCreation}, + token_types::VoucherCreation, }; +use ics721_types::token_types::{Class, ClassId, Token, TokenId}; use sg721::InstantiateMsg as Sg721InstantiateMsg; use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; use sha2::{digest::Update, Digest, Sha256}; diff --git a/packages/ics721-types/Cargo.toml b/packages/ics721-types/Cargo.toml new file mode 100644 index 00000000..fd3e8246 --- /dev/null +++ b/packages/ics721-types/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ics721-types" +version = "0.1.0" +edition = "2021" +authors = ["ekez ", "mr-t ", "Art3mix ", "m@publicawesome.com", "s+git@publicawesome.com"] +description = "an implementation of the ICS721 specification for transfering NFTs between blockchains" + +[dependencies] +cosmwasm-std = { workspace = true, features = ["cosmwasm_1_2"] } +cosmwasm-schema = { workspace = true } +cw-storage-plus = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } diff --git a/packages/ics721-types/src/error.rs b/packages/ics721-types/src/error.rs new file mode 100644 index 00000000..cc1baffe --- /dev/null +++ b/packages/ics721-types/src/error.rs @@ -0,0 +1,17 @@ +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ValidationError { + #[error("empty class ID")] + EmptyClassId {}, + + #[error("must transfer at least one token")] + NoTokens {}, + + #[error("optional fields may not be empty if provided")] + EmptyOptional {}, + + #[error("tokenIds, tokenUris, and tokenData must have the same length")] + TokenInfoLenMissmatch {}, + +} diff --git a/packages/ics721-types/src/ibc.rs b/packages/ics721-types/src/ibc.rs new file mode 100644 index 00000000..e71c0a1f --- /dev/null +++ b/packages/ics721-types/src/ibc.rs @@ -0,0 +1,160 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::Binary; + +use crate::{token_types::{ClassId, TokenId}, error::ValidationError}; + +#[cw_serde] +#[serde(rename_all = "camelCase")] +pub struct NonFungibleTokenPacketData { + /// Uniquely identifies the collection which the tokens being + /// transfered belong to on the sending chain. Must be non-empty. + pub class_id: ClassId, + /// Optional URL that points to metadata about the + /// collection. Must be non-empty if provided. + pub class_uri: Option, + /// Optional base64 encoded field which contains on-chain metadata + /// about the NFT class. Must be non-empty if provided. + pub class_data: Option, + /// Uniquely identifies the tokens in the NFT collection being + /// transfered. This MUST be non-empty. + pub token_ids: Vec, + /// Optional URL that points to metadata for each token being + /// transfered. `tokenUris[N]` should hold the metadata for + /// `tokenIds[N]` and both lists should have the same if + /// provided. Must be non-empty if provided. + pub token_uris: Option>, + /// Optional base64 encoded metadata for the tokens being + /// transfered. `tokenData[N]` should hold metadata for + /// `tokenIds[N]` and both lists should have the same length if + /// provided. Must be non-empty if provided. + pub token_data: Option>, + + /// The address sending the tokens on the sending chain. + pub sender: String, + /// The address that should receive the tokens on the receiving + /// chain. + pub receiver: String, + /// Memo to add custom string to the msg + pub memo: Option, +} + +macro_rules! non_empty_optional { + ($e:expr) => { + if $e.map_or(false, |data| data.is_empty()) { + return Err(ValidationError::EmptyOptional {}); + } + }; +} + +impl NonFungibleTokenPacketData { + pub fn validate(&self) -> Result<(), ValidationError> { + if self.class_id.is_empty() { + return Err(ValidationError::EmptyClassId {}); + } + + non_empty_optional!(self.class_uri.as_ref()); + non_empty_optional!(self.class_data.as_ref()); + + let token_count = self.token_ids.len(); + if token_count == 0 { + return Err(ValidationError::NoTokens {}); + } + + // Non-empty optionality of tokenData an tokenUris implicitly + // checked here. + if self + .token_data + .as_ref() + .map_or(false, |data| data.len() != token_count) + || self + .token_uris + .as_ref() + .map_or(false, |data| data.len() != token_count) + { + return Err(ValidationError::TokenInfoLenMissmatch {}); + } + + // This contract assumes that the backing cw721 is functional, + // so no need to check tokenIds for duplicates as the cw721 + // will prevent minting of duplicates. + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::token_types::{ClassId, TokenId}; + + #[test] + fn test_packet_validation() { + let default_token = NonFungibleTokenPacketData { + class_id: ClassId::new("id"), + class_uri: None, + class_data: None, + token_ids: vec![TokenId::new("1")], + token_uris: None, + token_data: None, + sender: "violet".to_string(), + receiver: "blue".to_string(), + memo: None, + }; + + let empty_class_id = NonFungibleTokenPacketData { + class_id: ClassId::new(""), + ..default_token.clone() + }; + let err = empty_class_id.validate().unwrap_err(); + assert_eq!(err, ValidationError::EmptyClassId {}); + + let empty_class_uri = NonFungibleTokenPacketData { + class_uri: Some("".to_string()), + ..default_token.clone() + }; + let err = empty_class_uri.validate().unwrap_err(); + assert_eq!(err, ValidationError::EmptyOptional {}); + + let empty_class_data = NonFungibleTokenPacketData { + class_data: Some(Binary::default()), + ..default_token.clone() + }; + let err = empty_class_data.validate().unwrap_err(); + assert_eq!(err, ValidationError::EmptyOptional {}); + + let no_tokens = NonFungibleTokenPacketData { + token_ids: vec![], + ..default_token.clone() + }; + let err = no_tokens.validate().unwrap_err(); + assert_eq!(err, ValidationError::NoTokens {}); + + let uri_imbalance_empty = NonFungibleTokenPacketData { + token_uris: Some(vec![]), + ..default_token.clone() + }; + let err = uri_imbalance_empty.validate().unwrap_err(); + assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + + let uri_imbalance = NonFungibleTokenPacketData { + token_uris: Some(vec!["a".to_string(), "b".to_string()]), + ..default_token.clone() + }; + let err = uri_imbalance.validate().unwrap_err(); + assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + + let data_imbalance_empty = NonFungibleTokenPacketData { + token_data: Some(vec![]), + ..default_token.clone() + }; + let err = data_imbalance_empty.validate().unwrap_err(); + assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + + let data_imbalance = NonFungibleTokenPacketData { + token_data: Some(vec![Binary::default(), Binary::default()]), + ..default_token + }; + let err = data_imbalance.validate().unwrap_err(); + assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + } +} diff --git a/packages/ics721-types/src/lib.rs b/packages/ics721-types/src/lib.rs new file mode 100644 index 00000000..15d960e0 --- /dev/null +++ b/packages/ics721-types/src/lib.rs @@ -0,0 +1,4 @@ +pub mod error; +pub mod ibc; +pub mod token_types; +pub mod types; diff --git a/packages/ics721-types/src/token_types.rs b/packages/ics721-types/src/token_types.rs new file mode 100644 index 00000000..3b988490 --- /dev/null +++ b/packages/ics721-types/src/token_types.rs @@ -0,0 +1,145 @@ +use std::ops::Deref; + +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Binary, StdResult}; +use cw_storage_plus::{Bound, Bounder, Key, KeyDeserialize, Prefixer, PrimaryKey}; + +/// A token ID according to the ICS-721 spec. The newtype pattern is +/// used here to provide some distinction between token and class IDs +/// in the type system. +#[cw_serde] +pub struct TokenId(String); + +/// A token according to the ICS-721 spec. +#[cw_serde] +pub struct Token { + /// A unique identifier for the token. + pub id: TokenId, + /// Optional URI pointing to off-chain metadata about the token. + pub uri: Option, + /// Optional base64 encoded metadata about the token. + pub data: Option, +} + +/// A class ID according to the ICS-721 spec. The newtype pattern is +/// used here to provide some distinction between token and class IDs +/// in the type system. +#[cw_serde] +pub struct ClassId(String); + +#[cw_serde] +pub struct Class { + /// A unique (from the source chain's perspective) identifier for + /// the class. + pub id: ClassId, + /// Optional URI pointing to off-chain metadata about the class. + pub uri: Option, + /// Optional base64 encoded metadata about the class. + pub data: Option, +} + +impl TokenId { + pub fn new(token_id: T) -> Self + where + T: Into, + { + Self(token_id.into()) + } +} + +impl ClassId { + pub fn new(class_id: T) -> Self + where + T: Into, + { + Self(class_id.into()) + } +} + +impl<'a> Bounder<'a> for ClassId { + fn inclusive_bound(self) -> Option> { + Some(Bound::inclusive(self)) + } + + fn exclusive_bound(self) -> Option> { + Some(Bound::exclusive(self)) + } +} + +// boilerplate for conversion between wrappers and the wrapped. + +impl From for String { + fn from(c: ClassId) -> Self { + c.0 + } +} + +impl From for String { + fn from(t: TokenId) -> Self { + t.0 + } +} + +impl Deref for ClassId { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::fmt::Display for ClassId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +// boilerplate for storing these wrapper types in CosmWasm maps. + +impl<'a> PrimaryKey<'a> for ClassId { + type Prefix = >::Prefix; + type SubPrefix = >::SubPrefix; + type Suffix = >::Suffix; + type SuperSuffix = >::SuperSuffix; + + fn key(&self) -> Vec { + self.0.key() + } +} + +impl<'a> PrimaryKey<'a> for TokenId { + type Prefix = >::Prefix; + type SubPrefix = >::SubPrefix; + type Suffix = >::Suffix; + type SuperSuffix = >::SuperSuffix; + + fn key(&self) -> Vec { + self.0.key() + } +} + +impl<'a> Prefixer<'a> for ClassId { + fn prefix(&self) -> Vec { + self.0.prefix() + } +} + +impl<'a> Prefixer<'a> for TokenId { + fn prefix(&self) -> Vec { + self.0.prefix() + } +} + +impl KeyDeserialize for ClassId { + type Output = ::Output; + fn from_vec(value: Vec) -> StdResult { + String::from_vec(value) + } +} + +impl KeyDeserialize for TokenId { + type Output = ::Output; + fn from_vec(value: Vec) -> StdResult { + String::from_vec(value) + } +} diff --git a/packages/ics721/src/types.rs b/packages/ics721-types/src/types.rs similarity index 100% rename from packages/ics721/src/types.rs rename to packages/ics721-types/src/types.rs diff --git a/packages/ics721/Cargo.toml b/packages/ics721/Cargo.toml index 563b6646..ac2685b9 100644 --- a/packages/ics721/Cargo.toml +++ b/packages/ics721/Cargo.toml @@ -15,6 +15,7 @@ cw-utils = { workspace = true } cw721 = { workspace = true } cw721-base = { workspace = true, features = ["library"] } cw721-base-016 = { workspace = true, features = ["library"] } +ics721-types = { workspace = true } thiserror = { workspace = true } serde = { workspace = true } cw-paginate-storage = { workspace = true } diff --git a/packages/ics721/src/error.rs b/packages/ics721/src/error.rs index 876eda4d..e3774975 100644 --- a/packages/ics721/src/error.rs +++ b/packages/ics721/src/error.rs @@ -1,10 +1,14 @@ use cosmwasm_std::{Instantiate2AddressError, StdError}; use cw_pause_once::PauseError; use cw_utils::ParseReplyError; +use ics721_types::error::ValidationError; use thiserror::Error; #[derive(Error, Debug, PartialEq)] pub enum ContractError { + #[error(transparent)] + ValidationError(#[from] ValidationError), + #[error(transparent)] Std(#[from] StdError), @@ -32,15 +36,6 @@ pub enum ContractError { #[error("class ID already exists")] ClassIdAlreadyExists {}, - #[error("empty class ID")] - EmptyClassId {}, - - #[error("must transfer at least one token")] - NoTokens {}, - - #[error("optional fields may not be empty if provided")] - EmptyOptional {}, - #[error("unrecognised reply ID")] UnrecognisedReplyId {}, @@ -57,9 +52,6 @@ pub enum ContractError { actual: Option, }, - #[error("tokenIds, tokenUris, and tokenData must have the same length")] - TokenInfoLenMissmatch {}, - #[error("Transfer contains both redemption and a creation action")] InvalidTransferBothActions, diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 2aa4266a..08980252 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -4,13 +4,14 @@ use cosmwasm_std::{ from_json, to_json_binary, Addr, Binary, ContractInfoResponse, Deps, DepsMut, Empty, Env, IbcMsg, MessageInfo, Response, StdResult, SubMsg, WasmMsg, }; +use ics721_types::{token_types::{TokenId, Class, ClassId, Token}, ibc::NonFungibleTokenPacketData}; use serde::{de::DeserializeOwned, Serialize}; use sha2::{Digest, Sha256}; use crate::{ helpers::get_instantiate2_address, ibc::{ - NonFungibleTokenPacketData, INSTANTIATE_CW721_REPLY_ID, + INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_INCOMING_PROXY_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, }, msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg}, @@ -19,7 +20,7 @@ use crate::{ CW721_CODE_ID, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA, }, - token_types::{Class, ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}, + token_types::{VoucherCreation, VoucherRedemption}, ContractError, }; diff --git a/packages/ics721/src/helpers.rs b/packages/ics721/src/helpers.rs index 4b912472..7df41158 100644 --- a/packages/ics721/src/helpers.rs +++ b/packages/ics721/src/helpers.rs @@ -5,13 +5,13 @@ use cosmwasm_std::{ use serde::Deserialize; use crate::{ - ibc::{NonFungibleTokenPacketData, ACK_CALLBACK_REPLY_ID}, - types::{ - Ics721AckCallbackMsg, Ics721Callbacks, Ics721Memo, Ics721ReceiveCallbackMsg, Ics721Status, - ReceiverExecuteMsg, - }, + ibc::ACK_CALLBACK_REPLY_ID, ContractError, }; +use ics721_types::{types::{ + Ics721AckCallbackMsg, Ics721Callbacks, Ics721Memo, Ics721ReceiveCallbackMsg, Ics721Status, + ReceiverExecuteMsg, +}, ibc::NonFungibleTokenPacketData}; /// Parse the memo field into the type we want /// Ideally it would be `Ics721Memo` type or any type that extends it diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index 30c96615..3f894ef0 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -1,11 +1,11 @@ -use cosmwasm_schema::cw_serde; use cosmwasm_std::{ - from_json, to_json_binary, Binary, DepsMut, Empty, Env, IbcBasicResponse, IbcChannelCloseMsg, + from_json, to_json_binary, DepsMut, Empty, Env, IbcBasicResponse, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, Never, Reply, Response, StdResult, SubMsgResult, WasmMsg, }; use cw_utils::parse_reply_instantiate_data; +use ics721_types::{ibc::NonFungibleTokenPacketData, types::Ics721Status}; use serde::{de::DeserializeOwned, Serialize}; use crate::{ @@ -16,8 +16,6 @@ use crate::{ CLASS_ID_TO_NFT_CONTRACT, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, TOKEN_METADATA, }, - token_types::{ClassId, TokenId}, - types::Ics721Status, ContractError, }; @@ -36,41 +34,6 @@ pub(crate) const ACK_CALLBACK_REPLY_ID: u64 = 3; /// The IBC version this contract expects to communicate with. pub const IBC_VERSION: &str = "ics721-1"; -#[cw_serde] -#[serde(rename_all = "camelCase")] -pub struct NonFungibleTokenPacketData { - /// Uniquely identifies the collection which the tokens being - /// transfered belong to on the sending chain. Must be non-empty. - pub class_id: ClassId, - /// Optional URL that points to metadata about the - /// collection. Must be non-empty if provided. - pub class_uri: Option, - /// Optional base64 encoded field which contains on-chain metadata - /// about the NFT class. Must be non-empty if provided. - pub class_data: Option, - /// Uniquely identifies the tokens in the NFT collection being - /// transfered. This MUST be non-empty. - pub token_ids: Vec, - /// Optional URL that points to metadata for each token being - /// transfered. `tokenUris[N]` should hold the metadata for - /// `tokenIds[N]` and both lists should have the same if - /// provided. Must be non-empty if provided. - pub token_uris: Option>, - /// Optional base64 encoded metadata for the tokens being - /// transfered. `tokenData[N]` should hold metadata for - /// `tokenIds[N]` and both lists should have the same length if - /// provided. Must be non-empty if provided. - pub token_data: Option>, - - /// The address sending the tokens on the sending chain. - pub sender: String, - /// The address that should receive the tokens on the receiving - /// chain. - pub receiver: String, - /// Memo to add custom string to the msg - pub memo: Option, -} - pub trait Ics721Ibc where T: Serialize + DeserializeOwned + Clone, diff --git a/packages/ics721/src/ibc_helpers.rs b/packages/ics721/src/ibc_helpers.rs index 98f8e9d2..51e44fb6 100644 --- a/packages/ics721/src/ibc_helpers.rs +++ b/packages/ics721/src/ibc_helpers.rs @@ -1,10 +1,11 @@ use cosmwasm_std::{ from_json, to_json_binary, Binary, IbcAcknowledgement, IbcChannel, IbcEndpoint, IbcOrder, }; +use ics721_types::ibc::NonFungibleTokenPacketData; use serde::{Deserialize, Serialize}; use crate::{ - ibc::{NonFungibleTokenPacketData, IBC_VERSION}, + ibc::IBC_VERSION, ContractError, }; @@ -120,54 +121,10 @@ pub(crate) fn validate_order_and_version( Ok(()) } -macro_rules! non_empty_optional { - ($e:expr) => { - if $e.map_or(false, |data| data.is_empty()) { - return Err(ContractError::EmptyOptional {}); - } - }; -} - -impl NonFungibleTokenPacketData { - pub fn validate(&self) -> Result<(), ContractError> { - if self.class_id.is_empty() { - return Err(ContractError::EmptyClassId {}); - } - - non_empty_optional!(self.class_uri.as_ref()); - non_empty_optional!(self.class_data.as_ref()); - - let token_count = self.token_ids.len(); - if token_count == 0 { - return Err(ContractError::NoTokens {}); - } - - // Non-empty optionality of tokenData an tokenUris implicitly - // checked here. - if self - .token_data - .as_ref() - .map_or(false, |data| data.len() != token_count) - || self - .token_uris - .as_ref() - .map_or(false, |data| data.len() != token_count) - { - return Err(ContractError::TokenInfoLenMissmatch {}); - } - - // This contract assumes that the backing cw721 is functional, - // so no need to check tokenIds for duplicates as the cw721 - // will prevent minting of duplicates. - - Ok(()) - } -} - #[cfg(test)] mod tests { use super::*; - use crate::token_types::{ClassId, TokenId}; + use ics721_types::token_types::{ClassId, TokenId}; #[test] fn test_pop_source_simple() { @@ -221,75 +178,4 @@ mod tests { None ); } - - #[test] - fn test_packet_validation() { - let default_token = NonFungibleTokenPacketData { - class_id: ClassId::new("id"), - class_uri: None, - class_data: None, - token_ids: vec![TokenId::new("1")], - token_uris: None, - token_data: None, - sender: "violet".to_string(), - receiver: "blue".to_string(), - memo: None, - }; - - let empty_class_id = NonFungibleTokenPacketData { - class_id: ClassId::new(""), - ..default_token.clone() - }; - let err = empty_class_id.validate().unwrap_err(); - assert_eq!(err, ContractError::EmptyClassId {}); - - let empty_class_uri = NonFungibleTokenPacketData { - class_uri: Some("".to_string()), - ..default_token.clone() - }; - let err = empty_class_uri.validate().unwrap_err(); - assert_eq!(err, ContractError::EmptyOptional {}); - - let empty_class_data = NonFungibleTokenPacketData { - class_data: Some(Binary::default()), - ..default_token.clone() - }; - let err = empty_class_data.validate().unwrap_err(); - assert_eq!(err, ContractError::EmptyOptional {}); - - let no_tokens = NonFungibleTokenPacketData { - token_ids: vec![], - ..default_token.clone() - }; - let err = no_tokens.validate().unwrap_err(); - assert_eq!(err, ContractError::NoTokens {}); - - let uri_imbalance_empty = NonFungibleTokenPacketData { - token_uris: Some(vec![]), - ..default_token.clone() - }; - let err = uri_imbalance_empty.validate().unwrap_err(); - assert_eq!(err, ContractError::TokenInfoLenMissmatch {}); - - let uri_imbalance = NonFungibleTokenPacketData { - token_uris: Some(vec!["a".to_string(), "b".to_string()]), - ..default_token.clone() - }; - let err = uri_imbalance.validate().unwrap_err(); - assert_eq!(err, ContractError::TokenInfoLenMissmatch {}); - - let data_imbalance_empty = NonFungibleTokenPacketData { - token_data: Some(vec![]), - ..default_token.clone() - }; - let err = data_imbalance_empty.validate().unwrap_err(); - assert_eq!(err, ContractError::TokenInfoLenMissmatch {}); - - let data_imbalance = NonFungibleTokenPacketData { - token_data: Some(vec![Binary::default(), Binary::default()]), - ..default_token - }; - let err = data_imbalance.validate().unwrap_err(); - assert_eq!(err, ContractError::TokenInfoLenMissmatch {}); - } } diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 61a7a978..67f564ee 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -7,17 +7,17 @@ use zip_optional::Zippable; use crate::{ helpers::{generate_receive_callback_msg, get_instantiate2_address, get_receive_callback}, - ibc::{NonFungibleTokenPacketData, ACK_AND_DO_NOTHING}, + ibc::{ACK_AND_DO_NOTHING}, ibc_helpers::{get_endpoint_prefix, try_pop_source_prefix}, msg::{CallbackMsg, ExecuteMsg}, state::{ CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO, }, - token_types::{Class, ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}, - types::Ics721ReceiveIbcPacketMsg, + token_types::{VoucherCreation, VoucherRedemption}, ContractError, }; +use ics721_types::{token_types::{Class, ClassId, Token, TokenId}, ibc::NonFungibleTokenPacketData, types::Ics721ReceiveIbcPacketMsg}; /// Every incoming token has some associated action. enum Action { diff --git a/packages/ics721/src/lib.rs b/packages/ics721/src/lib.rs index 5502942e..d1d2b499 100644 --- a/packages/ics721/src/lib.rs +++ b/packages/ics721/src/lib.rs @@ -8,9 +8,8 @@ pub mod msg; pub mod query; pub mod state; pub mod token_types; -pub mod types; pub mod utils; - +use ics721_types::{token_types::{Class, ClassId, Token, TokenId}, ibc::NonFungibleTokenPacketData}; pub use crate::error::ContractError; #[cfg(test)] diff --git a/packages/ics721/src/msg.rs b/packages/ics721/src/msg.rs index 9ff087ad..f5b71858 100644 --- a/packages/ics721/src/msg.rs +++ b/packages/ics721/src/msg.rs @@ -3,7 +3,8 @@ use cosmwasm_std::{Addr, IbcTimeout, WasmMsg}; use cw721_outgoing_proxy_derive::cw721_outgoing_proxy; use cw_cii::ContractInstantiateInfo; -use crate::token_types::{ClassId, Token, TokenId, VoucherCreation, VoucherRedemption}; +use crate::token_types::{VoucherCreation, VoucherRedemption}; +use ics721_types::token_types::{Class, ClassId, Token, TokenId}; #[cw_serde] pub struct InstantiateMsg { @@ -104,7 +105,7 @@ pub enum QueryMsg { /// Gets the classID this contract has stored for a given NFT /// contract. If there is no class ID for the provided contract, /// returns None. - #[returns(Option)] + #[returns(Option)] ClassId { contract: String }, /// Gets the NFT contract associated wtih the provided class @@ -116,10 +117,10 @@ pub enum QueryMsg { /// Gets the class level metadata URI for the provided /// class_id. If there is no metadata, returns None. Returns /// `Option`. - #[returns(Option)] + #[returns(Option)] ClassMetadata { class_id: String }, - #[returns(Option)] + #[returns(Option)] TokenMetadata { class_id: String, token_id: String }, /// Gets the owner of the NFT identified by CLASS_ID and diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index 404c5ea5..b406acae 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -8,8 +8,8 @@ use crate::{ INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA, }, - token_types::{Class, ClassId, Token, TokenId}, }; +use ics721_types::token_types::{Class, ClassId, Token, TokenId}; pub trait Ics721Query { fn query(&self, deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { diff --git a/packages/ics721/src/state.rs b/packages/ics721/src/state.rs index b631010e..bc75a832 100644 --- a/packages/ics721/src/state.rs +++ b/packages/ics721/src/state.rs @@ -4,7 +4,7 @@ use cw_pause_once::PauseOrchestrator; use cw_storage_plus::{Item, Map}; use serde::{Deserialize, Serialize}; -use crate::token_types::{Class, ClassId, TokenId}; +use ics721_types::token_types::{Class, ClassId, TokenId}; /// The code ID we will use for instantiating new cw721s. pub const CW721_CODE_ID: Item = Item::new("a"); diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index 5881976e..54b2ab7e 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -13,7 +13,7 @@ use cw_ownable::Ownership; use crate::{ execute::Ics721Execute, ibc::{ - Ics721Ibc, NonFungibleTokenPacketData, INSTANTIATE_INCOMING_PROXY_REPLY_ID, + Ics721Ibc, INSTANTIATE_INCOMING_PROXY_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, }, msg::{IbcOutgoingMsg, InstantiateMsg}, @@ -22,9 +22,9 @@ use crate::{ CollectionData, CLASS_ID_TO_CLASS, CW721_CODE_ID, INCOMING_PROXY, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, }, - token_types::{ClassId, TokenId}, utils::get_collection_data, }; +use ics721_types::{token_types::{ClassId, TokenId}, ibc::NonFungibleTokenPacketData}; const NFT_ADDR: &str = "nft"; const OWNER_ADDR: &str = "owner"; diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index 2fc2ddaa..44beed4a 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -11,18 +11,17 @@ use cosmwasm_std::{ use crate::{ execute::Ics721Execute, ibc::{ - Ics721Ibc, NonFungibleTokenPacketData, ACK_AND_DO_NOTHING, IBC_VERSION, + Ics721Ibc, ACK_AND_DO_NOTHING, IBC_VERSION, INSTANTIATE_CW721_REPLY_ID, }, ibc_helpers::{ack_fail, ack_success, try_get_ack_error}, msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, QueryMsg}, query::Ics721Query, state::{CollectionData, INCOMING_CLASS_TOKEN_TO_CHANNEL, NFT_CONTRACT_TO_CLASS_ID, PO}, - token_types::{ClassId, TokenId}, - types::Ics721Callbacks, utils::get_collection_data, ContractError, }; +use ics721_types::{token_types::{ClassId, TokenId}, ibc::NonFungibleTokenPacketData, types::Ics721Callbacks}; const CONTRACT_PORT: &str = "wasm.address1"; const REMOTE_PORT: &str = "stars.address1"; @@ -497,7 +496,7 @@ fn test_ibc_packet_receive_invalid_packet_data() { assert!(error .unwrap() - .starts_with("Error parsing into type ics721::ibc::NonFungibleTokenPacketData")) + .starts_with("Error parsing into type ics721_types::ibc::NonFungibleTokenPacketData")) } #[test] @@ -558,7 +557,7 @@ fn test_ibc_packet_receive_missmatched_lengths() { assert_eq!( error, - Some(ContractError::TokenInfoLenMissmatch {}.to_string()) + Some(ContractError::ValidationError(ics721_types::error::ValidationError::TokenInfoLenMissmatch{}).to_string()) ); // More token data are provided than tokens. @@ -590,7 +589,7 @@ fn test_ibc_packet_receive_missmatched_lengths() { assert_eq!( error, - Some(ContractError::TokenInfoLenMissmatch {}.to_string()) + Some(ContractError::ValidationError(ics721_types::error::ValidationError::TokenInfoLenMissmatch{}).to_string()) ) } diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 8dd4ca97..2f206621 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -22,9 +22,10 @@ use crate::{ msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg, QueryMsg}, query::Ics721Query, state::CollectionData, - token_types::{Class, ClassId, Token, TokenId, VoucherCreation}, + token_types::{VoucherCreation}, ContractError, }; +use ics721_types::token_types::{Class, ClassId, Token, TokenId}; use super::contract::Ics721Contract; diff --git a/packages/ics721/src/token_types.rs b/packages/ics721/src/token_types.rs index 8ddc16a5..e6996132 100644 --- a/packages/ics721/src/token_types.rs +++ b/packages/ics721/src/token_types.rs @@ -1,45 +1,9 @@ -use std::ops::Deref; - use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_json_binary, Addr, Binary, StdResult, WasmMsg}; -use cw_storage_plus::{Bound, Bounder, Key, KeyDeserialize, Prefixer, PrimaryKey}; +use cosmwasm_std::{to_json_binary, Addr, StdResult, WasmMsg}; +use ics721_types::token_types::{Class, TokenId, Token}; use crate::msg::{CallbackMsg, ExecuteMsg}; -/// A token ID according to the ICS-721 spec. The newtype pattern is -/// used here to provide some distinction between token and class IDs -/// in the type system. -#[cw_serde] -pub struct TokenId(String); - -/// A token according to the ICS-721 spec. -#[cw_serde] -pub struct Token { - /// A unique identifier for the token. - pub id: TokenId, - /// Optional URI pointing to off-chain metadata about the token. - pub uri: Option, - /// Optional base64 encoded metadata about the token. - pub data: Option, -} - -/// A class ID according to the ICS-721 spec. The newtype pattern is -/// used here to provide some distinction between token and class IDs -/// in the type system. -#[cw_serde] -pub struct ClassId(String); - -#[cw_serde] -pub struct Class { - /// A unique (from the source chain's perspective) identifier for - /// the class. - pub id: ClassId, - /// Optional URI pointing to off-chain metadata about the class. - pub uri: Option, - /// Optional base64 encoded metadata about the class. - pub data: Option, -} - #[cw_serde] pub struct VoucherRedemption { /// The class that these vouchers are being redeemed from. @@ -56,34 +20,6 @@ pub struct VoucherCreation { pub tokens: Vec, } -impl TokenId { - pub fn new(token_id: T) -> Self - where - T: Into, - { - Self(token_id.into()) - } -} - -impl ClassId { - pub fn new(class_id: T) -> Self - where - T: Into, - { - Self(class_id.into()) - } -} - -impl<'a> Bounder<'a> for ClassId { - fn inclusive_bound(self) -> Option> { - Some(Bound::inclusive(self)) - } - - fn exclusive_bound(self) -> Option> { - Some(Bound::exclusive(self)) - } -} - impl VoucherRedemption { /// Transforms information about a redemption of vouchers into a /// message that may be executed to redeem said vouchers. @@ -126,82 +62,4 @@ impl VoucherCreation { funds: vec![], }) } -} - -// boilerplate for conversion between wrappers and the wrapped. - -impl From for String { - fn from(c: ClassId) -> Self { - c.0 - } -} - -impl From for String { - fn from(t: TokenId) -> Self { - t.0 - } -} - -impl Deref for ClassId { - type Target = str; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::fmt::Display for ClassId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -// boilerplate for storing these wrapper types in CosmWasm maps. - -impl<'a> PrimaryKey<'a> for ClassId { - type Prefix = >::Prefix; - type SubPrefix = >::SubPrefix; - type Suffix = >::Suffix; - type SuperSuffix = >::SuperSuffix; - - fn key(&self) -> Vec { - self.0.key() - } -} - -impl<'a> PrimaryKey<'a> for TokenId { - type Prefix = >::Prefix; - type SubPrefix = >::SubPrefix; - type Suffix = >::Suffix; - type SuperSuffix = >::SuperSuffix; - - fn key(&self) -> Vec { - self.0.key() - } -} - -impl<'a> Prefixer<'a> for ClassId { - fn prefix(&self) -> Vec { - self.0.prefix() - } -} - -impl<'a> Prefixer<'a> for TokenId { - fn prefix(&self) -> Vec { - self.0.prefix() - } -} - -impl KeyDeserialize for ClassId { - type Output = ::Output; - fn from_vec(value: Vec) -> StdResult { - String::from_vec(value) - } -} - -impl KeyDeserialize for TokenId { - type Output = ::Output; - fn from_vec(value: Vec) -> StdResult { - String::from_vec(value) - } -} +} \ No newline at end of file From f5bba4c8857644f2313b51c769489f3565eb967d Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 17:18:29 +0100 Subject: [PATCH 11/40] cleanup --- contracts/sg-ics721/src/execute.rs | 6 ++--- packages/ics721-types/src/error.rs | 1 - packages/ics721-types/src/ibc.rs | 5 +++- packages/ics721/src/execute.rs | 9 ++++--- packages/ics721/src/helpers.rs | 14 +++++------ packages/ics721/src/ibc_helpers.rs | 7 +----- packages/ics721/src/ibc_packet_receive.rs | 8 ++++-- packages/ics721/src/lib.rs | 5 +++- packages/ics721/src/testing/contract.rs | 10 ++++---- packages/ics721/src/testing/ibc_tests.rs | 25 +++++++++++++------ .../ics721/src/testing/integration_tests.rs | 2 +- packages/ics721/src/token_types.rs | 4 +-- 12 files changed, 56 insertions(+), 40 deletions(-) diff --git a/contracts/sg-ics721/src/execute.rs b/contracts/sg-ics721/src/execute.rs index 98088abb..a937700d 100644 --- a/contracts/sg-ics721/src/execute.rs +++ b/contracts/sg-ics721/src/execute.rs @@ -1,8 +1,6 @@ use cosmwasm_std::{from_json, to_json_binary, Addr, Binary, Deps, DepsMut, Env, StdResult}; -use ics721::{ - execute::Ics721Execute, state::CollectionData, utils::get_collection_data, -}; -use ics721_types::token_types::{Class}; +use ics721::{execute::Ics721Execute, state::CollectionData, utils::get_collection_data}; +use ics721_types::token_types::Class; use sg721_base::msg::{CollectionInfoResponse, QueryMsg}; diff --git a/packages/ics721-types/src/error.rs b/packages/ics721-types/src/error.rs index cc1baffe..7cffae96 100644 --- a/packages/ics721-types/src/error.rs +++ b/packages/ics721-types/src/error.rs @@ -13,5 +13,4 @@ pub enum ValidationError { #[error("tokenIds, tokenUris, and tokenData must have the same length")] TokenInfoLenMissmatch {}, - } diff --git a/packages/ics721-types/src/ibc.rs b/packages/ics721-types/src/ibc.rs index e71c0a1f..c902afd7 100644 --- a/packages/ics721-types/src/ibc.rs +++ b/packages/ics721-types/src/ibc.rs @@ -1,7 +1,10 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::Binary; -use crate::{token_types::{ClassId, TokenId}, error::ValidationError}; +use crate::{ + error::ValidationError, + token_types::{ClassId, TokenId}, +}; #[cw_serde] #[serde(rename_all = "camelCase")] diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 08980252..6fe3bb7a 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -4,15 +4,18 @@ use cosmwasm_std::{ from_json, to_json_binary, Addr, Binary, ContractInfoResponse, Deps, DepsMut, Empty, Env, IbcMsg, MessageInfo, Response, StdResult, SubMsg, WasmMsg, }; -use ics721_types::{token_types::{TokenId, Class, ClassId, Token}, ibc::NonFungibleTokenPacketData}; +use ics721_types::{ + ibc::NonFungibleTokenPacketData, + token_types::{Class, ClassId, Token, TokenId}, +}; use serde::{de::DeserializeOwned, Serialize}; use sha2::{Digest, Sha256}; use crate::{ helpers::get_instantiate2_address, ibc::{ - INSTANTIATE_CW721_REPLY_ID, - INSTANTIATE_INCOMING_PROXY_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, + INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_INCOMING_PROXY_REPLY_ID, + INSTANTIATE_OUTGOING_PROXY_REPLY_ID, }, msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg}, state::{ diff --git a/packages/ics721/src/helpers.rs b/packages/ics721/src/helpers.rs index 7df41158..74de6637 100644 --- a/packages/ics721/src/helpers.rs +++ b/packages/ics721/src/helpers.rs @@ -4,14 +4,14 @@ use cosmwasm_std::{ }; use serde::Deserialize; -use crate::{ - ibc::ACK_CALLBACK_REPLY_ID, - ContractError, +use crate::{ibc::ACK_CALLBACK_REPLY_ID, ContractError}; +use ics721_types::{ + ibc::NonFungibleTokenPacketData, + types::{ + Ics721AckCallbackMsg, Ics721Callbacks, Ics721Memo, Ics721ReceiveCallbackMsg, Ics721Status, + ReceiverExecuteMsg, + }, }; -use ics721_types::{types::{ - Ics721AckCallbackMsg, Ics721Callbacks, Ics721Memo, Ics721ReceiveCallbackMsg, Ics721Status, - ReceiverExecuteMsg, -}, ibc::NonFungibleTokenPacketData}; /// Parse the memo field into the type we want /// Ideally it would be `Ics721Memo` type or any type that extends it diff --git a/packages/ics721/src/ibc_helpers.rs b/packages/ics721/src/ibc_helpers.rs index 51e44fb6..625adecc 100644 --- a/packages/ics721/src/ibc_helpers.rs +++ b/packages/ics721/src/ibc_helpers.rs @@ -1,13 +1,9 @@ use cosmwasm_std::{ from_json, to_json_binary, Binary, IbcAcknowledgement, IbcChannel, IbcEndpoint, IbcOrder, }; -use ics721_types::ibc::NonFungibleTokenPacketData; use serde::{Deserialize, Serialize}; -use crate::{ - ibc::IBC_VERSION, - ContractError, -}; +use crate::{ibc::IBC_VERSION, ContractError}; /// Tries to remove the source prefix from a given class_id. If the /// class_id does not begin with the given prefix, returns @@ -124,7 +120,6 @@ pub(crate) fn validate_order_and_version( #[cfg(test)] mod tests { use super::*; - use ics721_types::token_types::{ClassId, TokenId}; #[test] fn test_pop_source_simple() { diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 67f564ee..fe0c1c69 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -7,7 +7,7 @@ use zip_optional::Zippable; use crate::{ helpers::{generate_receive_callback_msg, get_instantiate2_address, get_receive_callback}, - ibc::{ACK_AND_DO_NOTHING}, + ibc::ACK_AND_DO_NOTHING, ibc_helpers::{get_endpoint_prefix, try_pop_source_prefix}, msg::{CallbackMsg, ExecuteMsg}, state::{ @@ -17,7 +17,11 @@ use crate::{ token_types::{VoucherCreation, VoucherRedemption}, ContractError, }; -use ics721_types::{token_types::{Class, ClassId, Token, TokenId}, ibc::NonFungibleTokenPacketData, types::Ics721ReceiveIbcPacketMsg}; +use ics721_types::{ + ibc::NonFungibleTokenPacketData, + token_types::{Class, ClassId, Token, TokenId}, + types::Ics721ReceiveIbcPacketMsg, +}; /// Every incoming token has some associated action. enum Action { diff --git a/packages/ics721/src/lib.rs b/packages/ics721/src/lib.rs index d1d2b499..abe5ffd8 100644 --- a/packages/ics721/src/lib.rs +++ b/packages/ics721/src/lib.rs @@ -9,8 +9,11 @@ pub mod query; pub mod state; pub mod token_types; pub mod utils; -use ics721_types::{token_types::{Class, ClassId, Token, TokenId}, ibc::NonFungibleTokenPacketData}; pub use crate::error::ContractError; +pub use ics721_types::{ + ibc::NonFungibleTokenPacketData, + token_types::{Class, ClassId, Token, TokenId}, +}; #[cfg(test)] pub mod testing; diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index 54b2ab7e..cac6569a 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -12,10 +12,7 @@ use cw_ownable::Ownership; use crate::{ execute::Ics721Execute, - ibc::{ - Ics721Ibc, INSTANTIATE_INCOMING_PROXY_REPLY_ID, - INSTANTIATE_OUTGOING_PROXY_REPLY_ID, - }, + ibc::{Ics721Ibc, INSTANTIATE_INCOMING_PROXY_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID}, msg::{IbcOutgoingMsg, InstantiateMsg}, query::Ics721Query, state::{ @@ -24,7 +21,10 @@ use crate::{ }, utils::get_collection_data, }; -use ics721_types::{token_types::{ClassId, TokenId}, ibc::NonFungibleTokenPacketData}; +use ics721_types::{ + ibc::NonFungibleTokenPacketData, + token_types::{ClassId, TokenId}, +}; const NFT_ADDR: &str = "nft"; const OWNER_ADDR: &str = "owner"; diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index 44beed4a..d7f66547 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -10,10 +10,7 @@ use cosmwasm_std::{ use crate::{ execute::Ics721Execute, - ibc::{ - Ics721Ibc, ACK_AND_DO_NOTHING, IBC_VERSION, - INSTANTIATE_CW721_REPLY_ID, - }, + ibc::{Ics721Ibc, ACK_AND_DO_NOTHING, IBC_VERSION, INSTANTIATE_CW721_REPLY_ID}, ibc_helpers::{ack_fail, ack_success, try_get_ack_error}, msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, QueryMsg}, query::Ics721Query, @@ -21,7 +18,11 @@ use crate::{ utils::get_collection_data, ContractError, }; -use ics721_types::{token_types::{ClassId, TokenId}, ibc::NonFungibleTokenPacketData, types::Ics721Callbacks}; +use ics721_types::{ + ibc::NonFungibleTokenPacketData, + token_types::{ClassId, TokenId}, + types::Ics721Callbacks, +}; const CONTRACT_PORT: &str = "wasm.address1"; const REMOTE_PORT: &str = "stars.address1"; @@ -557,7 +558,12 @@ fn test_ibc_packet_receive_missmatched_lengths() { assert_eq!( error, - Some(ContractError::ValidationError(ics721_types::error::ValidationError::TokenInfoLenMissmatch{}).to_string()) + Some( + ContractError::ValidationError( + ics721_types::error::ValidationError::TokenInfoLenMissmatch {} + ) + .to_string() + ) ); // More token data are provided than tokens. @@ -589,7 +595,12 @@ fn test_ibc_packet_receive_missmatched_lengths() { assert_eq!( error, - Some(ContractError::ValidationError(ics721_types::error::ValidationError::TokenInfoLenMissmatch{}).to_string()) + Some( + ContractError::ValidationError( + ics721_types::error::ValidationError::TokenInfoLenMissmatch {} + ) + .to_string() + ) ) } diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 2f206621..62243bd9 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -22,7 +22,7 @@ use crate::{ msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg, QueryMsg}, query::Ics721Query, state::CollectionData, - token_types::{VoucherCreation}, + token_types::VoucherCreation, ContractError, }; use ics721_types::token_types::{Class, ClassId, Token, TokenId}; diff --git a/packages/ics721/src/token_types.rs b/packages/ics721/src/token_types.rs index e6996132..9e955d9b 100644 --- a/packages/ics721/src/token_types.rs +++ b/packages/ics721/src/token_types.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::{to_json_binary, Addr, StdResult, WasmMsg}; -use ics721_types::token_types::{Class, TokenId, Token}; +use ics721_types::token_types::{Class, Token, TokenId}; use crate::msg::{CallbackMsg, ExecuteMsg}; @@ -62,4 +62,4 @@ impl VoucherCreation { funds: vec![], }) } -} \ No newline at end of file +} From b8fcdca6662b224b82c38a42c9205887f2c67b4b Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 21:13:54 +0100 Subject: [PATCH 12/40] integration test for incoming proxy --- e2e/test.sh | 1 + external-wasms/cw721_incoming_proxy.wasm | Bin 181642 -> 181642 bytes packages/ics721-types/src/types.rs | 11 ++-- packages/ics721/src/ibc_packet_receive.rs | 9 ++- ts-relayer-tests/build.sh | 9 ++- ts-relayer-tests/src/ics721.spec.ts | 72 ++++++++++++++++++++-- 6 files changed, 84 insertions(+), 18 deletions(-) diff --git a/e2e/test.sh b/e2e/test.sh index 92a9fb72..a50d6df6 100755 --- a/e2e/test.sh +++ b/e2e/test.sh @@ -1,6 +1,7 @@ #!/bin/bash SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # source: https://stackoverflow.com/a/246128/3437868 WORKSPACE_DIR=$(cd $SCRIPT_DIR/.. && pwd) +echo "sudo rm -rf $WORKSPACE_DIR/artifacts" sudo rm -rf $WORKSPACE_DIR/artifacts $WORKSPACE_DIR/ts-relayer-tests/build.sh echo "running tests..." diff --git a/external-wasms/cw721_incoming_proxy.wasm b/external-wasms/cw721_incoming_proxy.wasm index e07d7308de8e9debecb4112366e5e99274749608..08286f242e08050d8dcbaa34f4433c9b7e830349 100644 GIT binary patch delta 4237 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 diff --git a/packages/ics721-types/src/types.rs b/packages/ics721-types/src/types.rs index 11f01cda..a4070bb0 100644 --- a/packages/ics721-types/src/types.rs +++ b/packages/ics721-types/src/types.rs @@ -4,12 +4,6 @@ use serde::{Deserialize, Serialize}; use crate::ibc::NonFungibleTokenPacketData; -#[cw_serde] -pub struct Ics721ReceiveIbcPacketMsg { - pub packet: IbcPacket, - pub data: NonFungibleTokenPacketData, -} - #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug, PartialEq)] #[allow(clippy::derive_partial_eq_without_eq)] #[schemars(crate = "cosmwasm_schema::schemars")] @@ -74,4 +68,9 @@ pub enum ReceiverExecuteMsg { /// Being called as a status update of the transfer. (source side) /// Note - Failing this message will NOT fail the transfer, its just a status update. Ics721AckCallback(Ics721AckCallbackMsg), + + Ics721ReceivePacketMsg { + packet: IbcPacket, + data: NonFungibleTokenPacketData, + } } diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index fe0c1c69..414d05c1 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -19,8 +19,7 @@ use crate::{ }; use ics721_types::{ ibc::NonFungibleTokenPacketData, - token_types::{Class, ClassId, Token, TokenId}, - types::Ics721ReceiveIbcPacketMsg, + token_types::{Class, ClassId, Token, TokenId}, types::ReceiverExecuteMsg, }; /// Every incoming token has some associated action. @@ -62,13 +61,13 @@ pub(crate) fn receive_ibc_packet( let incoming_proxy_msg = match INCOMING_PROXY.load(deps.storage).ok().flatten() { Some(incoming_proxy) => { - let msg = Ics721ReceiveIbcPacketMsg { + let msg = to_json_binary(&ReceiverExecuteMsg::Ics721ReceivePacketMsg { packet: packet.clone(), data: data.clone(), - }; + })?; Some(WasmMsg::Execute { contract_addr: incoming_proxy.to_string(), - msg: to_json_binary(&msg)?, + msg, funds: vec![], }) } diff --git a/ts-relayer-tests/build.sh b/ts-relayer-tests/build.sh index bcef98c7..66276c45 100755 --- a/ts-relayer-tests/build.sh +++ b/ts-relayer-tests/build.sh @@ -1,4 +1,7 @@ #!/bin/bash +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # source: https://stackoverflow.com/a/246128/3437868 +ARTIFACTS_DIR="$SCRIPT_DIR/../artifacts" +EXTERNAL_WASMS_DIR="$SCRIPT_DIR/../external-wasms" ## Compiles an optimizes the local contracts for testing with ## ts-relayer. @@ -13,9 +16,9 @@ docker run --rm -v "$(pwd)":/code --platform linux/amd64 \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/workspace-optimizer:0.15.0 -mkdir -p ./ts-relayer-tests/internal -cp ./artifacts/*.wasm ./ts-relayer-tests/internal -cp ./external-wasms/*.wasm ./ts-relayer-tests/internal +mkdir -p $SCRIPT_DIR/internal +cp $ARTIFACTS_DIR/*.wasm $SCRIPT_DIR/internal +cp $EXTERNAL_WASMS_DIR/*.wasm $SCRIPT_DIR/internal echo "done. avaliable wasm blobs:" ls ./ts-relayer-tests/internal diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index 8f276f82..27ea73c1 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -181,7 +181,7 @@ const standardSetup = async (t: ExecutionContext) => { t.pass(); }; -test.serial("transfer NFT", async (t) => { +test.serial("transfer NFT: wasmd -> osmo", async (t) => { await standardSetup(t); const { @@ -213,7 +213,7 @@ test.serial("transfer NFT", async (t) => { }, }; - t.log("transfering to osmo chain"); + t.log(`transfering to osmo chain via ${channel.channel.src.channelId}`); const transferResponse = await sendNft( wasmClient, @@ -235,8 +235,6 @@ test.serial("transfer NFT", async (t) => { tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); t.is(wasmIcs721, tokenOwner.owner); - t.context.channel.channel.dest.channelId; - const osmoClassId = `${t.context.channel.channel.dest.portId}/${t.context.channel.channel.dest.channelId}/${t.context.wasmCw721}`; const osmoCw721 = await osmoClient.sign.queryContractSmart(osmoIcs721, { nft_contract: { class_id: osmoClassId }, @@ -246,6 +244,72 @@ test.serial("transfer NFT", async (t) => { t.is(osmoAddr, tokenOwner.owner); }); +test.serial.only( + "transfer NFT with incoming proxy: osmo -> wasmd", + async (t) => { + await standardSetup(t); + + const { + wasmClient, + wasmAddr, + wasmIcs721, + osmoClient, + osmoAddr, + osmoCw721, + osmoIcs721, + channel, + } = t.context; + + t.log(JSON.stringify(osmoClient, undefined, 2)); + const tokenId = "1"; + await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); + // assert token is minted + let tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoAddr, tokenOwner.owner); + + const ibcMsg = { + receiver: wasmAddr, + channel_id: channel.channel.dest.channelId, + timeout: { + block: { + revision: 1, + height: 90000, + }, + }, + }; + + t.log(`transfering to wasm chain via ${channel.channel.dest.channelId}`); + + const transferResponse = await sendNft( + osmoClient, + osmoCw721, + osmoIcs721, + ibcMsg, + tokenId + ); + t.truthy(transferResponse); + + t.log("relaying packets"); + + const info = await channel.link.relayAll(); + + // Verify we got a success + assertAckSuccess(info.acksFromA); + + // assert NFT on chain A is locked/owned by ICS contract + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoIcs721, tokenOwner.owner); + + const wasmClassId = `${t.context.channel.channel.src.portId}/${t.context.channel.channel.src.channelId}/${t.context.osmoCw721}`; + const wasmCw721 = await wasmClient.sign.queryContractSmart(wasmIcs721, { + nft_contract: { class_id: wasmClassId }, + }); + + tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); + t.is(wasmAddr, tokenOwner.owner); + } +); + test.serial("malicious NFT", async (t) => { await standardSetup(t); From 61a96cbf66c58a905425db76d3c8938261527038 Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 21:36:20 +0100 Subject: [PATCH 13/40] cleanup --- packages/ics721-types/src/types.rs | 2 +- packages/ics721/src/ibc_packet_receive.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ics721-types/src/types.rs b/packages/ics721-types/src/types.rs index a4070bb0..68b6810f 100644 --- a/packages/ics721-types/src/types.rs +++ b/packages/ics721-types/src/types.rs @@ -72,5 +72,5 @@ pub enum ReceiverExecuteMsg { Ics721ReceivePacketMsg { packet: IbcPacket, data: NonFungibleTokenPacketData, - } + }, } diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 414d05c1..eee645f8 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -19,7 +19,8 @@ use crate::{ }; use ics721_types::{ ibc::NonFungibleTokenPacketData, - token_types::{Class, ClassId, Token, TokenId}, types::ReceiverExecuteMsg, + token_types::{Class, ClassId, Token, TokenId}, + types::ReceiverExecuteMsg, }; /// Every incoming token has some associated action. From 0921f66384b92f0c727d79143fef30f8e285b89e Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 21:39:11 +0100 Subject: [PATCH 14/40] test sending to non-WLed channel in incoming proxy --- ts-relayer-tests/src/ics721.spec.ts | 58 ++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index 27ea73c1..d87d3102 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -258,16 +258,18 @@ test.serial.only( osmoCw721, osmoIcs721, channel, + otherChannel, } = t.context; - t.log(JSON.stringify(osmoClient, undefined, 2)); - const tokenId = "1"; + // test 1: transfer using WLed channel by incoming proxy + let tokenId = "1"; + t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); // assert token is minted let tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); t.is(osmoAddr, tokenOwner.owner); - const ibcMsg = { + let ibcMsg = { receiver: wasmAddr, channel_id: channel.channel.dest.channelId, timeout: { @@ -280,7 +282,7 @@ test.serial.only( t.log(`transfering to wasm chain via ${channel.channel.dest.channelId}`); - const transferResponse = await sendNft( + let transferResponse = await sendNft( osmoClient, osmoCw721, osmoIcs721, @@ -291,7 +293,7 @@ test.serial.only( t.log("relaying packets"); - const info = await channel.link.relayAll(); + let info = await channel.link.relayAll(); // Verify we got a success assertAckSuccess(info.acksFromA); @@ -299,6 +301,7 @@ test.serial.only( // assert NFT on chain A is locked/owned by ICS contract tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); t.is(osmoIcs721, tokenOwner.owner); + t.log(`NFT #${tokenId} locked by ICS721 contract`); const wasmClassId = `${t.context.channel.channel.src.portId}/${t.context.channel.channel.src.channelId}/${t.context.osmoCw721}`; const wasmCw721 = await wasmClient.sign.queryContractSmart(wasmIcs721, { @@ -307,6 +310,51 @@ test.serial.only( tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); t.is(wasmAddr, tokenOwner.owner); + t.log(`NFT #${tokenId} transferred to ${wasmAddr}`); + + // test 2: transfer using WLed channel by incoming proxy + tokenId = "2"; + t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); + await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); + // assert token is minted + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoAddr, tokenOwner.owner); + + ibcMsg = { + receiver: wasmAddr, + channel_id: otherChannel.channel.dest.channelId, + timeout: { + block: { + revision: 1, + height: 90000, + }, + }, + }; + + t.log( + `transfering to wasm chain via ${otherChannel.channel.dest.channelId}` + ); + + transferResponse = await sendNft( + osmoClient, + osmoCw721, + osmoIcs721, + ibcMsg, + tokenId + ); + t.truthy(transferResponse); + + t.log("relaying packets"); + + info = await otherChannel.link.relayAll(); + + // Verify we got a success + assertAckErrors(info.acksFromA); + + // assert NFT on chain A is returned to owner + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoClient.senderAddress, tokenOwner.owner); + t.log(`NFT #${tokenId} returned to owner`); } ); From a488a2335c928c92de9e7a7ede08032e4347e6fd Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 22:52:24 +0100 Subject: [PATCH 15/40] cleanup --- ts-relayer-tests/src/ics721.spec.ts | 217 ++++++++++++++-------------- 1 file changed, 106 insertions(+), 111 deletions(-) diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index d87d3102..737f7d06 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -244,119 +244,114 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { t.is(osmoAddr, tokenOwner.owner); }); -test.serial.only( - "transfer NFT with incoming proxy: osmo -> wasmd", - async (t) => { - await standardSetup(t); - - const { - wasmClient, - wasmAddr, - wasmIcs721, - osmoClient, - osmoAddr, - osmoCw721, - osmoIcs721, - channel, - otherChannel, - } = t.context; - - // test 1: transfer using WLed channel by incoming proxy - let tokenId = "1"; - t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); - await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); - // assert token is minted - let tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoAddr, tokenOwner.owner); - - let ibcMsg = { - receiver: wasmAddr, - channel_id: channel.channel.dest.channelId, - timeout: { - block: { - revision: 1, - height: 90000, - }, +test.serial("transfer NFT with incoming proxy: osmo -> wasmd", async (t) => { + await standardSetup(t); + + const { + wasmClient, + wasmAddr, + wasmIcs721, + osmoClient, + osmoAddr, + osmoCw721, + osmoIcs721, + channel, + otherChannel, + } = t.context; + + // test 1: transfer using WLed channel by incoming proxy + let tokenId = "1"; + t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); + await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); + // assert token is minted + let tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoAddr, tokenOwner.owner); + + let ibcMsg = { + receiver: wasmAddr, + channel_id: channel.channel.dest.channelId, + timeout: { + block: { + revision: 1, + height: 90000, }, - }; - - t.log(`transfering to wasm chain via ${channel.channel.dest.channelId}`); - - let transferResponse = await sendNft( - osmoClient, - osmoCw721, - osmoIcs721, - ibcMsg, - tokenId - ); - t.truthy(transferResponse); - - t.log("relaying packets"); - - let info = await channel.link.relayAll(); - - // Verify we got a success - assertAckSuccess(info.acksFromA); - - // assert NFT on chain A is locked/owned by ICS contract - tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoIcs721, tokenOwner.owner); - t.log(`NFT #${tokenId} locked by ICS721 contract`); - - const wasmClassId = `${t.context.channel.channel.src.portId}/${t.context.channel.channel.src.channelId}/${t.context.osmoCw721}`; - const wasmCw721 = await wasmClient.sign.queryContractSmart(wasmIcs721, { - nft_contract: { class_id: wasmClassId }, - }); - - tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); - t.is(wasmAddr, tokenOwner.owner); - t.log(`NFT #${tokenId} transferred to ${wasmAddr}`); - - // test 2: transfer using WLed channel by incoming proxy - tokenId = "2"; - t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); - await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); - // assert token is minted - tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoAddr, tokenOwner.owner); - - ibcMsg = { - receiver: wasmAddr, - channel_id: otherChannel.channel.dest.channelId, - timeout: { - block: { - revision: 1, - height: 90000, - }, + }, + }; + + t.log(`transfering to wasm chain via ${channel.channel.dest.channelId}`); + + let transferResponse = await sendNft( + osmoClient, + osmoCw721, + osmoIcs721, + ibcMsg, + tokenId + ); + t.truthy(transferResponse); + + t.log("relaying packets"); + + let info = await channel.link.relayAll(); + + // Verify we got a success + assertAckSuccess(info.acksFromA); + + // assert NFT on chain A is locked/owned by ICS contract + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoIcs721, tokenOwner.owner); + t.log(`NFT #${tokenId} locked by ICS721 contract`); + + const wasmClassId = `${t.context.channel.channel.src.portId}/${t.context.channel.channel.src.channelId}/${t.context.osmoCw721}`; + const wasmCw721 = await wasmClient.sign.queryContractSmart(wasmIcs721, { + nft_contract: { class_id: wasmClassId }, + }); + + tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); + t.is(wasmAddr, tokenOwner.owner); + t.log(`NFT #${tokenId} transferred to ${wasmAddr}`); + + // test 2: transfer using WLed channel by incoming proxy + tokenId = "2"; + t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); + await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); + // assert token is minted + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoAddr, tokenOwner.owner); + + ibcMsg = { + receiver: wasmAddr, + channel_id: otherChannel.channel.dest.channelId, + timeout: { + block: { + revision: 1, + height: 90000, }, - }; - - t.log( - `transfering to wasm chain via ${otherChannel.channel.dest.channelId}` - ); - - transferResponse = await sendNft( - osmoClient, - osmoCw721, - osmoIcs721, - ibcMsg, - tokenId - ); - t.truthy(transferResponse); - - t.log("relaying packets"); - - info = await otherChannel.link.relayAll(); - - // Verify we got a success - assertAckErrors(info.acksFromA); - - // assert NFT on chain A is returned to owner - tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoClient.senderAddress, tokenOwner.owner); - t.log(`NFT #${tokenId} returned to owner`); - } -); + }, + }; + + t.log(`transfering to wasm chain via ${otherChannel.channel.dest.channelId}`); + + transferResponse = await sendNft( + osmoClient, + osmoCw721, + osmoIcs721, + ibcMsg, + tokenId + ); + t.truthy(transferResponse); + + t.log("relaying packets"); + + info = await otherChannel.link.relayAll(); + + // Verify we got a success + assertAckErrors(info.acksFromA); + + // assert NFT on chain A is returned to owner + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoClient.senderAddress, tokenOwner.owner); + t.log(`NFT #${tokenId} returned to owner`); +}); test.serial("malicious NFT", async (t) => { await standardSetup(t); From 4e2f40000f5dc01645e32c7d708f9081b47aaf8e Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 27 Dec 2023 23:47:26 +0100 Subject: [PATCH 16/40] docs --- packages/ics721-types/Cargo.toml | 2 +- packages/ics721-types/README | 3 +++ packages/ics721-types/src/types.rs | 3 +++ packages/ics721/src/execute.rs | 7 ++++++- packages/ics721/src/ibc_packet_receive.rs | 3 +++ packages/ics721/src/testing/integration_tests.rs | 1 + 6 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 packages/ics721-types/README diff --git a/packages/ics721-types/Cargo.toml b/packages/ics721-types/Cargo.toml index fd3e8246..06bd28e9 100644 --- a/packages/ics721-types/Cargo.toml +++ b/packages/ics721-types/Cargo.toml @@ -2,7 +2,7 @@ name = "ics721-types" version = "0.1.0" edition = "2021" -authors = ["ekez ", "mr-t ", "Art3mix ", "m@publicawesome.com", "s+git@publicawesome.com"] +authors = ["ekez ", "mr-t ", "Art3mix "] description = "an implementation of the ICS721 specification for transfering NFTs between blockchains" [dependencies] diff --git a/packages/ics721-types/README b/packages/ics721-types/README new file mode 100644 index 00000000..ed516796 --- /dev/null +++ b/packages/ics721-types/README @@ -0,0 +1,3 @@ +# ICS721 Types Package + +Contains all types being used by ICS721, Incoming Proxy, and Outgoing Proxy. \ No newline at end of file diff --git a/packages/ics721-types/src/types.rs b/packages/ics721-types/src/types.rs index 68b6810f..35d0367b 100644 --- a/packages/ics721-types/src/types.rs +++ b/packages/ics721-types/src/types.rs @@ -69,6 +69,9 @@ pub enum ReceiverExecuteMsg { /// Note - Failing this message will NOT fail the transfer, its just a status update. Ics721AckCallback(Ics721AckCallbackMsg), + /// Being called on receiving the NFT before transfer is completed. (destination side) + /// `on_recieve` hook + /// Note - Failing this message will fail the transfer. Ics721ReceivePacketMsg { packet: IbcPacket, data: NonFungibleTokenPacketData, diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 6fe3bb7a..457fba58 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -41,20 +41,23 @@ where msg: InstantiateMsg, ) -> StdResult> { CW721_CODE_ID.save(deps.storage, &msg.cw721_base_code_id)?; - OUTGOING_PROXY.save(deps.storage, &None)?; + // proxy contracts are optional INCOMING_PROXY.save(deps.storage, &None)?; + OUTGOING_PROXY.save(deps.storage, &None)?; PO.set_pauser(deps.storage, deps.api, msg.pauser.as_deref())?; let mut proxies_instantiate: Vec> = Vec::new(); if let Some(cii) = msg.incoming_proxy { proxies_instantiate.push(SubMsg::reply_on_success( cii.into_wasm_msg(env.clone().contract.address), + // on reply proxy contract is set in INCOMING_PROXY INSTANTIATE_INCOMING_PROXY_REPLY_ID, )); } if let Some(cii) = msg.outgoing_proxy { proxies_instantiate.push(SubMsg::reply_on_success( cii.into_wasm_msg(env.contract.address), + // on reply proxy contract is set in OUTGOING_PROXY INSTANTIATE_OUTGOING_PROXY_REPLY_ID, )); } @@ -449,6 +452,7 @@ where outgoing_proxy, cw721_base_code_id, } => { + // disables incoming proxy if none is provided! INCOMING_PROXY.save( deps.storage, &incoming_proxy @@ -456,6 +460,7 @@ where .map(|h| deps.api.addr_validate(h)) .transpose()?, )?; + // disables outgoing proxy if none is provided! OUTGOING_PROXY.save( deps.storage, &outgoing_proxy diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index eee645f8..c00df453 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -60,6 +60,9 @@ pub(crate) fn receive_ibc_packet( let data: NonFungibleTokenPacketData = from_json(&packet.data)?; data.validate()?; + // If there is an incoming proxy, let proxy validate the packet, in case it fails, we fail the transfer + // This proxy for example whitelist channels that can send to this contract: + // https://github.com/arkprotocol/cw721-proxy/tree/main/contracts/cw721-incoming-proxy let incoming_proxy_msg = match INCOMING_PROXY.load(deps.storage).ok().flatten() { Some(incoming_proxy) => { let msg = to_json_binary(&ReceiverExecuteMsg::Ics721ReceivePacketMsg { diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 62243bd9..c203cdee 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -282,6 +282,7 @@ struct Test { } impl Test { + /// Test setup with optional pauser and proxy contracts. fn new( outgoing_proxy: bool, incoming_proxy: bool, From b1f5c077743b1eee2ec02bea0eacacbf5babd0d5 Mon Sep 17 00:00:00 2001 From: mr-t Date: Thu, 28 Dec 2023 00:15:46 +0100 Subject: [PATCH 17/40] use double quote to prevent globbing and word splitting --- ts-relayer-tests/build.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ts-relayer-tests/build.sh b/ts-relayer-tests/build.sh index 66276c45..09ac9dc7 100755 --- a/ts-relayer-tests/build.sh +++ b/ts-relayer-tests/build.sh @@ -16,9 +16,9 @@ docker run --rm -v "$(pwd)":/code --platform linux/amd64 \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/workspace-optimizer:0.15.0 -mkdir -p $SCRIPT_DIR/internal -cp $ARTIFACTS_DIR/*.wasm $SCRIPT_DIR/internal -cp $EXTERNAL_WASMS_DIR/*.wasm $SCRIPT_DIR/internal +mkdir -p "$SCRIPT_DIR/internal" +cp "$ARTIFACTS_DIR/*.wasm $SCRIPT_DIR/internal" +cp "$EXTERNAL_WASMS_DIR/*.wasm $SCRIPT_DIR/internal" echo "done. avaliable wasm blobs:" ls ./ts-relayer-tests/internal From 60277c0eafb835c559c7fbef76f7592ea603a918 Mon Sep 17 00:00:00 2001 From: mr-t Date: Thu, 28 Dec 2023 00:20:46 +0100 Subject: [PATCH 18/40] fix CI --- ts-relayer-tests/build.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ts-relayer-tests/build.sh b/ts-relayer-tests/build.sh index 09ac9dc7..bcef98c7 100755 --- a/ts-relayer-tests/build.sh +++ b/ts-relayer-tests/build.sh @@ -1,7 +1,4 @@ #!/bin/bash -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # source: https://stackoverflow.com/a/246128/3437868 -ARTIFACTS_DIR="$SCRIPT_DIR/../artifacts" -EXTERNAL_WASMS_DIR="$SCRIPT_DIR/../external-wasms" ## Compiles an optimizes the local contracts for testing with ## ts-relayer. @@ -16,9 +13,9 @@ docker run --rm -v "$(pwd)":/code --platform linux/amd64 \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/workspace-optimizer:0.15.0 -mkdir -p "$SCRIPT_DIR/internal" -cp "$ARTIFACTS_DIR/*.wasm $SCRIPT_DIR/internal" -cp "$EXTERNAL_WASMS_DIR/*.wasm $SCRIPT_DIR/internal" +mkdir -p ./ts-relayer-tests/internal +cp ./artifacts/*.wasm ./ts-relayer-tests/internal +cp ./external-wasms/*.wasm ./ts-relayer-tests/internal echo "done. avaliable wasm blobs:" ls ./ts-relayer-tests/internal From 49667d546af1ce07f40bd0720740aa3bcc72ec90 Mon Sep 17 00:00:00 2001 From: mr-t Date: Fri, 29 Dec 2023 00:21:12 +0100 Subject: [PATCH 19/40] cleanup based on review by humanalgorithm --- contracts/ics721-base-tester/src/contract.rs | 4 ++-- contracts/ics721-base-tester/src/msg.rs | 2 +- packages/ics721-types/src/{ibc.rs => ibc_types.rs} | 0 packages/ics721-types/src/lib.rs | 2 +- packages/ics721-types/src/types.rs | 2 +- packages/ics721/src/execute.rs | 2 +- packages/ics721/src/helpers.rs | 2 +- packages/ics721/src/ibc.rs | 12 ++++++------ packages/ics721/src/ibc_packet_receive.rs | 6 +++--- packages/ics721/src/lib.rs | 2 +- packages/ics721/src/testing/contract.rs | 2 +- packages/ics721/src/testing/ibc_tests.rs | 10 +++++----- 12 files changed, 23 insertions(+), 23 deletions(-) rename packages/ics721-types/src/{ibc.rs => ibc_types.rs} (100%) diff --git a/contracts/ics721-base-tester/src/contract.rs b/contracts/ics721-base-tester/src/contract.rs index 82218e67..8220048d 100644 --- a/contracts/ics721-base-tester/src/contract.rs +++ b/contracts/ics721-base-tester/src/contract.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{ StdResult, WasmMsg, }; use cw2::set_contract_version; -use ics721_types::ibc::NonFungibleTokenPacketData; +use ics721_types::ibc_types::NonFungibleTokenPacketData; use crate::{ error::ContractError, @@ -65,7 +65,7 @@ pub fn execute( mod receive_callbacks { use cosmwasm_std::{ensure_eq, from_json, DepsMut, MessageInfo, Response}; use ics721_types::{ - ibc::NonFungibleTokenPacketData, + ibc_types::NonFungibleTokenPacketData, types::{Ics721AckCallbackMsg, Ics721ReceiveCallbackMsg, Ics721Status}, }; diff --git a/contracts/ics721-base-tester/src/msg.rs b/contracts/ics721-base-tester/src/msg.rs index d84c3186..75a0bd3a 100644 --- a/contracts/ics721-base-tester/src/msg.rs +++ b/contracts/ics721-base-tester/src/msg.rs @@ -60,7 +60,7 @@ pub enum ExecuteMsg { channel_id: String, timeout: IbcTimeout, - data: ics721_types::ibc::NonFungibleTokenPacketData, + data: ics721_types::ibc_types::NonFungibleTokenPacketData, }, SetAckMode { ack_mode: AckMode, diff --git a/packages/ics721-types/src/ibc.rs b/packages/ics721-types/src/ibc_types.rs similarity index 100% rename from packages/ics721-types/src/ibc.rs rename to packages/ics721-types/src/ibc_types.rs diff --git a/packages/ics721-types/src/lib.rs b/packages/ics721-types/src/lib.rs index 15d960e0..d811044e 100644 --- a/packages/ics721-types/src/lib.rs +++ b/packages/ics721-types/src/lib.rs @@ -1,4 +1,4 @@ pub mod error; -pub mod ibc; +pub mod ibc_types; pub mod token_types; pub mod types; diff --git a/packages/ics721-types/src/types.rs b/packages/ics721-types/src/types.rs index 35d0367b..69160e94 100644 --- a/packages/ics721-types/src/types.rs +++ b/packages/ics721-types/src/types.rs @@ -2,7 +2,7 @@ use cosmwasm_schema::{cw_serde, schemars::JsonSchema}; use cosmwasm_std::{Binary, IbcPacket}; use serde::{Deserialize, Serialize}; -use crate::ibc::NonFungibleTokenPacketData; +use crate::ibc_types::NonFungibleTokenPacketData; #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug, PartialEq)] #[allow(clippy::derive_partial_eq_without_eq)] diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 457fba58..775b7c3f 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{ IbcMsg, MessageInfo, Response, StdResult, SubMsg, WasmMsg, }; use ics721_types::{ - ibc::NonFungibleTokenPacketData, + ibc_types::NonFungibleTokenPacketData, token_types::{Class, ClassId, Token, TokenId}, }; use serde::{de::DeserializeOwned, Serialize}; diff --git a/packages/ics721/src/helpers.rs b/packages/ics721/src/helpers.rs index 74de6637..3bedb933 100644 --- a/packages/ics721/src/helpers.rs +++ b/packages/ics721/src/helpers.rs @@ -6,7 +6,7 @@ use serde::Deserialize; use crate::{ibc::ACK_CALLBACK_REPLY_ID, ContractError}; use ics721_types::{ - ibc::NonFungibleTokenPacketData, + ibc_types::NonFungibleTokenPacketData, types::{ Ics721AckCallbackMsg, Ics721Callbacks, Ics721Memo, Ics721ReceiveCallbackMsg, Ics721Status, ReceiverExecuteMsg, diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index 3f894ef0..0b6b6b8b 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{ StdResult, SubMsgResult, WasmMsg, }; use cw_utils::parse_reply_instantiate_data; -use ics721_types::{ibc::NonFungibleTokenPacketData, types::Ics721Status}; +use ics721_types::{ibc_types::NonFungibleTokenPacketData, types::Ics721Status}; use serde::{de::DeserializeOwned, Serialize}; use crate::{ @@ -22,15 +22,15 @@ use crate::{ /// Submessage reply ID used for instantiating cw721 contracts. pub(crate) const INSTANTIATE_CW721_REPLY_ID: u64 = 0; /// Submessage reply ID used for instantiating the proxy contract. -pub(crate) const INSTANTIATE_INCOMING_PROXY_REPLY_ID: u64 = 4; +pub(crate) const INSTANTIATE_INCOMING_PROXY_REPLY_ID: u64 = 1; /// Submessage reply ID used for instantiating the proxy contract. -pub(crate) const INSTANTIATE_OUTGOING_PROXY_REPLY_ID: u64 = 1; +pub(crate) const INSTANTIATE_OUTGOING_PROXY_REPLY_ID: u64 = 2; /// Submessages dispatched with this reply ID will set the ack on the /// response depending on if the submessage execution succeded or /// failed. -pub(crate) const ACK_AND_DO_NOTHING: u64 = 2; +pub(crate) const ACK_AND_DO_NOTHING_REPLY_ID: u64 = 3; /// Reply on callback -pub(crate) const ACK_CALLBACK_REPLY_ID: u64 = 3; +pub(crate) const ACK_CALLBACK_REPLY_ID: u64 = 4; /// The IBC version this contract expects to communicate with. pub const IBC_VERSION: &str = "ics721-1"; @@ -271,7 +271,7 @@ where } // These messages don't need to do any state changes in the // reply - just need to commit an ack. - ACK_AND_DO_NOTHING => { + ACK_AND_DO_NOTHING_REPLY_ID => { match reply.result { // On success, set a successful ack. Nothing else to do. SubMsgResult::Ok(_) => Ok(Response::new().set_data(ack_success())), diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index c00df453..6a2f9332 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -7,7 +7,7 @@ use zip_optional::Zippable; use crate::{ helpers::{generate_receive_callback_msg, get_instantiate2_address, get_receive_callback}, - ibc::ACK_AND_DO_NOTHING, + ibc::ACK_AND_DO_NOTHING_REPLY_ID, ibc_helpers::{get_endpoint_prefix, try_pop_source_prefix}, msg::{CallbackMsg, ExecuteMsg}, state::{ @@ -18,7 +18,7 @@ use crate::{ ContractError, }; use ics721_types::{ - ibc::NonFungibleTokenPacketData, + ibc_types::NonFungibleTokenPacketData, token_types::{Class, ClassId, Token, TokenId}, types::ReceiverExecuteMsg, }; @@ -349,6 +349,6 @@ impl ActionAggregator { funds: vec![], } }; - Ok(SubMsg::reply_always(message, ACK_AND_DO_NOTHING)) + Ok(SubMsg::reply_always(message, ACK_AND_DO_NOTHING_REPLY_ID)) } } diff --git a/packages/ics721/src/lib.rs b/packages/ics721/src/lib.rs index abe5ffd8..75734a0f 100644 --- a/packages/ics721/src/lib.rs +++ b/packages/ics721/src/lib.rs @@ -11,7 +11,7 @@ pub mod token_types; pub mod utils; pub use crate::error::ContractError; pub use ics721_types::{ - ibc::NonFungibleTokenPacketData, + ibc_types::NonFungibleTokenPacketData, token_types::{Class, ClassId, Token, TokenId}, }; diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index cac6569a..0422538d 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -22,7 +22,7 @@ use crate::{ utils::get_collection_data, }; use ics721_types::{ - ibc::NonFungibleTokenPacketData, + ibc_types::NonFungibleTokenPacketData, token_types::{ClassId, TokenId}, }; diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index d7f66547..47c47ff1 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -10,7 +10,7 @@ use cosmwasm_std::{ use crate::{ execute::Ics721Execute, - ibc::{Ics721Ibc, ACK_AND_DO_NOTHING, IBC_VERSION, INSTANTIATE_CW721_REPLY_ID}, + ibc::{Ics721Ibc, ACK_AND_DO_NOTHING_REPLY_ID, IBC_VERSION, INSTANTIATE_CW721_REPLY_ID}, ibc_helpers::{ack_fail, ack_success, try_get_ack_error}, msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, QueryMsg}, query::Ics721Query, @@ -19,7 +19,7 @@ use crate::{ ContractError, }; use ics721_types::{ - ibc::NonFungibleTokenPacketData, + ibc_types::NonFungibleTokenPacketData, token_types::{ClassId, TokenId}, types::Ics721Callbacks, }; @@ -180,7 +180,7 @@ fn test_stateless_reply() { let mut deps = mock_dependencies(); let rep = Reply { - id: ACK_AND_DO_NOTHING, + id: ACK_AND_DO_NOTHING_REPLY_ID, result: SubMsgResult::Ok(SubMsgResponse { events: vec![], data: None, @@ -192,7 +192,7 @@ fn test_stateless_reply() { assert_eq!(res.data, Some(ack_success())); let rep = Reply { - id: ACK_AND_DO_NOTHING, + id: ACK_AND_DO_NOTHING_REPLY_ID, result: SubMsgResult::Err("some failure".to_string()), }; let res = Ics721Contract::default() @@ -497,7 +497,7 @@ fn test_ibc_packet_receive_invalid_packet_data() { assert!(error .unwrap() - .starts_with("Error parsing into type ics721_types::ibc::NonFungibleTokenPacketData")) + .starts_with("Error parsing into type ics721_types::ibc_types::NonFungibleTokenPacketData")) } #[test] From c46edd44c62939a527d3fb9827713056455453d7 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 13:51:32 +0100 Subject: [PATCH 20/40] remove ReceiveProxyNft (handled now by ReceiveNft) --- Cargo.lock | 2 +- Cargo.toml | 1 - contracts/ics721-base-tester/src/contract.rs | 4 +- .../src/testing/integration_tests.rs | 56 ++++++++++++------- packages/ics721-types/Cargo.toml | 1 + packages/ics721-types/src/ibc_types.rs | 22 +++++++- packages/ics721-types/src/token_types.rs | 6 ++ packages/ics721/Cargo.toml | 1 - packages/ics721/src/execute.rs | 35 +++++++++--- packages/ics721/src/msg.rs | 26 +-------- packages/ics721/src/query.rs | 4 +- packages/ics721/src/testing/contract.rs | 4 +- .../ics721/src/testing/integration_tests.rs | 56 ++++++++++++------- 13 files changed, 133 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d80bd6e..5b955aa4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -789,7 +789,6 @@ dependencies = [ "cw721-base 0.16.0", "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "cw721-incoming-proxy", - "cw721-outgoing-proxy-derive", "cw721-outgoing-proxy-rate-limit", "ics721-types 0.1.0", "serde", @@ -829,6 +828,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "serde", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 8866c042..762618cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ cw721-016 = { version = "0.16.0", package = "cw721" } cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdrawal_address"} # TODO switch to official repo, once merged cw721-base-016 = { version = "0.16.0", package = "cw721-base" } cw721-incoming-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git" } -cw721-outgoing-proxy-derive = { git = "https://github.com/arkprotocol/cw721-proxy.git" } cw721-outgoing-proxy-rate-limit = { git = "https://github.com/arkprotocol/cw721-proxy.git" } cw-multi-test = { version = "^0.20", features = ["cosmwasm_1_2"] } cw-utils = "^1.0" diff --git a/contracts/ics721-base-tester/src/contract.rs b/contracts/ics721-base-tester/src/contract.rs index 8220048d..15e3a988 100644 --- a/contracts/ics721-base-tester/src/contract.rs +++ b/contracts/ics721-base-tester/src/contract.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{ StdResult, WasmMsg, }; use cw2::set_contract_version; -use ics721_types::ibc_types::NonFungibleTokenPacketData; +use ics721_types::ibc_types::{IbcOutgoingMsg, NonFungibleTokenPacketData}; use crate::{ error::ContractError, @@ -220,7 +220,7 @@ fn execute_send_nft( msg: to_json_binary(&cw721::Cw721ExecuteMsg::SendNft { contract: ics721, token_id, - msg: to_json_binary(&ics721::msg::IbcOutgoingMsg { + msg: to_json_binary(&IbcOutgoingMsg { receiver: recipient, channel_id, timeout: IbcTimeout::with_timestamp(env.block.time.plus_seconds(1000)), diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index b671807e..3b81ec14 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -17,12 +17,15 @@ use cw_pause_once::PauseError; use ics721::{ execute::Ics721Execute, ibc::Ics721Ibc, - msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg, QueryMsg}, + msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}, query::Ics721Query, state::CollectionData, token_types::VoucherCreation, }; -use ics721_types::token_types::{Class, ClassId, Token, TokenId}; +use ics721_types::{ + ibc_types::{IbcOutgoingMsg, IbcOutgoingProxyMsg}, + token_types::{Class, ClassId, Token, TokenId}, +}; use sg721::InstantiateMsg as Sg721InstantiateMsg; use sg721_base::msg::{CollectionInfoResponse, QueryMsg as Sg721QueryMsg}; use sha2::{digest::Update, Digest, Sha256}; @@ -1997,14 +2000,24 @@ fn test_no_proxy_unauthorized() { .execute_contract( test.app.api().addr_make("proxy"), test.ics721, - &ExecuteMsg::ReceiveProxyNft { - eyeball: "nft".to_string(), - msg: cw721::Cw721ReceiveMsg { - sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), - token_id: "1".to_string(), - msg: to_json_binary("").unwrap(), - }, - }, + &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + token_id: "1".to_string(), + msg: to_json_binary(&IbcOutgoingProxyMsg { + collection: "foo".to_string(), + msg: to_json_binary(&IbcOutgoingMsg { + receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + channel_id: "channel-0".to_string(), + timeout: IbcTimeout::with_block(IbcTimeoutBlock { + revision: 0, + height: 10, + }), + memo: None, + }) + .unwrap(), + }) + .unwrap(), + }), &[], ) .unwrap_err() @@ -2081,15 +2094,15 @@ fn test_proxy_authorized() { .execute_contract( proxy_address, test.ics721, - &ExecuteMsg::ReceiveProxyNft { - eyeball: source_cw721.into_string(), - msg: cw721::Cw721ReceiveMsg { - sender: test - .app - .api() - .addr_make(COLLECTION_OWNER_SOURCE_CHAIN) - .to_string(), - token_id: "1".to_string(), + &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + sender: test + .app + .api() + .addr_make(COLLECTION_OWNER_SOURCE_CHAIN) + .to_string(), + token_id: "1".to_string(), + msg: to_json_binary(&IbcOutgoingProxyMsg { + collection: source_cw721.into_string(), msg: to_json_binary(&IbcOutgoingMsg { receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), channel_id: "channel-0".to_string(), @@ -2100,8 +2113,9 @@ fn test_proxy_authorized() { memo: None, }) .unwrap(), - }, - }, + }) + .unwrap(), + }), &[], ) .unwrap(); diff --git a/packages/ics721-types/Cargo.toml b/packages/ics721-types/Cargo.toml index 06bd28e9..1756369e 100644 --- a/packages/ics721-types/Cargo.toml +++ b/packages/ics721-types/Cargo.toml @@ -9,5 +9,6 @@ description = "an implementation of the ICS721 specification for transfering NFT cosmwasm-std = { workspace = true, features = ["cosmwasm_1_2"] } cosmwasm-schema = { workspace = true } cw-storage-plus = { workspace = true } +cw721 = { workspace = true } serde = { workspace = true } thiserror = { workspace = true } diff --git a/packages/ics721-types/src/ibc_types.rs b/packages/ics721-types/src/ibc_types.rs index c902afd7..d08be902 100644 --- a/packages/ics721-types/src/ibc_types.rs +++ b/packages/ics721-types/src/ibc_types.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::cw_serde; -use cosmwasm_std::Binary; +use cosmwasm_std::{Binary, IbcTimeout}; use crate::{ error::ValidationError, @@ -85,6 +85,26 @@ impl NonFungibleTokenPacketData { } } +#[cw_serde] +pub struct IbcOutgoingMsg { + /// The address that should receive the NFT being sent on the + /// *receiving chain*. + pub receiver: String, + /// The *local* channel ID this ought to be sent away on. This + /// contract must have a connection on this channel. + pub channel_id: String, + /// Timeout for the IBC message. + pub timeout: IbcTimeout, + /// Memo to add custom string to the msg + pub memo: Option, +} + +#[cw_serde] +pub struct IbcOutgoingProxyMsg { + pub collection: String, + pub msg: Binary, +} + #[cfg(test)] mod tests { use super::*; diff --git a/packages/ics721-types/src/token_types.rs b/packages/ics721-types/src/token_types.rs index 3b988490..04a9d560 100644 --- a/packages/ics721-types/src/token_types.rs +++ b/packages/ics721-types/src/token_types.rs @@ -56,6 +56,12 @@ impl ClassId { } } +#[cw_serde] +pub struct ClassToken { + pub class_id: ClassId, + pub token_id: TokenId, +} + impl<'a> Bounder<'a> for ClassId { fn inclusive_bound(self) -> Option> { Some(Bound::inclusive(self)) diff --git a/packages/ics721/Cargo.toml b/packages/ics721/Cargo.toml index ac2685b9..9778e9b1 100644 --- a/packages/ics721/Cargo.toml +++ b/packages/ics721/Cargo.toml @@ -20,7 +20,6 @@ thiserror = { workspace = true } serde = { workspace = true } cw-paginate-storage = { workspace = true } cw721-incoming-proxy = { workspace = true } -cw721-outgoing-proxy-derive = { workspace = true } cw-pause-once = { workspace = true } cw-cii = { workspace = true } sha2 = { workspace = true } diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 775b7c3f..148b2c97 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -5,7 +5,7 @@ use cosmwasm_std::{ IbcMsg, MessageInfo, Response, StdResult, SubMsg, WasmMsg, }; use ics721_types::{ - ibc_types::NonFungibleTokenPacketData, + ibc_types::{IbcOutgoingMsg, IbcOutgoingProxyMsg, NonFungibleTokenPacketData}, token_types::{Class, ClassId, Token, TokenId}, }; use serde::{de::DeserializeOwned, Serialize}; @@ -17,7 +17,7 @@ use crate::{ INSTANTIATE_CW721_REPLY_ID, INSTANTIATE_INCOMING_PROXY_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID, }, - msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg}, + msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg}, state::{ CollectionData, UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, @@ -82,9 +82,6 @@ where token_id, msg, }) => self.execute_receive_nft(deps, env, info, token_id, sender, msg), - ExecuteMsg::ReceiveProxyNft { eyeball, msg } => { - self.execute_receive_proxy_nft(deps, env, info, eyeball, msg) - } ExecuteMsg::Pause {} => self.execute_pause(deps, info), ExecuteMsg::Callback(msg) => self.execute_callback(deps, env, info, msg), } @@ -99,11 +96,31 @@ where sender: String, msg: Binary, ) -> Result, ContractError> { - if OUTGOING_PROXY.load(deps.storage)?.is_some() { - Err(ContractError::Unauthorized {}) + let result = if OUTGOING_PROXY.load(deps.storage)?.is_some() { + from_json::(msg).ok().and_then(|msg| { + let mut info = info; + match deps.api.addr_validate(&msg.collection) { + Ok(validated_addr) => { + info.sender = validated_addr; + Some(self.receive_nft( + deps, + env, + info, + TokenId::new(token_id), + sender, + msg.msg, + )) + } + Err(_) => None, + } + }) } else { - self.receive_nft(deps, env, info, TokenId::new(token_id), sender, msg) - } + from_json::(msg.clone()) + .ok() + .map(|_| self.receive_nft(deps, env, info, TokenId::new(token_id), sender, msg)) + }; + + result.ok_or(ContractError::Unauthorized {})? } fn execute_receive_proxy_nft( diff --git a/packages/ics721/src/msg.rs b/packages/ics721/src/msg.rs index f5b71858..f5a9401f 100644 --- a/packages/ics721/src/msg.rs +++ b/packages/ics721/src/msg.rs @@ -1,10 +1,9 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, IbcTimeout, WasmMsg}; -use cw721_outgoing_proxy_derive::cw721_outgoing_proxy; +use cosmwasm_std::{Addr, WasmMsg}; use cw_cii::ContractInstantiateInfo; use crate::token_types::{VoucherCreation, VoucherRedemption}; -use ics721_types::token_types::{Class, ClassId, Token, TokenId}; +use ics721_types::token_types::{Class, ClassId, ClassToken, Token, TokenId}; #[cw_serde] pub struct InstantiateMsg { @@ -32,7 +31,6 @@ pub struct InstantiateMsg { pub pauser: Option, } -#[cw721_outgoing_proxy] #[cw_serde] pub enum ExecuteMsg { /// Receives a NFT to be IBC transfered away. The `msg` field must @@ -85,20 +83,6 @@ pub enum CallbackMsg { Conjunction { operands: Vec }, } -#[cw_serde] -pub struct IbcOutgoingMsg { - /// The address that should receive the NFT being sent on the - /// *receiving chain*. - pub receiver: String, - /// The *local* channel ID this ought to be sent away on. This - /// contract must have a connection on this channel. - pub channel_id: String, - /// Timeout for the IBC message. - pub timeout: IbcTimeout, - /// Memo to add custom string to the msg - pub memo: Option, -} - #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { @@ -177,12 +161,6 @@ pub enum QueryMsg { }, } -#[cw_serde] -pub struct ClassToken { - pub class_id: ClassId, - pub token_id: TokenId, -} - #[cw_serde] pub enum MigrateMsg { WithUpdate { diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index b406acae..37c43e16 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -2,14 +2,14 @@ use cosmwasm_std::{to_json_binary, Addr, Binary, Deps, Env, Order, StdResult}; use cw_storage_plus::Map; use crate::{ - msg::{ClassToken, QueryMsg}, + msg::QueryMsg, state::{ UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA, }, }; -use ics721_types::token_types::{Class, ClassId, Token, TokenId}; +use ics721_types::token_types::{Class, ClassId, ClassToken, Token, TokenId}; pub trait Ics721Query { fn query(&self, deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index 0422538d..7d5acb48 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -13,7 +13,7 @@ use cw_ownable::Ownership; use crate::{ execute::Ics721Execute, ibc::{Ics721Ibc, INSTANTIATE_INCOMING_PROXY_REPLY_ID, INSTANTIATE_OUTGOING_PROXY_REPLY_ID}, - msg::{IbcOutgoingMsg, InstantiateMsg}, + msg::InstantiateMsg, query::Ics721Query, state::{ CollectionData, CLASS_ID_TO_CLASS, CW721_CODE_ID, INCOMING_PROXY, @@ -22,7 +22,7 @@ use crate::{ utils::get_collection_data, }; use ics721_types::{ - ibc_types::NonFungibleTokenPacketData, + ibc_types::{IbcOutgoingMsg, NonFungibleTokenPacketData}, token_types::{ClassId, TokenId}, }; diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index c203cdee..1ce6a4c3 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -19,13 +19,16 @@ use sha2::{digest::Update, Digest, Sha256}; use crate::{ execute::Ics721Execute, ibc::Ics721Ibc, - msg::{CallbackMsg, ExecuteMsg, IbcOutgoingMsg, InstantiateMsg, MigrateMsg, QueryMsg}, + msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}, query::Ics721Query, state::CollectionData, token_types::VoucherCreation, ContractError, }; -use ics721_types::token_types::{Class, ClassId, Token, TokenId}; +use ics721_types::{ + ibc_types::{IbcOutgoingMsg, IbcOutgoingProxyMsg}, + token_types::{Class, ClassId, Token, TokenId}, +}; use super::contract::Ics721Contract; @@ -1678,14 +1681,24 @@ fn test_no_proxy_unauthorized() { .execute_contract( test.app.api().addr_make("proxy"), test.ics721, - &ExecuteMsg::ReceiveProxyNft { - eyeball: "nft".to_string(), - msg: cw721::Cw721ReceiveMsg { - sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), - token_id: "1".to_string(), - msg: to_json_binary("").unwrap(), - }, - }, + &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + token_id: "1".to_string(), + msg: to_json_binary(&IbcOutgoingProxyMsg { + collection: "foo".to_string(), + msg: to_json_binary(&IbcOutgoingMsg { + receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + channel_id: "channel-0".to_string(), + timeout: IbcTimeout::with_block(IbcTimeoutBlock { + revision: 0, + height: 10, + }), + memo: None, + }) + .unwrap(), + }) + .unwrap(), + }), &[], ) .unwrap_err() @@ -1750,15 +1763,15 @@ fn test_proxy_authorized() { .execute_contract( proxy_address, test.ics721, - &ExecuteMsg::ReceiveProxyNft { - eyeball: source_cw721.into_string(), - msg: cw721::Cw721ReceiveMsg { - sender: test - .app - .api() - .addr_make(COLLECTION_OWNER_SOURCE_CHAIN) - .to_string(), - token_id: "1".to_string(), + &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + sender: test + .app + .api() + .addr_make(COLLECTION_OWNER_SOURCE_CHAIN) + .to_string(), + token_id: "1".to_string(), + msg: to_json_binary(&IbcOutgoingProxyMsg { + collection: source_cw721.into_string(), msg: to_json_binary(&IbcOutgoingMsg { receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), channel_id: "channel-0".to_string(), @@ -1769,8 +1782,9 @@ fn test_proxy_authorized() { memo: None, }) .unwrap(), - }, - }, + }) + .unwrap(), + }), &[], ) .unwrap(); From 9ec55edd96e004c4592593c1504a9c1791a810e2 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 19:18:16 +0100 Subject: [PATCH 21/40] cleanup --- Cargo.lock | 48 ++++++++++++++++++++++------------ Cargo.toml | 4 +-- packages/ics721/src/execute.rs | 4 +-- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b955aa4..eeb3f8ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,7 +234,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" dependencies = [ "cosmwasm-std", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -446,6 +446,18 @@ dependencies = [ "serde", ] +[[package]] +name = "cw721" +version = "0.18.0" +source = "git+https://github.com/CosmWasm/cw-nfts?branch=main#cc27e27d54e237709ebdcd478568126e109a8845" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 1.0.3", + "schemars", + "serde", +] + [[package]] name = "cw721" version = "0.18.0" @@ -497,7 +509,7 @@ dependencies = [ [[package]] name = "cw721-base" version = "0.18.0" -source = "git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address#8691baf71422448b50d98bc5e516b9115dc13336" +source = "git+https://github.com/CosmWasm/cw-nfts?branch=main#cc27e27d54e237709ebdcd478568126e109a8845" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -505,7 +517,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "cw721-base 0.16.0", "schemars", "serde", @@ -515,7 +527,7 @@ dependencies = [ [[package]] name = "cw721-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -534,7 +546,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -547,7 +559,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -558,7 +570,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-rate-limit" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c5fa004766f423538f5bfcca6370348a124fcdb7" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -568,6 +580,7 @@ dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721-outgoing-proxy", "cw721-outgoing-proxy-derive", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", "serde", "thiserror", ] @@ -580,7 +593,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721-base 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "thiserror", ] @@ -785,9 +798,9 @@ dependencies = [ "cw-utils 1.0.3", "cw2 1.1.2", "cw721 0.16.0", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "cw721-base 0.16.0", - "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721-base 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "cw721-incoming-proxy", "cw721-outgoing-proxy-rate-limit", "ics721-types 0.1.0", @@ -815,7 +828,7 @@ dependencies = [ "cosmwasm-storage", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "ics721", "ics721-types 0.1.0", "thiserror", @@ -828,7 +841,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "serde", "thiserror", ] @@ -836,11 +849,12 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#f112d264cdcd81a41a17a5a1ee8617f707a97966" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#c46edd44c62939a527d3fb9827713056455453d7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", + "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", "serde", "thiserror", ] @@ -1107,8 +1121,8 @@ dependencies = [ "cw-pause-once", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", - "cw721-base 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", + "cw721-base 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "cw721-incoming-proxy", "cw721-outgoing-proxy-rate-limit", "ics721", diff --git a/Cargo.toml b/Cargo.toml index 762618cb..95712bbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,9 @@ cw-ownable = "^0.5" cw-paginate-storage = { version = "^2.4", git = "https://github.com/DA0-DA0/dao-contracts.git" } cw-storage-plus = "1.1" cw2 = "1.1" -cw721 = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdrawal_address"} # TODO switch to official repo, once merged +cw721 = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main"} # TODO switch to version 0.18.1/0.19.0, once released cw721-016 = { version = "0.16.0", package = "cw721" } -cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "withdrawal_address"} # TODO switch to official repo, once merged +cw721-base = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main"} # TODO switch to version 0.18.1/0.19.0, once released cw721-base-016 = { version = "0.16.0", package = "cw721-base" } cw721-incoming-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git" } cw721-outgoing-proxy-rate-limit = { git = "https://github.com/arkprotocol/cw721-proxy.git" } diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 148b2c97..be90a2d1 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -100,8 +100,8 @@ where from_json::(msg).ok().and_then(|msg| { let mut info = info; match deps.api.addr_validate(&msg.collection) { - Ok(validated_addr) => { - info.sender = validated_addr; + Ok(collection_addr) => { + info.sender = collection_addr; Some(self.receive_nft( deps, env, From 549e9a00d2953864d9b4c8756c46e7aef6ab4208 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 19:26:15 +0100 Subject: [PATCH 22/40] cleanup --- Cargo.lock | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eeb3f8ad..9e0ecd64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,18 +458,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cw721" -version = "0.18.0" -source = "git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address#8691baf71422448b50d98bc5e516b9115dc13336" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils 1.0.3", - "schemars", - "serde", -] - [[package]] name = "cw721-base" version = "0.16.0" @@ -849,12 +837,12 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#c46edd44c62939a527d3fb9827713056455453d7" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#9ec55edd96e004c4592593c1504a9c1791a810e2" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", - "cw721 0.18.0 (git+https://github.com/arkprotocol/cw-nfts?branch=withdrawal_address)", + "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "serde", "thiserror", ] From 10d64ed8ee35e88458ee3a9c0f69407ee82e4c44 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 21:32:03 +0100 Subject: [PATCH 23/40] ts-relayer test for receive nft via outgoing proxy --- external-wasms/cw721_incoming_proxy.wasm | Bin 181642 -> 181642 bytes .../cw721_outgoing_proxy_rate_limit.wasm | Bin 0 -> 177902 bytes packages/ics721/src/error.rs | 3 + packages/ics721/src/execute.rs | 6 +- ts-relayer-tests/src/ics721-utils.ts | 5 +- ts-relayer-tests/src/ics721.spec.ts | 269 +++++++++++------- 6 files changed, 171 insertions(+), 112 deletions(-) create mode 100644 external-wasms/cw721_outgoing_proxy_rate_limit.wasm diff --git a/external-wasms/cw721_incoming_proxy.wasm b/external-wasms/cw721_incoming_proxy.wasm index 08286f242e08050d8dcbaa34f4433c9b7e830349..6c9ee13867e84b823a5f13dcdf9cb33146b76dac 100644 GIT binary patch delta 2310 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 literal 0 HcmV?d00001 diff --git a/packages/ics721/src/error.rs b/packages/ics721/src/error.rs index e3774975..50053b90 100644 --- a/packages/ics721/src/error.rs +++ b/packages/ics721/src/error.rs @@ -21,6 +21,9 @@ pub enum ContractError { #[error("unauthorized")] Unauthorized {}, + #[error("NFT not escrowed by ICS721! Owner: {0}")] + NotEscrowedByIcs721(String), + #[error("only unordered channels are supported")] OrderedChannel {}, diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index be90a2d1..9c3b47cb 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -198,7 +198,7 @@ where }, )?; if access.owner != env.contract.address { - return Err(ContractError::Unauthorized {}); + return Err(ContractError::NotEscrowedByIcs721(access.owner)); } // cw721 doesn't support on-chain metadata yet @@ -496,6 +496,10 @@ where "outgoing_proxy", outgoing_proxy.map_or_else(|| "none".to_string(), |or| or), ) + .add_attribute( + "incoming_proxy", + incoming_proxy.map_or_else(|| "none".to_string(), |or| or), + ) .add_attribute( "cw721_base_code_id", cw721_base_code_id.map_or_else(|| "none".to_string(), |or| or.to_string()), diff --git a/ts-relayer-tests/src/ics721-utils.ts b/ts-relayer-tests/src/ics721-utils.ts index 6bf96371..398eefac 100644 --- a/ts-relayer-tests/src/ics721-utils.ts +++ b/ts-relayer-tests/src/ics721-utils.ts @@ -6,10 +6,11 @@ export function migrate( client: CosmWasmSigner, contractAddress: string, codeId: number, - incoming_proxy: string + incoming_proxy?: string, + outgoing_proxy?: string ) { const msg = { - with_update: { incoming_proxy }, + with_update: { incoming_proxy, outgoing_proxy }, }; return client.sign.migrate( client.senderAddress, diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index 737f7d06..ca62b586 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -32,6 +32,7 @@ interface TestContext { osmoCw721: string; osmoIcs721: string; + osmoCw721OutgoingProxy: string; channel: ChannelAndLinkInfo; @@ -42,6 +43,8 @@ const test = anyTest as TestFn; const WASM_FILE_CW721 = "./internal/cw721_base_v0.18.0.wasm"; const WASM_FILE_CW721_INCOMING_PROXY = "./internal/cw721_incoming_proxy.wasm"; +const WASM_FILE_CW721_OUTGOING_PROXY = + "./internal/cw721_outgoing_proxy_rate_limit.wasm"; const WASM_FILE_CW_ICS721_ICS721 = "./internal/ics721_base.wasm"; const MALICIOUS_CW721 = "./internal/cw721_tester.wasm"; @@ -81,6 +84,10 @@ const standardSetup = async (t: ExecutionContext) => { minter: osmoClient.senderAddress, }, }, + cw721OutgoingProxy: { + path: WASM_FILE_CW721_OUTGOING_PROXY, + instantiateMsg: undefined, + }, ics721: { path: WASM_FILE_CW_ICS721_ICS721, instantiateMsg: undefined, @@ -95,13 +102,17 @@ const standardSetup = async (t: ExecutionContext) => { ); const wasmCw721Id = info.wasmContractInfos.cw721.codeId; + const osmoCw721Id = info.osmoContractInfos.cw721.codeId; + const wasmCw721IncomingProxyId = info.wasmContractInfos.cw721IncomingProxy.codeId; - const osmoCw721Id = info.osmoContractInfos.cw721.codeId; const wasmIcs721Id = info.wasmContractInfos.ics721.codeId; const osmoIcs721Id = info.osmoContractInfos.ics721.codeId; + const osmoCw721OutgoingProxyId = + info.osmoContractInfos.cw721OutgoingProxy.codeId; + t.context.wasmCw721 = info.wasmContractInfos.cw721.address as string; t.context.osmoCw721 = info.osmoContractInfos.cw721.address as string; @@ -154,8 +165,10 @@ const standardSetup = async (t: ExecutionContext) => { t.log(`- wasm cw721-incoming-proxy address: ${wasmCw721IncomingProxy}`); t.context.wasmCw721IncomingProxy = wasmCw721IncomingProxy; - t.log(`migrate ${wasmIcs721} contract to use incoming proxy`); - const migrateResult = await migrate( + t.log( + `migrate ${wasmIcs721} contract to use incoming proxy ${wasmCw721IncomingProxy}` + ); + let migrateResult = await migrate( wasmClient, wasmIcs721, wasmIcs721Id, @@ -165,6 +178,36 @@ const standardSetup = async (t: ExecutionContext) => { `- migrate result: ${JSON.stringify(migrateResult, bigIntReplacer, 2)}` ); + const per_block = 10; // use high rate limit to avoid test failures + t.log( + `instantiating osmo cw721-outgoing-proxy (${osmoCw721OutgoingProxyId}) with ${per_block} per blocks rate limit` + ); + const { contractAddress: osmoCw721OutgoingProxy } = await instantiateContract( + osmoClient, + osmoCw721OutgoingProxyId, + { + origin: osmoIcs721, + rate_limit: { per_block }, + }, + "label outgoing proxy" + ); + t.log(`- osmo cw721-outgoing-proxy address: ${osmoCw721OutgoingProxy}`); + t.context.osmoCw721OutgoingProxy = osmoCw721OutgoingProxy; + + t.log( + `migrate ${osmoIcs721} contract to use outgoing proxy ${osmoCw721OutgoingProxy}` + ); + migrateResult = await migrate( + osmoClient, + osmoIcs721, + osmoIcs721Id, + undefined, + osmoCw721OutgoingProxy + ); + t.log( + `- migrate result: ${JSON.stringify(migrateResult, bigIntReplacer, 2)}` + ); + t.log( `creating another IBC connection and channel between wasm and osmo (${wasmIcs721} <-> ${osmoIcs721})` ); @@ -244,114 +287,122 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { t.is(osmoAddr, tokenOwner.owner); }); -test.serial("transfer NFT with incoming proxy: osmo -> wasmd", async (t) => { - await standardSetup(t); - - const { - wasmClient, - wasmAddr, - wasmIcs721, - osmoClient, - osmoAddr, - osmoCw721, - osmoIcs721, - channel, - otherChannel, - } = t.context; - - // test 1: transfer using WLed channel by incoming proxy - let tokenId = "1"; - t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); - await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); - // assert token is minted - let tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoAddr, tokenOwner.owner); - - let ibcMsg = { - receiver: wasmAddr, - channel_id: channel.channel.dest.channelId, - timeout: { - block: { - revision: 1, - height: 90000, +test.serial( + "transfer NFT with osmo outgoing and wasm incoming proxy", + async (t) => { + await standardSetup(t); + + const { + wasmClient, + wasmAddr, + wasmIcs721, + osmoClient, + osmoAddr, + osmoCw721, + osmoIcs721, + osmoCw721OutgoingProxy, + channel, + otherChannel, + } = t.context; + + // test 1: transfer via outgoing proxy and using WLed channel by incoming proxy + let tokenId = "1"; + t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); + await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); + // assert token is minted + let tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoAddr, tokenOwner.owner); + + let ibcMsg = { + receiver: wasmAddr, + channel_id: channel.channel.dest.channelId, + timeout: { + block: { + revision: 1, + height: 90000, + }, }, - }, - }; - - t.log(`transfering to wasm chain via ${channel.channel.dest.channelId}`); - - let transferResponse = await sendNft( - osmoClient, - osmoCw721, - osmoIcs721, - ibcMsg, - tokenId - ); - t.truthy(transferResponse); - - t.log("relaying packets"); - - let info = await channel.link.relayAll(); - - // Verify we got a success - assertAckSuccess(info.acksFromA); - - // assert NFT on chain A is locked/owned by ICS contract - tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoIcs721, tokenOwner.owner); - t.log(`NFT #${tokenId} locked by ICS721 contract`); - - const wasmClassId = `${t.context.channel.channel.src.portId}/${t.context.channel.channel.src.channelId}/${t.context.osmoCw721}`; - const wasmCw721 = await wasmClient.sign.queryContractSmart(wasmIcs721, { - nft_contract: { class_id: wasmClassId }, - }); - - tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); - t.is(wasmAddr, tokenOwner.owner); - t.log(`NFT #${tokenId} transferred to ${wasmAddr}`); - - // test 2: transfer using WLed channel by incoming proxy - tokenId = "2"; - t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); - await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); - // assert token is minted - tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoAddr, tokenOwner.owner); - - ibcMsg = { - receiver: wasmAddr, - channel_id: otherChannel.channel.dest.channelId, - timeout: { - block: { - revision: 1, - height: 90000, + }; + + t.log( + `transfering to wasm chain via ${channel.channel.dest.channelId} and outgoing proxy ${osmoCw721OutgoingProxy}` + ); + + let transferResponse = await sendNft( + osmoClient, + osmoCw721, + osmoCw721OutgoingProxy, + ibcMsg, + tokenId + ); + t.truthy(transferResponse); + + t.log("relaying packets"); + + let info = await channel.link.relayAll(); + + // Verify we got a success + assertAckSuccess(info.acksFromA); + + // assert NFT on chain A is locked/owned by ICS contract + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoIcs721, tokenOwner.owner); + t.log(`NFT #${tokenId} locked by ICS721 contract`); + + const wasmClassId = `${t.context.channel.channel.src.portId}/${t.context.channel.channel.src.channelId}/${t.context.osmoCw721}`; + const wasmCw721 = await wasmClient.sign.queryContractSmart(wasmIcs721, { + nft_contract: { class_id: wasmClassId }, + }); + + tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); + t.is(wasmAddr, tokenOwner.owner); + t.log(`NFT #${tokenId} transferred to ${wasmAddr}`); + + // test 2: transfer via outgoing proxy and using unknown channel by incoming proxy + tokenId = "2"; + t.log(`transferring NFT #${tokenId} from osmo to wasmd chain`); + await mint(osmoClient, osmoCw721, tokenId, osmoAddr, undefined); + // assert token is minted + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoAddr, tokenOwner.owner); + + ibcMsg = { + receiver: wasmAddr, + channel_id: otherChannel.channel.dest.channelId, + timeout: { + block: { + revision: 1, + height: 90000, + }, }, - }, - }; - - t.log(`transfering to wasm chain via ${otherChannel.channel.dest.channelId}`); - - transferResponse = await sendNft( - osmoClient, - osmoCw721, - osmoIcs721, - ibcMsg, - tokenId - ); - t.truthy(transferResponse); - - t.log("relaying packets"); - - info = await otherChannel.link.relayAll(); - - // Verify we got a success - assertAckErrors(info.acksFromA); - - // assert NFT on chain A is returned to owner - tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); - t.is(osmoClient.senderAddress, tokenOwner.owner); - t.log(`NFT #${tokenId} returned to owner`); -}); + }; + + t.log( + `transfering to wasm chain via ${otherChannel.channel.dest.channelId}` + ); + + transferResponse = await sendNft( + osmoClient, + osmoCw721, + osmoCw721OutgoingProxy, + ibcMsg, + tokenId + ); + t.truthy(transferResponse); + + t.log("relaying packets"); + + info = await otherChannel.link.relayAll(); + + // Verify we got an error + assertAckErrors(info.acksFromA); + + // assert NFT on chain A is returned to owner + tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); + t.is(osmoClient.senderAddress, tokenOwner.owner); + t.log(`NFT #${tokenId} returned to owner`); + } +); test.serial("malicious NFT", async (t) => { await standardSetup(t); From 0cdc119b15405ee01fa223a8013a6767929e615c Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 22:59:36 +0100 Subject: [PATCH 24/40] fix test --- .../src/testing/integration_tests.rs | 70 ++++++++++---- packages/ics721/src/error.rs | 5 +- packages/ics721/src/execute.rs | 92 ++++++++----------- .../ics721/src/testing/integration_tests.rs | 74 +++++++++++---- ts-relayer-tests/src/ics721.spec.ts | 30 +++--- 5 files changed, 164 insertions(+), 107 deletions(-) diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index 3b81ec14..31479e74 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -1991,10 +1991,23 @@ fn test_do_instantiate_and_mint_permissions() { assert_eq!(err, ContractError::Unauthorized {}); } -/// Tests that we can not proxy NFTs if no proxy is configured. +/// Tests that we can not send IbcOutgoingProxyMsg if no proxy is configured. #[test] -fn test_no_proxy_unauthorized() { +fn test_no_proxy_unknown_msg() { let mut test = Test::new(false, false, None, None, sg721_base_contract()); + let msg = IbcOutgoingProxyMsg { + collection: "foo".to_string(), + msg: to_json_binary(&IbcOutgoingMsg { + receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + channel_id: "channel-0".to_string(), + timeout: IbcTimeout::with_block(IbcTimeoutBlock { + revision: 0, + height: 10, + }), + memo: None, + }) + .unwrap(), + }; let err: ContractError = test .app .execute_contract( @@ -2003,20 +2016,45 @@ fn test_no_proxy_unauthorized() { &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), - msg: to_json_binary(&IbcOutgoingProxyMsg { - collection: "foo".to_string(), - msg: to_json_binary(&IbcOutgoingMsg { - receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), - channel_id: "channel-0".to_string(), - timeout: IbcTimeout::with_block(IbcTimeoutBlock { - revision: 0, - height: 10, - }), - memo: None, - }) - .unwrap(), - }) - .unwrap(), + msg: to_json_binary(&msg).unwrap(), + }), + &[], + ) + .unwrap_err() + .downcast() + .unwrap(); + assert_eq!( + err, + ContractError::UnknownMsg(to_json_binary(&msg).unwrap()) + ); +} + +/// Tests that we can non-proxy addresses can send if proxy is configured. +#[test] +fn test_no_proxy_unauthorized() { + let mut test = Test::new(true, false, None, None, sg721_base_contract()); + let msg = IbcOutgoingProxyMsg { + collection: "foo".to_string(), + msg: to_json_binary(&IbcOutgoingMsg { + receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + channel_id: "channel-0".to_string(), + timeout: IbcTimeout::with_block(IbcTimeoutBlock { + revision: 0, + height: 10, + }), + memo: None, + }) + .unwrap(), + }; + let err: ContractError = test + .app + .execute_contract( + test.app.api().addr_make("foo"), + test.ics721, + &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + token_id: "1".to_string(), + msg: to_json_binary(&msg).unwrap(), }), &[], ) diff --git a/packages/ics721/src/error.rs b/packages/ics721/src/error.rs index 50053b90..8e1610f4 100644 --- a/packages/ics721/src/error.rs +++ b/packages/ics721/src/error.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Instantiate2AddressError, StdError}; +use cosmwasm_std::{Binary, Instantiate2AddressError, StdError}; use cw_pause_once::PauseError; use cw_utils::ParseReplyError; use ics721_types::error::ValidationError; @@ -21,6 +21,9 @@ pub enum ContractError { #[error("unauthorized")] Unauthorized {}, + #[error("unauthorized")] + UnknownMsg(Binary), + #[error("NFT not escrowed by ICS721! Owner: {0}")] NotEscrowedByIcs721(String), diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 9c3b47cb..76f7a038 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -93,60 +93,46 @@ where env: Env, info: MessageInfo, token_id: String, - sender: String, + nft_owner: String, msg: Binary, ) -> Result, ContractError> { - let result = if OUTGOING_PROXY.load(deps.storage)?.is_some() { - from_json::(msg).ok().and_then(|msg| { - let mut info = info; - match deps.api.addr_validate(&msg.collection) { - Ok(collection_addr) => { - info.sender = collection_addr; - Some(self.receive_nft( - deps, - env, - info, - TokenId::new(token_id), - sender, - msg.msg, - )) - } - Err(_) => None, + let result = match OUTGOING_PROXY.load(deps.storage)? { + Some(proxy) => { + if proxy != info.sender { + return Err(ContractError::Unauthorized {}); } - }) - } else { - from_json::(msg.clone()) - .ok() - .map(|_| self.receive_nft(deps, env, info, TokenId::new(token_id), sender, msg)) + from_json::(msg.clone()) + .ok() + .and_then(|msg| { + let mut info = info; + match deps.api.addr_validate(&msg.collection) { + Ok(collection_addr) => { + info.sender = collection_addr; + Some(self.receive_nft( + deps, + env, + info, + TokenId::new(token_id), + nft_owner, + msg.msg, + )) + } + Err(_) => None, + } + }) + } + None => from_json::(msg.clone()).ok().map(|_| { + self.receive_nft( + deps, + env, + info, + TokenId::new(token_id), + nft_owner, + msg.clone(), + ) + }), }; - - result.ok_or(ContractError::Unauthorized {})? - } - - fn execute_receive_proxy_nft( - &self, - deps: DepsMut, - env: Env, - info: MessageInfo, - eyeball: String, - msg: cw721::Cw721ReceiveMsg, - ) -> Result, ContractError> { - if OUTGOING_PROXY - .load(deps.storage)? - .map_or(true, |proxy| info.sender != proxy) - { - return Err(ContractError::Unauthorized {}); - } - let mut info = info; - info.sender = deps.api.addr_validate(&eyeball)?; - let cw721::Cw721ReceiveMsg { - token_id, - sender, - msg, - } = msg; - let res = self.receive_nft(deps, env, info, TokenId::new(token_id), sender, msg)?; - // override method key - Ok(res.add_attribute("method", "execute_receive_proxy_nft")) + result.ok_or(ContractError::UnknownMsg(msg))? } fn get_class_data(&self, deps: &DepsMut, sender: &Addr) -> StdResult>; @@ -157,10 +143,10 @@ where env: Env, info: MessageInfo, token_id: TokenId, - sender: String, + nft_owner: String, msg: Binary, ) -> Result, ContractError> { - let sender = deps.api.addr_validate(&sender)?; + let nft_owner = deps.api.addr_validate(&nft_owner)?; let msg: IbcOutgoingMsg = from_json(msg)?; let class = match NFT_CONTRACT_TO_CLASS_ID.may_load(deps.storage, info.sender.clone())? { @@ -217,7 +203,7 @@ where token_uris: info.token_uri.map(|uri| vec![uri]), token_data: token_metadata.map(|metadata| vec![metadata]), - sender: sender.into_string(), + sender: nft_owner.into_string(), receiver: msg.receiver, memo: msg.memo, }; diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 1ce6a4c3..4a1e4a34 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -1672,10 +1672,23 @@ fn test_do_instantiate_and_mint_permissions() { assert_eq!(err, ContractError::Unauthorized {}); } -/// Tests that we can not proxy NFTs if no proxy is configured. +/// Tests that we can not send IbcOutgoingProxyMsg if no proxy is configured. #[test] -fn test_no_proxy_unauthorized() { +fn test_no_proxy_unknown_msg() { let mut test = Test::new(false, false, None, None, cw721_base_contract(), true); + let msg = IbcOutgoingProxyMsg { + collection: "foo".to_string(), + msg: to_json_binary(&IbcOutgoingMsg { + receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + channel_id: "channel-0".to_string(), + timeout: IbcTimeout::with_block(IbcTimeoutBlock { + revision: 0, + height: 10, + }), + memo: None, + }) + .unwrap(), + }; let err: ContractError = test .app .execute_contract( @@ -1684,20 +1697,45 @@ fn test_no_proxy_unauthorized() { &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), - msg: to_json_binary(&IbcOutgoingProxyMsg { - collection: "foo".to_string(), - msg: to_json_binary(&IbcOutgoingMsg { - receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), - channel_id: "channel-0".to_string(), - timeout: IbcTimeout::with_block(IbcTimeoutBlock { - revision: 0, - height: 10, - }), - memo: None, - }) - .unwrap(), - }) - .unwrap(), + msg: to_json_binary(&msg).unwrap(), + }), + &[], + ) + .unwrap_err() + .downcast() + .unwrap(); + assert_eq!( + err, + ContractError::UnknownMsg(to_json_binary(&msg).unwrap()) + ); +} + +/// Tests that we can non-proxy addresses can send if proxy is configured. +#[test] +fn test_no_proxy_unauthorized() { + let mut test = Test::new(true, false, None, None, cw721_base_contract(), true); + let msg = IbcOutgoingProxyMsg { + collection: "foo".to_string(), + msg: to_json_binary(&IbcOutgoingMsg { + receiver: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + channel_id: "channel-0".to_string(), + timeout: IbcTimeout::with_block(IbcTimeoutBlock { + revision: 0, + height: 10, + }), + memo: None, + }) + .unwrap(), + }; + let err: ContractError = test + .app + .execute_contract( + test.app.api().addr_make("foo"), + test.ics721, + &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), + token_id: "1".to_string(), + msg: to_json_binary(&msg).unwrap(), }), &[], ) @@ -1740,8 +1778,8 @@ fn test_proxy_authorized() { None, ) .unwrap(); - // simplify: instead of `send_nft` to proxy, and proxy transfer NFT to ics721 and call receiveproy, - // here it is directly transfer to ics721 and then call receiveproxy + // simplify: instead of `send_nft` to proxy, and proxy transfer NFT to ics721 and call receive proxy, + // here it is directly transferred to ics721 and then call receive proxy test.app .execute_contract( test.app.api().addr_make(COLLECTION_OWNER_SOURCE_CHAIN), diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index ca62b586..678d968d 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -168,15 +168,7 @@ const standardSetup = async (t: ExecutionContext) => { t.log( `migrate ${wasmIcs721} contract to use incoming proxy ${wasmCw721IncomingProxy}` ); - let migrateResult = await migrate( - wasmClient, - wasmIcs721, - wasmIcs721Id, - wasmCw721IncomingProxy - ); - t.log( - `- migrate result: ${JSON.stringify(migrateResult, bigIntReplacer, 2)}` - ); + await migrate(wasmClient, wasmIcs721, wasmIcs721Id, wasmCw721IncomingProxy); const per_block = 10; // use high rate limit to avoid test failures t.log( @@ -197,16 +189,13 @@ const standardSetup = async (t: ExecutionContext) => { t.log( `migrate ${osmoIcs721} contract to use outgoing proxy ${osmoCw721OutgoingProxy}` ); - migrateResult = await migrate( + await migrate( osmoClient, osmoIcs721, osmoIcs721Id, undefined, osmoCw721OutgoingProxy ); - t.log( - `- migrate result: ${JSON.stringify(migrateResult, bigIntReplacer, 2)}` - ); t.log( `creating another IBC connection and channel between wasm and osmo (${wasmIcs721} <-> ${osmoIcs721})` @@ -409,12 +398,13 @@ test.serial("malicious NFT", async (t) => { const { wasmClient, - osmoClient, - channel, - osmoAddr, wasmAddr, wasmIcs721, + osmoClient, + osmoAddr, osmoIcs721, + osmoCw721OutgoingProxy, + channel, } = t.context; const tokenId = "1"; @@ -445,7 +435,7 @@ test.serial("malicious NFT", async (t) => { }, }; - t.log("transfering to osmo chain"); + t.log("transferring to osmo chain"); let transferResponse = await sendNft( wasmClient, @@ -462,6 +452,8 @@ test.serial("malicious NFT", async (t) => { assertAckSuccess(info.acksFromB); + t.log("transferring back to wasm chain"); + const osmoClassId = `${t.context.channel.channel.dest.portId}/${t.context.channel.channel.dest.channelId}/${cw721}`; const osmoCw721 = await osmoClient.sign.queryContractSmart(osmoIcs721, { nft_contract: { class_id: osmoClassId }, @@ -481,7 +473,7 @@ test.serial("malicious NFT", async (t) => { transferResponse = await sendNft( osmoClient, osmoCw721, - osmoIcs721, + osmoCw721OutgoingProxy, ibcMsg, tokenId ); @@ -492,7 +484,7 @@ test.serial("malicious NFT", async (t) => { const pending = await channel.link.getPendingPackets("B"); t.is(pending.length, 1); - // Despite the transfer panicing, a fail ack should be returned. + // Despite the transfer panicking, a fail ack should be returned. info = await channel.link.relayAll(); assertAckErrors(info.acksFromA); }); From 28d28fea7919106be49c98fba848f7928c8aed74 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 23:14:07 +0100 Subject: [PATCH 25/40] cleanup --- packages/ics721-types/src/error.rs | 2 +- packages/ics721-types/src/ibc_types.rs | 28 ++++++++++++------------ packages/ics721/src/error.rs | 20 ++--------------- packages/ics721/src/testing/ibc_tests.rs | 4 ++-- 4 files changed, 19 insertions(+), 35 deletions(-) diff --git a/packages/ics721-types/src/error.rs b/packages/ics721-types/src/error.rs index 7cffae96..73b2ebcb 100644 --- a/packages/ics721-types/src/error.rs +++ b/packages/ics721-types/src/error.rs @@ -1,7 +1,7 @@ use thiserror::Error; #[derive(Error, Debug, PartialEq)] -pub enum ValidationError { +pub enum Ics721Error { #[error("empty class ID")] EmptyClassId {}, diff --git a/packages/ics721-types/src/ibc_types.rs b/packages/ics721-types/src/ibc_types.rs index d08be902..ed43aa0c 100644 --- a/packages/ics721-types/src/ibc_types.rs +++ b/packages/ics721-types/src/ibc_types.rs @@ -2,7 +2,7 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::{Binary, IbcTimeout}; use crate::{ - error::ValidationError, + error::Ics721Error, token_types::{ClassId, TokenId}, }; @@ -44,15 +44,15 @@ pub struct NonFungibleTokenPacketData { macro_rules! non_empty_optional { ($e:expr) => { if $e.map_or(false, |data| data.is_empty()) { - return Err(ValidationError::EmptyOptional {}); + return Err(Ics721Error::EmptyOptional {}); } }; } impl NonFungibleTokenPacketData { - pub fn validate(&self) -> Result<(), ValidationError> { + pub fn validate(&self) -> Result<(), Ics721Error> { if self.class_id.is_empty() { - return Err(ValidationError::EmptyClassId {}); + return Err(Ics721Error::EmptyClassId {}); } non_empty_optional!(self.class_uri.as_ref()); @@ -60,7 +60,7 @@ impl NonFungibleTokenPacketData { let token_count = self.token_ids.len(); if token_count == 0 { - return Err(ValidationError::NoTokens {}); + return Err(Ics721Error::NoTokens {}); } // Non-empty optionality of tokenData an tokenUris implicitly @@ -74,7 +74,7 @@ impl NonFungibleTokenPacketData { .as_ref() .map_or(false, |data| data.len() != token_count) { - return Err(ValidationError::TokenInfoLenMissmatch {}); + return Err(Ics721Error::TokenInfoLenMissmatch {}); } // This contract assumes that the backing cw721 is functional, @@ -129,55 +129,55 @@ mod tests { ..default_token.clone() }; let err = empty_class_id.validate().unwrap_err(); - assert_eq!(err, ValidationError::EmptyClassId {}); + assert_eq!(err, Ics721Error::EmptyClassId {}); let empty_class_uri = NonFungibleTokenPacketData { class_uri: Some("".to_string()), ..default_token.clone() }; let err = empty_class_uri.validate().unwrap_err(); - assert_eq!(err, ValidationError::EmptyOptional {}); + assert_eq!(err, Ics721Error::EmptyOptional {}); let empty_class_data = NonFungibleTokenPacketData { class_data: Some(Binary::default()), ..default_token.clone() }; let err = empty_class_data.validate().unwrap_err(); - assert_eq!(err, ValidationError::EmptyOptional {}); + assert_eq!(err, Ics721Error::EmptyOptional {}); let no_tokens = NonFungibleTokenPacketData { token_ids: vec![], ..default_token.clone() }; let err = no_tokens.validate().unwrap_err(); - assert_eq!(err, ValidationError::NoTokens {}); + assert_eq!(err, Ics721Error::NoTokens {}); let uri_imbalance_empty = NonFungibleTokenPacketData { token_uris: Some(vec![]), ..default_token.clone() }; let err = uri_imbalance_empty.validate().unwrap_err(); - assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + assert_eq!(err, Ics721Error::TokenInfoLenMissmatch {}); let uri_imbalance = NonFungibleTokenPacketData { token_uris: Some(vec!["a".to_string(), "b".to_string()]), ..default_token.clone() }; let err = uri_imbalance.validate().unwrap_err(); - assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + assert_eq!(err, Ics721Error::TokenInfoLenMissmatch {}); let data_imbalance_empty = NonFungibleTokenPacketData { token_data: Some(vec![]), ..default_token.clone() }; let err = data_imbalance_empty.validate().unwrap_err(); - assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + assert_eq!(err, Ics721Error::TokenInfoLenMissmatch {}); let data_imbalance = NonFungibleTokenPacketData { token_data: Some(vec![Binary::default(), Binary::default()]), ..default_token }; let err = data_imbalance.validate().unwrap_err(); - assert_eq!(err, ValidationError::TokenInfoLenMissmatch {}); + assert_eq!(err, Ics721Error::TokenInfoLenMissmatch {}); } } diff --git a/packages/ics721/src/error.rs b/packages/ics721/src/error.rs index 8e1610f4..919db6f3 100644 --- a/packages/ics721/src/error.rs +++ b/packages/ics721/src/error.rs @@ -1,13 +1,13 @@ use cosmwasm_std::{Binary, Instantiate2AddressError, StdError}; use cw_pause_once::PauseError; use cw_utils::ParseReplyError; -use ics721_types::error::ValidationError; +use ics721_types::error::Ics721Error; use thiserror::Error; #[derive(Error, Debug, PartialEq)] pub enum ContractError { #[error(transparent)] - ValidationError(#[from] ValidationError), + ValidationError(#[from] Ics721Error), #[error(transparent)] Std(#[from] StdError), @@ -36,28 +36,12 @@ pub enum ContractError { #[error("ICS 721 channels may not be closed")] CantCloseChannel {}, - #[error("unrecognised class ID")] - UnrecognisedClassId {}, - - #[error("class ID already exists")] - ClassIdAlreadyExists {}, - #[error("unrecognised reply ID")] UnrecognisedReplyId {}, #[error(transparent)] ParseReplyError(#[from] ParseReplyError), - #[error("must provide same number of token IDs and URIs")] - ImbalancedTokenInfo {}, - - #[error("unexpected uri for classID {class_id} - got ({actual:?}), expected ({expected:?})")] - ClassUriClash { - class_id: String, - expected: Option, - actual: Option, - }, - #[error("Transfer contains both redemption and a creation action")] InvalidTransferBothActions, diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index 47c47ff1..33c69f7c 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -560,7 +560,7 @@ fn test_ibc_packet_receive_missmatched_lengths() { error, Some( ContractError::ValidationError( - ics721_types::error::ValidationError::TokenInfoLenMissmatch {} + ics721_types::error::Ics721Error::TokenInfoLenMissmatch {} ) .to_string() ) @@ -597,7 +597,7 @@ fn test_ibc_packet_receive_missmatched_lengths() { error, Some( ContractError::ValidationError( - ics721_types::error::ValidationError::TokenInfoLenMissmatch {} + ics721_types::error::Ics721Error::TokenInfoLenMissmatch {} ) .to_string() ) From fee2aaadd7f222b939e37673e9f7ed803a1762ba Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 23:15:27 +0100 Subject: [PATCH 26/40] cleanup --- packages/ics721/src/error.rs | 2 +- packages/ics721/src/testing/ibc_tests.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/ics721/src/error.rs b/packages/ics721/src/error.rs index 919db6f3..5f7d04e0 100644 --- a/packages/ics721/src/error.rs +++ b/packages/ics721/src/error.rs @@ -7,7 +7,7 @@ use thiserror::Error; #[derive(Error, Debug, PartialEq)] pub enum ContractError { #[error(transparent)] - ValidationError(#[from] Ics721Error), + Ics721Error(#[from] Ics721Error), #[error(transparent)] Std(#[from] StdError), diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index 33c69f7c..39ced734 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -559,10 +559,8 @@ fn test_ibc_packet_receive_missmatched_lengths() { assert_eq!( error, Some( - ContractError::ValidationError( - ics721_types::error::Ics721Error::TokenInfoLenMissmatch {} - ) - .to_string() + ContractError::Ics721Error(ics721_types::error::Ics721Error::TokenInfoLenMissmatch {}) + .to_string() ) ); @@ -596,10 +594,8 @@ fn test_ibc_packet_receive_missmatched_lengths() { assert_eq!( error, Some( - ContractError::ValidationError( - ics721_types::error::Ics721Error::TokenInfoLenMissmatch {} - ) - .to_string() + ContractError::Ics721Error(ics721_types::error::Ics721Error::TokenInfoLenMissmatch {}) + .to_string() ) ) } From 03091a00fb0d4e372437bcacfa7aaf8f1d4359eb Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 23:52:17 +0100 Subject: [PATCH 27/40] moved to helper --- packages/ics721/src/helpers.rs | 27 +++++++++++++++++++--- packages/ics721/src/ibc_packet_receive.rs | 28 ++++++----------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/ics721/src/helpers.rs b/packages/ics721/src/helpers.rs index 3bedb933..3d6dace1 100644 --- a/packages/ics721/src/helpers.rs +++ b/packages/ics721/src/helpers.rs @@ -1,10 +1,10 @@ use cosmwasm_std::{ - from_json, instantiate2_address, to_json_binary, Addr, Binary, CodeInfoResponse, Deps, SubMsg, - WasmMsg, + from_json, instantiate2_address, to_json_binary, Addr, Binary, CodeInfoResponse, Deps, + IbcPacket, StdResult, Storage, SubMsg, WasmMsg, }; use serde::Deserialize; -use crate::{ibc::ACK_CALLBACK_REPLY_ID, ContractError}; +use crate::{ibc::ACK_CALLBACK_REPLY_ID, state::INCOMING_PROXY, ContractError}; use ics721_types::{ ibc_types::NonFungibleTokenPacketData, types::{ @@ -67,6 +67,27 @@ pub(crate) fn ack_callback_msg( )) } +/// If there is an incoming proxy, let proxy validate the packet, in case it fails, we fail the transfer +/// This proxy for example whitelist channels that can send to this contract: +/// https://github.com/arkprotocol/cw721-proxy/tree/main/contracts/cw721-incoming-proxy +pub(crate) fn get_incoming_proxy_msg( + storage: &dyn Storage, + packet: IbcPacket, + data: NonFungibleTokenPacketData, +) -> StdResult> { + match INCOMING_PROXY.load(storage).ok().flatten() { + Some(incoming_proxy) => { + let msg = to_json_binary(&ReceiverExecuteMsg::Ics721ReceivePacketMsg { packet, data })?; + Ok(Some(WasmMsg::Execute { + contract_addr: incoming_proxy.to_string(), + msg, + funds: vec![], + })) + } + None => Ok(None), + } +} + /// Get the msg and address from the memo field /// if there is no receive callback returns None pub(crate) fn get_receive_callback( diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 6a2f9332..e4542bd4 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -6,12 +6,15 @@ use sha2::{Digest, Sha256}; use zip_optional::Zippable; use crate::{ - helpers::{generate_receive_callback_msg, get_instantiate2_address, get_receive_callback}, + helpers::{ + generate_receive_callback_msg, get_incoming_proxy_msg, get_instantiate2_address, + get_receive_callback, + }, ibc::ACK_AND_DO_NOTHING_REPLY_ID, ibc_helpers::{get_endpoint_prefix, try_pop_source_prefix}, msg::{CallbackMsg, ExecuteMsg}, state::{ - CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, + CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO, }, token_types::{VoucherCreation, VoucherRedemption}, @@ -20,7 +23,6 @@ use crate::{ use ics721_types::{ ibc_types::NonFungibleTokenPacketData, token_types::{Class, ClassId, Token, TokenId}, - types::ReceiverExecuteMsg, }; /// Every incoming token has some associated action. @@ -60,24 +62,6 @@ pub(crate) fn receive_ibc_packet( let data: NonFungibleTokenPacketData = from_json(&packet.data)?; data.validate()?; - // If there is an incoming proxy, let proxy validate the packet, in case it fails, we fail the transfer - // This proxy for example whitelist channels that can send to this contract: - // https://github.com/arkprotocol/cw721-proxy/tree/main/contracts/cw721-incoming-proxy - let incoming_proxy_msg = match INCOMING_PROXY.load(deps.storage).ok().flatten() { - Some(incoming_proxy) => { - let msg = to_json_binary(&ReceiverExecuteMsg::Ics721ReceivePacketMsg { - packet: packet.clone(), - data: data.clone(), - })?; - Some(WasmMsg::Execute { - contract_addr: incoming_proxy.to_string(), - msg, - funds: vec![], - }) - } - None => None, - }; - let cloned_data = data.clone(); let receiver = deps.api.addr_validate(&data.receiver)?; let token_count = data.token_ids.len(); @@ -195,6 +179,8 @@ pub(crate) fn receive_ibc_packet( None }; + let incoming_proxy_msg = + get_incoming_proxy_msg(deps.storage, packet.clone(), cloned_data.clone())?; let submessage = action_aggregator.into_submessage( env.contract.address, receiver, From 88ae912c5defd352c54dfa62b0743843dc2ba8f3 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 30 Dec 2023 23:57:01 +0100 Subject: [PATCH 28/40] increase capacity to 3 --- packages/ics721/src/ibc_packet_receive.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index e4542bd4..02951694 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -311,16 +311,19 @@ impl ActionAggregator { callback_msg: Option, incoming_proxy_msg: Option, ) -> StdResult> { - let mut m = Vec::with_capacity(2); + let mut m = Vec::with_capacity(3); // 3 is the max number of submessages we can have if let Some(incoming_proxy_msg) = incoming_proxy_msg { m.push(incoming_proxy_msg) } + + // we can only have redeem or create, not both if let Some(redeem) = self.redemption { m.push(redeem.into_wasm_msg(contract.clone(), receiver.to_string())?) } if let Some(create) = self.creation { m.push(create.into_wasm_msg(contract.clone(), receiver.into_string())?) } + if let Some(callback_msg) = callback_msg { m.push(callback_msg) } From 62e118ea8815ea6ee03c05333a1a3c1c7e4ecd85 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sun, 31 Dec 2023 00:10:41 +0100 Subject: [PATCH 29/40] update versions --- Cargo.lock | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e0ecd64..2891c68d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.77" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" +checksum = "ca87830a3e3fb156dc96cfbd31cb620265dd053be734723f22b760d6cc3c3051" [[package]] name = "base16ct" @@ -234,7 +234,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" dependencies = [ "cosmwasm-std", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "cw721-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -534,7 +534,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -558,7 +558,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-rate-limit" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#c9d847abcfddaa33b9c339c0a96d2400f4898fcb" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -566,6 +566,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw2 1.1.2", "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721-outgoing-proxy", "cw721-outgoing-proxy-derive", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -837,7 +838,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#9ec55edd96e004c4592593c1504a9c1791a810e2" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#88ae912c5defd352c54dfa62b0743843dc2ba8f3" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1252,18 +1253,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", From a7a4778d7ea6f8f28ab370b86278f43a8d06a026 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sun, 31 Dec 2023 00:28:08 +0100 Subject: [PATCH 30/40] docs --- packages/ics721-types/src/token_types.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/ics721-types/src/token_types.rs b/packages/ics721-types/src/token_types.rs index 04a9d560..78a9590d 100644 --- a/packages/ics721-types/src/token_types.rs +++ b/packages/ics721-types/src/token_types.rs @@ -72,8 +72,7 @@ impl<'a> Bounder<'a> for ClassId { } } -// boilerplate for conversion between wrappers and the wrapped. - +// Allow ClassId to be inferred into String impl From for String { fn from(c: ClassId) -> Self { c.0 @@ -100,8 +99,7 @@ impl std::fmt::Display for ClassId { } } -// boilerplate for storing these wrapper types in CosmWasm maps. - +// Allow ClassId to be inferred into Key - using String.key() impl<'a> PrimaryKey<'a> for ClassId { type Prefix = >::Prefix; type SubPrefix = >::SubPrefix; From b930ded200d6db49162b6c3b15b37f6705eeaa34 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sun, 31 Dec 2023 13:23:27 +0100 Subject: [PATCH 31/40] detailed docs on receive nft --- packages/ics721/src/execute.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 76f7a038..36e403df 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -87,6 +87,20 @@ where } } + /// ICS721 may receive an NFT from 2 sources: + /// 1. From a local cw721 contract (e.g. cw721-base) + /// 2. From a(n outgoing) proxy contract. + /// + /// In case of 2. outgoing proxy calls 2 messages: + /// a) tranfer NFT to ICS721 + /// b) call/forwards "ReceiveNFt" message to ICS721. + /// + /// Unlike 1) proxy passes in b) an IbcOutgoingProxyMsg (and not an IbcOutgoingMsg) + /// which also holds the collection address, since info.sender + /// is the proxy contract - and not the collection. + /// + /// NB: outgoing proxy can use `SendNft` on collectio and pass it directly to ICS721, + /// since one `OUTGOING_PROXY` is defined in ICS721, it accepts only NFT receives from this proxy. fn execute_receive_nft( &self, deps: DepsMut, @@ -96,8 +110,10 @@ where nft_owner: String, msg: Binary, ) -> Result, ContractError> { + // if there is an outgoing proxy, we need to check if the msg is IbcOutgoingProxyMsg let result = match OUTGOING_PROXY.load(deps.storage)? { Some(proxy) => { + // accept only messages from the proxy if proxy != info.sender { return Err(ContractError::Unauthorized {}); } @@ -107,6 +123,7 @@ where let mut info = info; match deps.api.addr_validate(&msg.collection) { Ok(collection_addr) => { + // set collection address as (initial) sender info.sender = collection_addr; Some(self.receive_nft( deps, @@ -117,7 +134,7 @@ where msg.msg, )) } - Err(_) => None, + Err(err) => Some(Err(ContractError::Std(err))), } }) } From f8c42c069446c88eeaa79e56db879862f95bd22e Mon Sep 17 00:00:00 2001 From: mr-t Date: Sun, 31 Dec 2023 13:41:38 +0100 Subject: [PATCH 32/40] update libs --- Cargo.lock | 22 ++++++++++-------- external-wasms/cw721_incoming_proxy.wasm | Bin 181642 -> 181642 bytes .../cw721_outgoing_proxy_rate_limit.wasm | Bin 177902 -> 191092 bytes 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2891c68d..f71ce152 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,7 +234,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" dependencies = [ "cosmwasm-std", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "cw721-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -534,20 +534,22 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "cw721-outgoing-proxy-derive", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", "thiserror", ] [[package]] name = "cw721-outgoing-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -558,7 +560,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-rate-limit" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#4112564d235ee7c8f5bd0ffb33226bd40e9717d3" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -838,7 +840,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#88ae912c5defd352c54dfa62b0743843dc2ba8f3" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#b930ded200d6db49162b6c3b15b37f6705eeaa34" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -932,9 +934,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "a293318316cf6478ec1ad2a21c49390a8d5b5eae9fab736467d93fbc0edc29c5" dependencies = [ "unicode-ident", ] diff --git a/external-wasms/cw721_incoming_proxy.wasm b/external-wasms/cw721_incoming_proxy.wasm index 6c9ee13867e84b823a5f13dcdf9cb33146b76dac..3e1719d369d41e0bb5dfa25c635602ff8ac6c379 100644 GIT binary patch delta 1064 zcmYLHZ)_A*5bwIAw*)KE#yh>9+2q~Z!^+A z`3x{LCA`Y)v~YpeR9z0>?>V{bSm0_#cu#IFST_znb@q$OP@mwUYAmA6F*+(*VzrLKsis}R1A=k+ja zb435yWl!|fx~z#FnXK;(xkEV7Sjx*cB$VY19H2%oCZ%b`m1BrBQ(*tkt73Gr$SKUE zSKeCA%H(WDcD3cKvr;6xlHJi)&-&UMW8MDPFA}rBx;;=++j!)4kyBg^D*+ma+`{o!&kDvQefS;_v zLFl4A7q|o)T19bbrZonw7|?hPN#_tEnU3kciD>DwA?qgQWB z5>uZ4cc=_nt%GHdhF1Gt8AL)z^7cay!=%Hp?>4|afS7e_13U;ZyW$Cm_~5!7ZHAYF z_<7d;XeT@>z@k053+g@ieqaBcIM{dM_{C}~ZeX?btbtEim-4vBx@(|ftv0aIx?tdA z);a@gtkZd1Wf@Lg#zfI-G_l^QHPL4cn7B&X($STScO>`4lWnbCd#!?rYpneyhV7Fk HPB;DstVV7< delta 1045 zcmYLHYitx%6z(}QyR+Nf&TPBe?pD~aMX5_xLr4n5HLYEewpQDOYI%f*WJ4RIX}98z z+bm8W`^bMMeW$IwB?*`Gn+Y@AErtn@L|A|ENQsU_?A%XEL)06+Qq<`=`f!5mR5K75vryojbgVV#&Ibj>n8P{=Sw3NG%?vOG-{pB}G@JN;} zgx0RYds$l1a?XkA4E=uB5Qo2{X*9ZvX9DBxb7*%5Fo>gAa zY6;z(u4G-5^fa4#d!_=|BP-dL*+Ir~KQiQqx)sXkL-iZO>bYS?qo0g?B(Nkn8f39$ z^lKJvr$P*=AoJX{hi9OBYW#hYrq}ggXk;503Y#nu<%zwN96QjHk=TEh{ffmZ%n@mIGmzK zXZE7;M=kf7(D@E%eSKQDn;V{~j)eChb5m^h1;Wv=~BO z{57LLzZxbDj{aK}JO$XKJzNjZ!6vhT+T9#JqX{`|)5de?*QT=glIG2!sGZH?3XSHlRIAQmjrN+#?!BU-L$jzD zu566O@vhx*xh)))lkc?0!{NGELTglUnf9TIHvP1U(>4DA Dd&+7_ diff --git a/external-wasms/cw721_outgoing_proxy_rate_limit.wasm b/external-wasms/cw721_outgoing_proxy_rate_limit.wasm index 641d2402df3afa798fd7713b63b0ff83bd199d61..b670deda2c50f578c9642154c1789f6c33bc962b 100644 GIT binary patch delta 77764 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 T+aR28@bd)DQ}G+!&HldtD8z)A delta 67550 zcmb?^3t$!1ng5)b`%3OjGC%@(!p!BB0Fj57@DO3BK~xm+QN>b~im$|~ptZK5H&j#* z6mZZ%Ma7B*x2X6=MTpk6)MCZ1wREMGuDZpRw%EG6ZngFQ`+aBT-kSin-Th0OnK^Uj zobP<^^PTUU`_Y@}Km5LQ<*<~>8Rx}vx!kHT532a8w??SAZ>iVt_YKu&-jn9zW|^`Q zNy{oJu@wHZ_%DI~rBX`8`Ohj*mSH3kR?;xy@}FT?C^1Y^C6r3?vogyxQPL}BsYC+x z@E@A7@MI}}mf7cQ1C1GIN9i}ouq)P5u{ioqm7<4qDxJ0xMvS#kJI-4C&q|=fcyD%> zP-qJOE03c_92fsZ^XyT5`GEl-`o)s!3Uw#`#Vuv@O4L|6<#l#;8R?wi-MaK8xvpI5 zPq!L!XCyDU=7RITcGU&O7vl>qxZ=`p7-z=kf9-+=-!RTf&As%}%g>*SSNEyXc^BlL z?pOAL3+8|Ak_8uBdG3{0&F#44vWtxMs#kH@f{XZBap5IbU9e#8RhKV7VO757`Iq~D zwMwip#(MvNRb9Pa^||CS)Vpx*`4^mf^#u#AyyWuB&K-xBPOKsKYmC@a={wZeW#*B) z)G;-6-m$e)zcAu)HEErCPz@RSfcmz2NPS0bP#e|5>R;4%)h6|bntc4U3D236rnen8 ze(c=yzko9R!8KP-YG0(Ty8LTbPkKUqW9*Y^xp}8K_BAzj((CFcYNz^@nl$}q>Mb?-4Ltn2 zdRM)v_Nrg2Nk3JS{;EDvpQ`bb{-P#-%Uo>UZQfK=2Q`GEO?`EBz-bG><+ z`Mg>B+h3JDZu-Ymyrf>d-9AzMz@K5C;IB?BR44kqk`t4EQ%2hUO!=oJm!M=%a$=vb z#7H}q=d=$p(tkAljV0^M`0@S;rL}4AFUz_NFK)kR*7}P|PpSoTZ) zuS!q!8<7Z_}E*LG4b=zDGGpFV*hEon)gqD2t~?bAO%G-S5dyGg(#qSzLcM zvizcHTUT@$_Cuzl0L1( z?(+APA6N4xn(|ul=^u@DZ~00*?86^BF#Xl`_tlI3r}1h2x?TzOBY#7$&(zEQhTix1 z_vvU|WF&R$jK6#gSH zR}dInuW|vc_p!gY^3>s<8toyPEYEIdvC-aa7!!au3w4cev>3hQ&b-Q3Rp<6z2HX|n zb;Tn88>J`vT~#H?9n#?s{asbnx#G?XT}$UJ=2>ho-_ac0v%2N&21+)PHYq1%SIB2& z#B$;7X1+~0$?&a=$78=36w{YB4b&?@g5HTgPfLugWG{ zt@8j(velfCG0CW`V0pzz*(D_hV`Wx|l@@$TT6gPj^gqxczX2@Mg-@pY{rcVBdnJa~ zWEibLz5=6rYZm!0^qY}$%qFY)6w*#m5wo?d$delf8%$}>szLn5XfZ1tHC45m8R6_~ z0+&p?7cwx|z=SM13HvFNxT6HPCgdr`+e}tuqLNH(;%!`*Sb0ZI=@?{Sj9$pQ%A4Gs zb&a%);R=CpN(T|>e^_06q~Ld)#%~7r^$a(TmyqBX(mKVVcmvIpERJ-{cQF3Os!G<{r{S}s5xx7`+E$a(cGc3 zaj)vQG7I04a|!nPFO1dz@0Eh5{a=4!1jbQ*?3Z;hS+gAVzJBav6hC|H2v?8+3Y6PV zqt#~PSV+3*jf0kg#>%EqH`cZ~EwzAeK0nwt6W{*1Ekw;epe7B}44XE+L959KHA$kT z#G_s%zWf!_hSqhfLDa+w@86h4)cj^z6HwFZxR#o*ZiA;>D^o@E=)Si4=N&f|=(*## zmg=p7icT||Bq|8HqoI8FxK=&nPE*4-Wcs+80hBx4jP2Ce1Dx8nGQ+W91in6fn|j`F zIsQDg+YgRE3UIu3{22B8?I(=F?dTKkfrWbQgo4egIPo0d;Ib2suMS72fh=X~(1}FT z>n9E~e|MAr$%z-6AKv6&Fk>zn`r(Wg^zyeE&A1krw)J1PB{*6pK;0}DXH{-cS@#`U-fBo%Gw;OZNUQIqYU^+&pO}y<&FLovuaEE z9s*>x4+>UYt45n!Zuj?(ZA_m8t{+7s{bSQ#@j_p7oARf;=xR;@3KUr4loqf4;TvBv zU>$0qRg^tD8*3{|fas8LR(Pc44wx(>?I}Fc`lBPqzkSwy728d421uEjYD_J)xBHV% zU7@!7ub=w7xz+cVoi@(xgcbFUWD^qJp!t=b-px>=1#fx8LMcHbT6scpfi@2DD%!}1^(05f>?W;L-KbSa~x z11NsJYh10aQ_bh6gKKVq`fV8eu--F9~nOd&5m9QKlVBQ+zH1H*@niO zjZvPO-&U65?P%{4NYdCsG(@{!wK_>+w{+yI33OHzeNq##gNM+konHU zM)h`Z;xgr`t-)89q2Ke4J{lGGE>lavb>~i~dN#LQH7I}fF(b{cRV1Q1$$#>gF$Ef# zLZf(F8FiKe(L%Foa{sc(o3WtbpYlgcp3_36hyg!?j0!q&LPAqW80q}j!8-pre_`!F zt&cwjcb5Q-->n@xSd_~FDbPCTBjskm36yqdp#v%lO!~39ABU<9#VmNcjykNazByEF zkaMEp^!k|%bUCPv%`y`z+Jbp^Qr??X(Ui=t`ssDuYEVzb3-1RuP}*iSv_cOpZJ5*? z)@{hxnA_CT*8%7M25mDDBL#=wcn?e=39T?ClSsIF|{nu*p zfywy%L4Q!yA2T3StDP3SRt)Eo0kcxthe4f}2YjjUFxZ&_FfVk50nAm-l=`jWx3Pmx zD_ibWO@ko*fWs)eyWZvn@4)v{pR;#3W!x20@QNizFa|FJ~8;@80B38Q2#v zo;k1uO8d5fU#|?u(~zkkLeYb_d68c;XomUDP5woLF61Y#54sLKd(z;E7~;~wCse*e z;>GNS3>*hjJbDc3H-pC{Hqg4H{0D~D_~VA0gKvT%6Z;5vI*A2t(&^P!))$=iw*USR zkzp~jU1qztY>|J&(6MTZfBw*(A5_W*j}Lv-+|cP?*Vqrh-_bZ2!+)VMtGSiBHKOfK z<@N$hU7A~Il>wUBbd^Tb78JAKTTQ2;fuA)MaVyDNK5T01e{pQ!Xz=QB@F(ClDH!2$ zFG&hoUia5&rO{xuFHgKF7jT|y)+}`T{YS`GCJe$VIrU`(l-}d+2A^rU4 zhnM*?htDwo>n8u+;jIL3_>I8#mqv^R9&a5%DR^PT^r}#BLfo@~B$}^ocJal8=B8rt zd%?e|c_50{G`DC((eH{7wVK1yo)?&OrAE}Bn-_*06(Z`|BThyGuO1P~frb}qXynw^ zzY0L`0PWQQsUn-u&xL{?j8zf|Bo#9EZRCN7bO0aidPG zfh5GdQ61iAYQ7t@C^B@W;;;s5M~#Hc>>SmMzkeCEoJ}klJrbzdGWrYn_|wrp#oyP* z+y*qAbL5la`lj2QzHPLjX>{w3?J&Q8qkr32R~XXtR$8=|A6YUN3m&*tRoB2W*&W%q z7^YNvHfF+gr=K13e=_UX;L^2bc`~U*G+4COJfb4yBpz9qO**Nw%U~^I!M3&LkYkcl zORrxDUWfYb$eMUT3yX-1s&oXvOzHe;gy;^}oq{x9r?fBhM5{6XbCe4{`5 zjGFB1tO9~OI8EAPfGOon4aTa)j5&t4_-6moGmb2L(E9g2Sa)+5CPDaA&-0Rkl=Ld! zeX$>`r?*Kp=B=-GYMTATRyVcrR?UpTudh&b{s~*_^CkXeTfdUp%-5!UvOj-YEnF

JU?B=(!r1`BT%)XFsEPyrVMROonYIBfj` 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 Date: Sun, 31 Dec 2023 14:51:08 +0100 Subject: [PATCH 33/40] update lib --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index f71ce152..86c4681c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#b930ded200d6db49162b6c3b15b37f6705eeaa34" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#f8c42c069446c88eeaa79e56db879862f95bd22e" dependencies = [ "cosmwasm-schema", "cosmwasm-std", From 565f56e5b236a8b1a74397f4cde1034ee6fef8d8 Mon Sep 17 00:00:00 2001 From: mr-t Date: Mon, 1 Jan 2024 21:52:27 +0100 Subject: [PATCH 34/40] update wasm files for tests --- external-wasms/cw721_incoming_proxy.wasm | Bin 181642 -> 190431 bytes .../cw721_outgoing_proxy_rate_limit.wasm | Bin 191092 -> 191092 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/external-wasms/cw721_incoming_proxy.wasm b/external-wasms/cw721_incoming_proxy.wasm index 3e1719d369d41e0bb5dfa25c635602ff8ac6c379..38a79605266ca9c525c99a91b2436666d8f65033 100644 GIT binary patch delta 63826 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 Q!EpHqD-m`hyw~6RKi!*+_5c6? diff --git a/external-wasms/cw721_outgoing_proxy_rate_limit.wasm b/external-wasms/cw721_outgoing_proxy_rate_limit.wasm index b670deda2c50f578c9642154c1789f6c33bc962b..803f471f78088040928aa4bc15154c83d8b95e15 100644 GIT binary patch delta 1652 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 Tle0`tqFEd#)1_^k{66bn%iAeD From d796fc947c48c88777f24fc76fcfd3667749ffa6 Mon Sep 17 00:00:00 2001 From: mr-t Date: Mon, 1 Jan 2024 21:54:03 +0100 Subject: [PATCH 35/40] update cw721-proxy --- Cargo.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86c4681c..8f418258 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,7 +234,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" dependencies = [ "cosmwasm-std", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -514,8 +514,8 @@ dependencies = [ [[package]] name = "cw721-incoming-proxy" -version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -534,7 +534,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -549,7 +549,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -559,8 +559,8 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-rate-limit" -version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#ef620cbea1d1e5dbb6695d6388b4893872508381" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#f8c42c069446c88eeaa79e56db879862f95bd22e" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#565f56e5b236a8b1a74397f4cde1034ee6fef8d8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -934,9 +934,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a293318316cf6478ec1ad2a21c49390a8d5b5eae9fab736467d93fbc0edc29c5" +checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1" dependencies = [ "unicode-ident", ] @@ -961,14 +961,14 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.45", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" dependencies = [ "proc-macro2", ] @@ -1074,7 +1074,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.45", ] [[package]] @@ -1090,9 +1090,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" dependencies = [ "itoa", "ryu", @@ -1244,9 +1244,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.43" +version = "2.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "0eae3c679c56dc214320b67a1bc04ef3dfbd6411f6443974b5e4893231298e66" dependencies = [ "proc-macro2", "quote", @@ -1270,7 +1270,7 @@ checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.45", ] [[package]] From 8bcfc385c3365ff67cb5c1a0d7e92b21773c8adb Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 2 Jan 2024 00:01:40 +0100 Subject: [PATCH 36/40] update incoming wasm --- external-wasms/cw721_incoming_proxy.wasm | Bin 190431 -> 190347 bytes ts-relayer-tests/src/ics721.spec.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/external-wasms/cw721_incoming_proxy.wasm b/external-wasms/cw721_incoming_proxy.wasm index 38a79605266ca9c525c99a91b2436666d8f65033..96a03f967a881683d9375a0d8e0784bd3db5fc22 100644 GIT binary patch delta 18339 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 delta 18574 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


&M{aV5s)*k#-$Wvh&t*jf%^md)V` zn|1CG&V zD&aIvt{}0D&!3xZ%tGyPcuites&5{O`m6!7?=~TC-DaAuz%LYZA&A<;>D+w2Hk3Q3 zIX#{wU3Nux`S+nb3|+o_7>{dY?Ty2%R(>#y#|9#O8;W+wwPv^Bc%daXwWe3zxFm#c zZSAQTzLwoHoYTSsZ+ZXE!?_I|(McmX7w*x21h>wXYu(7*F5XYTx}G6&w~Nn&Ld#u> zM(}xIHNkj{(zX%20_8_t0c|_=tSflT81X-aN32#P@SBN&6L2)R170Bo19+&0J&R04 z=TTBKGl0uZYa_30PCgme}MPxQwo`Hy?FC4|= z!f|Z%DDGfMSXcf|ywdwdaod*G-7~JYr&>|Vnw!X6c&>!U?b5xkG@C8OsqA3s40#ZIJ#RFtMt0af+Ooru(cHURy%hPgjcEGM_N<0wF&m#B!!yjI z@?D2NQcR$#agdXO)a&kJxkd76`9AJ21cEUOjM!5aL*F$Pv$b4*IhNC7EA9omeC0S4 z+a#ZYi}EdkY|;vh*lPLS92zl>+f&gxX?Gd^h?GFJ%t1B?QtluEBVv_;R5%=g5wR_T zY;rgPBVwDQIUZac*HaLWHuQa0aT1)k{3^?dw_e3#@}kEG&tb6XaDrqu{AD=qnf^!L z=@goIHLoOIiqrkI+#mD#vTL~=R_9x<<&OF5us}(umFH1$2ql4!2`^u~YPn6vB$F>y z1WTBNlu2WG1m^OHpnR#N>#HrRt#ZhCJh)i@_qE*m>dG&KBm0F_b@Jupm1;n?PT{Co zwo?DQI@DrKWu$P>&~`((AYwJ!~KUhW61|u!7%W8t;3T+Gdz{A~d7Jw^{TZG3X zn{E9vFj!tKE%qqE)RS)D)?FRrLlF*+jz#6EBH_h^ZC|{XLcLz`@8hADZs3QBKGB0F zaQD_<{9Y|DC0JGCBk%~T?}ZQ#Yv3GoN|#RHzVy1@GlA3THGOmfuWjN@wDa7k+ zGzCvPuvnV#mq6fay#7}){r9JHp6^tNz3V|Uk7(}#iSY@_Fzc`8v1G`-x=dQ>1dU{7S89pXjka_`Fsa)$sc;s z0vuETcQ4>zvz=$qAGr)fwM+ldXBKcP;bku5VZ8KDJ!K*6Q>#}kB9eHPVc zQ#IYeEmIqq2^O=3!_2*dbCN3H`rQoU0z>8*o{B%CC*1+V{Qs=&+*IrBQGzOy>F7ME z5=?LU8y|$7@4b_+(>x9_`7(waC+pxrd0?F6OoZe_xDKDqwJljSpVJLj^B& z@GVRD62bpi!kqy_o$ux8M75zum+}XMmo)|V;h+up=>7bP8-Zxlaw`zwpTM-xMa!|y zH6~rMf^WgzY10ZTYT3de2%qNU4PsEs6%kvIfQi8d#PqNCAY+?Qw zSrS?R$b35?yqmnEcC9SKt9FkK{rMcbEQCb3Ppj<*(vNlv4H+jcuB3we%1-)JU3ouC}Kd#&-&hSUL;mYSYsQ% z%Niap_E92 z?MiRx=Igj^=03QU9VaCi#>l@`gQ>8Ts5kY
N#s!nLpAn3=x*s~+5{&^iw!)fe> zCpZgr-0=jzWXF^#QK2Oz@RyKM^CUmS{%s``C)@UF!}~-=Xy()0j6I{~70g~Ze9kSp z*#-our`992o45g~-@Df1_1mZGxp%0?2HqVLH)qDY**6#5sQ-A5$LZ0}^K&#z(+m7w zQd&a5xXdt&)%Ydgm!>~^f!o9vgPaKTAx)LsZOA$YeE~29kAmkfOFzH#2neDtuZG0b6(oj!5i+{visc38x&!*uHCYogEu z$hFdkUgWm4RMSg5HKh`io55*`UlJnKqZrohtczdbEEUa*2S1Es?_`-V8jt383iI`$ zm-vGCa(}?+BE@yEif_YFa&;AVij(_W?>%-+`r9h5No|)HFor^|9J-nbY!<+_Xs!Ne zGe3*{$sI3qo7_tRwnK~tB*>g?l=H!pQ68<|dzm}t5jt z0Q4*T7(JkShLHGpAarAhZzh_m-`>JHsWLfWOoXZo{KPdX_0(6nb9%290gDu7_Xf){ zKG;lJAKa^+&|-zw1Ck^^ri-k34rs^ zpXL^>>)zli6Dq)0Hs0q=zPyu>9*_kuBEKmjZ$t}ouk9pZf%_ADybbGE@D`f0rl$C|5kXdCxWUjSwvY8yL!>hu}6 zO*ac>&z>EDcI%9M zaUFMiUHJk2(bOJLM&S|yyG7y4@hy`$EH4W~w7lS%QT#Pc_=4vcMo~n85F|c_6+VgY=nATUcZlK( zF5VQDe+A!S%rIVwZ;8`k{2;#DMBzs)yr@Co`z8Ya)dc@{6WopY9Iepb1W###rvvvx zN4P-&!7qs-#5EE41H9-0|7?OE597M!9=^9neNMnw0Fta0;^txeDSS)Z3geIBTMSjN zcke+cE!REva?fi{cZ4%XNiD{=%%O0parl-sD2!i&Z*i_LJ{;dNTw%N`zQrHv^&5M+ zsAyTIfH58DO8lfxVSE+72RFe7MBy6W(el#xXuP}${&*97t&QIlsqkJ9dg2#ufZ*+; z@TK_f+XU|%g%7~D_;tAaKzz%*Sf*Qj#8Z(Y`TIxQA?fNa0jrq>fMVrFGJnOnhY0bWCq;Kv9w1vmVDj0&~VB)7S@k9Ozw4!#JYb@8`}j?yljW;4;#>>Sy-z4e@J1 zlhNL+{WVx~YIJT57REDrRt>ie_UUG?3Sv6xTo@mPC@vGCkAAs^ze~8HyB%KL-Ssn{ z@I~>6n?gLoWRo zt#h3?*Hzr>7&xfXs6`3+uP*{#_}l1dYcYE2akYGHtA4;u$czUR`}GA9mMzx1YjN25 zRG;@5{{qnQAa@S#gK`%Zpz7D9A{Z)?w>PgG9r<`8#Ip3j=JVP;V{G<01I#7qB#V&n$9ghf( z>TT~T#{) => { wasmCw721IncomingProxyId, { origin: wasmIcs721, - source_channels: [channelInfo.channel.src.channelId], + channels: [channelInfo.channel.src.channelId], }, "label incoming proxy" ); From 3ec3ed5a233de9f2555f0b1b041b99c756c336f2 Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 2 Jan 2024 00:20:58 +0100 Subject: [PATCH 37/40] update incoming proxy --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f418258..3f7ff337 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,7 +234,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-std", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "cw721-incoming-proxy" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -534,7 +534,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -549,7 +549,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-rate-limit" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#f82d3d8f8240960846d22a69853d1efd31f49957" +source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#565f56e5b236a8b1a74397f4cde1034ee6fef8d8" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#8bcfc385c3365ff67cb5c1a0d7e92b21773c8adb" dependencies = [ "cosmwasm-schema", "cosmwasm-std", From a2d4965572485c1085b4ece2cbb9d55a896b5b74 Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 2 Jan 2024 12:14:39 +0100 Subject: [PATCH 38/40] use tag cw-721proxy v0.1.0 --- Cargo.lock | 58 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 4 ++-- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f7ff337..51d2ea92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca87830a3e3fb156dc96cfbd31cb620265dd053be734723f22b760d6cc3c3051" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "base16ct" @@ -234,7 +234,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "cw-incoming-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-std", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "cw721-incoming-proxy" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -534,7 +534,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -549,7 +549,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-derive" version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "cw721-outgoing-proxy-rate-limit" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw721-proxy.git#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#8bcfc385c3365ff67cb5c1a0d7e92b21773c8adb" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#3ec3ed5a233de9f2555f0b1b041b99c756c336f2" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -934,9 +934,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.73" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ "unicode-ident", ] @@ -961,14 +961,14 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.46", ] [[package]] name = "quote" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1050,9 +1050,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" dependencies = [ "serde_derive", ] @@ -1068,13 +1068,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.46", ] [[package]] @@ -1090,9 +1090,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.109" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" +checksum = "6fbd975230bada99c8bb618e0c365c2eefa219158d5c6c29610fd09ff1833257" dependencies = [ "itoa", "ryu", @@ -1244,9 +1244,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.45" +version = "2.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eae3c679c56dc214320b67a1bc04ef3dfbd6411f6443974b5e4893231298e66" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" dependencies = [ "proc-macro2", "quote", @@ -1255,22 +1255,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.45", + "syn 2.0.46", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 95712bbb..7715ff12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,8 +20,8 @@ cw721 = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main"} # TODO s cw721-016 = { version = "0.16.0", package = "cw721" } cw721-base = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main"} # TODO switch to version 0.18.1/0.19.0, once released cw721-base-016 = { version = "0.16.0", package = "cw721-base" } -cw721-incoming-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git" } -cw721-outgoing-proxy-rate-limit = { git = "https://github.com/arkprotocol/cw721-proxy.git" } +cw721-incoming-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.1.0" } +cw721-outgoing-proxy-rate-limit = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.1.0" } cw-multi-test = { version = "^0.20", features = ["cosmwasm_1_2"] } cw-utils = "^1.0" sha2 = "^0.10" From 1fadd3b4869b7cdcbc54128d34ad86b2fdfed0b2 Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 2 Jan 2024 15:24:25 +0100 Subject: [PATCH 39/40] rename cw721 -> cw-ics721 --- Cargo.lock | 157 +++++++++--------- Cargo.toml | 5 +- README.md | 2 +- contracts/sg-ics721/Cargo.toml | 4 +- .../src/testing/integration_tests.rs | 28 ++-- packages/ics721/Cargo.toml | 4 +- packages/ics721/src/execute.rs | 8 +- packages/ics721/src/helpers.rs | 2 +- .../ics721/src/testing/integration_tests.rs | 28 ++-- 9 files changed, 122 insertions(+), 116 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51d2ea92..b32013ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,13 +232,13 @@ dependencies = [ ] [[package]] -name = "cw-incoming-proxy" -version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +name = "cw-ics721-incoming-proxy" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-incoming-proxy-derive", + "cw-ics721-incoming-proxy-derive", "cw-paginate-storage", "cw-storage-plus 1.2.0", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", @@ -248,17 +248,82 @@ dependencies = [ ] [[package]] -name = "cw-incoming-proxy-derive" -version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +name = "cw-ics721-incoming-proxy-base" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ics721-incoming-proxy", + "cw-ics721-incoming-proxy-derive", + "cw-ics721-outgoing-proxy", + "cw-ics721-outgoing-proxy-derive", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", + "serde", + "thiserror", +] + +[[package]] +name = "cw-ics721-incoming-proxy-derive" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cw-ics721-outgoing-proxy" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" dependencies = [ + "cosmwasm-schema", "cosmwasm-std", + "cw-ics721-outgoing-proxy-derive", + "cw-storage-plus 1.2.0", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", + "thiserror", +] + +[[package]] +name = "cw-ics721-outgoing-proxy-derive" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +dependencies = [ + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "cw-ics721-outgoing-proxy-rate-limit" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ics721-outgoing-proxy", + "cw-ics721-outgoing-proxy-derive", + "cw-rate-limiter", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", + "serde", + "thiserror", +] + [[package]] name = "cw-multi-test" version = "0.20.0" @@ -329,8 +394,8 @@ dependencies = [ [[package]] name = "cw-rate-limiter" -version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" +version = "0.1.0" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -512,70 +577,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "cw721-incoming-proxy" -version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-incoming-proxy", - "cw-incoming-proxy-derive", - "cw-storage-plus 1.2.0", - "cw2 1.1.2", - "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw721-outgoing-proxy", - "cw721-outgoing-proxy-derive", - "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", - "serde", - "thiserror", -] - -[[package]] -name = "cw721-outgoing-proxy" -version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus 1.2.0", - "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw721-outgoing-proxy-derive", - "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", - "thiserror", -] - -[[package]] -name = "cw721-outgoing-proxy-derive" -version = "0.0.1" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" -dependencies = [ - "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cw721-outgoing-proxy-rate-limit" -version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw721-proxy.git?tag=v0.1.0#07eb53fa4d39a7ef4412ab3bb74b1052b4d376b8" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-rate-limiter", - "cw-storage-plus 1.2.0", - "cw2 1.1.2", - "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cw721-outgoing-proxy", - "cw721-outgoing-proxy-derive", - "ics721-types 0.1.0 (git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy)", - "serde", - "thiserror", -] - [[package]] name = "cw721-tester" version = "0.1.0" @@ -781,6 +782,8 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-cii", + "cw-ics721-incoming-proxy-base", + "cw-ics721-outgoing-proxy-rate-limit", "cw-multi-test", "cw-ownable", "cw-paginate-storage", @@ -792,8 +795,6 @@ dependencies = [ "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "cw721-base 0.16.0", "cw721-base 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", - "cw721-incoming-proxy", - "cw721-outgoing-proxy-rate-limit", "ics721-types 0.1.0", "serde", "sha2 0.10.8", @@ -840,7 +841,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#3ec3ed5a233de9f2555f0b1b041b99c756c336f2" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#a2d4965572485c1085b4ece2cbb9d55a896b5b74" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1108,14 +1109,14 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-cii", + "cw-ics721-incoming-proxy-base", + "cw-ics721-outgoing-proxy-rate-limit", "cw-multi-test", "cw-pause-once", "cw-storage-plus 1.2.0", "cw2 1.1.2", "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "cw721-base 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", - "cw721-incoming-proxy", - "cw721-outgoing-proxy-rate-limit", "ics721", "ics721-types 0.1.0", "sg-std", diff --git a/Cargo.toml b/Cargo.toml index 7715ff12..b4b09abd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,8 +20,9 @@ cw721 = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main"} # TODO s cw721-016 = { version = "0.16.0", package = "cw721" } cw721-base = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main"} # TODO switch to version 0.18.1/0.19.0, once released cw721-base-016 = { version = "0.16.0", package = "cw721-base" } -cw721-incoming-proxy = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.1.0" } -cw721-outgoing-proxy-rate-limit = { git = "https://github.com/arkprotocol/cw721-proxy.git", tag = "v0.1.0" } +cw-ics721-incoming-proxy = { git = "https://github.com/arkprotocol/cw-ics721-proxy.git", tag = "v0.1.0" } +cw-ics721-incoming-proxy-base = { git = "https://github.com/arkprotocol/cw-ics721-proxy.git", tag = "v0.1.0" } +cw-ics721-outgoing-proxy-rate-limit = { git = "https://github.com/arkprotocol/cw-ics721-proxy.git", tag = "v0.1.0" } cw-multi-test = { version = "^0.20", features = ["cosmwasm_1_2"] } cw-utils = "^1.0" sha2 = "^0.10" diff --git a/README.md b/README.md index b51ce829..d4725043 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Pause functionality is designed to allow for quick pauses by a trusted group, wi After a pause, the ICS721 contract will remain paused until governance chooses to unpause it. During the unpause process governance may appoint a new subDAO or reappoint the existing one as pause manager. It is imagined that the admin of this contract will be a chain's community pool, and the pause manager will be a small, active subDAO. This process means that the subDAO may pause the contract in the event of a problem, but may not lock the contract, as in pausing the contract the subDAO burns its ability to do so again. -Filtering is enabled by an optional proxy that the ICS721 contract may be configured to use. If a proxy is configured, the ICS721 contract will only accept NFTs delivered by the proxy address. This proxy interface is very minimal and enables very flexible rate limiting and filtering. Currently, per-collection rate limiting is implemented. Users of this ICS721 contract are encouraged to implement their own filtering regimes and may add them to the [proxy repository](https://github.com/arkprotocol/cw721-proxy) so that others may use them. +Filtering is enabled by an optional proxy that the ICS721 contract may be configured to use. If a proxy is configured, the ICS721 contract will only accept NFTs delivered by the proxy address. This proxy interface is very minimal and enables very flexible rate limiting and filtering. Currently, per-collection rate limiting is implemented. Users of this ICS721 contract are encouraged to implement their own filtering regimes and may add them to the [proxy repository](https://github.com/arkprotocol/cw-ics721-proxy) so that others may use them. ## Failure handling errata diff --git a/contracts/sg-ics721/Cargo.toml b/contracts/sg-ics721/Cargo.toml index cf98d0fa..63ac889c 100644 --- a/contracts/sg-ics721/Cargo.toml +++ b/contracts/sg-ics721/Cargo.toml @@ -31,7 +31,7 @@ cw-multi-test = { workspace = true } cw-pause-once = { workspace = true } cw-storage-plus = { workspace = true } cw721 = { workspace = true} -cw721-incoming-proxy = { workspace = true } -cw721-outgoing-proxy-rate-limit = { workspace = true } +cw-ics721-incoming-proxy-base = { workspace = true } +cw-ics721-outgoing-proxy-rate-limit = { workspace = true } cw721-base = { workspace = true} sha2 = { workspace = true } diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index 31479e74..90cb9fa8 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -288,7 +288,7 @@ impl Test { fn new( outgoing_proxy: bool, incoming_proxy: bool, - source_channels: Option>, + channels: Option>, admin_and_pauser: Option, cw721_code: Box>, ) -> Self { @@ -307,10 +307,12 @@ impl Test { let proxy_id = app.store_code(outgoing_proxy_contract()); Some(ContractInstantiateInfo { code_id: proxy_id, - msg: to_json_binary(&cw721_outgoing_proxy_rate_limit::msg::InstantiateMsg { - rate_limit: cw721_outgoing_proxy_rate_limit::Rate::PerBlock(10), - origin: None, - }) + msg: to_json_binary( + &cw_ics721_outgoing_proxy_rate_limit::msg::InstantiateMsg { + rate_limit: cw_ics721_outgoing_proxy_rate_limit::Rate::PerBlock(10), + origin: None, + }, + ) .unwrap(), admin: Some(Admin::Instantiator {}), label: "outgoing proxy rate limit".to_string(), @@ -324,9 +326,9 @@ impl Test { let proxy_id = app.store_code(incoming_proxy_contract()); Some(ContractInstantiateInfo { code_id: proxy_id, - msg: to_json_binary(&cw721_incoming_proxy::msg::InstantiateMsg { + msg: to_json_binary(&cw_ics721_incoming_proxy_base::msg::InstantiateMsg { origin: None, - source_channels, + channels, }) .unwrap(), admin: Some(Admin::Instantiator {}), @@ -546,18 +548,18 @@ fn ics721_contract() -> Box> { fn incoming_proxy_contract() -> Box> { let contract = ContractWrapper::new( - cw721_incoming_proxy::contract::execute, - cw721_incoming_proxy::contract::instantiate, - cw721_incoming_proxy::contract::query, + cw_ics721_incoming_proxy_base::contract::execute, + cw_ics721_incoming_proxy_base::contract::instantiate, + cw_ics721_incoming_proxy_base::contract::query, ); Box::new(contract) } fn outgoing_proxy_contract() -> Box> { let contract = ContractWrapper::new( - cw721_outgoing_proxy_rate_limit::contract::execute, - cw721_outgoing_proxy_rate_limit::contract::instantiate, - cw721_outgoing_proxy_rate_limit::contract::query, + cw_ics721_outgoing_proxy_rate_limit::contract::execute, + cw_ics721_outgoing_proxy_rate_limit::contract::instantiate, + cw_ics721_outgoing_proxy_rate_limit::contract::query, ); Box::new(contract) } diff --git a/packages/ics721/Cargo.toml b/packages/ics721/Cargo.toml index 9778e9b1..e850a9fb 100644 --- a/packages/ics721/Cargo.toml +++ b/packages/ics721/Cargo.toml @@ -19,7 +19,6 @@ ics721-types = { workspace = true } thiserror = { workspace = true } serde = { workspace = true } cw-paginate-storage = { workspace = true } -cw721-incoming-proxy = { workspace = true } cw-pause-once = { workspace = true } cw-cii = { workspace = true } sha2 = { workspace = true } @@ -27,7 +26,8 @@ zip-optional = { workspace = true } [dev-dependencies] anyhow = { workspace = true } +cw-ics721-incoming-proxy-base = { workspace = true } +cw-ics721-outgoing-proxy-rate-limit = { workspace = true } cw-multi-test = { workspace = true } cw2 = { workspace = true } cw721-016 = { workspace = true } -cw721-outgoing-proxy-rate-limit = { workspace = true } diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 36e403df..9eb345ac 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -119,22 +119,22 @@ where } from_json::(msg.clone()) .ok() - .and_then(|msg| { + .map(|msg| { let mut info = info; match deps.api.addr_validate(&msg.collection) { Ok(collection_addr) => { // set collection address as (initial) sender info.sender = collection_addr; - Some(self.receive_nft( + self.receive_nft( deps, env, info, TokenId::new(token_id), nft_owner, msg.msg, - )) + ) } - Err(err) => Some(Err(ContractError::Std(err))), + Err(err) => Err(ContractError::Std(err)), } }) } diff --git a/packages/ics721/src/helpers.rs b/packages/ics721/src/helpers.rs index 3d6dace1..f2d83586 100644 --- a/packages/ics721/src/helpers.rs +++ b/packages/ics721/src/helpers.rs @@ -69,7 +69,7 @@ pub(crate) fn ack_callback_msg( /// If there is an incoming proxy, let proxy validate the packet, in case it fails, we fail the transfer /// This proxy for example whitelist channels that can send to this contract: -/// https://github.com/arkprotocol/cw721-proxy/tree/main/contracts/cw721-incoming-proxy +/// https://github.com/arkprotocol/cw-ics721-proxy/tree/main/contracts/cw-ics721-incoming-proxy-base pub(crate) fn get_incoming_proxy_msg( storage: &dyn Storage, packet: IbcPacket, diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 4a1e4a34..f6814f2c 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -289,7 +289,7 @@ impl Test { fn new( outgoing_proxy: bool, incoming_proxy: bool, - source_channels: Option>, + channels: Option>, admin_and_pauser: Option, cw721_code: Box>, is_cw721_018: bool, @@ -309,10 +309,12 @@ impl Test { let proxy_id = app.store_code(outgoing_proxy_contract()); Some(ContractInstantiateInfo { code_id: proxy_id, - msg: to_json_binary(&cw721_outgoing_proxy_rate_limit::msg::InstantiateMsg { - rate_limit: cw721_outgoing_proxy_rate_limit::Rate::PerBlock(10), - origin: None, - }) + msg: to_json_binary( + &cw_ics721_outgoing_proxy_rate_limit::msg::InstantiateMsg { + rate_limit: cw_ics721_outgoing_proxy_rate_limit::Rate::PerBlock(10), + origin: None, + }, + ) .unwrap(), admin: Some(Admin::Instantiator {}), label: "outgoing proxy rate limit".to_string(), @@ -326,9 +328,9 @@ impl Test { let proxy_id = app.store_code(incoming_proxy_contract()); Some(ContractInstantiateInfo { code_id: proxy_id, - msg: to_json_binary(&cw721_incoming_proxy::msg::InstantiateMsg { + msg: to_json_binary(&cw_ics721_incoming_proxy_base::msg::InstantiateMsg { origin: None, - source_channels, + channels, }) .unwrap(), admin: Some(Admin::Instantiator {}), @@ -550,18 +552,18 @@ fn ics721_contract() -> Box> { fn incoming_proxy_contract() -> Box> { let contract = ContractWrapper::new( - cw721_incoming_proxy::contract::execute, - cw721_incoming_proxy::contract::instantiate, - cw721_incoming_proxy::contract::query, + cw_ics721_incoming_proxy_base::contract::execute, + cw_ics721_incoming_proxy_base::contract::instantiate, + cw_ics721_incoming_proxy_base::contract::query, ); Box::new(contract) } fn outgoing_proxy_contract() -> Box> { let contract = ContractWrapper::new( - cw721_outgoing_proxy_rate_limit::contract::execute, - cw721_outgoing_proxy_rate_limit::contract::instantiate, - cw721_outgoing_proxy_rate_limit::contract::query, + cw_ics721_outgoing_proxy_rate_limit::contract::execute, + cw_ics721_outgoing_proxy_rate_limit::contract::instantiate, + cw_ics721_outgoing_proxy_rate_limit::contract::query, ); Box::new(contract) } From 0b4fd68c7aafd650bb693081e6ebcfbeebed05e2 Mon Sep 17 00:00:00 2001 From: mr-t Date: Tue, 2 Jan 2024 21:01:11 +0100 Subject: [PATCH 40/40] cw-ics721-proxy: update lib --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b32013ef..2d1f648f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,7 +234,7 @@ dependencies = [ [[package]] name = "cw-ics721-incoming-proxy" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#cc1c156b1c0d2941c62b4291444674baf1ec855b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -250,7 +250,7 @@ dependencies = [ [[package]] name = "cw-ics721-incoming-proxy-base" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#cc1c156b1c0d2941c62b4291444674baf1ec855b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -269,7 +269,7 @@ dependencies = [ [[package]] name = "cw-ics721-incoming-proxy-derive" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#cc1c156b1c0d2941c62b4291444674baf1ec855b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -282,7 +282,7 @@ dependencies = [ [[package]] name = "cw-ics721-outgoing-proxy" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#cc1c156b1c0d2941c62b4291444674baf1ec855b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -297,7 +297,7 @@ dependencies = [ [[package]] name = "cw-ics721-outgoing-proxy-derive" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#cc1c156b1c0d2941c62b4291444674baf1ec855b" dependencies = [ "cw721 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2", @@ -308,7 +308,7 @@ dependencies = [ [[package]] name = "cw-ics721-outgoing-proxy-rate-limit" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#cc1c156b1c0d2941c62b4291444674baf1ec855b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -395,7 +395,7 @@ dependencies = [ [[package]] name = "cw-rate-limiter" version = "0.1.0" -source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#4d6e3b0e168305044db00176494a28b318ae8dfe" +source = "git+https://github.com/arkprotocol/cw-ics721-proxy.git?tag=v0.1.0#cc1c156b1c0d2941c62b4291444674baf1ec855b" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -841,7 +841,7 @@ dependencies = [ [[package]] name = "ics721-types" version = "0.1.0" -source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#a2d4965572485c1085b4ece2cbb9d55a896b5b74" +source = "git+https://github.com/arkprotocol/ark-cw-ics721?branch=incoming_proxy#1fadd3b4869b7cdcbc54128d34ad86b2fdfed0b2" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1045,9 +1045,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde"