From a6efdbed0a1f4b4178bfc0580ef518a290d10100 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Thu, 06 May 2021 15:13:49 +0000 Subject: [PATCH] Merge commit 'b3fda41c65ef3d5198749d60622f0184af244734' into feature/NFTPAR-366_upstream_updates --- --- a/pallets/nft/src/eth/mod.rs +++ b/pallets/nft/src/eth/mod.rs @@ -117,8 +117,8 @@ let recipient = T::CrossAccountId::from_eth(recipient); >::transfer_internal( - sender, - recipient, + &sender, + &recipient, &collection, 1, amount, @@ -143,8 +143,8 @@ let spender = T::CrossAccountId::from_eth(spender); >::approve_internal( - sender, - spender, + &sender, + &spender, &collection, 1, amount, @@ -160,8 +160,8 @@ let token_id = token_id.try_into().map_err(|_| "bad token id")?; >::approve_internal( - sender, - approved, + &sender, + &approved, &collection, token_id, 1, @@ -176,9 +176,9 @@ let recipient = T::CrossAccountId::from_eth(recipient); >::transfer_from_internal( - sender, - from, - recipient, + &sender, + &from, + &recipient, &collection, 1, amount, @@ -195,9 +195,9 @@ let token_id = token_id.try_into().map_err(|_| "bad token id")?; >::transfer_from_internal( - sender, - from, - recipient, + &sender, + &from, + &recipient, &collection, token_id, 1, --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -870,10 +870,14 @@ let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); let collection = Self::get_collection(collection_id)?; - Self::check_owner_or_admin_permissions(&collection, &sender)?; - >::insert(collection_id, address.as_sub(), true); - + Self::toggle_white_list_internal( + &sender, + &collection, + &address, + true, + )?; + Ok(()) } @@ -895,9 +899,13 @@ let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); let collection = Self::get_collection(collection_id)?; - Self::check_owner_or_admin_permissions(&collection, &sender)?; - >::remove(collection_id, address.as_sub()); + Self::toggle_white_list_internal( + &sender, + &collection, + &address, + false, + )?; Ok(()) } @@ -1137,16 +1145,12 @@ #[weight = ::WeightInfo::create_item(data.len())] #[transactional] pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResult { - let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); + let collection = Self::get_collection(collection_id)?; - let target_collection = Self::get_collection(collection_id)?; + Self::create_item_internal(&sender, &collection, &owner, data); - Self::can_create_items_in_collection(&target_collection, &sender, &owner, 1)?; - Self::validate_create_item_args(&target_collection, &data)?; - Self::create_item_no_validation(&target_collection, owner, data)?; - - Self::submit_logs(target_collection)?; + Self::submit_logs(collection)?; Ok(()) } @@ -1178,7 +1182,7 @@ let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); let collection = Self::get_collection(collection_id)?; - Self::create_multiple_items_internal(sender, &collection, owner, items_data)?; + Self::create_multiple_items_internal(&sender, &collection, &owner, items_data)?; Self::submit_logs(collection)?; Ok(()) @@ -1239,7 +1243,7 @@ let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); let collection = Self::get_collection(collection_id)?; - Self::transfer_internal(sender, recipient, &collection, item_id, value)?; + Self::transfer_internal(&sender, &recipient, &collection, item_id, value)?; Self::submit_logs(collection)?; Ok(()) @@ -1263,11 +1267,10 @@ #[weight = ::WeightInfo::approve()] #[transactional] pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResult { - let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); let collection = Self::get_collection(collection_id)?; - Self::approve_internal(sender, spender, &collection, item_id, amount)?; + Self::approve_internal(&sender, &spender, &collection, item_id, amount)?; Self::submit_logs(collection)?; Ok(()) @@ -1295,19 +1298,15 @@ #[weight = ::WeightInfo::transfer_from()] #[transactional] pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResult { - let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); let collection = Self::get_collection(collection_id)?; - Self::transfer_from_internal(sender, from, recipient, &collection, item_id, value)?; + Self::transfer_from_internal(&sender, &from, &recipient, &collection, item_id, value)?; Self::submit_logs(collection)?; Ok(()) } - // #[weight = 0] - // pub fn safe_transfer_from(origin, collection_id: CollectionId, item_id: TokenId, new_owner: T::AccountId) -> DispatchResult { - // // let no_perm_mes = "You do not have permissions to modify this collection"; // // ensure!(>::contains_key((collection_id, item_id)), no_perm_mes); // // let list_itm = >::get((collection_id, item_id)); @@ -1342,8 +1341,9 @@ ) -> DispatchResult { let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); - let target_collection = Self::get_collection(collection_id)?; - Self::set_variable_meta_data_internal(sender, &target_collection, item_id, data)?; + let collection = Self::get_collection(collection_id)?; + + Self::set_variable_meta_data_internal(&sender, &collection, item_id, data)?; Ok(()) } @@ -1679,8 +1679,15 @@ } impl Module { + pub fn create_item_internal(sender: &T::CrossAccountId, collection: &CollectionHandle, owner: &T::CrossAccountId, data: CreateItemData) -> DispatchResult { + Self::can_create_items_in_collection(&collection, &sender, &owner, 1)?; + Self::validate_create_item_args(&collection, &data)?; + Self::create_item_no_validation(&collection, owner, data)?; + + Ok(()) + } - pub fn transfer_internal(sender: T::CrossAccountId, recipient: T::CrossAccountId, target_collection: &CollectionHandle, item_id: TokenId, value: u128) -> DispatchResult { + pub fn transfer_internal(sender: &T::CrossAccountId, recipient: &T::CrossAccountId, target_collection: &CollectionHandle, item_id: TokenId, value: u128) -> DispatchResult { // Limits check Self::is_correct_transfer(target_collection, &recipient)?; @@ -1702,14 +1709,14 @@ _ => () }; - Self::deposit_event(RawEvent::Transfer(target_collection.id, item_id, sender, recipient, value)); + Self::deposit_event(RawEvent::Transfer(target_collection.id, item_id, sender.clone(), recipient.clone(), value)); Ok(()) } pub fn approve_internal( - sender: T::CrossAccountId, - spender: T::CrossAccountId, + sender: &T::CrossAccountId, + spender: &T::CrossAccountId, collection: &CollectionHandle, item_id: TokenId, amount: u128 @@ -1772,14 +1779,14 @@ ); } - Self::deposit_event(RawEvent::Approved(collection.id, item_id, sender, spender, allowance)); + Self::deposit_event(RawEvent::Approved(collection.id, item_id, sender.clone(), spender.clone(), allowance)); Ok(()) } pub fn transfer_from_internal( - sender: T::CrossAccountId, - from: T::CrossAccountId, - recipient: T::CrossAccountId, + sender: &T::CrossAccountId, + from: &T::CrossAccountId, + recipient: &T::CrossAccountId, collection: &CollectionHandle, item_id: TokenId, amount: u128, @@ -1841,7 +1848,7 @@ } pub fn set_variable_meta_data_internal( - sender: T::CrossAccountId, + sender: &T::CrossAccountId, collection: &CollectionHandle, item_id: TokenId, data: Vec, @@ -1867,9 +1874,9 @@ } pub fn create_multiple_items_internal( - sender: T::CrossAccountId, + sender: &T::CrossAccountId, collection: &CollectionHandle, - owner: T::CrossAccountId, + owner: &T::CrossAccountId, items_data: Vec, ) -> DispatchResult { Self::can_create_items_in_collection(&collection, &sender, &owner, items_data.len() as u32)?; @@ -1878,7 +1885,7 @@ Self::validate_create_item_args(&collection, data)?; } for data in &items_data { - Self::create_item_no_validation(&collection, owner.clone(), data.clone())?; + Self::create_item_no_validation(&collection, owner, data.clone())?; } Ok(()) @@ -1914,6 +1921,23 @@ Ok(()) } + pub fn toggle_white_list_internal( + sender: &T::CrossAccountId, + collection: &CollectionHandle, + address: &T::CrossAccountId, + whitelisted: bool, + ) -> DispatchResult { + Self::check_owner_or_admin_permissions(&collection, &sender)?; + + if whitelisted { + >::insert(collection.id, address.as_sub(), true); + } else { + >::remove(collection.id, address.as_sub()); + } + + Ok(()) + } + fn is_correct_transfer(collection: &CollectionHandle, recipient: &T::CrossAccountId) -> DispatchResult { let collection_id = collection.id; @@ -1984,7 +2008,7 @@ Ok(()) } - fn create_item_no_validation(collection: &CollectionHandle, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResult { + fn create_item_no_validation(collection: &CollectionHandle, owner: &T::CrossAccountId, data: CreateItemData) -> DispatchResult { match data { CreateItemData::NFT(data) => { --- a/runtime/src/chain_extension.rs +++ b/runtime/src/chain_extension.rs @@ -17,10 +17,17 @@ extern crate pallet_nft; pub use pallet_nft::*; -use crate::Runtime; -use sp_runtime::AccountId32; +use pallet_nft::CrossAccountId; use crate::Vec; +/// Create item parameters +#[derive(Debug, PartialEq, Encode, Decode)] +pub struct NFTExtCreateItem { + pub owner: ::AccountId, + pub collection_id: u32, + pub data: CreateItemData, +} + /// Transfer parameters #[derive(Debug, PartialEq, Encode, Decode)] pub struct NFTExtTransfer { @@ -30,12 +37,51 @@ pub amount: u128, } +#[derive(Debug, PartialEq, Encode, Decode)] +pub struct NFTExtCreateMultipleItems { + pub owner: ::AccountId, + pub collection_id: u32, + pub data: Vec, +} + +#[derive(Debug, PartialEq, Encode, Decode)] +pub struct NFTExtApprove { + pub spender: ::AccountId, + pub collection_id: u32, + pub item_id: u32, + pub amount: u128, +} + +#[derive(Debug, PartialEq, Encode, Decode)] +pub struct NFTExtTransferFrom { + pub owner: ::AccountId, + pub recipient: ::AccountId, + pub collection_id: u32, + pub item_id: u32, + pub amount: u128, +} + +#[derive(Debug, PartialEq, Encode, Decode)] +pub struct NFTExtSetVariableMetaData { + pub collection_id: u32, + pub item_id: u32, + pub data: Vec, +} + +#[derive(Debug, PartialEq, Encode, Decode)] +pub struct NFTExtToggleWhiteList { + pub collection_id: u32, + pub address: ::AccountId, + pub whitelisted: bool, +} + /// The chain Extension of NFT pallet pub struct NFTExtension; impl ChainExtension for NFTExtension { fn call(func_id: u32, env: Environment) -> Result where + E: Ext, ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, { // The memory of the vm stores buf in scale-codec @@ -44,37 +90,118 @@ let mut env = env.buf_in_buf_out(); let input: NFTExtTransfer = env.read_as()?; - // Sender to AccountId32 - let mut bytes_sender: [u8; 32] = [0; 32]; - let addr_vec_sender: Vec = env.ext().caller().encode(); - for i in 0..32 { - bytes_sender[i] = addr_vec_sender[i]; + let collection = pallet_nft::Module::::get_collection(input.collection_id)?; + + match pallet_nft::Module::::transfer_internal( + &C::CrossAccountId::from_sub(env.ext().caller().clone()), + &C::CrossAccountId::from_sub(input.recipient), + &collection, + input.token_id, + input.amount, + ) { + Ok(_) => Ok(RetVal::Converging(func_id)), + _ => Err(DispatchError::Other("Transfer error")) } - let sender = AccountId32::from(bytes_sender); + }, + 1 => { + // Create Item + let mut env = env.buf_in_buf_out(); + let input: NFTExtCreateItem = env.read_as()?; - // Recipient to AccountId32 - let mut bytes_rec: [u8; 32] = [0; 32]; - let addr_vec_rec: Vec = input.recipient.encode(); - for i in 0..32 { - bytes_rec[i] = addr_vec_rec[i]; + let collection = pallet_nft::Module::::get_collection(input.collection_id)?; + + match pallet_nft::Module::::create_item_internal( + &C::CrossAccountId::from_sub(env.ext().address().clone()), + &collection, + &C::CrossAccountId::from_sub(input.owner), + input.data, + ) { + Ok(_) => Ok(RetVal::Converging(func_id)), + _ => Err(DispatchError::Other("CreateItem error")) } - let recipient = AccountId32::from(bytes_rec); + }, + 2 => { + // Create multiple items + let mut env = env.buf_in_buf_out(); + let input: NFTExtCreateMultipleItems = env.read_as()?; - let collection = pallet_nft::Module::::get_collection(input.collection_id)?; + let collection = pallet_nft::Module::::get_collection(input.collection_id)?; - match pallet_nft::Module::::transfer_internal( - ::CrossAccountId::from_sub(sender), - ::CrossAccountId::from_sub(recipient), + match pallet_nft::Module::::create_multiple_items_internal( + &C::CrossAccountId::from_sub(env.ext().address().clone()), &collection, - input.token_id, - input.amount, + &C::CrossAccountId::from_sub(input.owner), + input.data, ) { Ok(_) => Ok(RetVal::Converging(func_id)), - _ => Err(DispatchError::Other("Transfer error")) + _ => Err(DispatchError::Other("CreateMultipleItems error")) } }, - _ => { - panic!("Passed unknown func_id to test chain extension: {}", func_id); + 3 => { + // Approve + let mut env = env.buf_in_buf_out(); + let input: NFTExtApprove = env.read_as()?; + + let collection = pallet_nft::Module::::get_collection(input.collection_id)?; + + pallet_nft::Module::::approve_internal( + &C::CrossAccountId::from_sub(env.ext().address().clone()), + &C::CrossAccountId::from_sub(input.spender), + &collection, + input.item_id, + input.amount, + )?; + Ok(RetVal::Converging(func_id)) + }, + 4 => { + // Transfer from + let mut env = env.buf_in_buf_out(); + let input: NFTExtTransferFrom = env.read_as()?; + + let collection = pallet_nft::Module::::get_collection(input.collection_id)?; + + pallet_nft::Module::::transfer_from_internal( + &C::CrossAccountId::from_sub(env.ext().address().clone()), + &C::CrossAccountId::from_sub(input.owner), + &C::CrossAccountId::from_sub(input.recipient), + &collection, + input.item_id, + input.amount + )?; + Ok(RetVal::Converging(func_id)) + }, + 5 => { + // Set variable metadata + let mut env = env.buf_in_buf_out(); + let input: NFTExtSetVariableMetaData = env.read_as()?; + + let collection = pallet_nft::Module::::get_collection(input.collection_id)?; + + pallet_nft::Module::::set_variable_meta_data_internal( + &C::CrossAccountId::from_sub(env.ext().address().clone()), + &collection, + input.item_id, + input.data, + )?; + Ok(RetVal::Converging(func_id)) + }, + 6 => { + // Toggle whitelist + let mut env = env.buf_in_buf_out(); + let input: NFTExtToggleWhiteList = env.read_as()?; + + let collection = pallet_nft::Module::::get_collection(input.collection_id)?; + + pallet_nft::Module::::toggle_white_list_internal( + &C::CrossAccountId::from_sub(env.ext().address().clone()), + &collection, + &C::CrossAccountId::from_sub(input.address), + input.whitelisted, + )?; + Ok(RetVal::Converging(func_id)) + } + _ => { + panic!("Passed unknown func_id to test chain extension: {}", func_id); } } } -- gitstuff