difftreelog
Merge branch 'develop' into tests/increase_timeout
in: master
3 files changed
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 ethereum as _;21use evm_coder::{execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};22use frame_support::traits::Get;23use crate::Pallet;2425use pallet_common::{26 CollectionById,27 dispatch::CollectionDispatch,28 erc::{static_property::key, CollectionHelpersEvents},29 Pallet as PalletCommon,30};31use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};32use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};33use sp_std::vec;34use up_data_structs::{35 CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix,36 CreateCollectionData,37};3839use crate::{weights::WeightInfo, Config, SelfWeightOf};4041use alloc::format;42use sp_std::vec::Vec;4344/// See [`CollectionHelpersCall`]45pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);46impl<T: Config> WithRecorder<T> for EvmCollectionHelpers<T> {47 fn recorder(&self) -> &SubstrateRecorder<T> {48 &self.049 }5051 fn into_recorder(self) -> SubstrateRecorder<T> {52 self.053 }54}5556fn convert_data<T: Config>(57 caller: caller,58 name: string,59 description: string,60 token_prefix: string,61) -> Result<(62 T::CrossAccountId,63 CollectionName,64 CollectionDescription,65 CollectionTokenPrefix,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_field_too_long(stringify!(name), CollectionName::bound()))?;73 let description = description74 .encode_utf16()75 .collect::<Vec<u16>>()76 .try_into()77 .map_err(|_| {78 error_field_too_long(stringify!(description), CollectionDescription::bound())79 })?;80 let token_prefix = token_prefix.into_bytes().try_into().map_err(|_| {81 error_field_too_long(stringify!(token_prefix), CollectionTokenPrefix::bound())82 })?;83 Ok((caller, name, description, token_prefix))84}8586#[inline(always)]87fn create_collection_internal<T: Config>(88 caller: caller,89 value: value,90 name: string,91 collection_mode: CollectionMode,92 description: string,93 token_prefix: string,94) -> Result<address> {95 let (caller, name, description, token_prefix) =96 convert_data::<T>(caller, name, description, token_prefix)?;97 let data = CreateCollectionData {98 name,99 mode: collection_mode,100 description,101 token_prefix,102 ..Default::default()103 };104 check_sent_amount_equals_collection_creation_price::<T>(value)?;105 let collection_helpers_address =106 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());107108 let collection_id = T::CollectionDispatch::create(109 caller.clone(),110 collection_helpers_address,111 data,112 Default::default(),113 )114 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;115 let address = pallet_common::eth::collection_id_to_address(collection_id);116 Ok(address)117}118119fn check_sent_amount_equals_collection_creation_price<T: Config>(value: value) -> Result<()> {120 let value = value.as_u128();121 let creation_price: u128 = T::CollectionCreationPrice::get()122 .try_into()123 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait124 .expect("Collection creation price should be convertible to u128");125 if value != creation_price {126 return Err(format!(127 "Sent amount not equals to collection creation price ({0})",128 creation_price129 )130 .into());131 }132 Ok(())133}134135/// @title Contract, which allows users to operate with collections136#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]137impl<T> EvmCollectionHelpers<T>138where139 T: Config + pallet_common::Config + pallet_nonfungible::Config + pallet_refungible::Config,140{141 /// Create an NFT collection142 /// @param name Name of the collection143 /// @param description Informative description of the collection144 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications145 /// @return address Address of the newly created collection146 #[weight(<SelfWeightOf<T>>::create_collection())]147 #[solidity(rename_selector = "createNFTCollection")]148 fn create_nft_collection(149 &mut self,150 caller: caller,151 value: value,152 name: string,153 description: string,154 token_prefix: string,155 ) -> Result<address> {156 let (caller, name, description, token_prefix) =157 convert_data::<T>(caller, name, description, token_prefix)?;158 let data = CreateCollectionData {159 name,160 mode: CollectionMode::NFT,161 description,162 token_prefix,163 ..Default::default()164 };165 check_sent_amount_equals_collection_creation_price::<T>(value)?;166 let collection_helpers_address =167 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());168 let collection_id = T::CollectionDispatch::create(169 caller,170 collection_helpers_address,171 data,172 Default::default(),173 )174 .map_err(dispatch_to_evm::<T>)?;175176 let address = pallet_common::eth::collection_id_to_address(collection_id);177 Ok(address)178 }179 /// Create an NFT collection180 /// @param name Name of the collection181 /// @param description Informative description of the collection182 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications183 /// @return address Address of the newly created collection184 #[weight(<SelfWeightOf<T>>::create_collection())]185 #[deprecated(note = "mathod was renamed to `create_nft_collection`, prefer it instead")]186 #[solidity(hide)]187 fn create_nonfungible_collection(188 &mut self,189 caller: caller,190 value: value,191 name: string,192 description: string,193 token_prefix: string,194 ) -> Result<address> {195 create_collection_internal::<T>(196 caller,197 value,198 name,199 CollectionMode::NFT,200 description,201 token_prefix,202 )203 }204205 #[weight(<SelfWeightOf<T>>::create_collection())]206 #[solidity(rename_selector = "createRFTCollection")]207 fn create_rft_collection(208 &mut self,209 caller: caller,210 value: value,211 name: string,212 description: string,213 token_prefix: string,214 ) -> Result<address> {215 create_collection_internal::<T>(216 caller,217 value,218 name,219 CollectionMode::ReFungible,220 description,221 token_prefix,222 )223 }224225 #[weight(<SelfWeightOf<T>>::create_collection())]226 #[solidity(rename_selector = "createFTCollection")]227 fn create_fungible_collection(228 &mut self,229 caller: caller,230 value: value,231 name: string,232 decimals: uint8,233 description: string,234 token_prefix: string,235 ) -> Result<address> {236 create_collection_internal::<T>(237 caller,238 value,239 name,240 CollectionMode::Fungible(decimals),241 description,242 token_prefix,243 )244 }245246 #[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")]247 fn make_collection_metadata_compatible(248 &mut self,249 caller: caller,250 collection: address,251 base_uri: string,252 ) -> Result<()> {253 let caller = T::CrossAccountId::from_eth(caller);254 let collection =255 pallet_common::eth::map_eth_to_id(&collection).ok_or("not a collection address")?;256 let mut collection =257 <crate::CollectionHandle<T>>::new(collection).ok_or("collection not found")?;258259 if !matches!(260 collection.mode,261 CollectionMode::NFT | CollectionMode::ReFungible262 ) {263 return Err("target collection should be either NFT or Refungible".into());264 }265266 self.recorder().consume_sstore()?;267 collection268 .check_is_owner_or_admin(&caller)269 .map_err(dispatch_to_evm::<T>)?;270271 if collection.flags.erc721metadata {272 return Err("target collection is already Erc721Metadata compatible".into());273 }274 collection.flags.erc721metadata = true;275276 let all_permissions = <pallet_common::CollectionPropertyPermissions<T>>::get(collection.id);277 if all_permissions.get(&key::url()).is_none() {278 self.recorder().consume_sstore()?;279 <PalletCommon<T>>::set_property_permission(280 &collection,281 &caller,282 up_data_structs::PropertyKeyPermission {283 key: key::url(),284 permission: up_data_structs::PropertyPermission {285 mutable: true,286 collection_admin: true,287 token_owner: false,288 },289 },290 )291 .map_err(dispatch_to_evm::<T>)?;292 }293 if all_permissions.get(&key::suffix()).is_none() {294 self.recorder().consume_sstore()?;295 <PalletCommon<T>>::set_property_permission(296 &collection,297 &caller,298 up_data_structs::PropertyKeyPermission {299 key: key::suffix(),300 permission: up_data_structs::PropertyPermission {301 mutable: true,302 collection_admin: true,303 token_owner: false,304 },305 },306 )307 .map_err(dispatch_to_evm::<T>)?;308 }309310 let all_properties = <pallet_common::CollectionProperties<T>>::get(collection.id);311 if all_properties.get(&key::base_uri()).is_none() && !base_uri.is_empty() {312 self.recorder().consume_sstore()?;313 <PalletCommon<T>>::set_collection_properties(314 &collection,315 &caller,316 vec![up_data_structs::Property {317 key: key::base_uri(),318 value: base_uri319 .into_bytes()320 .try_into()321 .map_err(|_| "base uri is too large")?,322 }],323 )324 .map_err(dispatch_to_evm::<T>)?;325 }326327 self.recorder().consume_sstore()?;328 collection.save().map_err(dispatch_to_evm::<T>)?;329330 Ok(())331 }332333 #[weight(<SelfWeightOf<T>>::destroy_collection())]334 fn destroy_collection(&mut self, caller: caller, collection_address: address) -> Result<void> {335 let caller = T::CrossAccountId::from_eth(caller);336337 let collection_id = pallet_common::eth::map_eth_to_id(&collection_address)338 .ok_or("Invalid collection address format")?;339 <Pallet<T>>::destroy_collection_internal(caller, collection_id)340 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)341 }342343 /// Check if a collection exists344 /// @param collectionAddress Address of the collection in question345 /// @return bool Does the collection exist?346 fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {347 if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {348 let collection_id = id;349 return Ok(<CollectionById<T>>::contains_key(collection_id));350 }351352 Ok(false)353 }354355 fn collection_creation_fee(&self) -> Result<value> {356 let price: u128 = T::CollectionCreationPrice::get()357 .try_into()358 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait359 .expect("Collection creation price should be convertible to u128");360 Ok(price.into())361 }362}363364/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]365pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);366impl<T: Config + pallet_nonfungible::Config + pallet_refungible::Config> OnMethodCall<T>367 for CollectionHelpersOnMethodCall<T>368{369 fn is_reserved(contract: &sp_core::H160) -> bool {370 contract == &T::ContractAddress::get()371 }372373 fn is_used(contract: &sp_core::H160) -> bool {374 contract == &T::ContractAddress::get()375 }376377 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {378 if handle.code_address() != T::ContractAddress::get() {379 return None;380 }381382 let helpers =383 EvmCollectionHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));384 pallet_evm_coder_substrate::call(handle, helpers)385 }386387 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {388 (contract == &T::ContractAddress::get())389 .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec())390 }391}392393generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);394generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);395396fn error_field_too_long(feild: &str, bound: usize) -> Error {397 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))398}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 ethereum as _;21use evm_coder::{execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};22use frame_support::traits::Get;23use crate::Pallet;2425use pallet_common::{26 CollectionById, dispatch::CollectionDispatch, erc::static_property::key, Pallet as PalletCommon,27};28use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};29use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};30use sp_std::vec;31use up_data_structs::{32 CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix,33 CreateCollectionData,34};3536use crate::{weights::WeightInfo, Config, SelfWeightOf};3738use alloc::format;39use sp_std::vec::Vec;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) -> Result<(59 T::CrossAccountId,60 CollectionName,61 CollectionDescription,62 CollectionTokenPrefix,63)> {64 let caller = T::CrossAccountId::from_eth(caller);65 let name = name66 .encode_utf16()67 .collect::<Vec<u16>>()68 .try_into()69 .map_err(|_| error_field_too_long(stringify!(name), CollectionName::bound()))?;70 let description = description71 .encode_utf16()72 .collect::<Vec<u16>>()73 .try_into()74 .map_err(|_| {75 error_field_too_long(stringify!(description), CollectionDescription::bound())76 })?;77 let token_prefix = token_prefix.into_bytes().try_into().map_err(|_| {78 error_field_too_long(stringify!(token_prefix), CollectionTokenPrefix::bound())79 })?;80 Ok((caller, name, description, token_prefix))81}8283#[inline(always)]84fn create_collection_internal<T: Config>(85 caller: caller,86 value: value,87 name: string,88 collection_mode: CollectionMode,89 description: string,90 token_prefix: string,91) -> Result<address> {92 let (caller, name, description, token_prefix) =93 convert_data::<T>(caller, name, description, token_prefix)?;94 let data = CreateCollectionData {95 name,96 mode: collection_mode,97 description,98 token_prefix,99 ..Default::default()100 };101 check_sent_amount_equals_collection_creation_price::<T>(value)?;102 let collection_helpers_address =103 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());104105 let collection_id = T::CollectionDispatch::create(106 caller.clone(),107 collection_helpers_address,108 data,109 Default::default(),110 )111 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;112 let address = pallet_common::eth::collection_id_to_address(collection_id);113 Ok(address)114}115116fn check_sent_amount_equals_collection_creation_price<T: Config>(value: value) -> Result<()> {117 let value = value.as_u128();118 let creation_price: u128 = T::CollectionCreationPrice::get()119 .try_into()120 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait121 .expect("Collection creation price should be convertible to u128");122 if value != creation_price {123 return Err(format!(124 "Sent amount not equals to collection creation price ({0})",125 creation_price126 )127 .into());128 }129 Ok(())130}131132/// @title Contract, which allows users to operate with collections133#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]134impl<T> EvmCollectionHelpers<T>135where136 T: Config + pallet_common::Config + pallet_nonfungible::Config + pallet_refungible::Config,137{138 /// Create an NFT collection139 /// @param name Name of the collection140 /// @param description Informative description of the collection141 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications142 /// @return address Address of the newly created collection143 #[weight(<SelfWeightOf<T>>::create_collection())]144 #[solidity(rename_selector = "createNFTCollection")]145 fn create_nft_collection(146 &mut self,147 caller: caller,148 value: value,149 name: string,150 description: string,151 token_prefix: string,152 ) -> Result<address> {153 let (caller, name, description, token_prefix) =154 convert_data::<T>(caller, name, description, token_prefix)?;155 let data = CreateCollectionData {156 name,157 mode: CollectionMode::NFT,158 description,159 token_prefix,160 ..Default::default()161 };162 check_sent_amount_equals_collection_creation_price::<T>(value)?;163 let collection_helpers_address =164 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());165 let collection_id = T::CollectionDispatch::create(166 caller,167 collection_helpers_address,168 data,169 Default::default(),170 )171 .map_err(dispatch_to_evm::<T>)?;172173 let address = pallet_common::eth::collection_id_to_address(collection_id);174 Ok(address)175 }176 /// Create an NFT collection177 /// @param name Name of the collection178 /// @param description Informative description of the collection179 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications180 /// @return address Address of the newly created collection181 #[weight(<SelfWeightOf<T>>::create_collection())]182 #[deprecated(note = "mathod was renamed to `create_nft_collection`, prefer it instead")]183 #[solidity(hide)]184 fn create_nonfungible_collection(185 &mut self,186 caller: caller,187 value: value,188 name: string,189 description: string,190 token_prefix: string,191 ) -> Result<address> {192 create_collection_internal::<T>(193 caller,194 value,195 name,196 CollectionMode::NFT,197 description,198 token_prefix,199 )200 }201202 #[weight(<SelfWeightOf<T>>::create_collection())]203 #[solidity(rename_selector = "createRFTCollection")]204 fn create_rft_collection(205 &mut self,206 caller: caller,207 value: value,208 name: string,209 description: string,210 token_prefix: string,211 ) -> Result<address> {212 create_collection_internal::<T>(213 caller,214 value,215 name,216 CollectionMode::ReFungible,217 description,218 token_prefix,219 )220 }221222 #[weight(<SelfWeightOf<T>>::create_collection())]223 #[solidity(rename_selector = "createFTCollection")]224 fn create_fungible_collection(225 &mut self,226 caller: caller,227 value: value,228 name: string,229 decimals: uint8,230 description: string,231 token_prefix: string,232 ) -> Result<address> {233 create_collection_internal::<T>(234 caller,235 value,236 name,237 CollectionMode::Fungible(decimals),238 description,239 token_prefix,240 )241 }242243 #[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")]244 fn make_collection_metadata_compatible(245 &mut self,246 caller: caller,247 collection: address,248 base_uri: string,249 ) -> Result<()> {250 let caller = T::CrossAccountId::from_eth(caller);251 let collection =252 pallet_common::eth::map_eth_to_id(&collection).ok_or("not a collection address")?;253 let mut collection =254 <crate::CollectionHandle<T>>::new(collection).ok_or("collection not found")?;255256 if !matches!(257 collection.mode,258 CollectionMode::NFT | CollectionMode::ReFungible259 ) {260 return Err("target collection should be either NFT or Refungible".into());261 }262263 self.recorder().consume_sstore()?;264 collection265 .check_is_owner_or_admin(&caller)266 .map_err(dispatch_to_evm::<T>)?;267268 if collection.flags.erc721metadata {269 return Err("target collection is already Erc721Metadata compatible".into());270 }271 collection.flags.erc721metadata = true;272273 let all_permissions = <pallet_common::CollectionPropertyPermissions<T>>::get(collection.id);274 if all_permissions.get(&key::url()).is_none() {275 self.recorder().consume_sstore()?;276 <PalletCommon<T>>::set_property_permission(277 &collection,278 &caller,279 up_data_structs::PropertyKeyPermission {280 key: key::url(),281 permission: up_data_structs::PropertyPermission {282 mutable: true,283 collection_admin: true,284 token_owner: false,285 },286 },287 )288 .map_err(dispatch_to_evm::<T>)?;289 }290 if all_permissions.get(&key::suffix()).is_none() {291 self.recorder().consume_sstore()?;292 <PalletCommon<T>>::set_property_permission(293 &collection,294 &caller,295 up_data_structs::PropertyKeyPermission {296 key: key::suffix(),297 permission: up_data_structs::PropertyPermission {298 mutable: true,299 collection_admin: true,300 token_owner: false,301 },302 },303 )304 .map_err(dispatch_to_evm::<T>)?;305 }306307 let all_properties = <pallet_common::CollectionProperties<T>>::get(collection.id);308 if all_properties.get(&key::base_uri()).is_none() && !base_uri.is_empty() {309 self.recorder().consume_sstore()?;310 <PalletCommon<T>>::set_collection_properties(311 &collection,312 &caller,313 vec![up_data_structs::Property {314 key: key::base_uri(),315 value: base_uri316 .into_bytes()317 .try_into()318 .map_err(|_| "base uri is too large")?,319 }],320 )321 .map_err(dispatch_to_evm::<T>)?;322 }323324 self.recorder().consume_sstore()?;325 collection.save().map_err(dispatch_to_evm::<T>)?;326327 Ok(())328 }329330 #[weight(<SelfWeightOf<T>>::destroy_collection())]331 fn destroy_collection(&mut self, caller: caller, collection_address: address) -> Result<void> {332 let caller = T::CrossAccountId::from_eth(caller);333334 let collection_id = pallet_common::eth::map_eth_to_id(&collection_address)335 .ok_or("Invalid collection address format")?;336 <Pallet<T>>::destroy_collection_internal(caller, collection_id)337 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)338 }339340 /// Check if a collection exists341 /// @param collectionAddress Address of the collection in question342 /// @return bool Does the collection exist?343 fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {344 if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {345 let collection_id = id;346 return Ok(<CollectionById<T>>::contains_key(collection_id));347 }348349 Ok(false)350 }351352 fn collection_creation_fee(&self) -> Result<value> {353 let price: u128 = T::CollectionCreationPrice::get()354 .try_into()355 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait356 .expect("Collection creation price should be convertible to u128");357 Ok(price.into())358 }359}360361/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]362pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);363impl<T: Config + pallet_nonfungible::Config + pallet_refungible::Config> OnMethodCall<T>364 for CollectionHelpersOnMethodCall<T>365{366 fn is_reserved(contract: &sp_core::H160) -> bool {367 contract == &T::ContractAddress::get()368 }369370 fn is_used(contract: &sp_core::H160) -> bool {371 contract == &T::ContractAddress::get()372 }373374 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {375 if handle.code_address() != T::ContractAddress::get() {376 return None;377 }378379 let helpers =380 EvmCollectionHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));381 pallet_evm_coder_substrate::call(handle, helpers)382 }383384 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {385 (contract == &T::ContractAddress::get())386 .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec())387 }388}389390generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);391generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);392393fn error_field_too_long(feild: &str, bound: usize) -> Error {394 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))395}runtime/common/config/pallets/scheduler.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/scheduler.rs
+++ b/runtime/common/config/pallets/scheduler.rs
@@ -25,7 +25,7 @@
use codec::Decode;
use crate::{
runtime_common::{scheduler::SchedulerPaymentExecutor, config::substrate::RuntimeBlockWeights},
- Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, OriginCaller,
+ Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, OriginCaller, Balances,
};
use pallet_unique_scheduler::ScheduledEnsureOriginSuccess;
use up_common::types::AccountId;
runtime/common/scheduler.rsdiffbeforeafterboth--- a/runtime/common/scheduler.rs
+++ b/runtime/common/scheduler.rs
@@ -14,16 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo, DispatchInfo};
+use frame_support::{
+ traits::NamedReservableCurrency,
+ dispatch::{GetDispatchInfo, PostDispatchInfo, DispatchInfo},
+};
use sp_runtime::{
traits::{Dispatchable, Applyable, Member},
generic::Era,
transaction_validity::TransactionValidityError,
- DispatchErrorWithPostInfo,
+ DispatchErrorWithPostInfo, DispatchError,
};
use codec::Encode;
-use crate::{Runtime, RuntimeCall, RuntimeOrigin};
-use up_common::types::AccountId;
+use crate::{Runtime, RuntimeCall, RuntimeOrigin, Balances};
+use up_common::types::{AccountId, Balance};
use fp_self_contained::SelfContainedCall;
use pallet_unique_scheduler::DispatchCall;
use pallet_transaction_payment::ChargeTransactionPayment;