difftreelog
patch: Change dispathed call for create item (return collection id).
in: master
4 files changed
pallets/common/src/dispatch.rsdiffbeforeafterboth--- a/pallets/common/src/dispatch.rs
+++ b/pallets/common/src/dispatch.rs
@@ -8,6 +8,7 @@
weights::Pays,
traits::Get,
};
+use sp_runtime::DispatchError;
use up_data_structs::{CollectionId, CreateCollectionData};
use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle};
@@ -78,7 +79,7 @@
fn create(
sender: T::CrossAccountId,
data: CreateCollectionData<T::AccountId>,
- ) -> DispatchResult;
+ ) -> Result<CollectionId, DispatchError>;
/// Delete the collection.
///
pallets/unique/src/eth/mod.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Implementation of CollectionHelpers contract.1819use core::marker::PhantomData;20use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};21use ethereum as _;22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};23use pallet_evm::{OnMethodCall, PrecompileResult, account::CrossAccountId, PrecompileHandle};24use up_data_structs::{25 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,26 CollectionMode, PropertyValue,27};28use frame_support::traits::Get;29use pallet_common::{30 CollectionById,31 erc::{32 static_property::{key, value as property_value},33 CollectionHelpersEvents,34 },35};36use crate::{SelfWeightOf, Config, weights::WeightInfo};3738use sp_std::vec::Vec;39use alloc::format;4041/// See [`CollectionHelpersCall`]42pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);43impl<T: Config> WithRecorder<T> for EvmCollectionHelpers<T> {44 fn recorder(&self) -> &SubstrateRecorder<T> {45 &self.046 }4748 fn into_recorder(self) -> SubstrateRecorder<T> {49 self.050 }51}5253fn convert_data<T: Config>(54 caller: caller,55 name: string,56 description: string,57 token_prefix: string,58 base_uri: string,59) -> Result<(60 T::CrossAccountId,61 CollectionName,62 CollectionDescription,63 CollectionTokenPrefix,64 PropertyValue,65)> {66 let caller = T::CrossAccountId::from_eth(caller);67 let name = name68 .encode_utf16()69 .collect::<Vec<u16>>()70 .try_into()71 .map_err(|_| error_feild_too_long(stringify!(name), CollectionName::bound()))?;72 let description = description73 .encode_utf16()74 .collect::<Vec<u16>>()75 .try_into()76 .map_err(|_| {77 error_feild_too_long(stringify!(description), CollectionDescription::bound())78 })?;79 let token_prefix = token_prefix.into_bytes().try_into().map_err(|_| {80 error_feild_too_long(stringify!(token_prefix), CollectionTokenPrefix::bound())81 })?;82 let base_uri_value = base_uri83 .into_bytes()84 .try_into()85 .map_err(|_| error_feild_too_long(stringify!(token_prefix), PropertyValue::bound()))?;86 Ok((caller, name, description, token_prefix, base_uri_value))87}8889fn make_data<T: Config>(90 name: CollectionName,91 mode: CollectionMode,92 description: CollectionDescription,93 token_prefix: CollectionTokenPrefix,94 base_uri_value: PropertyValue,95 add_properties: bool,96) -> Result<CreateCollectionData<T::AccountId>> {97 let mut properties = up_data_structs::CollectionPropertiesVec::default();98 let mut token_property_permissions =99 up_data_structs::CollectionPropertiesPermissionsVec::default();100101 token_property_permissions102 .try_push(up_data_structs::PropertyKeyPermission {103 key: key::url(),104 permission: up_data_structs::PropertyPermission {105 mutable: false,106 collection_admin: true,107 token_owner: false,108 },109 })110 .map_err(|e| Error::Revert(format!("{:?}", e)))?;111112 if add_properties {113 token_property_permissions114 .try_push(up_data_structs::PropertyKeyPermission {115 key: key::suffix(),116 permission: up_data_structs::PropertyPermission {117 mutable: false,118 collection_admin: true,119 token_owner: false,120 },121 })122 .map_err(|e| Error::Revert(format!("{:?}", e)))?;123124 properties125 .try_push(up_data_structs::Property {126 key: key::schema_name(),127 value: property_value::erc721(),128 })129 .map_err(|e| Error::Revert(format!("{:?}", e)))?;130131 if !base_uri_value.is_empty() {132 properties133 .try_push(up_data_structs::Property {134 key: key::base_uri(),135 value: base_uri_value,136 })137 .map_err(|e| Error::Revert(format!("{:?}", e)))?;138 }139 }140141 let data = CreateCollectionData {142 name,143 mode,144 description,145 token_prefix,146 token_property_permissions,147 properties,148 ..Default::default()149 };150 Ok(data)151}152153/// @title Contract, which allows users to operate with collections154#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]155impl<T> EvmCollectionHelpers<T>156where157 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,158{159 /// Create an NFT collection160 /// @param name Name of the collection161 /// @param description Informative description of the collection162 /// @param token_prefix Token prefix to represent the collection tokens in UI and user applications163 /// @return address Address of the newly created collection164 #[weight(<SelfWeightOf<T>>::create_collection())]165 fn create_nonfungible_collection(166 &mut self,167 caller: caller,168 name: string,169 description: string,170 token_prefix: string,171 ) -> Result<address> {172 let (caller, name, description, token_prefix, _base_uri_value) =173 convert_data::<T>(caller, name, description, token_prefix, "".into())?;174 let data = make_data::<T>(175 name,176 CollectionMode::NFT,177 description,178 token_prefix,179 Default::default(),180 false,181 )?;182 let collection_id =183 <pallet_nonfungible::Pallet<T>>::init_collection(caller.clone(), data, false)184 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;185186 let address = pallet_common::eth::collection_id_to_address(collection_id);187 Ok(address)188 }189190 #[weight(<SelfWeightOf<T>>::create_collection())]191 #[solidity(rename_selector = "createERC721MetadataCompatibleCollection")]192 fn create_nonfungible_collection_with_properties(193 &mut self,194 caller: caller,195 name: string,196 description: string,197 token_prefix: string,198 base_uri: string,199 ) -> Result<address> {200 let (caller, name, description, token_prefix, base_uri_value) =201 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;202 let data = make_data::<T>(203 name,204 CollectionMode::NFT,205 description,206 token_prefix,207 base_uri_value,208 true,209 )?;210 let collection_id =211 <pallet_nonfungible::Pallet<T>>::init_collection(caller.clone(), data, true)212 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;213214 let address = pallet_common::eth::collection_id_to_address(collection_id);215 Ok(address)216 }217218 #[weight(<SelfWeightOf<T>>::create_collection())]219 fn create_refungible_collection(220 &self,221 caller: caller,222 name: string,223 description: string,224 token_prefix: string,225 ) -> Result<address> {226 let (caller, name, description, token_prefix, _base_uri) =227 convert_data::<T>(caller, name, description, token_prefix, "".into())?;228 let data = make_data::<T>(229 name,230 CollectionMode::ReFungible,231 description,232 token_prefix,233 Default::default(),234 false,235 )?;236 let collection_id = <pallet_refungible::Pallet<T>>::init_collection(caller.clone(), data)237 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;238239 let address = pallet_common::eth::collection_id_to_address(collection_id);240 Ok(address)241 }242243 #[weight(<SelfWeightOf<T>>::create_collection())]244 #[solidity(rename_selector = "createERC721MetadataCompatibleRFTCollection")]245 fn create_refungible_collection_with_properties(246 &mut self,247 caller: caller,248 name: string,249 description: string,250 token_prefix: string,251 base_uri: string,252 ) -> Result<address> {253 let (caller, name, description, token_prefix, base_uri_value) =254 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;255 let data = make_data::<T>(256 name,257 CollectionMode::NFT,258 description,259 token_prefix,260 base_uri_value,261 true,262 )?;263 let collection_id = <pallet_refungible::Pallet<T>>::init_collection(caller.clone(), data)264 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;265266 let address = pallet_common::eth::collection_id_to_address(collection_id);267 Ok(address)268 }269270 /// Check if a collection exists271 /// @param collection_address Address of the collection in question272 /// @return bool Does the collection exist?273 fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {274 if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {275 let collection_id = id;276 return Ok(<CollectionById<T>>::contains_key(collection_id));277 }278279 Ok(false)280 }281}282283/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]284pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);285impl<T: Config + pallet_nonfungible::Config + pallet_refungible::Config> OnMethodCall<T>286 for CollectionHelpersOnMethodCall<T>287{288 fn is_reserved(contract: &sp_core::H160) -> bool {289 contract == &T::ContractAddress::get()290 }291292 fn is_used(contract: &sp_core::H160) -> bool {293 contract == &T::ContractAddress::get()294 }295296 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {297 if handle.code_address() != T::ContractAddress::get() {298 return None;299 }300301 let helpers =302 EvmCollectionHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));303 pallet_evm_coder_substrate::call(handle, helpers)304 }305306 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {307 (contract == &T::ContractAddress::get())308 .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec())309 }310}311312generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);313generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);314315fn error_feild_too_long(feild: &str, bound: usize) -> Error {316 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))317}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Implementation of CollectionHelpers contract.1819use core::marker::PhantomData;20use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};21use ethereum as _;22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};23use pallet_evm::{OnMethodCall, PrecompileResult, account::CrossAccountId, PrecompileHandle};24use up_data_structs::{25 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,26 CollectionMode, PropertyValue,27};28use frame_support::traits::Get;29use pallet_common::{30 CollectionById,31 erc::{32 static_property::{key, value as property_value},33 CollectionHelpersEvents,34 },35 dispatch::CollectionDispatch,36};37use crate::{SelfWeightOf, Config, weights::WeightInfo};3839use sp_std::vec::Vec;40use alloc::format;4142/// See [`CollectionHelpersCall`]43pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);44impl<T: Config> WithRecorder<T> for EvmCollectionHelpers<T> {45 fn recorder(&self) -> &SubstrateRecorder<T> {46 &self.047 }4849 fn into_recorder(self) -> SubstrateRecorder<T> {50 self.051 }52}5354fn convert_data<T: Config>(55 caller: caller,56 name: string,57 description: string,58 token_prefix: string,59 base_uri: string,60) -> Result<(61 T::CrossAccountId,62 CollectionName,63 CollectionDescription,64 CollectionTokenPrefix,65 PropertyValue,66)> {67 let caller = T::CrossAccountId::from_eth(caller);68 let name = name69 .encode_utf16()70 .collect::<Vec<u16>>()71 .try_into()72 .map_err(|_| error_feild_too_long(stringify!(name), CollectionName::bound()))?;73 let description = description74 .encode_utf16()75 .collect::<Vec<u16>>()76 .try_into()77 .map_err(|_| {78 error_feild_too_long(stringify!(description), CollectionDescription::bound())79 })?;80 let token_prefix = token_prefix.into_bytes().try_into().map_err(|_| {81 error_feild_too_long(stringify!(token_prefix), CollectionTokenPrefix::bound())82 })?;83 let base_uri_value = base_uri84 .into_bytes()85 .try_into()86 .map_err(|_| error_feild_too_long(stringify!(token_prefix), PropertyValue::bound()))?;87 Ok((caller, name, description, token_prefix, base_uri_value))88}8990fn make_data<T: Config>(91 name: CollectionName,92 mode: CollectionMode,93 description: CollectionDescription,94 token_prefix: CollectionTokenPrefix,95 base_uri_value: PropertyValue,96 add_properties: bool,97) -> Result<CreateCollectionData<T::AccountId>> {98 let mut properties = up_data_structs::CollectionPropertiesVec::default();99 let mut token_property_permissions =100 up_data_structs::CollectionPropertiesPermissionsVec::default();101102 token_property_permissions103 .try_push(up_data_structs::PropertyKeyPermission {104 key: key::url(),105 permission: up_data_structs::PropertyPermission {106 mutable: false,107 collection_admin: true,108 token_owner: false,109 },110 })111 .map_err(|e| Error::Revert(format!("{:?}", e)))?;112113 if add_properties {114 token_property_permissions115 .try_push(up_data_structs::PropertyKeyPermission {116 key: key::suffix(),117 permission: up_data_structs::PropertyPermission {118 mutable: false,119 collection_admin: true,120 token_owner: false,121 },122 })123 .map_err(|e| Error::Revert(format!("{:?}", e)))?;124125 properties126 .try_push(up_data_structs::Property {127 key: key::schema_name(),128 value: property_value::erc721(),129 })130 .map_err(|e| Error::Revert(format!("{:?}", e)))?;131132 if !base_uri_value.is_empty() {133 properties134 .try_push(up_data_structs::Property {135 key: key::base_uri(),136 value: base_uri_value,137 })138 .map_err(|e| Error::Revert(format!("{:?}", e)))?;139 }140 }141142 let data = CreateCollectionData {143 name,144 mode,145 description,146 token_prefix,147 token_property_permissions,148 properties,149 ..Default::default()150 };151 Ok(data)152}153154/// @title Contract, which allows users to operate with collections155#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]156impl<T> EvmCollectionHelpers<T>157where158 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,159{160 /// Create an NFT collection161 /// @param name Name of the collection162 /// @param description Informative description of the collection163 /// @param token_prefix Token prefix to represent the collection tokens in UI and user applications164 /// @return address Address of the newly created collection165 #[weight(<SelfWeightOf<T>>::create_collection())]166 fn create_nonfungible_collection(167 &mut self,168 caller: caller,169 name: string,170 description: string,171 token_prefix: string,172 ) -> Result<address> {173 let (caller, name, description, token_prefix, _base_uri_value) =174 convert_data::<T>(caller, name, description, token_prefix, "".into())?;175 let data = make_data::<T>(176 name,177 CollectionMode::NFT,178 description,179 token_prefix,180 Default::default(),181 false,182 )?;183 let collection_id = T::CollectionDispatch::create(caller, data)184 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;185186 let address = pallet_common::eth::collection_id_to_address(collection_id);187 Ok(address)188 }189190 #[weight(<SelfWeightOf<T>>::create_collection())]191 #[solidity(rename_selector = "createERC721MetadataCompatibleCollection")]192 fn create_nonfungible_collection_with_properties(193 &mut self,194 caller: caller,195 name: string,196 description: string,197 token_prefix: string,198 base_uri: string,199 ) -> Result<address> {200 let (caller, name, description, token_prefix, base_uri_value) =201 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;202 let data = make_data::<T>(203 name,204 CollectionMode::NFT,205 description,206 token_prefix,207 base_uri_value,208 true,209 )?;210 let collection_id = T::CollectionDispatch::create(caller, data)211 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;212213 let address = pallet_common::eth::collection_id_to_address(collection_id);214 Ok(address)215 }216217 #[weight(<SelfWeightOf<T>>::create_collection())]218 fn create_refungible_collection(219 &self,220 caller: caller,221 name: string,222 description: string,223 token_prefix: string,224 ) -> Result<address> {225 let (caller, name, description, token_prefix, _base_uri) =226 convert_data::<T>(caller, name, description, token_prefix, "".into())?;227 let data = make_data::<T>(228 name,229 CollectionMode::ReFungible,230 description,231 token_prefix,232 Default::default(),233 false,234 )?;235 let collection_id = T::CollectionDispatch::create(caller, data)236 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;237238 let address = pallet_common::eth::collection_id_to_address(collection_id);239 Ok(address)240 }241242 #[weight(<SelfWeightOf<T>>::create_collection())]243 #[solidity(rename_selector = "createERC721MetadataCompatibleRFTCollection")]244 fn create_refungible_collection_with_properties(245 &mut self,246 caller: caller,247 name: string,248 description: string,249 token_prefix: string,250 base_uri: string,251 ) -> Result<address> {252 let (caller, name, description, token_prefix, base_uri_value) =253 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;254 let data = make_data::<T>(255 name,256 CollectionMode::NFT,257 description,258 token_prefix,259 base_uri_value,260 true,261 )?;262 let collection_id = T::CollectionDispatch::create(caller, data)263 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;264265 let address = pallet_common::eth::collection_id_to_address(collection_id);266 Ok(address)267 }268269 /// Check if a collection exists270 /// @param collection_address Address of the collection in question271 /// @return bool Does the collection exist?272 fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {273 if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {274 let collection_id = id;275 return Ok(<CollectionById<T>>::contains_key(collection_id));276 }277278 Ok(false)279 }280}281282/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]283pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);284impl<T: Config + pallet_nonfungible::Config + pallet_refungible::Config> OnMethodCall<T>285 for CollectionHelpersOnMethodCall<T>286{287 fn is_reserved(contract: &sp_core::H160) -> bool {288 contract == &T::ContractAddress::get()289 }290291 fn is_used(contract: &sp_core::H160) -> bool {292 contract == &T::ContractAddress::get()293 }294295 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {296 if handle.code_address() != T::ContractAddress::get() {297 return None;298 }299300 let helpers =301 EvmCollectionHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));302 pallet_evm_coder_substrate::call(handle, helpers)303 }304305 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {306 (contract == &T::ContractAddress::get())307 .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec())308 }309}310311generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);312generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);313314fn error_feild_too_long(feild: &str, bound: usize) -> Error {315 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))316}pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -352,7 +352,7 @@
// =========
- T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;
+ let _id = T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;
Ok(())
}
runtime/common/src/dispatch.rsdiffbeforeafterboth--- a/runtime/common/src/dispatch.rs
+++ b/runtime/common/src/dispatch.rs
@@ -17,6 +17,7 @@
use frame_support::{dispatch::DispatchResult, ensure};
use pallet_evm::{PrecompileHandle, PrecompileResult};
use sp_core::H160;
+use sp_runtime::DispatchError;
use sp_std::{borrow::ToOwned, vec::Vec};
use pallet_common::{
CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler,
@@ -30,6 +31,7 @@
};
use up_data_structs::{
CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,
+ CollectionId,
};
pub enum CollectionDispatchT<T>
@@ -51,8 +53,8 @@
fn create(
sender: T::CrossAccountId,
data: CreateCollectionData<T::AccountId>,
- ) -> DispatchResult {
- let _id = match data.mode {
+ ) -> Result<CollectionId, DispatchError> {
+ let id = match data.mode {
CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,
CollectionMode::Fungible(decimal_points) => {
// check params
@@ -64,7 +66,7 @@
}
CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,
};
- Ok(())
+ Ok(id)
}
fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {