From dd6d7882e0088054958063180dd6e3253be9afc3 Mon Sep 17 00:00:00 2001 From: mr-t Date: Fri, 31 May 2024 20:39:01 +0200 Subject: [PATCH 01/18] new GetNftContractByInstantiate2 --- contracts/ics721-base/src/lib.rs | 2 +- contracts/sg-ics721/src/lib.rs | 2 +- .../src/testing/integration_tests.rs | 2 +- packages/ics721/src/ibc_packet_receive.rs | 2 +- packages/ics721/src/msg.rs | 6 ++ packages/ics721/src/query.rs | 96 ++++++++++++------- .../ics721/src/testing/integration_tests.rs | 2 +- 7 files changed, 74 insertions(+), 38 deletions(-) diff --git a/contracts/ics721-base/src/lib.rs b/contracts/ics721-base/src/lib.rs index 5d699ced..f10b7a68 100644 --- a/contracts/ics721-base/src/lib.rs +++ b/contracts/ics721-base/src/lib.rs @@ -45,7 +45,7 @@ pub fn execute( } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { Ics721Contract::default().query(deps, env, msg) } diff --git a/contracts/sg-ics721/src/lib.rs b/contracts/sg-ics721/src/lib.rs index b57043e4..30b0acf2 100644 --- a/contracts/sg-ics721/src/lib.rs +++ b/contracts/sg-ics721/src/lib.rs @@ -45,7 +45,7 @@ pub fn execute( } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { SgIcs721Contract::default().query(deps, env, msg) } diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index a6bdc3f7..49cf3b00 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -103,7 +103,7 @@ fn execute( SgIcs721Contract::default().execute(deps, env, info, msg) } -fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { SgIcs721Contract::default().query(deps, env, msg) } diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 5aff2200..223944e3 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -233,7 +233,7 @@ fn create_callback_msg( .map_err(|_| ContractError::NoNftContractForClassId(local_class_id.to_string())) } else { // If its a creation action, we can use the instantiate2 function to get the nft contract - // we don't care of the contract is instantiated yet or not, as later submessage will instantiate it if its not. + // we don't care if the contract is instantiated yet or not, as later submessage will instantiate it if its not. // The reason we use instantiate2 here is because we don't know if it was already instantiated or not. let cw721_code_id = CW721_CODE_ID.load(deps.storage)?; diff --git a/packages/ics721/src/msg.rs b/packages/ics721/src/msg.rs index e2f58ebf..a70cf8df 100644 --- a/packages/ics721/src/msg.rs +++ b/packages/ics721/src/msg.rs @@ -125,6 +125,12 @@ pub enum QueryMsg { #[returns(Option<::cosmwasm_std::Addr>)] NftContract { class_id: String }, + #[returns(Option<::cosmwasm_std::Addr>)] + GetNftContractByInstantiate2 { + class_id: String, + cw721_code_id: Option, + }, + /// Gets the class level metadata URI for the provided /// class_id. If there is no metadata, returns None. Returns /// `Option`. diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index afafc25a..4881ddad 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -1,57 +1,65 @@ use cosmwasm_std::{to_json_binary, Addr, Binary, Deps, Env, Order, StdError, StdResult, Storage}; use cw_storage_plus::{Bound, Map}; +use sha2::{Digest, Sha256}; use crate::{ + helpers::get_instantiate2_address, msg::QueryMsg, state::{ UniversalAllNftInfoResponse, ADMIN_USED_FOR_CW721, CLASS_ID_AND_NFT_CONTRACT_INFO, CLASS_ID_TO_CLASS, CONTRACT_ADDR_LENGTH, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA, }, + ContractError, }; use ics721_types::token_types::{Class, ClassId, ClassToken, Token, TokenId}; pub trait Ics721Query { - fn query(&self, deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + fn query(&self, deps: Deps, env: Env, msg: QueryMsg) -> Result { match msg { - QueryMsg::ClassId { contract } => { - to_json_binary(&query_class_id_for_nft_contract(deps, contract)?) - } - QueryMsg::NftContract { class_id } => { - to_json_binary(&query_nft_contract_for_class_id(deps.storage, class_id)?) - } + QueryMsg::ClassId { contract } => Ok(to_json_binary( + &query_class_id_for_nft_contract(deps, contract)?, + )?), + QueryMsg::NftContract { class_id } => Ok(to_json_binary( + &query_nft_contract_for_class_id(deps.storage, class_id)?, + )?), + QueryMsg::GetNftContractByInstantiate2 { + class_id, + cw721_code_id, + } => Ok(to_json_binary(&query_get_nft_contract_for_class_id( + deps, + &env, + class_id, + cw721_code_id, + )?)?), QueryMsg::ClassMetadata { class_id } => { - to_json_binary(&query_class_metadata(deps, class_id)?) - } - QueryMsg::TokenMetadata { class_id, token_id } => { - to_json_binary(&query_token_metadata(deps, class_id, token_id)?) + Ok(to_json_binary(&query_class_metadata(deps, class_id)?)?) } + QueryMsg::TokenMetadata { class_id, token_id } => Ok(to_json_binary( + &query_token_metadata(deps, class_id, token_id)?, + )?), QueryMsg::Owner { class_id, token_id } => { - to_json_binary(&query_owner(deps, class_id, token_id)?) - } - QueryMsg::Pauser {} => to_json_binary(&PO.query_pauser(deps.storage)?), - QueryMsg::Paused {} => to_json_binary(&PO.query_paused(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(&query_cw721_code_id(deps)?), - QueryMsg::Cw721Admin {} => to_json_binary(&ADMIN_USED_FOR_CW721.load(deps.storage)?), - QueryMsg::ContractAddrLength {} => { - to_json_binary(&CONTRACT_ADDR_LENGTH.may_load(deps.storage)?) + Ok(to_json_binary(&query_owner(deps, class_id, token_id)?)?) } - QueryMsg::NftContracts { start_after, limit } => { - to_json_binary(&query_nft_contracts(deps, start_after, limit)?) + QueryMsg::Pauser {} => Ok(to_json_binary(&PO.query_pauser(deps.storage)?)?), + QueryMsg::Paused {} => Ok(to_json_binary(&PO.query_paused(deps.storage)?)?), + QueryMsg::OutgoingProxy {} => Ok(to_json_binary(&OUTGOING_PROXY.load(deps.storage)?)?), + QueryMsg::IncomingProxy {} => Ok(to_json_binary(&INCOMING_PROXY.load(deps.storage)?)?), + QueryMsg::Cw721CodeId {} => Ok(to_json_binary(&query_cw721_code_id(deps)?)?), + QueryMsg::Cw721Admin {} => { + Ok(to_json_binary(&ADMIN_USED_FOR_CW721.load(deps.storage)?)?) } - QueryMsg::OutgoingChannels { start_after, limit } => to_json_binary(&query_channels( - deps, - &OUTGOING_CLASS_TOKEN_TO_CHANNEL, - start_after, - limit, + QueryMsg::ContractAddrLength {} => Ok(to_json_binary( + &CONTRACT_ADDR_LENGTH.may_load(deps.storage)?, )?), - QueryMsg::IncomingChannels { start_after, limit } => to_json_binary(&query_channels( - deps, - &INCOMING_CLASS_TOKEN_TO_CHANNEL, - start_after, - limit, + QueryMsg::NftContracts { start_after, limit } => Ok(to_json_binary( + &query_nft_contracts(deps, start_after, limit)?, + )?), + QueryMsg::OutgoingChannels { start_after, limit } => Ok(to_json_binary( + &query_channels(deps, &OUTGOING_CLASS_TOKEN_TO_CHANNEL, start_after, limit)?, + )?), + QueryMsg::IncomingChannels { start_after, limit } => Ok(to_json_binary( + &query_channels(deps, &INCOMING_CLASS_TOKEN_TO_CHANNEL, start_after, limit)?, )?), } } @@ -88,6 +96,28 @@ pub fn query_nft_contract_for_class_id( .map(|e| e.map(|(_, v)| v.address)) } +pub fn query_get_nft_contract_for_class_id( + deps: Deps, + env: &Env, + class_id: String, + cw721_code_id: Option, +) -> Result { + let class_id = ClassId::new(class_id); + let cw721_code_id = if let Some(cw721_code_id) = cw721_code_id { + cw721_code_id + } else { + CW721_CODE_ID.load(deps.storage)? + }; + + let mut hasher = Sha256::new(); + hasher.update(class_id.as_bytes()); + let salt = hasher.finalize().to_vec(); + + let nft_contract = + get_instantiate2_address(deps, env.contract.address.as_str(), &salt, cw721_code_id)?; + Ok(nft_contract) +} + pub fn load_nft_contract_for_class_id(storage: &dyn Storage, class_id: String) -> StdResult { query_nft_contract_for_class_id(storage, class_id.clone())?.map_or_else( || { diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index 09e4e904..bda6f06b 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -101,7 +101,7 @@ fn execute( Ics721Contract::default().execute(deps, env, info, msg) } -fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { Ics721Contract::default().query(deps, env, msg) } From 917512bedd37872422f27bce64f5adcbc937c71b Mon Sep 17 00:00:00 2001 From: mr-t Date: Fri, 31 May 2024 23:10:05 +0200 Subject: [PATCH 02/18] fix nft contract retrieval using CLASS_ID_AND_NFT_CONTRACT_INFO --- packages/ics721/src/ibc_packet_receive.rs | 26 +++++------------------ 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 223944e3..8a33e2eb 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -2,19 +2,15 @@ use cosmwasm_std::{ from_json, to_json_binary, Addr, Binary, Deps, DepsMut, Empty, Env, IbcPacket, IbcReceiveResponse, StdResult, SubMsg, WasmMsg, }; -use sha2::{Digest, Sha256}; use zip_optional::Zippable; use crate::{ - helpers::{ - generate_receive_callback_msg, get_incoming_proxy_msg, get_instantiate2_address, - get_receive_callback, - }, + helpers::{generate_receive_callback_msg, get_incoming_proxy_msg, get_receive_callback}, ibc::ACK_AND_DO_NOTHING_REPLY_ID, ibc_helpers::{get_endpoint_prefix, try_pop_source_prefix}, msg::{CallbackMsg, ExecuteMsg}, query::load_nft_contract_for_class_id, - state::{CW721_CODE_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO}, + state::{CLASS_ID_AND_NFT_CONTRACT_INFO, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO}, token_types::{VoucherCreation, VoucherRedemption}, ContractError, }; @@ -58,7 +54,6 @@ pub(crate) fn receive_ibc_packet( // - one optional callback message let callback_msg = create_callback_msg( deps.as_ref(), - &env, &data, is_redemption, callback, @@ -218,7 +213,6 @@ fn create_voucher_and_channel_messages( fn create_callback_msg( deps: Deps, - env: &Env, data: &NonFungibleTokenPacketData, is_redemption: bool, callback: Option<(Binary, Option)>, @@ -232,19 +226,9 @@ fn create_callback_msg( load_nft_contract_for_class_id(deps.storage, local_class_id.to_string()) .map_err(|_| ContractError::NoNftContractForClassId(local_class_id.to_string())) } else { - // If its a creation action, we can use the instantiate2 function to get the nft contract - // we don't care if the contract is instantiated yet or not, as later submessage will instantiate it if its not. - // The reason we use instantiate2 here is because we don't know if it was already instantiated or not. - - let cw721_code_id = CW721_CODE_ID.load(deps.storage)?; - // for creating a predictable nft contract using, using instantiate2, we need: checksum, creator, and salt: - // - using class id as salt for instantiating nft contract guarantees a) predictable address and b) uniqueness - // for this salt must be of length 32 bytes, so we use sha256 to hash class id - let mut hasher = Sha256::new(); - hasher.update(local_class_id.as_bytes()); - let salt = hasher.finalize().to_vec(); - - get_instantiate2_address(deps, env.contract.address.as_str(), &salt, cw721_code_id) + Ok(CLASS_ID_AND_NFT_CONTRACT_INFO + .load(deps.storage, &local_class_id)? + .address) }?; Ok(generate_receive_callback_msg( From 4f228d3d8674f6d039a2b75b705a400055bb8c46 Mon Sep 17 00:00:00 2001 From: mr-t Date: Fri, 31 May 2024 23:32:00 +0200 Subject: [PATCH 03/18] cleanup --- packages/ics721/schema/ics721.json | 36 +++++++++++++++++++ packages/ics721/schema/raw/query.json | 30 ++++++++++++++++ ...onse_to_get_instantiate2_nft_contract.json | 6 ++++ packages/ics721/src/ibc_packet_receive.rs | 2 ++ packages/ics721/src/msg.rs | 6 ++-- packages/ics721/src/query.rs | 2 +- 6 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 packages/ics721/schema/raw/response_to_get_instantiate2_nft_contract.json diff --git a/packages/ics721/schema/ics721.json b/packages/ics721/schema/ics721.json index b59a2e48..305a3fd8 100644 --- a/packages/ics721/schema/ics721.json +++ b/packages/ics721/schema/ics721.json @@ -899,6 +899,36 @@ }, "additionalProperties": false }, + { + "description": "Returns predictable NFT contract using instantiate2. If no cw721_code_id is provided, default cw721_code_id from storage is used.", + "type": "object", + "required": [ + "get_instantiate2_nft_contract" + ], + "properties": { + "get_instantiate2_nft_contract": { + "type": "object", + "required": [ + "class_id" + ], + "properties": { + "class_id": { + "type": "string" + }, + "cw721_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "description": "Gets the class level metadata URI for the provided class_id. If there is no metadata, returns None. Returns `Option`.", "type": "object", @@ -1320,6 +1350,12 @@ "format": "uint64", "minimum": 0.0 }, + "get_instantiate2_nft_contract": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "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" + }, "incoming_channels": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Array_of_Tuple_of_Tuple_of_ClassId_and_TokenId_and_String", diff --git a/packages/ics721/schema/raw/query.json b/packages/ics721/schema/raw/query.json index b6c82f81..1b27072d 100644 --- a/packages/ics721/schema/raw/query.json +++ b/packages/ics721/schema/raw/query.json @@ -46,6 +46,36 @@ }, "additionalProperties": false }, + { + "description": "Returns predictable NFT contract using instantiate2. If no cw721_code_id is provided, default cw721_code_id from storage is used.", + "type": "object", + "required": [ + "get_instantiate2_nft_contract" + ], + "properties": { + "get_instantiate2_nft_contract": { + "type": "object", + "required": [ + "class_id" + ], + "properties": { + "class_id": { + "type": "string" + }, + "cw721_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "description": "Gets the class level metadata URI for the provided class_id. If there is no metadata, returns None. Returns `Option`.", "type": "object", diff --git a/packages/ics721/schema/raw/response_to_get_instantiate2_nft_contract.json b/packages/ics721/schema/raw/response_to_get_instantiate2_nft_contract.json new file mode 100644 index 00000000..4c7f1934 --- /dev/null +++ b/packages/ics721/schema/raw/response_to_get_instantiate2_nft_contract.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "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/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 8a33e2eb..8a1435a5 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -226,6 +226,8 @@ fn create_callback_msg( load_nft_contract_for_class_id(deps.storage, local_class_id.to_string()) .map_err(|_| ContractError::NoNftContractForClassId(local_class_id.to_string())) } else { + // here we know NFT contract is always instantiated, so it is safe getting it from storage + // NEVER use instantiate2 to get the NFT contract address here, since code id may change! Ok(CLASS_ID_AND_NFT_CONTRACT_INFO .load(deps.storage, &local_class_id)? .address) diff --git a/packages/ics721/src/msg.rs b/packages/ics721/src/msg.rs index a70cf8df..4d2563a3 100644 --- a/packages/ics721/src/msg.rs +++ b/packages/ics721/src/msg.rs @@ -125,8 +125,10 @@ pub enum QueryMsg { #[returns(Option<::cosmwasm_std::Addr>)] NftContract { class_id: String }, - #[returns(Option<::cosmwasm_std::Addr>)] - GetNftContractByInstantiate2 { + /// Returns predictable NFT contract using instantiate2. If no + /// cw721_code_id is provided, default cw721_code_id from storage is used. + #[returns(::cosmwasm_std::Addr)] + GetInstantiate2NftContract { class_id: String, cw721_code_id: Option, }, diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index 4881ddad..9a0cefc2 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -23,7 +23,7 @@ pub trait Ics721Query { QueryMsg::NftContract { class_id } => Ok(to_json_binary( &query_nft_contract_for_class_id(deps.storage, class_id)?, )?), - QueryMsg::GetNftContractByInstantiate2 { + QueryMsg::GetInstantiate2NftContract { class_id, cw721_code_id, } => Ok(to_json_binary(&query_get_nft_contract_for_class_id( From bfe24cb7a9f2908504c5b2ec0ef28285f7eca7c9 Mon Sep 17 00:00:00 2001 From: mr-t Date: Sat, 1 Jun 2024 00:21:10 +0200 Subject: [PATCH 04/18] add events --- packages/ics721/src/execute.rs | 32 +++++++++++++++++++++++++------- packages/ics721/src/ibc.rs | 11 +++++++++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 5e604303..7809e466 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use cosmwasm_std::{ from_json, to_json_binary, Addr, Binary, ContractInfoResponse, Deps, DepsMut, Empty, Env, - IbcMsg, MessageInfo, Order, Response, StdResult, SubMsg, WasmMsg, + Event, IbcMsg, MessageInfo, Order, Response, StdResult, SubMsg, WasmMsg, }; use cw_storage_plus::Map; use ics721_types::{ @@ -524,15 +524,23 @@ where msg: to_json_binary(&ExecuteMsg::Callback(CallbackMsg::Mint { class_id: class.id.clone(), receiver, - tokens, + tokens: tokens.clone(), }))?, funds: vec![], }; - let instantiate = self.create_instantiate_msg(deps, &env, class.clone())?; + let (class_id_info, instantiate) = + self.create_instantiate_msg(deps, &env, class.clone())?; + + let token_ids = format!("{:?}", tokens); + let event = Event::new("ics721_receive_create_vouchers") + .add_attribute("class_id", class_id_info.class_id) + .add_attribute("nft_contract", class_id_info.address) + .add_attribute("token_ids", token_ids); Ok(Response::::default() .add_attribute("method", "callback_create_vouchers") + .add_event(event) .add_submessages(instantiate) .add_message(mint)) } @@ -542,9 +550,11 @@ where deps: DepsMut, env: &Env, class: Class, - ) -> Result>, ContractError> { - if CLASS_ID_AND_NFT_CONTRACT_INFO.has(deps.storage, class.id.to_string().as_str()) { - Ok(vec![]) + ) -> Result<(ClassIdInfo, Vec>), ContractError> { + let maybe_class_id_info = + CLASS_ID_AND_NFT_CONTRACT_INFO.may_load(deps.as_ref().storage, &class.id)?; + if let Some(nft_contract) = maybe_class_id_info { + Ok((nft_contract, vec![])) } else { let class_id = ClassId::new(class.id.clone()); let cw721_code_id = CW721_CODE_ID.load(deps.storage)?; @@ -586,7 +596,7 @@ where }, INSTANTIATE_CW721_REPLY_ID, ); - Ok(vec![message]) + Ok((class_id_info, vec![message])) } } @@ -629,8 +639,16 @@ where let VoucherRedemption { class, token_ids } = redeem; let nft_contract = load_nft_contract_for_class_id(deps.storage, class.id.to_string())?; let receiver = deps.api.addr_validate(&receiver)?; + + let token_ids_string = format!("{:?}", token_ids); + let event = Event::new("ics721_receive_redeem_vouchers") + .add_attribute("class_id", class.id) + .add_attribute("nft_contract", nft_contract.clone()) + .add_attribute("token_ids", token_ids_string); + Ok(Response::default() .add_attribute("method", "callback_redeem_vouchers") + .add_event(event) .add_messages( token_ids .into_iter() diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index 5f7cdaf8..be36d70c 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{ - from_json, to_json_binary, DepsMut, Empty, Env, IbcBasicResponse, IbcChannelCloseMsg, + from_json, to_json_binary, DepsMut, Empty, Env, Event, IbcBasicResponse, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, Never, Reply, Response, StdResult, SubMsgResult, WasmMsg, @@ -162,6 +162,12 @@ where None => vec![], }; + let token_ids = format!("{:?}", msg.token_ids); + let event = Event::new("ics721_ack_burn_vouchers") + .add_attribute("class_id", msg.class_id.to_string()) + .add_attribute("nft_contract", nft_contract.clone()) + .add_attribute("token_ids", token_ids.clone()); + Ok(IbcBasicResponse::new() .add_messages(burn_notices) .add_submessages(callback) @@ -169,7 +175,8 @@ where .add_attribute("sender", msg.sender) .add_attribute("receiver", msg.receiver) .add_attribute("classId", msg.class_id) - .add_attribute("token_ids", format!("{:?}", msg.token_ids))) + .add_attribute("token_ids", token_ids) + .add_event(event)) } } From 04acd23b6997cffb3c8d364bff1f5b123f23b433 Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 5 Jun 2024 15:04:38 +0200 Subject: [PATCH 05/18] cleanup --- packages/ics721-types/src/token_types.rs | 6 ++++++ packages/ics721/src/execute.rs | 4 ++-- packages/ics721/src/query.rs | 23 +++++++++-------------- packages/ics721/src/testing/contract.rs | 4 ++-- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/ics721-types/src/token_types.rs b/packages/ics721-types/src/token_types.rs index 78a9590d..01535c5d 100644 --- a/packages/ics721-types/src/token_types.rs +++ b/packages/ics721-types/src/token_types.rs @@ -79,6 +79,12 @@ impl From for String { } } +impl From for ClassId { + fn from(s: String) -> Self { + Self(s) + } +} + impl From for String { fn from(t: TokenId) -> Self { t.0 diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 7809e466..67d4297d 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -157,7 +157,7 @@ where let token_id = TokenId::new(token_id); let child_class_id = ClassId::new(child_class_id); let child_collection = deps.api.addr_validate(&child_collection)?; - match query_nft_contract_for_class_id(deps.storage, child_class_id.to_string())? { + match query_nft_contract_for_class_id(deps.storage, child_class_id.clone())? { Some(cw721_addr) => { if cw721_addr != child_collection { return Err(ContractError::NoNftContractMatch { @@ -240,7 +240,7 @@ where // check given home class id and home collection is the same as stored in the contract let home_class_id = ClassId::new(home_class_id); let home_collection = deps.api.addr_validate(&home_collection)?; - match query_nft_contract_for_class_id(deps.storage, home_class_id.to_string())? { + match query_nft_contract_for_class_id(deps.storage, home_class_id.clone())? { Some(cw721_addr) => { if cw721_addr != home_collection { return Err(ContractError::NoNftContractMatch { diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index 9a0cefc2..4f756cd3 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -21,15 +21,15 @@ pub trait Ics721Query { &query_class_id_for_nft_contract(deps, contract)?, )?), QueryMsg::NftContract { class_id } => Ok(to_json_binary( - &query_nft_contract_for_class_id(deps.storage, class_id)?, + &query_nft_contract_for_class_id(deps.storage, class_id.into())?, )?), QueryMsg::GetInstantiate2NftContract { class_id, cw721_code_id, - } => Ok(to_json_binary(&query_get_nft_contract_for_class_id( + } => Ok(to_json_binary(&query_get_instantiate2_nft_contract( deps, &env, - class_id, + class_id.into(), cw721_code_id, )?)?), QueryMsg::ClassMetadata { class_id } => { @@ -83,26 +83,22 @@ pub fn load_class_id_for_nft_contract( pub fn query_nft_contract_for_class_id( storage: &dyn Storage, - class_id: String, + class_id: ClassId, ) -> StdResult> { - // Convert the class_id string to ClassId type if necessary - let class_id_key = ClassId::new(class_id); - // Query the IndexedMap using the class_id index CLASS_ID_AND_NFT_CONTRACT_INFO .idx .class_id - .item(storage, class_id_key) + .item(storage, class_id) .map(|e| e.map(|(_, v)| v.address)) } -pub fn query_get_nft_contract_for_class_id( +pub fn query_get_instantiate2_nft_contract( deps: Deps, env: &Env, - class_id: String, + class_id: ClassId, cw721_code_id: Option, ) -> Result { - let class_id = ClassId::new(class_id); let cw721_code_id = if let Some(cw721_code_id) = cw721_code_id { cw721_code_id } else { @@ -119,7 +115,7 @@ pub fn query_get_nft_contract_for_class_id( } pub fn load_nft_contract_for_class_id(storage: &dyn Storage, class_id: String) -> StdResult { - query_nft_contract_for_class_id(storage, class_id.clone())?.map_or_else( + query_nft_contract_for_class_id(storage, class_id.clone().into())?.map_or_else( || { Err(StdError::NotFound { kind: format!("NFT contract not found for class id {}", class_id), @@ -148,8 +144,7 @@ pub fn query_token_metadata( // metadata entry, we have no entry for this token at all. return Ok(None); }; - let Some(nft_contract) = query_nft_contract_for_class_id(deps.storage, class_id.to_string())? - else { + let Some(nft_contract) = query_nft_contract_for_class_id(deps.storage, class_id)? else { debug_assert!(false, "token_metadata != None => token_contract != None"); return Ok(None); }; diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index 8f057ea7..6980a4f3 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -652,10 +652,10 @@ fn test_migrate() { assert_eq!(nft_contract_and_class_id_list[1].1, NFT_CONTRACT_2); // test query and indexers for class id and addr are working let nft_contract_1 = - query_nft_contract_for_class_id(&deps.storage, CLASS_ID_1.to_string()).unwrap(); + query_nft_contract_for_class_id(&deps.storage, CLASS_ID_1.to_string().into()).unwrap(); assert_eq!(nft_contract_1, Some(Addr::unchecked(NFT_CONTRACT_1))); let nft_contract_2 = - query_nft_contract_for_class_id(&deps.storage, CLASS_ID_2.to_string()).unwrap(); + query_nft_contract_for_class_id(&deps.storage, CLASS_ID_2.to_string().into()).unwrap(); assert_eq!(nft_contract_2, Some(Addr::unchecked(NFT_CONTRACT_2))); let class_id_1 = query_class_id_for_nft_contract(deps.as_ref(), NFT_CONTRACT_1.to_string()).unwrap(); From 4861d1be40edb3912f6273c5a13667e2b523e8b2 Mon Sep 17 00:00:00 2001 From: mr-t Date: Wed, 5 Jun 2024 15:47:01 +0200 Subject: [PATCH 06/18] use instantiate2 in case addr not in storage --- packages/ics721/src/ibc_packet_receive.rs | 32 ++++++++++++++++++----- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 8a1435a5..94ae0987 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -9,8 +9,11 @@ use crate::{ ibc::ACK_AND_DO_NOTHING_REPLY_ID, ibc_helpers::{get_endpoint_prefix, try_pop_source_prefix}, msg::{CallbackMsg, ExecuteMsg}, - query::load_nft_contract_for_class_id, - state::{CLASS_ID_AND_NFT_CONTRACT_INFO, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO}, + query::{ + load_nft_contract_for_class_id, query_get_instantiate2_nft_contract, + query_nft_contract_for_class_id, + }, + state::{CW721_CODE_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL, PO}, token_types::{VoucherCreation, VoucherRedemption}, ContractError, }; @@ -54,6 +57,7 @@ pub(crate) fn receive_ibc_packet( // - one optional callback message let callback_msg = create_callback_msg( deps.as_ref(), + &env, &data, is_redemption, callback, @@ -213,6 +217,7 @@ fn create_voucher_and_channel_messages( fn create_callback_msg( deps: Deps, + env: &Env, data: &NonFungibleTokenPacketData, is_redemption: bool, callback: Option<(Binary, Option)>, @@ -226,11 +231,24 @@ fn create_callback_msg( load_nft_contract_for_class_id(deps.storage, local_class_id.to_string()) .map_err(|_| ContractError::NoNftContractForClassId(local_class_id.to_string())) } else { - // here we know NFT contract is always instantiated, so it is safe getting it from storage - // NEVER use instantiate2 to get the NFT contract address here, since code id may change! - Ok(CLASS_ID_AND_NFT_CONTRACT_INFO - .load(deps.storage, &local_class_id)? - .address) + let nft_contract = + match query_nft_contract_for_class_id(deps.storage, local_class_id.clone()) { + Ok(nft_contract) => nft_contract, + Err(_) => None, // not found, occurs on initial transfer when we don't have the contract address + }; + match nft_contract { + Some(nft_contract) => Ok(nft_contract), + None => { + // contract not yet instantiated, so we use instantiate2 to get the contract address + let cw721_code_id = CW721_CODE_ID.load(deps.storage)?; + query_get_instantiate2_nft_contract( + deps, + env, + local_class_id.clone(), + Some(cw721_code_id), + ) + } + } }?; Ok(generate_receive_callback_msg( From ceb3a29a32175d4e095c72b220a4da0e6703fbb6 Mon Sep 17 00:00:00 2001 From: mr-t Date: Mon, 10 Jun 2024 20:19:14 +0200 Subject: [PATCH 07/18] log more attributes (nft_contract and is_redemption) --- packages/ics721/src/ibc.rs | 12 ++-- packages/ics721/src/ibc_packet_receive.rs | 70 +++++++++++------------ 2 files changed, 39 insertions(+), 43 deletions(-) diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index be36d70c..fa96eef6 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -164,18 +164,20 @@ where let token_ids = format!("{:?}", msg.token_ids); let event = Event::new("ics721_ack_burn_vouchers") - .add_attribute("class_id", msg.class_id.to_string()) .add_attribute("nft_contract", nft_contract.clone()) + .add_attribute("class_id", msg.class_id.to_string()) .add_attribute("token_ids", token_ids.clone()); Ok(IbcBasicResponse::new() - .add_messages(burn_notices) - .add_submessages(callback) - .add_attribute("method", "acknowledge") + .add_attribute("burn_notices", (!burn_notices.is_empty()).to_string()) + .add_attribute("method", "ibc_packet_ack_success") .add_attribute("sender", msg.sender) .add_attribute("receiver", msg.receiver) + .add_attribute("nft_contract", nft_contract) .add_attribute("classId", msg.class_id) .add_attribute("token_ids", token_ids) + .add_messages(burn_notices) + .add_submessages(callback) .add_event(event)) } } @@ -232,7 +234,7 @@ where Ok(IbcBasicResponse::new() .add_messages(messages) .add_submessages(callback) - .add_attribute("method", "handle_packet_fail") + .add_attribute("method", "ibc_packet_ack_fail") .add_attribute("token_ids", format!("{:?}", message.token_ids)) .add_attribute("class_id", message.class_id) .add_attribute("channel_id", packet.src.channel_id) diff --git a/packages/ics721/src/ibc_packet_receive.rs b/packages/ics721/src/ibc_packet_receive.rs index 94ae0987..7180dec6 100644 --- a/packages/ics721/src/ibc_packet_receive.rs +++ b/packages/ics721/src/ibc_packet_receive.rs @@ -55,14 +55,35 @@ pub(crate) fn receive_ibc_packet( let incoming_proxy_msg = get_incoming_proxy_msg(deps.as_ref().storage, packet.clone(), data.clone())?; // - one optional callback message - let callback_msg = create_callback_msg( - deps.as_ref(), - &env, - &data, - is_redemption, - callback, - local_class_id, - )?; + // callback require the nft contract, get it using the class id from the action + let nft_contract = if is_redemption { + // If its a redemption, it means we already have the contract address in storage + + load_nft_contract_for_class_id(deps.storage, local_class_id.to_string()) + .map_err(|_| ContractError::NoNftContractForClassId(local_class_id.to_string())) + } else { + let nft_contract = + match query_nft_contract_for_class_id(deps.storage, local_class_id.clone()) { + Ok(nft_contract) => nft_contract, + Err(_) => None, // not found, occurs on initial transfer when we don't have the contract address + }; + match nft_contract { + Some(nft_contract) => Ok(nft_contract), + None => { + // contract not yet instantiated, so we use instantiate2 to get the contract address + let cw721_code_id = CW721_CODE_ID.load(deps.storage)?; + query_get_instantiate2_nft_contract( + deps.as_ref(), + &env, + local_class_id.clone(), + Some(cw721_code_id), + ) + } + } + }?; + + let callback_msg = + create_callback_msg(deps.as_ref(), &data, nft_contract.to_string(), callback)?; let submessage = into_submessage( env.contract.address, @@ -81,6 +102,8 @@ pub(crate) fn receive_ibc_packet( Ok(response .add_submessage(submessage) .add_attribute("method", "receive_ibc_packet") + .add_attribute("nft_contract", nft_contract.to_string()) + .add_attribute("is_redemption", is_redemption.to_string()) .add_attribute("class_id", data.class_id) .add_attribute("local_channel", packet.dest.channel_id) .add_attribute("counterparty_channel", packet.src.channel_id)) @@ -217,40 +240,11 @@ fn create_voucher_and_channel_messages( fn create_callback_msg( deps: Deps, - env: &Env, data: &NonFungibleTokenPacketData, - is_redemption: bool, + nft_contract: String, callback: Option<(Binary, Option)>, - local_class_id: ClassId, ) -> Result, ContractError> { if let Some((receive_callback_data, receive_callback_addr)) = callback { - // callback require the nft contract, get it using the class id from the action - let nft_contract = if is_redemption { - // If its a redemption, it means we already have the contract address in storage - - load_nft_contract_for_class_id(deps.storage, local_class_id.to_string()) - .map_err(|_| ContractError::NoNftContractForClassId(local_class_id.to_string())) - } else { - let nft_contract = - match query_nft_contract_for_class_id(deps.storage, local_class_id.clone()) { - Ok(nft_contract) => nft_contract, - Err(_) => None, // not found, occurs on initial transfer when we don't have the contract address - }; - match nft_contract { - Some(nft_contract) => Ok(nft_contract), - None => { - // contract not yet instantiated, so we use instantiate2 to get the contract address - let cw721_code_id = CW721_CODE_ID.load(deps.storage)?; - query_get_instantiate2_nft_contract( - deps, - env, - local_class_id.clone(), - Some(cw721_code_id), - ) - } - } - }?; - Ok(generate_receive_callback_msg( deps, data, From 315aaeeaf35478804fb636301db291d45ef8c860 Mon Sep 17 00:00:00 2001 From: mr-t Date: Mon, 10 Jun 2024 21:39:12 +0200 Subject: [PATCH 08/18] fix test --- packages/ics721/src/testing/ibc_tests.rs | 58 +++++++++++++++++++++--- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/packages/ics721/src/testing/ibc_tests.rs b/packages/ics721/src/testing/ibc_tests.rs index d1ecb44b..32313df0 100644 --- a/packages/ics721/src/testing/ibc_tests.rs +++ b/packages/ics721/src/testing/ibc_tests.rs @@ -16,7 +16,7 @@ use crate::{ ibc_helpers::{ack_fail, ack_success, try_get_ack_error}, msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, QueryMsg}, query::Ics721Query, - state::{ClassIdInfo, CollectionData, CLASS_ID_AND_NFT_CONTRACT_INFO, PO}, + state::{ClassIdInfo, CollectionData, CLASS_ID_AND_NFT_CONTRACT_INFO, CW721_CODE_ID, PO}, utils::get_collection_data, ContractError, }; @@ -34,7 +34,7 @@ const DEFAULT_TIMEOUT: u64 = 42; // Seconds. const ADDR1: &str = "addr1"; const RELAYER_ADDR: &str = "relayer"; -const CW721_CODE_ID: u64 = 0; +const CW721_BASE_CODE_ID: u64 = 0; #[derive(Default)] pub struct Ics721Contract {} @@ -106,7 +106,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, + cw721_base_code_id: CW721_BASE_CODE_ID, incoming_proxy: None, outgoing_proxy: None, pauser: None, @@ -437,6 +437,22 @@ fn test_ibc_channel_connect_invalid_version_counterparty() { #[test] fn test_ibc_packet_receive() { + let mut deps = mock_dependencies(); + CW721_CODE_ID + .save(&mut deps.storage, &CW721_BASE_CODE_ID) + .unwrap(); + let dest_class_id = format!("{}/{}/{}", CONTRACT_PORT, CHANNEL_ID, "id"); + CLASS_ID_AND_NFT_CONTRACT_INFO + .save( + &mut deps.storage, + &ClassId::new(dest_class_id.clone()), + &ClassIdInfo { + class_id: ClassId::new(dest_class_id), + address: Addr::unchecked("cosmos2contract"), + }, + ) + .unwrap(); + let data = to_json_binary(&NonFungibleTokenPacketData { class_id: ClassId::new("id"), class_uri: None, @@ -451,7 +467,6 @@ fn test_ibc_packet_receive() { .unwrap(); let ibc_packet = mock_packet(data); let packet = IbcPacketReceiveMsg::new(ibc_packet.clone(), Addr::unchecked(RELAYER_ADDR)); - let mut deps = mock_dependencies(); let env = mock_env(); PO.set_pauser(&mut deps.storage, &deps.api, None).unwrap(); let response = Ics721Contract::default() @@ -539,6 +554,22 @@ fn test_ibc_packet_receive_invalid_packet_data() { #[test] fn test_ibc_packet_receive_emits_memo() { + let mut deps = mock_dependencies(); + CW721_CODE_ID + .save(&mut deps.storage, &CW721_BASE_CODE_ID) + .unwrap(); + let dest_class_id = format!("{}/{}/{}", CONTRACT_PORT, CHANNEL_ID, "id"); + CLASS_ID_AND_NFT_CONTRACT_INFO + .save( + &mut deps.storage, + &ClassId::new(dest_class_id.clone()), + &ClassIdInfo { + class_id: ClassId::new(dest_class_id), + address: Addr::unchecked("cosmos2contract"), + }, + ) + .unwrap(); + let data = to_json_binary(&NonFungibleTokenPacketData { class_id: ClassId::new("id"), class_uri: None, @@ -552,12 +583,12 @@ fn test_ibc_packet_receive_emits_memo() { }) .unwrap(); let packet = IbcPacketReceiveMsg::new(mock_packet(data), Addr::unchecked(RELAYER_ADDR)); - let mut deps = mock_dependencies(); let env = mock_env(); PO.set_pauser(&mut deps.storage, &deps.api, None).unwrap(); let res = Ics721Contract::default() .ibc_packet_receive(deps.as_mut(), env, packet) .unwrap(); + println!(">>>>>>>>>>> memo: {:?}", res.attributes); assert!(res.attributes.contains(&Attribute { key: "ics721_memo".to_string(), value: "memo".to_string() @@ -700,6 +731,22 @@ fn test_no_receive_when_paused() { #[test] fn test_different_memo_ignored() { + let mut deps = mock_dependencies(); + CW721_CODE_ID + .save(&mut deps.storage, &CW721_BASE_CODE_ID) + .unwrap(); + let dest_class_id = format!("{}/{}/{}", CONTRACT_PORT, CHANNEL_ID, "id"); + CLASS_ID_AND_NFT_CONTRACT_INFO + .save( + &mut deps.storage, + &ClassId::new(dest_class_id.clone()), + &ClassIdInfo { + class_id: ClassId::new(dest_class_id), + address: Addr::unchecked("cosmos2contract"), + }, + ) + .unwrap(); + #[cw_serde] struct DifferentMemo { different: Option, @@ -732,7 +779,6 @@ fn test_different_memo_ignored() { }; let ibc_packet = mock_packet(to_json_binary(&data).unwrap()); let packet = IbcPacketReceiveMsg::new(ibc_packet, Addr::unchecked(RELAYER_ADDR)); - let mut deps = mock_dependencies(); let env = mock_env(); PO.set_pauser(&mut deps.storage, &deps.api, None).unwrap(); From 2cfa2f5205da497c43b8c9bae071e9a429910946 Mon Sep 17 00:00:00 2001 From: mr-t Date: Thu, 6 Jun 2024 23:13:19 +0200 Subject: [PATCH 09/18] use pre-release cw721 v0.19 --- Cargo.lock | 302 +++++++++------ Cargo.toml | 16 +- contracts/cw721-tester/src/lib.rs | 20 +- contracts/ics721-base-tester/src/contract.rs | 32 +- contracts/ics721-base-tester/src/msg.rs | 2 +- contracts/ics721-base-tester/src/state.rs | 4 +- .../src/testing/integration_tests.rs | 358 +++++++++++++----- packages/ics721/src/execute.rs | 65 +++- packages/ics721/src/ibc.rs | 13 +- packages/ics721/src/msg.rs | 4 +- packages/ics721/src/query.rs | 21 +- packages/ics721/src/state.rs | 14 +- packages/ics721/src/testing/contract.rs | 109 ++++-- .../ics721/src/testing/integration_tests.rs | 339 ++++++++++++----- packages/ics721/src/utils.rs | 30 +- 15 files changed, 935 insertions(+), 394 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f471560..1a2afa76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "base16ct" @@ -75,9 +75,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cfg-if" @@ -93,9 +93,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cosmwasm-crypto" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9934c79e58d9676edfd592557dee765d2a6ef54c09d5aa2edb06156b00148966" +checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" dependencies = [ "digest 0.10.7", "ecdsa", @@ -107,18 +107,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5e72e330bd3bdab11c52b5ecbdeb6a8697a004c57964caeb5d876f0b088b3c" +checksum = "242e98e7a231c122e08f300d9db3262d1007b51758a8732cd6210b3e9faa4f3a" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-schema" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e3a2136e2a60e8b6582f5dffca5d1a683ed77bf38537d330bc1dfccd69010" +checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d803bea6bd9ed61bd1ee0b4a2eb09ee20dbb539cc6e0b8795614d20952ebb1" +checksum = "0bb57855fbfc83327f8445ae0d413b1a05ac0d68c396ab4d122b2abd7bb82cb6" dependencies = [ "proc-macro2", "quote", @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8666e572a3a2519010dde88c04d16e9339ae751b56b2bb35081fe3f7d6be74" +checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ "base64", "bech32", @@ -223,6 +223,14 @@ dependencies = [ "cosmwasm-std", ] +[[package]] +name = "cw-address-like" +version = "1.0.4" +source = "git+https://github.com/public-awesome/cw-plus-plus.git?branch=main#28c1a09bfc6b4f1942fefe3eb0b50faf9d3b1523" +dependencies = [ + "cosmwasm-std", +] + [[package]] name = "cw-cii" version = "0.1.0" @@ -289,7 +297,7 @@ dependencies = [ "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)", + "cw721-base 0.18.0", "ics721-types 0.1.0 (git+https://github.com/public-awesome/cw-ics721?tag=v0.1.5)", "thiserror", ] @@ -318,7 +326,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-base 0.18.0", "ics721-types 0.1.0 (git+https://github.com/public-awesome/cw-ics721?tag=v0.1.5)", "serde", "thiserror", @@ -326,9 +334,9 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fff029689ae89127cf6d7655809a68d712f3edbdb9686c70b018ba438b26ca" +checksum = "cc392a5cb7e778e3f90adbf7faa43c4db7f35b6623224b08886d796718edb875" dependencies = [ "anyhow", "bech32", @@ -336,7 +344,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "derivative", - "itertools 0.12.1", + "itertools", "prost", "schemars", "serde", @@ -352,8 +360,22 @@ checksum = "093dfb4520c48b5848274dd88ea99e280a04bc08729603341c7fb0d758c74321" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-address-like", - "cw-ownable-derive", + "cw-address-like 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cw-ownable-derive 0.5.1", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "thiserror", +] + +[[package]] +name = "cw-ownable" +version = "0.6.0" +source = "git+https://github.com/public-awesome/cw-plus-plus.git?branch=main#28c1a09bfc6b4f1942fefe3eb0b50faf9d3b1523" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-address-like 1.0.4 (git+https://github.com/public-awesome/cw-plus-plus.git?branch=main)", + "cw-ownable-derive 0.6.0", "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "thiserror", @@ -370,10 +392,20 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cw-ownable-derive" +version = "0.6.0" +source = "git+https://github.com/public-awesome/cw-plus-plus.git?branch=main#28c1a09bfc6b4f1942fefe3eb0b50faf9d3b1523" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "cw-paginate-storage" -version = "2.4.0" -source = "git+https://github.com/DA0-DA0/dao-contracts.git#43eccded799ea63ea19a81ed64054848e689ff73" +version = "2.4.2" +source = "git+https://github.com/DA0-DA0/dao-contracts.git#bb8224ef1285266f4c8f11448e361f66c6a7e879" dependencies = [ "cosmwasm-std", "cw-storage-plus 1.2.0", @@ -497,6 +529,18 @@ dependencies = [ "serde", ] +[[package]] +name = "cw721" +version = "0.16.0" +source = "git+https://github.com/CosmWasm/cw-nfts?tag=v0.16.0#2cad1d3e15e0a34d466a0b51e02c58b82ebe5ecd" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "schemars", + "serde", +] + [[package]] name = "cw721" version = "0.18.0" @@ -522,6 +566,25 @@ dependencies = [ "serde", ] +[[package]] +name = "cw721" +version = "0.19.0" +source = "git+https://github.com/arkprotocol/cw-nfts?branch=collection-info#228c9ef0c9ff9386a964296e0924b27b57cc5083" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ownable 0.6.0", + "cw-paginate-storage", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw721 0.16.0 (git+https://github.com/CosmWasm/cw-nfts?tag=v0.16.0)", + "schemars", + "serde", + "thiserror", + "url", +] + [[package]] name = "cw721-base" version = "0.16.0" @@ -533,7 +596,23 @@ dependencies = [ "cw-storage-plus 0.16.0", "cw-utils 0.16.0", "cw2 0.16.0", - "cw721 0.16.0", + "cw721 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw721-base" +version = "0.16.0" +source = "git+https://github.com/CosmWasm/cw-nfts?tag=v0.16.0#2cad1d3e15e0a34d466a0b51e02c58b82ebe5ecd" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "cw721 0.16.0 (git+https://github.com/CosmWasm/cw-nfts?tag=v0.16.0)", "schemars", "serde", "thiserror", @@ -547,12 +626,12 @@ checksum = "da518d9f68bfda7d972cbaca2e8fcf04651d0edc3de72b04ae2bcd9289c81614" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-ownable", + "cw-ownable 0.5.1", "cw-storage-plus 1.2.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", + "cw721-base 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "schemars", "serde", "thiserror", @@ -560,20 +639,14 @@ dependencies = [ [[package]] name = "cw721-base" -version = "0.18.0" -source = "git+https://github.com/CosmWasm/cw-nfts?branch=main#e63a7bbb620e6ea39224bb5580967477066cb7ae" +version = "0.19.0" +source = "git+https://github.com/arkprotocol/cw-nfts?branch=collection-info#228c9ef0c9ff9386a964296e0924b27b57cc5083" dependencies = [ - "cosmwasm-schema", "cosmwasm-std", - "cw-ownable", - "cw-storage-plus 1.2.0", - "cw-utils 1.0.3", + "cw-ownable 0.6.0", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", - "cw721-base 0.16.0", - "schemars", + "cw721 0.19.0", "serde", - "thiserror", ] [[package]] @@ -584,15 +657,15 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721-base 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", + "cw721-base 0.19.0", "thiserror", ] [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -632,9 +705,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ecdsa" @@ -667,9 +740,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -728,9 +801,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -784,16 +857,16 @@ dependencies = [ "cw-ics721-incoming-proxy-base", "cw-ics721-outgoing-proxy-rate-limit", "cw-multi-test", - "cw-ownable", + "cw-ownable 0.5.1", "cw-paginate-storage", "cw-pause-once", "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.2", - "cw721 0.16.0", - "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 0.16.0 (git+https://github.com/CosmWasm/cw-nfts?tag=v0.16.0)", + "cw721 0.19.0", + "cw721-base 0.16.0 (git+https://github.com/CosmWasm/cw-nfts?tag=v0.16.0)", + "cw721-base 0.19.0", "ics721-types 0.1.0", "serde", "sha2 0.10.8", @@ -819,7 +892,7 @@ dependencies = [ "cosmwasm-storage", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", + "cw721 0.19.0", "ics721", "ics721-types 0.1.0", "thiserror", @@ -832,7 +905,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", - "cw721 0.18.0 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", + "cw721 0.19.0", "serde", "thiserror", ] @@ -860,15 +933,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.12.1" @@ -880,9 +944,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "k256" @@ -900,9 +964,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "once_cell" @@ -912,9 +976,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "percent-encoding" @@ -934,18 +998,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -953,22 +1017,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1000,15 +1064,15 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "schemars_derive", @@ -1018,14 +1082,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -1044,15 +1108,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.196" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -1068,31 +1132,31 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1114,8 +1178,8 @@ dependencies = [ "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 0.19.0", + "cw721-base 0.19.0", "ics721", "ics721-types 0.1.0", "sg-std", @@ -1141,33 +1205,33 @@ dependencies = [ [[package]] name = "sg721" -version = "3.5.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f59f52a646afc7e20dd55a873df667c6c995deb7495c6cf9b0f3d8f340dd227" +checksum = "05327a3a8a44de4c4c97e02fd98dd87917c051b76b7a64f8c47865b5a80cd47c" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-ownable", + "cw-ownable 0.5.1", "cw-utils 1.0.3", - "cw721-base 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.18.0", "serde", "thiserror", ] [[package]] name = "sg721-base" -version = "3.5.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e903e3e9bd2f8641d03a7ef3e9e40a7188f655d9e1cdfd220ba7c01e8d0b35b" +checksum = "f97deda0edefd15494052003a1f79fd9b06c26d8b7448a3174deb7529a2251f0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-ownable", + "cw-ownable 0.5.1", "cw-storage-plus 1.2.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)", + "cw721-base 0.18.0", "serde", "sg-std", "sg721", @@ -1244,9 +1308,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -1255,22 +1319,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.66", ] [[package]] @@ -1308,9 +1372,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -1340,9 +1404,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zip-optional" diff --git a/Cargo.toml b/Cargo.toml index b4b09abd..a259f8dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,17 +12,17 @@ bech32 = "^0.9" cosmwasm-std = "^1.5" cosmwasm-schema = "^1.5" cosmwasm-storage = "^1.5" -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/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/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" } +cw2 = "^1.1" +cw721 = { git = "https://github.com/arkprotocol/cw-nfts", branch = "collection-info"} # TODO switch to version 0.18.1/0.19.0, once released +cw721-base = { git = "https://github.com/arkprotocol/cw-nfts", branch = "collection-info"} # TODO switch to version 0.18.1/0.19.0, once released +cw721-016 = { git = "https://github.com/CosmWasm/cw-nfts", tag = "v0.16.0", package = "cw721" } +cw721-base-016 = { git = "https://github.com/CosmWasm/cw-nfts", tag = "v0.16.0", package = "cw721-base" } 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-ownable = "^0.5" +cw-paginate-storage = { version = "^2.4", git = "https://github.com/DA0-DA0/dao-contracts.git" } +cw-storage-plus = "^1.1" cw-multi-test = { version = "^0.20", features = ["cosmwasm_1_2"] } cw-utils = "^1.0" sha2 = "^0.10" diff --git a/contracts/cw721-tester/src/lib.rs b/contracts/cw721-tester/src/lib.rs index d7b74e5a..cce998b2 100644 --- a/contracts/cw721-tester/src/lib.rs +++ b/contracts/cw721-tester/src/lib.rs @@ -1,13 +1,19 @@ use cosmwasm_schema::cw_serde; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult}; +use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response}; use cw2::set_contract_version; -use cw721_base::{msg, ContractError, Extension}; +use cw721_base::{ + error::ContractError, msg, DefaultOptionalCollectionExtension, + DefaultOptionalCollectionExtensionMsg, DefaultOptionalNftExtension, + DefaultOptionalNftExtensionMsg, +}; use cw_storage_plus::Item; -pub type ExecuteMsg = msg::ExecuteMsg; -pub type QueryMsg = msg::QueryMsg; +pub type ExecuteMsg = + msg::ExecuteMsg; +pub type QueryMsg = + msg::QueryMsg; #[cw_serde] pub struct InstantiateMsg { @@ -36,10 +42,12 @@ pub fn instantiate( deps.branch(), env, info, - msg::InstantiateMsg { + msg::InstantiateMsg:: { name: msg.name, symbol: msg.symbol, minter: Some(msg.minter), + creator: None, + collection_info_extension: None, withdraw_address: None, }, )?; @@ -71,6 +79,6 @@ pub fn execute( } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { cw721_base::entry::query(deps, env, msg) } diff --git a/contracts/ics721-base-tester/src/contract.rs b/contracts/ics721-base-tester/src/contract.rs index 15e3a988..8c9fecee 100644 --- a/contracts/ics721-base-tester/src/contract.rs +++ b/contracts/ics721-base-tester/src/contract.rs @@ -1,10 +1,11 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_json_binary, Binary, Deps, DepsMut, Env, IbcMsg, IbcTimeout, MessageInfo, Response, + to_json_binary, Binary, Deps, DepsMut, Empty, Env, IbcMsg, IbcTimeout, MessageInfo, Response, StdResult, WasmMsg, }; use cw2::set_contract_version; +use cw721::{DefaultOptionalCollectionExtensionMsg, DefaultOptionalNftExtensionMsg}; use ics721_types::ibc_types::{IbcOutgoingMsg, NonFungibleTokenPacketData}; use crate::{ @@ -63,7 +64,8 @@ pub fn execute( } mod receive_callbacks { - use cosmwasm_std::{ensure_eq, from_json, DepsMut, MessageInfo, Response}; + use cosmwasm_std::{ensure_eq, from_json, DepsMut, Empty, MessageInfo, Response}; + use cw721::{DefaultOptionalCollectionExtension, DefaultOptionalNftExtension}; use ics721_types::{ ibc_types::NonFungibleTokenPacketData, types::{Ics721AckCallbackMsg, Ics721ReceiveCallbackMsg, Ics721Status}, @@ -77,7 +79,7 @@ mod receive_callbacks { pub(crate) fn handle_receive_cw_callback( deps: DepsMut, - _msg: cw721::Cw721ReceiveMsg, + _msg: cw721::receiver::Cw721ReceiveMsg, ) -> Result { // We got the callback, so its working CW721_RECEIVE.save(deps.storage, &"success".to_string())?; @@ -128,11 +130,15 @@ mod receive_callbacks { NFT_CONTRACT.save(deps.storage, &deps.api.addr_validate(&nft_contract)?)?; - let owner: Option = deps + let owner: Option = deps .querier - .query_wasm_smart::( + .query_wasm_smart::( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: packet.token_ids[0].clone().into(), include_expired: None, }, @@ -173,9 +179,13 @@ mod receive_callbacks { let owner = deps .querier - .query_wasm_smart::( + .query_wasm_smart::( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: packet.token_ids[0].clone().into(), include_expired: None, }, @@ -217,7 +227,11 @@ fn execute_send_nft( // Send send msg to cw721, send it to ics721 with the correct msg. let msg = WasmMsg::Execute { contract_addr: cw721, - msg: to_json_binary(&cw721::Cw721ExecuteMsg::SendNft { + msg: to_json_binary(&cw721::msg::Cw721ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::SendNft { contract: ics721, token_id, msg: to_json_binary(&IbcOutgoingMsg { diff --git a/contracts/ics721-base-tester/src/msg.rs b/contracts/ics721-base-tester/src/msg.rs index 75a0bd3a..c86291eb 100644 --- a/contracts/ics721-base-tester/src/msg.rs +++ b/contracts/ics721-base-tester/src/msg.rs @@ -42,7 +42,7 @@ pub struct InstantiateMsg { #[allow(clippy::large_enum_variant)] // `data` field is a bit large // for clippy's taste. pub enum ExecuteMsg { - ReceiveNft(cw721::Cw721ReceiveMsg), + ReceiveNft(cw721::receiver::Cw721ReceiveMsg), Ics721ReceiveCallback(ics721_types::types::Ics721ReceiveCallbackMsg), Ics721AckCallback(ics721_types::types::Ics721AckCallbackMsg), SendNft { diff --git a/contracts/ics721-base-tester/src/state.rs b/contracts/ics721-base-tester/src/state.rs index 4ad7df15..6eb17fc4 100644 --- a/contracts/ics721-base-tester/src/state.rs +++ b/contracts/ics721-base-tester/src/state.rs @@ -7,7 +7,7 @@ pub const ACK_MODE: Item = Item::new("ack_mode"); pub const LAST_ACK: Item = Item::new("ack_mode"); pub const ICS721: Item = Item::new("ics721"); -pub const SENT_CALLBACK: Item> = Item::new("sent"); -pub const RECEIVED_CALLBACK: Item> = Item::new("received"); +pub const SENT_CALLBACK: Item> = Item::new("sent"); +pub const RECEIVED_CALLBACK: Item> = Item::new("received"); pub const NFT_CONTRACT: Item = Item::new("nft_contract"); pub const CW721_RECEIVE: Item = Item::new("cw721_received"); diff --git a/contracts/sg-ics721/src/testing/integration_tests.rs b/contracts/sg-ics721/src/testing/integration_tests.rs index 49cf3b00..7251b23d 100644 --- a/contracts/sg-ics721/src/testing/integration_tests.rs +++ b/contracts/sg-ics721/src/testing/integration_tests.rs @@ -7,6 +7,10 @@ use cosmwasm_std::{ RecoverPubkeyError, Reply, Response, StdError, StdResult, Storage, VerificationError, WasmMsg, }; use cw2::set_contract_version; +use cw721::{ + DefaultOptionalCollectionExtension, DefaultOptionalCollectionExtensionMsg, + DefaultOptionalNftExtension, DefaultOptionalNftExtensionMsg, +}; use cw721_base::msg::QueryMsg as Cw721QueryMsg; use cw_cii::{Admin, ContractInstantiateInfo}; use cw_multi_test::{ @@ -19,7 +23,7 @@ use ics721::{ ibc::Ics721Ibc, msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}, query::Ics721Query, - state::CollectionData, + state::{CollectionData, UniversalCollectionInfoResponse, UniversalNftInfoResponse}, token_types::VoucherCreation, }; use ics721_types::{ @@ -288,6 +292,7 @@ struct Test { } impl Test { + /// Test setup with optional pauser and proxy contracts. fn new( outgoing_proxy: bool, incoming_proxy: bool, @@ -518,7 +523,11 @@ impl Test { .execute_contract( self.source_cw721_owner.clone(), self.source_cw721.clone(), - &cw721_base::msg::ExecuteMsg::::Mint { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::Mint { token_id: self.nfts_minted.to_string(), owner: owner.to_string(), token_uri: None, @@ -710,19 +719,24 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info: cw721::ContractInfoResponse = test + #[allow(deprecated)] + let contract_info: UniversalCollectionInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + UniversalCollectionInfoResponse { name: class_id.to_string(), // name is set to class_id - symbol: class_id.to_string() // symbol is set to class_id + symbol: class_id.to_string(), // symbol is set to class_id } ); @@ -748,12 +762,16 @@ fn test_do_instantiate_and_mint() { ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -762,12 +780,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -779,7 +801,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), token_id: "1".to_string(), }, @@ -788,7 +814,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -802,12 +828,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -886,19 +916,24 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol is using class data for instantiated nft contract - let contract_info: cw721::ContractInfoResponse = test + #[allow(deprecated)] + let contract_info: UniversalCollectionInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + UniversalCollectionInfoResponse { name: "ark".to_string(), - symbol: "protocol".to_string() + symbol: "protocol".to_string(), } ); @@ -924,12 +959,16 @@ fn test_do_instantiate_and_mint() { ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -938,12 +977,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -955,7 +998,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), // new recipient - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), token_id: "1".to_string(), }, @@ -964,7 +1011,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -978,12 +1025,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1060,19 +1111,24 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info: cw721::ContractInfoResponse = test + let contract_info: UniversalCollectionInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + UniversalCollectionInfoResponse { name: class_id.to_string(), - symbol: class_id.to_string() + symbol: class_id.to_string(), } ); @@ -1098,12 +1154,16 @@ fn test_do_instantiate_and_mint() { ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -1112,12 +1172,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -1129,7 +1193,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), // new owner token_id: "1".to_string(), }, @@ -1138,7 +1206,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1153,12 +1221,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1238,19 +1310,24 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info: cw721::ContractInfoResponse = test + let contract_info: UniversalCollectionInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + UniversalCollectionInfoResponse { name: "collection-name".to_string(), - symbol: "collection-symbol".to_string() + symbol: "collection-symbol".to_string(), } ); @@ -1276,12 +1353,16 @@ fn test_do_instantiate_and_mint() { ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -1290,12 +1371,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -1307,7 +1392,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), // new owner token_id: "1".to_string(), }, @@ -1316,7 +1405,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1331,12 +1420,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1416,19 +1509,24 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info: cw721::ContractInfoResponse = test + let contract_info: UniversalCollectionInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + UniversalCollectionInfoResponse { name: "collection-name".to_string(), - symbol: "collection-symbol".to_string() + symbol: "collection-symbol".to_string(), } ); @@ -1454,12 +1552,16 @@ fn test_do_instantiate_and_mint() { ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: UniversalNftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -1468,12 +1570,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: UniversalNftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -1485,7 +1591,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), // new owner token_id: "1".to_string(), }, @@ -1494,7 +1604,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1509,12 +1619,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1629,34 +1743,44 @@ fn test_do_instantiate_and_mint_2_different_collections() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info_1: cw721::ContractInfoResponse = test + let contract_info_1: UniversalCollectionInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_1.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); - let contract_info_2: cw721::ContractInfoResponse = test + let contract_info_2: UniversalCollectionInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_2.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info_1, - cw721::ContractInfoResponse { + UniversalCollectionInfoResponse { name: class_id_1.to_string(), // name is set to class_id - symbol: class_id_1.to_string() // symbol is set to class_id + symbol: class_id_1.to_string(), // symbol is set to class_id } ); assert_eq!( contract_info_2, - cw721::ContractInfoResponse { + UniversalCollectionInfoResponse { name: class_id_2.to_string(), // name is set to class_id - symbol: class_id_2.to_string() // symbol is set to class_id + symbol: class_id_2.to_string(), // symbol is set to class_id } ); @@ -1699,22 +1823,30 @@ fn test_do_instantiate_and_mint_2_different_collections() { ); // Check that token_uri was set properly. - let token_info_1_1: cw721::NftInfoResponse = test + let token_info_1_1: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_1.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) .unwrap(); - let token_info_2_1: cw721::NftInfoResponse = test + let token_info_2_1: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_2.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -1724,22 +1856,30 @@ fn test_do_instantiate_and_mint_2_different_collections() { Some("https://moonphase.is/image.svg".to_string()) ); assert_eq!(token_info_2_1.token_uri, Some("https://mr.t".to_string())); - let token_info_1_2: cw721::NftInfoResponse = test + let token_info_1_2: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_1.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) .unwrap(); - let token_info_2_2: cw721::NftInfoResponse = test + let token_info_2_2: UniversalNftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_2.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -1758,7 +1898,11 @@ fn test_do_instantiate_and_mint_2_different_collections() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract_1.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract_1.to_string(), token_id: "1".to_string(), }, @@ -1769,7 +1913,11 @@ fn test_do_instantiate_and_mint_2_different_collections() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract_2.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract_2.to_string(), token_id: "1".to_string(), }, @@ -1778,7 +1926,7 @@ fn test_do_instantiate_and_mint_2_different_collections() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner_1: cw721::OwnerOfResponse = test + let owner_1: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1789,7 +1937,7 @@ fn test_do_instantiate_and_mint_2_different_collections() { }, ) .unwrap(); - let owner_2: cw721::OwnerOfResponse = test + let owner_2: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1804,23 +1952,31 @@ fn test_do_instantiate_and_mint_2_different_collections() { assert_eq!(owner_2.owner, nft_contract_2.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner_1: cw721::OwnerOfResponse = test + let base_owner_1: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract_1, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, ) .unwrap(); - let base_owner_2: cw721::OwnerOfResponse = test + let base_owner_2: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract_2, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1946,12 +2102,16 @@ fn test_do_instantiate_and_mint_no_instantiate() { ); // Make sure we have our tokens. - let tokens: cw721::TokensResponse = test + let tokens: cw721::msg::TokensResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::AllTokens { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::AllTokens { start_after: None, limit: None, }, @@ -2035,7 +2195,7 @@ fn test_no_proxy_unknown_msg() { .execute_contract( test.app.api().addr_make("proxy"), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), msg: to_json_binary(&msg).unwrap(), @@ -2073,7 +2233,7 @@ fn test_no_proxy_unauthorized() { .execute_contract( test.app.api().addr_make("foo"), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), msg: to_json_binary(&msg).unwrap(), @@ -2131,17 +2291,21 @@ 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), source_cw721.clone(), - &cw721_base::ExecuteMsg::::Mint { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::Mint { token_id: "1".to_string(), owner: test.ics721.to_string(), token_uri: None, - extension: Empty::default(), + extension: None, }, &[], ) @@ -2154,7 +2318,7 @@ fn test_proxy_authorized() { .execute_contract( proxy_address, test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test .app .api() @@ -2194,7 +2358,7 @@ fn test_receive_nft() { .execute_contract( test.source_cw721.clone(), test.ics721.clone(), - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.source_cw721_owner.to_string(), token_id, msg: to_json_binary(&IbcOutgoingMsg { @@ -2269,7 +2433,7 @@ fn test_no_receive_with_proxy() { .execute_contract( test.app.api().addr_make("cw721"), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), msg: to_json_binary(&IbcOutgoingMsg { diff --git a/packages/ics721/src/execute.rs b/packages/ics721/src/execute.rs index 67d4297d..1865fc14 100644 --- a/packages/ics721/src/execute.rs +++ b/packages/ics721/src/execute.rs @@ -4,6 +4,10 @@ use cosmwasm_std::{ from_json, to_json_binary, Addr, Binary, ContractInfoResponse, Deps, DepsMut, Empty, Env, Event, IbcMsg, MessageInfo, Order, Response, StdResult, SubMsg, WasmMsg, }; +use cw721::{ + DefaultOptionalCollectionExtension, DefaultOptionalCollectionExtensionMsg, + DefaultOptionalNftExtension, DefaultOptionalNftExtensionMsg, +}; use cw_storage_plus::Map; use ics721_types::{ ibc_types::{IbcOutgoingMsg, IbcOutgoingProxyMsg, NonFungibleTokenPacketData}, @@ -107,7 +111,7 @@ where ) -> Result, ContractError> { PO.error_if_paused(deps.storage)?; match msg { - ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender, token_id, msg, @@ -185,7 +189,11 @@ where .querier .query_wasm_smart( child_collection.clone(), - &cw721::Cw721QueryMsg::AllNftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::AllNftInfo { token_id: token_id.clone().into(), include_expired: None, }, @@ -206,7 +214,11 @@ where // note: this requires approval from recipient, or recipient burns it himself let burn_msg = WasmMsg::Execute { contract_addr: child_collection.to_string(), - msg: to_json_binary(&cw721::Cw721ExecuteMsg::Burn { + msg: to_json_binary(&cw721::msg::Cw721ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::Burn { token_id: token_id.clone().into(), })?, funds: vec![], @@ -268,7 +280,11 @@ where .querier .query_wasm_smart( home_collection.clone(), - &cw721::Cw721QueryMsg::AllNftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::AllNftInfo { token_id: token_id.clone().into(), include_expired: None, }, @@ -284,7 +300,11 @@ where // transfer NFT let transfer_msg = WasmMsg::Execute { contract_addr: home_collection.to_string(), - msg: to_json_binary(&cw721::Cw721ExecuteMsg::TransferNft { + msg: to_json_binary(&cw721::msg::Cw721ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: recipient.to_string(), token_id: token_id.clone().into(), })?, @@ -401,7 +421,11 @@ where // make sure NFT is escrowed by ics721 let UniversalAllNftInfoResponse { access, info } = deps.querier.query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::AllNftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::AllNftInfo { token_id: token_id.clone().into(), include_expired: None, }, @@ -608,12 +632,15 @@ where .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: Some(env.contract.address.to_string()), - withdraw_address: Some(creator), - }; + let mut instantiate_msg = + cw721_base::msg::InstantiateMsg:: { + name: class.id.clone().into(), + symbol: class.id.clone().into(), + minter: Some(env.contract.address.to_string()), + creator: None, + collection_info_extension: None, + withdraw_address: Some(creator), + }; // use collection data for setting name and symbol let collection_data = class @@ -655,7 +682,11 @@ where .map(|token_id| { Ok(WasmMsg::Execute { contract_addr: nft_contract.to_string(), - msg: to_json_binary(&cw721::Cw721ExecuteMsg::TransferNft { + msg: to_json_binary(&cw721::msg::Cw721ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: receiver.to_string(), token_id: token_id.into(), })?, @@ -686,11 +717,15 @@ where // Also note that this is set for every token, regardless of if data is None. TOKEN_METADATA.save(deps.storage, (class_id.clone(), id.clone()), &data)?; - let msg = cw721_base::msg::ExecuteMsg::::Mint { + let msg = cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::Mint { token_id: id.into(), token_uri: uri, owner: receiver.to_string(), - extension: Empty::default(), + extension: None, }; Ok(WasmMsg::Execute { contract_addr: nft_contract.to_string(), diff --git a/packages/ics721/src/ibc.rs b/packages/ics721/src/ibc.rs index fa96eef6..b6190a9d 100644 --- a/packages/ics721/src/ibc.rs +++ b/packages/ics721/src/ibc.rs @@ -4,6 +4,7 @@ use cosmwasm_std::{ IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, Never, Reply, Response, StdResult, SubMsgResult, WasmMsg, }; +use cw721::{DefaultOptionalCollectionExtensionMsg, DefaultOptionalNftExtensionMsg}; use cw_utils::parse_reply_instantiate_data; use ics721_types::{ibc_types::NonFungibleTokenPacketData, types::Ics721Status}; use serde::{de::DeserializeOwned, Serialize}; @@ -142,7 +143,11 @@ where messages.push(WasmMsg::Execute { contract_addr: nft_contract.to_string(), - msg: to_json_binary(&cw721::Cw721ExecuteMsg::Burn { + msg: to_json_binary(&cw721::msg::Cw721ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::Burn { token_id: token.into(), })?, funds: vec![], @@ -212,7 +217,11 @@ where .remove(deps.storage, (message.class_id.clone(), token_id.clone())); Ok(WasmMsg::Execute { contract_addr: nft_contract.to_string(), - msg: to_json_binary(&cw721::Cw721ExecuteMsg::TransferNft { + msg: to_json_binary(&cw721::msg::Cw721ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: sender.to_string(), token_id: token_id.into(), })?, diff --git a/packages/ics721/src/msg.rs b/packages/ics721/src/msg.rs index 4d2563a3..c60e57c8 100644 --- a/packages/ics721/src/msg.rs +++ b/packages/ics721/src/msg.rs @@ -39,7 +39,7 @@ pub struct InstantiateMsg { pub enum ExecuteMsg { /// Receives a NFT to be IBC transfered away. The `msg` field must /// be a binary encoded `IbcOutgoingMsg`. - ReceiveNft(cw721::Cw721ReceiveMsg), + ReceiveNft(cw721::receiver::Cw721ReceiveMsg), /// Pauses the ICS721 contract. Only the pauser may call this. In pausing /// the contract, the pauser burns the right to do so again. @@ -145,7 +145,7 @@ pub enum QueryMsg { /// Gets the owner of the NFT identified by CLASS_ID and /// TOKEN_ID. Errors if no such NFT exists. Returns /// `cw721::OwnerOfResonse`. - #[returns(::cw721::OwnerOfResponse)] + #[returns(::cw721::msg::OwnerOfResponse)] Owner { class_id: String, token_id: String }, /// Gets the address that may pause this contract if one is set. diff --git a/packages/ics721/src/query.rs b/packages/ics721/src/query.rs index 4f756cd3..f0a43b3a 100644 --- a/packages/ics721/src/query.rs +++ b/packages/ics721/src/query.rs @@ -1,4 +1,7 @@ -use cosmwasm_std::{to_json_binary, Addr, Binary, Deps, Env, Order, StdError, StdResult, Storage}; +use cosmwasm_std::{ + to_json_binary, Addr, Binary, Deps, Empty, Env, Order, StdError, StdResult, Storage, +}; +use cw721::{DefaultOptionalCollectionExtension, DefaultOptionalNftExtension}; use cw_storage_plus::{Bound, Map}; use sha2::{Digest, Sha256}; @@ -150,7 +153,11 @@ pub fn query_token_metadata( }; let UniversalAllNftInfoResponse { info, .. } = deps.querier.query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::AllNftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::AllNftInfo { token_id: token_id.clone().into(), include_expired: None, }, @@ -166,11 +173,15 @@ pub fn query_owner( deps: Deps, class_id: String, token_id: String, -) -> StdResult { +) -> StdResult { let nft_contract = load_nft_contract_for_class_id(deps.storage, class_id)?; - let resp: cw721::OwnerOfResponse = deps.querier.query_wasm_smart( + let resp: cw721::msg::OwnerOfResponse = deps.querier.query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id, include_expired: None, }, diff --git a/packages/ics721/src/state.rs b/packages/ics721/src/state.rs index 0c43b0bc..b7841c87 100644 --- a/packages/ics721/src/state.rs +++ b/packages/ics721/src/state.rs @@ -54,20 +54,20 @@ pub const ADMIN_USED_FOR_CW721: Item> = Item::new("l"); /// Bug: https://github.com/CosmWasm/cosmwasm/issues/2155 pub const CONTRACT_ADDR_LENGTH: Item = Item::new("n"); -#[derive(Deserialize)] +#[derive(Deserialize, Debug, PartialEq)] pub struct UniversalAllNftInfoResponse { pub access: UniversalOwnerOfResponse, pub info: UniversalNftInfoResponse, } /// Based on `cw721::ContractInfoResponse v0.18` -#[derive(Deserialize)] +#[derive(Deserialize, Debug, PartialEq)] pub struct UniversalCollectionInfoResponse { pub name: String, pub symbol: String, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug, PartialEq)] pub struct UniversalNftInfoResponse { pub token_uri: Option, @@ -93,7 +93,7 @@ pub struct CollectionData { pub num_tokens: Option, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug, PartialEq)] pub struct UniversalOwnerOfResponse { pub owner: String, @@ -131,12 +131,12 @@ mod tests { #[test] fn test_universal_deserialize() { - let start = cw721::AllNftInfoResponse:: { - access: cw721::OwnerOfResponse { + let start = cw721::msg::AllNftInfoResponse:: { + access: cw721::msg::OwnerOfResponse { owner: "foo".to_string(), approvals: vec![], }, - info: cw721::NftInfoResponse { + info: cw721::msg::NftInfoResponse { token_uri: None, extension: Coin::new(100, "ujuno"), }, diff --git a/packages/ics721/src/testing/contract.rs b/packages/ics721/src/testing/contract.rs index 6980a4f3..d2cd6456 100644 --- a/packages/ics721/src/testing/contract.rs +++ b/packages/ics721/src/testing/contract.rs @@ -5,8 +5,11 @@ use cosmwasm_std::{ to_json_binary, Addr, ContractResult, CosmosMsg, DepsMut, Empty, IbcMsg, IbcTimeout, Order, QuerierResult, Response, StdResult, SubMsg, Timestamp, WasmQuery, }; -use cw721::{AllNftInfoResponse, NftInfoResponse, NumTokensResponse}; -use cw721_base::QueryMsg; +use cw721::{ + msg::{AllNftInfoResponse, NftInfoResponse, NumTokensResponse}, + DefaultOptionalCollectionExtension, DefaultOptionalNftExtension, +}; +use cw721_base::msg::QueryMsg; use cw_cii::ContractInstantiateInfo; use cw_ownable::Ownership; use cw_storage_plus::Map; @@ -85,7 +88,25 @@ fn mock_querier(query: &WasmQuery) -> QuerierResult { cosmwasm_std::WasmQuery::Smart { contract_addr: _, msg, - } => match from_json::>(&msg).unwrap() { + } => match from_json::< + cw721_base::msg::QueryMsg< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >, + >(&msg) + .unwrap() + { + #[allow(deprecated)] + QueryMsg::Minter {} => QuerierResult::Ok(ContractResult::Ok( + to_json_binary(&Ownership:: { + owner: Some(Addr::unchecked(OWNER_ADDR)), + pending_owner: None, + pending_expiry: None, + }) + .unwrap(), + )), + #[allow(deprecated)] QueryMsg::Ownership {} => QuerierResult::Ok(ContractResult::Ok( to_json_binary(&Ownership:: { owner: Some(Addr::unchecked(OWNER_ADDR)), @@ -94,9 +115,17 @@ fn mock_querier(query: &WasmQuery) -> QuerierResult { }) .unwrap(), )), + QueryMsg::GetMinterOwnership {} => QuerierResult::Ok(ContractResult::Ok( + to_json_binary(&Ownership:: { + owner: Some(Addr::unchecked(OWNER_ADDR)), + pending_owner: None, + pending_expiry: None, + }) + .unwrap(), + )), QueryMsg::AllNftInfo { .. } => QuerierResult::Ok(ContractResult::Ok( to_json_binary(&AllNftInfoResponse::> { - access: cw721::OwnerOfResponse { + access: cw721::msg::OwnerOfResponse { owner: MOCK_CONTRACT_ADDR.to_string(), approvals: vec![], }, @@ -107,10 +136,26 @@ fn mock_querier(query: &WasmQuery) -> QuerierResult { }) .unwrap(), )), + #[allow(deprecated)] QueryMsg::ContractInfo {} => QuerierResult::Ok(ContractResult::Ok( - to_json_binary(&cw721::ContractInfoResponse { + to_json_binary(&cw721::msg::CollectionInfoAndExtensionResponse::< + DefaultOptionalCollectionExtension, + > { + name: "name".to_string(), + symbol: "symbol".to_string(), + extension: DefaultOptionalCollectionExtension::default(), + updated_at: Timestamp::default(), + }) + .unwrap(), + )), + QueryMsg::GetCollectionInfoAndExtension {} => QuerierResult::Ok(ContractResult::Ok( + to_json_binary(&cw721::msg::CollectionInfoAndExtensionResponse::< + DefaultOptionalCollectionExtension, + > { name: "name".to_string(), symbol: "symbol".to_string(), + extension: DefaultOptionalCollectionExtension::default(), + updated_at: Timestamp::default(), }) .unwrap(), )), @@ -138,9 +183,9 @@ fn mock_querier_v016(query: &WasmQuery) -> QuerierResult { cosmwasm_std::WasmQuery::Smart { contract_addr: _, msg, - } => match from_json::>(&msg).unwrap() { + } => match from_json::>(&msg).unwrap() { // unwrap using latest (not old) cw721-base, since it is backwards compatible - cw721_base::msg::QueryMsg::Minter {} => QuerierResult::Ok(ContractResult::Ok( + cw721_base_016::msg::QueryMsg::Minter {} => QuerierResult::Ok(ContractResult::Ok( to_json_binary( // return v016 response &cw721_base_016::msg::MinterResponse { @@ -149,30 +194,34 @@ fn mock_querier_v016(query: &WasmQuery) -> QuerierResult { ) .unwrap(), )), - cw721_base::msg::QueryMsg::AllNftInfo { .. } => QuerierResult::Ok(ContractResult::Ok( - to_json_binary( - // return v016 response - &cw721_016::AllNftInfoResponse::> { - access: cw721_016::OwnerOfResponse { - owner: MOCK_CONTRACT_ADDR.to_string(), - approvals: vec![], + cw721_base_016::msg::QueryMsg::AllNftInfo { .. } => { + QuerierResult::Ok(ContractResult::Ok( + to_json_binary( + // return v016 response + &cw721_016::AllNftInfoResponse::> { + access: cw721_016::OwnerOfResponse { + owner: MOCK_CONTRACT_ADDR.to_string(), + approvals: vec![], + }, + info: cw721_016::NftInfoResponse { + token_uri: Some("https://moonphase.is/image.svg".to_string()), + extension: None, + }, }, - info: cw721_016::NftInfoResponse { - token_uri: Some("https://moonphase.is/image.svg".to_string()), - extension: None, - }, - }, - ) - .unwrap(), - )), - QueryMsg::ContractInfo {} => QuerierResult::Ok(ContractResult::Ok( - to_json_binary(&cw721_016::ContractInfoResponse { - name: "name".to_string(), - symbol: "symbol".to_string(), - }) - .unwrap(), - )), - QueryMsg::NumTokens {} => QuerierResult::Ok(ContractResult::Ok( + ) + .unwrap(), + )) + } + cw721_base_016::msg::QueryMsg::ContractInfo {} => { + QuerierResult::Ok(ContractResult::Ok( + to_json_binary(&cw721_016::ContractInfoResponse { + name: "name".to_string(), + symbol: "symbol".to_string(), + }) + .unwrap(), + )) + } + cw721_base_016::msg::QueryMsg::NumTokens {} => QuerierResult::Ok(ContractResult::Ok( to_json_binary(&cw721_016::NumTokensResponse { count: 1 }).unwrap(), )), _ => QuerierResult::Err(cosmwasm_std::SystemError::Unknown {}), // throws error for Ownership query diff --git a/packages/ics721/src/testing/integration_tests.rs b/packages/ics721/src/testing/integration_tests.rs index bda6f06b..009a73bb 100644 --- a/packages/ics721/src/testing/integration_tests.rs +++ b/packages/ics721/src/testing/integration_tests.rs @@ -7,6 +7,10 @@ use cosmwasm_std::{ RecoverPubkeyError, Reply, Response, StdError, StdResult, Storage, VerificationError, WasmMsg, }; use cw2::set_contract_version; +use cw721::{ + DefaultOptionalCollectionExtension, DefaultOptionalCollectionExtensionMsg, + DefaultOptionalNftExtension, DefaultOptionalNftExtensionMsg, +}; use cw721_base::msg::{InstantiateMsg as Cw721InstantiateMsg, QueryMsg as Cw721QueryMsg}; use cw_cii::{Admin, ContractInstantiateInfo}; use cw_multi_test::{ @@ -368,10 +372,12 @@ impl Test { .instantiate_contract( source_cw721_id, source_cw721_owner.clone(), - &Cw721InstantiateMsg { + &Cw721InstantiateMsg:: { name: "name".to_string(), symbol: "symbol".to_string(), minter: Some(source_cw721_owner.to_string()), + creator: None, + collection_info_extension: None, withdraw_address: None, }, &[], @@ -523,7 +529,11 @@ impl Test { .wrap() .query_wasm_smart( self.source_cw721.clone(), - &cw721_base::msg::QueryMsg::::AllNftInfo { + &cw721_base::msg::QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::AllNftInfo { token_id, include_expired: None, }, @@ -538,7 +548,11 @@ impl Test { .execute_contract( self.source_cw721_owner.clone(), self.source_cw721.clone(), - &cw721_base::msg::ExecuteMsg::::Mint { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::Mint { token_id: self.nfts_minted.to_string(), owner: owner.to_string(), token_uri: None, @@ -733,29 +747,40 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol contains class id for instantiated nft contract + #[allow(deprecated)] let contract_info: cw721::ContractInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + cw721::msg::CollectionInfoAndExtensionResponse:: { name: class_id.to_string(), // name is set to class_id - symbol: class_id.to_string() // symbol is set to class_id + symbol: class_id.to_string(), // symbol is set to class_id + extension: None, + updated_at: contract_info.updated_at, // ignore this field } ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -764,12 +789,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -781,7 +810,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), token_id: "1".to_string(), }, @@ -790,7 +823,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -804,12 +837,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -887,29 +924,40 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol is using class data for instantiated nft contract + #[allow(deprecated)] let contract_info: cw721::ContractInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + cw721::msg::CollectionInfoAndExtensionResponse:: { name: "ark".to_string(), - symbol: "protocol".to_string() + symbol: "protocol".to_string(), + extension: None, + updated_at: contract_info.updated_at, // ignore this field } ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -918,12 +966,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -935,7 +987,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), // new recipient - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), token_id: "1".to_string(), }, @@ -944,7 +1000,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -958,12 +1014,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1040,29 +1100,41 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info: cw721::ContractInfoResponse = test + let contract_info: cw721::msg::CollectionInfoAndExtensionResponse< + DefaultOptionalCollectionExtension, + > = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::GetCollectionInfoAndExtension {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + cw721::msg::CollectionInfoAndExtensionResponse:: { name: class_id.to_string(), - symbol: class_id.to_string() + symbol: class_id.to_string(), + extension: None, + updated_at: contract_info.updated_at, // ignore this field } ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -1071,12 +1143,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -1088,7 +1164,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), // new owner token_id: "1".to_string(), }, @@ -1097,7 +1177,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1112,12 +1192,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1197,29 +1281,42 @@ fn test_do_instantiate_and_mint() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info: cw721::ContractInfoResponse = test + let contract_info: cw721::msg::CollectionInfoAndExtensionResponse< + DefaultOptionalCollectionExtension, + > = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info, - cw721::ContractInfoResponse { + cw721::msg::CollectionInfoAndExtensionResponse:: { name: "collection-name".to_string(), - symbol: "collection-symbol".to_string() + symbol: "collection-symbol".to_string(), + extension: None, + updated_at: contract_info.updated_at, // ignore this field } ); // Check that token_uri was set properly. - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -1228,12 +1325,16 @@ fn test_do_instantiate_and_mint() { token_info.token_uri, Some("https://moonphase.is/image.svg".to_string()) ); - let token_info: cw721::NftInfoResponse = test + let token_info: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -1245,7 +1346,11 @@ fn test_do_instantiate_and_mint() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract.to_string(), // new owner token_id: "1".to_string(), }, @@ -1254,7 +1359,7 @@ fn test_do_instantiate_and_mint() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner: cw721::OwnerOfResponse = test + let owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1269,12 +1374,16 @@ fn test_do_instantiate_and_mint() { assert_eq!(owner.owner, nft_contract.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner: cw721::OwnerOfResponse = test + let base_owner: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1389,54 +1498,80 @@ fn test_do_instantiate_and_mint_2_different_collections() { .unwrap(); // check name and symbol contains class id for instantiated nft contract - let contract_info_1: cw721::ContractInfoResponse = test + let contract_info_1: cw721::msg::CollectionInfoAndExtensionResponse< + DefaultOptionalCollectionExtension, + > = test .app .wrap() .query_wasm_smart( nft_contract_1.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); - let contract_info_2: cw721::ContractInfoResponse = test + let contract_info_2: cw721::msg::CollectionInfoAndExtensionResponse< + DefaultOptionalCollectionExtension, + > = test .app .wrap() .query_wasm_smart( nft_contract_2.clone(), - &Cw721QueryMsg::::ContractInfo {}, + #[allow(deprecated)] + &Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, ) .unwrap(); assert_eq!( contract_info_1, - cw721::ContractInfoResponse { + cw721::msg::CollectionInfoAndExtensionResponse:: { name: class_id_1.to_string(), // name is set to class_id - symbol: class_id_1.to_string() // symbol is set to class_id + symbol: class_id_1.to_string(), // symbol is set to class_id + extension: None, + updated_at: contract_info_1.updated_at, // ignore this field } ); assert_eq!( contract_info_2, - cw721::ContractInfoResponse { + cw721::msg::CollectionInfoAndExtensionResponse:: { name: class_id_2.to_string(), // name is set to class_id - symbol: class_id_2.to_string() // symbol is set to class_id + symbol: class_id_2.to_string(), // symbol is set to class_id + extension: None, + updated_at: contract_info_2.updated_at, // ignore this field } ); // Check that token_uri was set properly. - let token_info_1_1: cw721::NftInfoResponse = test + let token_info_1_1: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_1.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) .unwrap(); - let token_info_2_1: cw721::NftInfoResponse = test + let token_info_2_1: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_2.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "1".to_string(), }, ) @@ -1446,22 +1581,30 @@ fn test_do_instantiate_and_mint_2_different_collections() { Some("https://moonphase.is/image.svg".to_string()) ); assert_eq!(token_info_2_1.token_uri, Some("https://mr.t".to_string())); - let token_info_1_2: cw721::NftInfoResponse = test + let token_info_1_2: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_1.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) .unwrap(); - let token_info_2_2: cw721::NftInfoResponse = test + let token_info_2_2: cw721::msg::NftInfoResponse = test .app .wrap() .query_wasm_smart( nft_contract_2.clone(), - &cw721::Cw721QueryMsg::NftInfo { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NftInfo { token_id: "2".to_string(), }, ) @@ -1480,7 +1623,11 @@ fn test_do_instantiate_and_mint_2_different_collections() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract_1.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract_1.to_string(), token_id: "1".to_string(), }, @@ -1491,7 +1638,11 @@ fn test_do_instantiate_and_mint_2_different_collections() { .execute_contract( test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN), nft_contract_2.clone(), - &cw721_base::msg::ExecuteMsg::::TransferNft { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::TransferNft { recipient: nft_contract_2.to_string(), token_id: "1".to_string(), }, @@ -1500,7 +1651,7 @@ fn test_do_instantiate_and_mint_2_different_collections() { .unwrap(); // ics721 owner query and check nft contract owns it - let owner_1: cw721::OwnerOfResponse = test + let owner_1: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1511,7 +1662,7 @@ fn test_do_instantiate_and_mint_2_different_collections() { }, ) .unwrap(); - let owner_2: cw721::OwnerOfResponse = test + let owner_2: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( @@ -1526,23 +1677,31 @@ fn test_do_instantiate_and_mint_2_different_collections() { assert_eq!(owner_2.owner, nft_contract_2.to_string()); // check cw721 owner query matches ics721 owner query - let base_owner_1: cw721::OwnerOfResponse = test + let base_owner_1: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract_1, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, ) .unwrap(); - let base_owner_2: cw721::OwnerOfResponse = test + let base_owner_2: cw721::msg::OwnerOfResponse = test .app .wrap() .query_wasm_smart( nft_contract_2, - &cw721::Cw721QueryMsg::OwnerOf { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::OwnerOf { token_id: "1".to_string(), include_expired: None, }, @@ -1647,12 +1806,16 @@ fn test_do_instantiate_and_mint_no_instantiate() { .unwrap(); // Make sure we have our tokens. - let tokens: cw721::TokensResponse = test + let tokens: cw721::msg::TokensResponse = test .app .wrap() .query_wasm_smart( nft_contract, - &cw721::Cw721QueryMsg::AllTokens { + &cw721::msg::Cw721QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::AllTokens { start_after: None, limit: None, }, @@ -1736,7 +1899,7 @@ fn test_no_proxy_unknown_msg() { .execute_contract( test.app.api().addr_make("proxy"), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), msg: to_json_binary(&msg).unwrap(), @@ -1774,7 +1937,7 @@ fn test_no_proxy_unauthorized() { .execute_contract( test.app.api().addr_make("foo"), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), msg: to_json_binary(&msg).unwrap(), @@ -1805,7 +1968,7 @@ fn test_proxy_authorized() { .instantiate_contract( source_cw721_id, test.app.api().addr_make("ekez"), - &cw721_base::InstantiateMsg { + &cw721_base::msg::InstantiateMsg:: { name: "token".to_string(), symbol: "nonfungible".to_string(), minter: Some( @@ -1814,6 +1977,8 @@ fn test_proxy_authorized() { .addr_make(COLLECTION_OWNER_SOURCE_CHAIN) .to_string(), ), + creator: None, + collection_info_extension: None, withdraw_address: None, }, &[], @@ -1827,11 +1992,15 @@ fn test_proxy_authorized() { .execute_contract( test.app.api().addr_make(COLLECTION_OWNER_SOURCE_CHAIN), source_cw721.clone(), - &cw721_base::ExecuteMsg::::Mint { + &cw721_base::msg::ExecuteMsg::< + DefaultOptionalNftExtensionMsg, + DefaultOptionalCollectionExtensionMsg, + Empty, + >::Mint { token_id: "1".to_string(), owner: test.ics721.to_string(), token_uri: None, - extension: Empty::default(), + extension: None, }, &[], ) @@ -1844,7 +2013,7 @@ fn test_proxy_authorized() { .execute_contract( proxy_address, test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test .app .api() @@ -1886,7 +2055,7 @@ fn test_receive_nft() { .execute_contract( test.source_cw721.clone(), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.source_cw721_owner.to_string(), token_id, msg: to_json_binary(&IbcOutgoingMsg { @@ -1954,7 +2123,7 @@ fn test_receive_nft() { .execute_contract( test.source_cw721.clone(), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.source_cw721_owner.to_string(), token_id, msg: to_json_binary(&IbcOutgoingMsg { @@ -2035,7 +2204,7 @@ fn test_admin_clean_and_unescrow_nft() { .execute_contract( test.source_cw721.clone(), test.ics721.clone(), - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.source_cw721_owner.to_string(), token_id: token_id_escrowed_by_ics721.clone(), msg: to_json_binary(&IbcOutgoingMsg { @@ -2169,7 +2338,7 @@ fn test_no_receive_with_proxy() { .execute_contract( test.app.api().addr_make("cw721"), test.ics721, - &ExecuteMsg::ReceiveNft(cw721::Cw721ReceiveMsg { + &ExecuteMsg::ReceiveNft(cw721::receiver::Cw721ReceiveMsg { sender: test.app.api().addr_make(NFT_OWNER_TARGET_CHAIN).to_string(), token_id: "1".to_string(), msg: to_json_binary(&IbcOutgoingMsg { diff --git a/packages/ics721/src/utils.rs b/packages/ics721/src/utils.rs index 3a29e4e5..e0cc99f4 100644 --- a/packages/ics721/src/utils.rs +++ b/packages/ics721/src/utils.rs @@ -1,14 +1,22 @@ use cosmwasm_std::{Addr, DepsMut, Empty, Env, StdResult}; -use cw721::NumTokensResponse; +use cw721::{ + msg::NumTokensResponse, DefaultOptionalCollectionExtension, DefaultOptionalNftExtension, +}; use cw_ownable::Ownership; use crate::state::{CollectionData, UniversalCollectionInfoResponse}; pub fn get_collection_data(deps: &DepsMut, collection: &Addr) -> StdResult { // cw721 v0.17 and higher holds ownership in the contract - let ownership: StdResult> = deps - .querier - .query_wasm_smart(collection, &cw721_base::msg::QueryMsg::Ownership:: {}); + #[allow(deprecated)] + let ownership: StdResult> = deps.querier.query_wasm_smart( + collection, + &cw721_base::msg::QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::Minter {}, + ); let owner = match ownership { Ok(ownership) => ownership.owner.map(|a| a.to_string()), Err(_) => { @@ -21,13 +29,23 @@ pub fn get_collection_data(deps: &DepsMut, collection: &Addr) -> StdResult::ContractInfo {}, + &cw721_base::msg::QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::ContractInfo {}, )?; let NumTokensResponse { count } = deps.querier.query_wasm_smart( collection, - &cw721_base::msg::QueryMsg::::NumTokens {}, + &cw721_base::msg::QueryMsg::< + DefaultOptionalNftExtension, + DefaultOptionalCollectionExtension, + Empty, + >::NumTokens {}, )?; Ok(CollectionData { From 6ef5aaad0ea4cdd02c053b3df7e3c46fd9153383 Mon Sep 17 00:00:00 2001 From: mr-t Date: Fri, 7 Jun 2024 13:04:52 +0200 Subject: [PATCH 10/18] format --- ts-relayer-tests/src/ics721.spec.ts | 520 +++++++--------------------- 1 file changed, 118 insertions(+), 402 deletions(-) diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index 746ff153..204b22db 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -1,19 +1,11 @@ -import { CosmWasmSigner } from "@confio/relayer"; -import { fromUtf8 } from "@cosmjs/encoding"; -import anyTest, { ExecutionContext, TestFn } from "ava"; -import { Order } from "cosmjs-types/ibc/core/channel/v1/channel"; - -import { instantiateContract } from "./controller"; -import { allTokens, approve, mint, ownerOf, sendNft } from "./cw721-utils"; -import { - adminCleanAndBurnNft, - adminCleanAndUnescrowNft, - incomingChannels, - migrate, - migrateIncomingProxy, - nftContracts, - outgoingChannels, -} from "./ics721-utils"; +import { CosmWasmSigner } from '@confio/relayer'; +import { fromUtf8 } from '@cosmjs/encoding'; +import anyTest, { ExecutionContext, TestFn } from 'ava'; +import { Order } from 'cosmjs-types/ibc/core/channel/v1/channel'; + +import { instantiateContract } from './controller'; +import { allTokens, approve, mint, ownerOf, sendNft } from './cw721-utils'; +import { adminCleanAndBurnNft, adminCleanAndUnescrowNft, incomingChannels, migrate, migrateIncomingProxy, nftContracts, outgoingChannels } from './ics721-utils'; import { assertAckErrors, assertAckSuccess, @@ -26,7 +18,7 @@ import { setupWasmClient, uploadAndInstantiate, uploadAndInstantiateAll, -} from "./utils"; +} from './utils'; interface TestContext { wasmClient: CosmWasmSigner; @@ -53,12 +45,11 @@ interface TestContext { 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"; +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'; const standardSetup = async (t: ExecutionContext) => { t.context.wasmClient = await setupWasmClient(MNEMONIC); @@ -73,8 +64,8 @@ const standardSetup = async (t: ExecutionContext) => { cw721: { path: WASM_FILE_CW721, instantiateMsg: { - name: "ark", - symbol: "ark", + name: 'ark', + symbol: 'ark', minter: wasmClient.senderAddress, }, }, @@ -95,8 +86,8 @@ const standardSetup = async (t: ExecutionContext) => { cw721: { path: WASM_FILE_CW721, instantiateMsg: { - name: "ark", - symbol: "ark", + name: 'ark', + symbol: 'ark', minter: osmoClient.senderAddress, }, }, @@ -114,76 +105,40 @@ const standardSetup = async (t: ExecutionContext) => { }, }; - const info = await uploadAndInstantiateAll( - wasmClient, - osmoClient, - wasmContracts, - osmoContracts - ); + const info = await uploadAndInstantiateAll(wasmClient, osmoClient, wasmContracts, osmoContracts); const wasmCw721Id = info.wasmContractInfos.cw721.codeId; const osmoCw721Id = info.osmoContractInfos.cw721.codeId; - const wasmCw721IncomingProxyId = - info.wasmContractInfos.cw721IncomingProxy.codeId; + const wasmCw721IncomingProxyId = info.wasmContractInfos.cw721IncomingProxy.codeId; t.context.wasmCw721IncomingProxyId = wasmCw721IncomingProxyId; - const osmoCw721IncomingProxyId = - info.osmoContractInfos.cw721IncomingProxy.codeId; + const osmoCw721IncomingProxyId = info.osmoContractInfos.cw721IncomingProxy.codeId; const wasmIcs721Id = info.wasmContractInfos.ics721.codeId; const osmoIcs721Id = info.osmoContractInfos.ics721.codeId; - const wasmCw721OutgoingProxyId = - info.wasmContractInfos.cw721OutgoingProxy.codeId; - const osmoCw721OutgoingProxyId = - info.osmoContractInfos.cw721OutgoingProxy.codeId; + const wasmCw721OutgoingProxyId = info.wasmContractInfos.cw721OutgoingProxy.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; t.log(`instantiating wasm ICS721 contract (${wasmIcs721Id})`); - const { contractAddress: wasmIcs721 } = await instantiateContract( - wasmClient, - wasmIcs721Id, - { cw721_base_code_id: wasmCw721Id }, - "label ics721" - ); + 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" - ); + 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, - wasmIcs721, - osmoIcs721, - Order.ORDER_UNORDERED, - "ics721-1" - ); - t.log( - `- channel for incoming proxy on both chains: ${JSON.stringify( - channelInfo.channel, - bigIntReplacer, - 2 - )}` - ); + t.log(`creating IBC connection and channel between ${wasmIcs721} <-> ${osmoIcs721}`); + const channelInfo = await createIbcConnectionAndChannel(wasmClient, osmoClient, wasmIcs721, osmoIcs721, Order.ORDER_UNORDERED, 'ics721-1'); + t.log(`- channel for incoming proxy on both chains: ${JSON.stringify(channelInfo.channel, bigIntReplacer, 2)}`); t.context.channel = channelInfo; - t.log( - `instantiating wasm cw721-incoming-proxy (${wasmCw721IncomingProxyId}) with channel ${channelInfo.channel.src.channelId}` - ); + t.log(`instantiating wasm cw721-incoming-proxy (${wasmCw721IncomingProxyId}) with channel ${channelInfo.channel.src.channelId}`); const { contractAddress: wasmCw721IncomingProxy } = await instantiateContract( wasmClient, wasmCw721IncomingProxyId, @@ -191,55 +146,33 @@ const standardSetup = async (t: ExecutionContext) => { origin: wasmIcs721, channels: [channelInfo.channel.src.channelId], }, - "label incoming proxy" + 'label incoming proxy' ); t.log(`- wasm cw721-incoming-proxy address: ${wasmCw721IncomingProxy}`); t.context.wasmCw721IncomingProxy = wasmCw721IncomingProxy; - t.log( - `migrate ${wasmIcs721} contract with incoming proxy ${wasmCw721IncomingProxy}` - ); + t.log(`migrate ${wasmIcs721} contract with incoming proxy ${wasmCw721IncomingProxy}`); await migrate(wasmClient, wasmIcs721, wasmIcs721Id, wasmCw721IncomingProxy); - const onlyOsmoIncomingChannelInfo = await createIbcConnectionAndChannel( - wasmClient, - osmoClient, - wasmIcs721, - osmoIcs721, - Order.ORDER_UNORDERED, - "ics721-1" - ); - t.log( - `- channel for incoming proxy only on wasm chain: ${JSON.stringify( - onlyOsmoIncomingChannelInfo.channel, - bigIntReplacer, - 2 - )}` - ); + const onlyOsmoIncomingChannelInfo = await createIbcConnectionAndChannel(wasmClient, osmoClient, wasmIcs721, osmoIcs721, Order.ORDER_UNORDERED, 'ics721-1'); + t.log(`- channel for incoming proxy only on wasm chain: ${JSON.stringify(onlyOsmoIncomingChannelInfo.channel, bigIntReplacer, 2)}`); t.context.onlyOsmoIncomingChannel = onlyOsmoIncomingChannelInfo; - t.log( - `instantiating osmo cw721-incoming-proxy (${osmoCw721IncomingProxyId}) with channel ${channelInfo.channel.dest.channelId}and ${onlyOsmoIncomingChannelInfo.channel.dest.channelId}` - ); + t.log(`instantiating osmo cw721-incoming-proxy (${osmoCw721IncomingProxyId}) with channel ${channelInfo.channel.dest.channelId}and ${onlyOsmoIncomingChannelInfo.channel.dest.channelId}`); const { contractAddress: osmoCw721IncomingProxy } = await instantiateContract( osmoClient, osmoCw721IncomingProxyId, { origin: osmoIcs721, - channels: [ - channelInfo.channel.dest.channelId, - onlyOsmoIncomingChannelInfo.channel.dest.channelId, - ], + channels: [channelInfo.channel.dest.channelId, onlyOsmoIncomingChannelInfo.channel.dest.channelId], }, - "label incoming proxy" + 'label incoming proxy' ); t.log(`- osmo cw721-incoming-proxy address: ${osmoCw721IncomingProxy}`); t.context.osmoCw721IncomingProxy = osmoCw721IncomingProxy; const per_block = 10; // use high rate limit to avoid test failures - t.log( - `instantiating wasm cw721-outgoing-proxy (${wasmCw721OutgoingProxyId}) with ${per_block} per blocks rate limit` - ); + t.log(`instantiating wasm cw721-outgoing-proxy (${wasmCw721OutgoingProxyId}) with ${per_block} per blocks rate limit`); const { contractAddress: wasmCw721OutgoingProxy } = await instantiateContract( wasmClient, wasmCw721OutgoingProxyId, @@ -247,14 +180,12 @@ const standardSetup = async (t: ExecutionContext) => { origin: wasmIcs721, rate_limit: { per_block }, }, - "label outgoing proxy" + 'label outgoing proxy' ); t.log(`- wasm cw721-outgoing-proxy address: ${wasmCw721OutgoingProxy}`); t.context.wasmCw721OutgoingProxy = wasmCw721OutgoingProxy; - t.log( - `instantiating osmo cw721-outgoing-proxy (${osmoCw721OutgoingProxyId}) with ${per_block} per blocks rate limit` - ); + t.log(`instantiating osmo cw721-outgoing-proxy (${osmoCw721OutgoingProxyId}) with ${per_block} per blocks rate limit`); const { contractAddress: osmoCw721OutgoingProxy } = await instantiateContract( osmoClient, osmoCw721OutgoingProxyId, @@ -262,57 +193,26 @@ const standardSetup = async (t: ExecutionContext) => { origin: osmoIcs721, rate_limit: { per_block }, }, - "label outgoing proxy" + 'label outgoing proxy' ); t.log(`- osmo cw721-outgoing-proxy address: ${osmoCw721OutgoingProxy}`); t.context.osmoCw721OutgoingProxy = osmoCw721OutgoingProxy; - t.log( - `migrate ${wasmIcs721} contract with incoming (${wasmCw721IncomingProxy}) and outgoing proxy (${wasmCw721OutgoingProxy})` - ); - await migrate( - wasmClient, - wasmIcs721, - wasmIcs721Id, - wasmCw721IncomingProxy, - wasmCw721OutgoingProxy - ); + t.log(`migrate ${wasmIcs721} contract with incoming (${wasmCw721IncomingProxy}) and outgoing proxy (${wasmCw721OutgoingProxy})`); + await migrate(wasmClient, wasmIcs721, wasmIcs721Id, wasmCw721IncomingProxy, wasmCw721OutgoingProxy); - t.log( - `migrate ${osmoIcs721} contract with incoming (${osmoCw721IncomingProxy}) and outgoing proxy (${osmoCw721OutgoingProxy})` - ); - await migrate( - osmoClient, - osmoIcs721, - osmoIcs721Id, - osmoCw721IncomingProxy, - osmoCw721OutgoingProxy - ); + t.log(`migrate ${osmoIcs721} contract with incoming (${osmoCw721IncomingProxy}) and outgoing proxy (${osmoCw721OutgoingProxy})`); + await migrate(osmoClient, osmoIcs721, osmoIcs721Id, osmoCw721IncomingProxy, osmoCw721OutgoingProxy); - 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.log( - `- other channel not WLed for incoming proxy: ${JSON.stringify( - otherChannelInfo.channel, - 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.log(`- other channel not WLed for incoming proxy: ${JSON.stringify(otherChannelInfo.channel, bigIntReplacer, 2)}`); t.context.otherChannel = otherChannelInfo; t.pass(); }; -test.serial("transfer NFT: wasmd -> osmo", async (t) => { +test.serial('transfer NFT: wasmd -> osmo', async (t) => { await standardSetup(t); const { @@ -331,7 +231,7 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { onlyOsmoIncomingChannel, } = t.context; - let tokenId = "1"; + let tokenId = '1'; await mint(wasmClient, wasmCw721, tokenId, wasmAddr, undefined); // assert token is minted let tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); @@ -350,17 +250,11 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { }, }, }; - let transferResponse = await sendNft( - wasmClient, - wasmCw721, - wasmCw721OutgoingProxy, - ibcMsg, - tokenId - ); + let transferResponse = await sendNft(wasmClient, wasmCw721, wasmCw721OutgoingProxy, ibcMsg, tokenId); t.truthy(transferResponse); // Relay and verify we got a success - t.log("relaying packets"); + t.log('relaying packets'); let info = await channel.link.relayAll(); assertAckSuccess(info.acksFromA); @@ -397,7 +291,7 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { tokenId ); t.truthy(transferResponse); - t.log("relaying packets"); + t.log('relaying packets'); // Verify we got a success info = await channel.link.relayAll(); @@ -412,39 +306,19 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { // ==== test transfer NFT to osmo chain via unknown, not WLed channel by incoming proxy ==== // test rejected NFT transfer due to unknown channel by incoming proxy - tokenId = "2"; + tokenId = '2'; await mint(wasmClient, wasmCw721, tokenId, wasmAddr, undefined); // assert token is minted tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); t.is(wasmAddr, tokenOwner.owner); - t.log( - `transfering to osmo chain via unknown ${otherChannel.channel.src.channelId}` - ); - const beforeWasmOutgoingClassTokenToChannelList = await outgoingChannels( - wasmClient, - wasmIcs721 - ); - const beforeWasmIncomingClassTokenToChannelList = await incomingChannels( - wasmClient, - wasmIcs721 - ); - const beforeWasmNftContractsToClassIdList = await nftContracts( - wasmClient, - wasmIcs721 - ); - const beforeOsmoOutgoingClassTokenToChannelList = await outgoingChannels( - osmoClient, - osmoIcs721 - ); - const beforeOsmoIncomingClassTokenToChannelList = await incomingChannels( - osmoClient, - osmoIcs721 - ); - const beforeOsmoNftContractsToClassIdList = await nftContracts( - osmoClient, - osmoIcs721 - ); + t.log(`transfering to osmo chain via unknown ${otherChannel.channel.src.channelId}`); + const beforeWasmOutgoingClassTokenToChannelList = await outgoingChannels(wasmClient, wasmIcs721); + const beforeWasmIncomingClassTokenToChannelList = await incomingChannels(wasmClient, wasmIcs721); + const beforeWasmNftContractsToClassIdList = await nftContracts(wasmClient, wasmIcs721); + const beforeOsmoOutgoingClassTokenToChannelList = await outgoingChannels(osmoClient, osmoIcs721); + const beforeOsmoIncomingClassTokenToChannelList = await incomingChannels(osmoClient, osmoIcs721); + const beforeOsmoNftContractsToClassIdList = await nftContracts(osmoClient, osmoIcs721); ibcMsg = { receiver: osmoAddr, @@ -456,32 +330,17 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { }, }, }; - transferResponse = await sendNft( - wasmClient, - wasmCw721, - wasmCw721OutgoingProxy, - ibcMsg, - tokenId - ); + transferResponse = await sendNft(wasmClient, wasmCw721, wasmCw721OutgoingProxy, ibcMsg, tokenId); t.truthy(transferResponse); // Relay and verify we got an error - t.log("relaying packets"); + t.log('relaying packets'); info = await otherChannel.link.relayAll(); assertAckErrors(info.acksFromA); // assert no change before and after relay - const afterWasmOutgoingClassTokenToChannelList = await outgoingChannels( - wasmClient, - wasmIcs721 - ); - const afterWasmIncomingClassTokenToChannelList = await incomingChannels( - wasmClient, - wasmIcs721 - ); - const afterWasmNftContractsToClassIdList = await nftContracts( - wasmClient, - wasmIcs721 - ); + const afterWasmOutgoingClassTokenToChannelList = await outgoingChannels(wasmClient, wasmIcs721); + const afterWasmIncomingClassTokenToChannelList = await incomingChannels(wasmClient, wasmIcs721); + const afterWasmNftContractsToClassIdList = await nftContracts(wasmClient, wasmIcs721); t.deepEqual( beforeWasmOutgoingClassTokenToChannelList, afterWasmOutgoingClassTokenToChannelList, @@ -503,18 +362,9 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { - wasm before: ${JSON.stringify(beforeWasmNftContractsToClassIdList)} - wasm after: ${JSON.stringify(afterWasmNftContractsToClassIdList)}` ); - const afterOsmoOutgoingClassTokenToChannelList = await outgoingChannels( - osmoClient, - osmoIcs721 - ); - const afterOsmoIncomingClassTokenToChannelList = await incomingChannels( - osmoClient, - osmoIcs721 - ); - const afterOsmoNftContractsToClassIdList = await nftContracts( - osmoClient, - osmoIcs721 - ); + const afterOsmoOutgoingClassTokenToChannelList = await outgoingChannels(osmoClient, osmoIcs721); + const afterOsmoIncomingClassTokenToChannelList = await incomingChannels(osmoClient, osmoIcs721); + const afterOsmoNftContractsToClassIdList = await nftContracts(osmoClient, osmoIcs721); t.deepEqual( beforeOsmoOutgoingClassTokenToChannelList, afterOsmoOutgoingClassTokenToChannelList, @@ -542,16 +392,14 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { t.is(wasmAddr, tokenOwner.owner); // ==== test transfer NFT to osmo chain via channel WLed ONLY on osmo incoming proxy and back to wasm chain ==== - tokenId = "3"; + tokenId = '3'; await mint(wasmClient, wasmCw721, tokenId, wasmAddr, undefined); // assert token is minted tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); t.is(wasmAddr, tokenOwner.owner); // test transfer NFT to osmo chain - t.log( - `transfering to osmo chain via ${onlyOsmoIncomingChannel.channel.src.channelId}` - ); + t.log(`transfering to osmo chain via ${onlyOsmoIncomingChannel.channel.src.channelId}`); ibcMsg = { receiver: osmoAddr, channel_id: onlyOsmoIncomingChannel.channel.src.channelId, @@ -562,36 +410,18 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { }, }, }; - transferResponse = await sendNft( - wasmClient, - wasmCw721, - wasmCw721OutgoingProxy, - ibcMsg, - tokenId - ); + transferResponse = await sendNft(wasmClient, wasmCw721, wasmCw721OutgoingProxy, ibcMsg, tokenId); t.truthy(transferResponse); // Relay and verify we got a success - t.log("relaying packets"); + t.log('relaying packets'); info = await onlyOsmoIncomingChannel.link.relayAll(); assertAckSuccess(info.acksFromA); // assert 1 entry for outgoing channels - let wasmOutgoingClassTokenToChannelList = await outgoingChannels( - wasmClient, - wasmIcs721 - ); - t.log( - `- outgoing channels: ${JSON.stringify( - wasmOutgoingClassTokenToChannelList - )}` - ); - t.true( - wasmOutgoingClassTokenToChannelList.length === 1, - `outgoing channels must have one entry: ${JSON.stringify( - wasmOutgoingClassTokenToChannelList - )}` - ); + let wasmOutgoingClassTokenToChannelList = await outgoingChannels(wasmClient, wasmIcs721); + t.log(`- outgoing channels: ${JSON.stringify(wasmOutgoingClassTokenToChannelList)}`); + t.true(wasmOutgoingClassTokenToChannelList.length === 1, `outgoing channels must have one entry: ${JSON.stringify(wasmOutgoingClassTokenToChannelList)}`); // assert NFT minted on chain B osmoClassId = `${onlyOsmoIncomingChannel.channel.dest.portId}/${onlyOsmoIncomingChannel.channel.dest.channelId}/${t.context.wasmCw721}`; @@ -615,9 +445,7 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { t.is(osmoAddr, tokenOwner.owner); // test back transfer NFT to wasm chain, where onlyOsmoIncomingChannel is not WLed on wasm chain - t.log( - `transfering back to wasm chain via unknown ${onlyOsmoIncomingChannel.channel.dest.channelId}` - ); + t.log(`transfering back to wasm chain via unknown ${onlyOsmoIncomingChannel.channel.dest.channelId}`); transferResponse = await sendNft( osmoClient, osmoCw721, @@ -640,7 +468,7 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { t.is(osmoIcs721, tokenOwner.owner); // Relay and verify we got an error - t.log("relaying packets"); + t.log('relaying packets'); info = await onlyOsmoIncomingChannel.link.relayAll(); for (const ack of info.acksFromB) { const parsed = JSON.parse(fromUtf8(ack.acknowledgement)); @@ -656,23 +484,11 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { t.is(osmoAddr, tokenOwner.owner); // ==== WL channel on wasm chain and test back transfer again ==== - t.log( - `migrate ${wasmCw721IncomingProxy} contract and add channel ${onlyOsmoIncomingChannel.channel.src.channelId}` - ); - await migrateIncomingProxy( - wasmClient, - wasmCw721IncomingProxy, - wasmCw721IncomingProxyId, - [ - channel.channel.src.channelId, - onlyOsmoIncomingChannel.channel.src.channelId, - ] - ); + t.log(`migrate ${wasmCw721IncomingProxy} contract and add channel ${onlyOsmoIncomingChannel.channel.src.channelId}`); + await migrateIncomingProxy(wasmClient, wasmCw721IncomingProxy, wasmCw721IncomingProxyId, [channel.channel.src.channelId, onlyOsmoIncomingChannel.channel.src.channelId]); // test back transfer NFT to wasm chain, where onlyOsmoIncomingChannel is not WLed on wasm chain - t.log( - `transfering back to wasm chain via WLed ${onlyOsmoIncomingChannel.channel.dest.channelId}` - ); + t.log(`transfering back to wasm chain via WLed ${onlyOsmoIncomingChannel.channel.dest.channelId}`); transferResponse = await sendNft( osmoClient, osmoCw721, @@ -700,15 +516,10 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { // query nft contracts let nftContractsToClassIdList = await nftContracts(wasmClient, wasmIcs721); t.log(`- nft contracts: ${JSON.stringify(nftContractsToClassIdList)}`); - t.true( - nftContractsToClassIdList.length === 1, - `nft contracts must have exactly one entry: ${JSON.stringify( - nftContractsToClassIdList - )}` - ); + t.true(nftContractsToClassIdList.length === 1, `nft contracts must have exactly one entry: ${JSON.stringify(nftContractsToClassIdList)}`); // Relay and verify success - t.log("relaying packets"); + t.log('relaying packets'); info = await onlyOsmoIncomingChannel.link.relayAll(); for (const ack of info.acksFromB) { const parsed = JSON.parse(fromUtf8(ack.acknowledgement)); @@ -717,16 +528,8 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { assertAckSuccess(info.acksFromB); // assert outgoing channels is empty - wasmOutgoingClassTokenToChannelList = await outgoingChannels( - wasmClient, - wasmIcs721 - ); - t.true( - wasmOutgoingClassTokenToChannelList.length === 0, - `outgoing channels not empty: ${JSON.stringify( - wasmOutgoingClassTokenToChannelList - )}` - ); + wasmOutgoingClassTokenToChannelList = await outgoingChannels(wasmClient, wasmIcs721); + t.true(wasmOutgoingClassTokenToChannelList.length === 0, `outgoing channels not empty: ${JSON.stringify(wasmOutgoingClassTokenToChannelList)}`); // assert after success relay, NFT on chain B is burned allNFTs = await allTokens(osmoClient, osmoCw721); @@ -735,33 +538,18 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => { // assert list is unchanged nftContractsToClassIdList = await nftContracts(wasmClient, wasmIcs721); t.log(`- nft contracts: ${JSON.stringify(nftContractsToClassIdList)}`); - t.true( - nftContractsToClassIdList.length === 1, - `nft contracts must have exactly one entry: ${JSON.stringify( - nftContractsToClassIdList - )}` - ); + t.true(nftContractsToClassIdList.length === 1, `nft contracts must have exactly one entry: ${JSON.stringify(nftContractsToClassIdList)}`); // assert NFT is returned to sender on wasm chain tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); t.is(wasmAddr, tokenOwner.owner); }); -test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { +test.serial('admin unescrow and burn NFT: wasmd -> osmo', async (t) => { await standardSetup(t); - const { - wasmClient, - wasmAddr, - wasmCw721, - wasmIcs721, - wasmCw721OutgoingProxy, - osmoClient, - osmoAddr, - osmoIcs721, - channel, - } = t.context; + const { wasmClient, wasmAddr, wasmCw721, wasmIcs721, wasmCw721OutgoingProxy, osmoClient, osmoAddr, osmoIcs721, channel } = t.context; - const tokenId = "1"; + const tokenId = '1'; await mint(wasmClient, wasmCw721, tokenId, wasmAddr, undefined); // assert token is minted let tokenOwner = await ownerOf(wasmClient, wasmCw721, tokenId); @@ -780,17 +568,11 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { }, }, }; - const transferResponse = await sendNft( - wasmClient, - wasmCw721, - wasmCw721OutgoingProxy, - ibcMsg, - tokenId - ); + const transferResponse = await sendNft(wasmClient, wasmCw721, wasmCw721OutgoingProxy, ibcMsg, tokenId); t.truthy(transferResponse); // Relay and verify we got a success - t.log("relaying packets"); + t.log('relaying packets'); const info = await channel.link.relayAll(); assertAckSuccess(info.acksFromA); @@ -808,10 +590,7 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); t.is(osmoAddr, tokenOwner.owner); - const beforeWasmOutgoingClassTokenToChannelList = await outgoingChannels( - wasmClient, - wasmIcs721 - ); + const beforeWasmOutgoingClassTokenToChannelList = await outgoingChannels(wasmClient, wasmIcs721); // there should be one outgoing channel entry t.deepEqual( beforeWasmOutgoingClassTokenToChannelList, @@ -820,10 +599,7 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { - before: ${JSON.stringify(beforeWasmOutgoingClassTokenToChannelList)}` ); // no incoming channel entry - const beforeWasmIncomingClassTokenToChannelList = await incomingChannels( - wasmClient, - wasmIcs721 - ); + const beforeWasmIncomingClassTokenToChannelList = await incomingChannels(wasmClient, wasmIcs721); t.deepEqual( beforeWasmIncomingClassTokenToChannelList, [], @@ -831,10 +607,7 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { - before: ${JSON.stringify(beforeWasmIncomingClassTokenToChannelList)}` ); // one nft contract entry - const beforeWasmNftContractsToClassIdList = await nftContracts( - wasmClient, - wasmIcs721 - ); + const beforeWasmNftContractsToClassIdList = await nftContracts(wasmClient, wasmIcs721); t.deepEqual( beforeWasmNftContractsToClassIdList, [[wasmCw721, wasmCw721]], @@ -843,10 +616,7 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { ); // no outgoing channel entry - const beforeOsmoOutgoingClassTokenToChannelList = await outgoingChannels( - osmoClient, - osmoIcs721 - ); + const beforeOsmoOutgoingClassTokenToChannelList = await outgoingChannels(osmoClient, osmoIcs721); t.deepEqual( beforeOsmoOutgoingClassTokenToChannelList, [], @@ -854,10 +624,7 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { - before: ${JSON.stringify(beforeOsmoOutgoingClassTokenToChannelList)}` ); // there should be one incoming channel entry - const beforeOsmoIncomingClassTokenToChannelList = await incomingChannels( - osmoClient, - osmoIcs721 - ); + const beforeOsmoIncomingClassTokenToChannelList = await incomingChannels(osmoClient, osmoIcs721); t.deepEqual( beforeOsmoIncomingClassTokenToChannelList, [[[osmoClassId, tokenId], channel.channel.dest.channelId]], @@ -865,10 +632,7 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { - before: ${JSON.stringify(beforeOsmoIncomingClassTokenToChannelList)}` ); // one nft contract entry - const beforeOsmoNftContractsToClassIdList = await nftContracts( - osmoClient, - osmoIcs721 - ); + const beforeOsmoNftContractsToClassIdList = await nftContracts(osmoClient, osmoIcs721); t.deepEqual( beforeOsmoNftContractsToClassIdList, [[osmoClassId, osmoCw721]], @@ -878,19 +642,9 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { // ==== test unescrow NFT on wasm chain ==== t.log(`unescrow NFT on wasm chain`); - await adminCleanAndUnescrowNft( - wasmClient, - wasmIcs721, - wasmAddr, - tokenId, - wasmCw721, - wasmCw721 - ); + await adminCleanAndUnescrowNft(wasmClient, wasmIcs721, wasmAddr, tokenId, wasmCw721, wasmCw721); // there should be no outgoing channel entry - const afterWasmOutgoingClassTokenToChannelList = await outgoingChannels( - wasmClient, - wasmIcs721 - ); + const afterWasmOutgoingClassTokenToChannelList = await outgoingChannels(wasmClient, wasmIcs721); t.deepEqual( afterWasmOutgoingClassTokenToChannelList, [], @@ -907,22 +661,12 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { const response = await approve(osmoClient, osmoCw721, osmoIcs721, tokenId); t.log(`- response: ${JSON.stringify(response, bigIntReplacer, 2)}`); t.log(`burn NFT on osmo chain`); - await adminCleanAndBurnNft( - osmoClient, - osmoIcs721, - osmoAddr, - tokenId, - osmoClassId, - osmoCw721 - ); + await adminCleanAndBurnNft(osmoClient, osmoIcs721, osmoAddr, tokenId, osmoClassId, osmoCw721); t.log(`- response: ${JSON.stringify(response, bigIntReplacer, 2)}`); allNFTs = await allTokens(osmoClient, osmoCw721); t.is(allNFTs.tokens.length, 0); // there should be no incoming channel entry - const afterOsmoIncomingClassTokenToChannelList = await incomingChannels( - osmoClient, - osmoIcs721 - ); + const afterOsmoIncomingClassTokenToChannelList = await incomingChannels(osmoClient, osmoIcs721); t.deepEqual( afterOsmoIncomingClassTokenToChannelList, [], @@ -931,30 +675,20 @@ test.serial("admin unescrow and burn NFT: wasmd -> osmo", async (t) => { ); }); -test.serial("malicious NFT", async (t) => { +test.serial('malicious NFT', async (t) => { await standardSetup(t); - const { - wasmClient, - wasmAddr, - wasmIcs721, - wasmCw721OutgoingProxy, - osmoClient, - osmoAddr, - osmoIcs721, - osmoCw721OutgoingProxy, - channel, - } = t.context; - const tokenId = "1"; + const { wasmClient, wasmAddr, wasmIcs721, wasmCw721OutgoingProxy, osmoClient, osmoAddr, osmoIcs721, osmoCw721OutgoingProxy, channel } = t.context; + const tokenId = '1'; // instantiate malicious cw721 contract const res = await uploadAndInstantiate(wasmClient, { cw721_gas_tester: { path: MALICIOUS_CW721, instantiateMsg: { - name: "evil", - symbol: "evil", + name: 'evil', + symbol: 'evil', minter: wasmClient.senderAddress, - banned_recipient: "banned_recipient", // panic every time, on back transfer, when ICS721 tries to transfer/unescrow NFT to this address + banned_recipient: 'banned_recipient', // panic every time, on back transfer, when ICS721 tries to transfer/unescrow NFT to this address }, }, }); @@ -962,7 +696,7 @@ test.serial("malicious NFT", async (t) => { // ==== test malicious NFT transfer to osmo chain ==== await mint(wasmClient, cw721, tokenId, wasmAddr, undefined); - t.log("transferring to osmo chain"); + t.log('transferring to osmo chain'); let ibcMsg = { receiver: osmoAddr, channel_id: channel.channel.src.channelId, @@ -973,16 +707,10 @@ test.serial("malicious NFT", async (t) => { }, }, }; - let transferResponse = await sendNft( - wasmClient, - cw721, - wasmCw721OutgoingProxy, - ibcMsg, - tokenId - ); + let transferResponse = await sendNft(wasmClient, cw721, wasmCw721OutgoingProxy, ibcMsg, tokenId); t.truthy(transferResponse); - t.log("relaying packets"); + t.log('relaying packets'); let info = await channel.link.relayAll(); assertAckSuccess(info.acksFromB); @@ -998,9 +726,9 @@ test.serial("malicious NFT", async (t) => { t.is(osmoAddr, tokenOwner.owner); // ==== test malicious NFT back transfer to banned recipient on wasm chain ==== - t.log("transferring back to wasm chain to banned recipient"); + t.log('transferring back to wasm chain to banned recipient'); ibcMsg = { - receiver: "banned_recipient", + receiver: 'banned_recipient', channel_id: channel.channel.dest.channelId, timeout: { block: { @@ -1009,20 +737,14 @@ test.serial("malicious NFT", async (t) => { }, }, }; - transferResponse = await sendNft( - osmoClient, - osmoCw721, - osmoCw721OutgoingProxy, - ibcMsg, - tokenId - ); + transferResponse = await sendNft(osmoClient, osmoCw721, osmoCw721OutgoingProxy, ibcMsg, tokenId); t.truthy(transferResponse); // before relay NFT escrowed by ICS721 tokenOwner = await ownerOf(osmoClient, osmoCw721, tokenId); t.is(osmoIcs721, tokenOwner.owner); - t.log("relaying packets"); - let pending = await channel.link.getPendingPackets("B"); + t.log('relaying packets'); + let pending = await channel.link.getPendingPackets('B'); t.is(pending.length, 1); // Despite the transfer panicking, a fail ack should be returned. info = await channel.link.relayAll(); @@ -1033,7 +755,7 @@ test.serial("malicious NFT", async (t) => { t.log(`NFT #${tokenId} returned to owner`); // ==== test malicious NFT transfer to regular recipient wasm chain ==== - t.log("transferring back to wasm chain to recipient", wasmAddr); + t.log('transferring back to wasm chain to recipient', wasmAddr); ibcMsg = { receiver: wasmAddr, channel_id: channel.channel.dest.channelId, @@ -1045,18 +767,12 @@ test.serial("malicious NFT", async (t) => { }, }; - transferResponse = await sendNft( - osmoClient, - osmoCw721, - osmoCw721OutgoingProxy, - ibcMsg, - tokenId - ); + transferResponse = await sendNft(osmoClient, osmoCw721, osmoCw721OutgoingProxy, ibcMsg, tokenId); t.truthy(transferResponse); // Relay and verify we got a success - t.log("relaying packets"); - pending = await channel.link.getPendingPackets("B"); + t.log('relaying packets'); + pending = await channel.link.getPendingPackets('B'); t.is(pending.length, 1); info = await channel.link.relayAll(); assertAckSuccess(info.acksFromB); From 08b47479842165c1e723cd00091ea9f429e7263e Mon Sep 17 00:00:00 2001 From: mr-t Date: Fri, 7 Jun 2024 13:05:45 +0200 Subject: [PATCH 11/18] more test output --- ts-relayer-tests/src/ics721.spec.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ts-relayer-tests/src/ics721.spec.ts b/ts-relayer-tests/src/ics721.spec.ts index 204b22db..ee269d72 100644 --- a/ts-relayer-tests/src/ics721.spec.ts +++ b/ts-relayer-tests/src/ics721.spec.ts @@ -56,7 +56,9 @@ const standardSetup = async (t: ExecutionContext) => { t.context.osmoClient = await setupOsmosisClient(MNEMONIC); t.context.wasmAddr = t.context.wasmClient.senderAddress; + t.log(`wasm client address: ${t.context.wasmAddr}`); t.context.osmoAddr = t.context.osmoClient.senderAddress; + t.log(`osmo client address: ${t.context.osmoAddr}`); const { wasmClient, osmoClient } = t.context; @@ -331,6 +333,7 @@ test.serial('transfer NFT: wasmd -> osmo', async (t) => { }, }; transferResponse = await sendNft(wasmClient, wasmCw721, wasmCw721OutgoingProxy, ibcMsg, tokenId); + t.log(`- transfer response: ${JSON.stringify(transferResponse)}`); t.truthy(transferResponse); // Relay and verify we got an error From f379588e7033de21f8ba33b4d10cd3e691586464 Mon Sep 17 00:00:00 2001 From: mr-t Date: Fri, 7 Jun 2024 13:23:25 +0200 Subject: [PATCH 12/18] update wasm files --- external-wasms/checksums.txt | 3 +++ external-wasms/cw721_base_v0.18.0.wasm | Bin 327759 -> 0 bytes external-wasms/cw721_base_v0.19.0.wasm | Bin 0 -> 787052 bytes ...asm => cw_ics721_incoming_proxy_base.wasm} | Bin 190347 -> 190467 bytes ... cw_ics721_outgoing_proxy_rate_limit.wasm} | Bin 191092 -> 191119 bytes ts-relayer-tests/src/ics721.spec.ts | 6 +++--- 6 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 external-wasms/checksums.txt delete mode 100644 external-wasms/cw721_base_v0.18.0.wasm create mode 100644 external-wasms/cw721_base_v0.19.0.wasm rename external-wasms/{cw721_incoming_proxy.wasm => cw_ics721_incoming_proxy_base.wasm} (53%) rename external-wasms/{cw721_outgoing_proxy_rate_limit.wasm => cw_ics721_outgoing_proxy_rate_limit.wasm} (55%) diff --git a/external-wasms/checksums.txt b/external-wasms/checksums.txt new file mode 100644 index 00000000..90583ebe --- /dev/null +++ b/external-wasms/checksums.txt @@ -0,0 +1,3 @@ +cw721_base_v0.19.0.wasm 96b5cd406ec19804d12052f9a87b78989c9094d319b5dabdb45e975258ec6575, collection-info branch: https://github.com/arkprotocol/cw-nfts/tree/228c9ef0c9ff9386a964296e0924b27b57cc5083 +cw_ics721_incoming_proxy_base.wasm 32dd48b27688b4f7783bccd506006b6c0754db79deccca92a9db13d8e4aa7355, https://github.com/arkprotocol/cw-ics721-proxy/releases/tag/v0.1.1 +cw_ics721_outgoing_proxy_rate_limit.wasm aae9d990fa4bd4b2d25692c0d6496b52865c64fdb2df3911deb093060871a72f, https://github.com/arkprotocol/cw-ics721-proxy/releases/tag/v0.1.1 \ No newline at end of file diff --git a/external-wasms/cw721_base_v0.18.0.wasm b/external-wasms/cw721_base_v0.18.0.wasm deleted file mode 100644 index 86f066963d17797150c0623ff47d3a6aa8817a20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 327759 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
l3#U7 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

%>29s4KE6Ir18`P^JZ+h>19kZ6|d$wRfG$ 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

AyV{ua%WsB*kj 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