difftreelog
refactor split common pallet
in: master
16 files changed
pallets/common/Cargo.tomldiffbeforeafterbothno changes
pallets/common/src/account.rsdiffbeforeafterbothno changes
pallets/common/src/benchmarking.rsdiffbeforeafterbothno changes
pallets/common/src/erc.rsdiffbeforeafterbothno changes
pallets/common/src/eth.rsdiffbeforeafterbothno changes
pallets/common/src/lib.rsdiffbeforeafterbothno changes
pallets/nft/src/eth/account.rsdiffbeforeafterbothno changes
pallets/nft/src/eth/erc.rsdiffbeforeafterbothno changes
pallets/nft/src/eth/mod.rsdiffbeforeafterboth1pub mod account;1pub mod sponsoring;23use pallet_common::{4 CollectionById,2pub mod erc;5 erc::CommonEvmHandler,6 eth::{map_eth_to_id, map_eth_to_token_id},7};3pub mod sponsoring;8use pallet_fungible::FungibleHandle;45use pallet_evm_coder_substrate::call_internal;9use pallet_nonfungible::NonfungibleHandle;10use pallet_refungible::{RefungibleHandle, erc::RefungibleTokenHandle};6use sp_std::borrow::ToOwned;11use sp_std::borrow::ToOwned;7use sp_std::vec::Vec;12use sp_std::vec::Vec;8use pallet_evm::{PrecompileOutput};13use pallet_evm::{PrecompileOutput};9use sp_core::{H160, U256};14use sp_core::{H160, U256};10use frame_support::storage::StorageMap;11use crate::{Config, CollectionById, CollectionHandle, CollectionId, CollectionMode};15use crate::{CollectionMode, Config, dispatch::Dispatched};12use erc::{UniqueFungibleCall, UniqueNFTCall};16use pallet_common::CollectionHandle;131714pub struct NftErcSupport<T: Config>(core::marker::PhantomData<T>);18pub struct NftErcSupport<T: Config>(core::marker::PhantomData<T>);1516// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection17// TODO: Unhardcode prefix18const ETH_ACCOUNT_PREFIX: [u8; 16] = [19 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,20];2122fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {23 if eth[0..16] != ETH_ACCOUNT_PREFIX {24 return None;25 }26 let mut id_bytes = [0; 4];27 id_bytes.copy_from_slice(ð[16..20]);28 Some(u32::from_be_bytes(id_bytes))29}30pub fn collection_id_to_address(id: u32) -> H160 {31 let mut out = [0; 20];32 out[0..16].copy_from_slice(Ð_ACCOUNT_PREFIX);33 out[16..20].copy_from_slice(&u32::to_be_bytes(id));34 H160(out)35}3637/*38fn call_internal<T: Config>(39 collection: &mut CollectionHandle<T>,40 caller: caller,41 method_id: u32,42 mut input: AbiReader,43 value: U256,44) -> Result<Option<AbiWriter>> {45 match collection.mode.clone() {46 CollectionMode::Fungible(_) => {47 call_internal();48 let call = match UniqueFungibleCall::parse(method_id, &mut input)? {49 Some(v) => v,50 None => {51 #[cfg(feature = "std")]52 {53 println!("Method not found");54 }55 return Ok(None);56 }57 };58 Ok(Some(<CollectionHandle<T> as UniqueFungible>::call(59 collection,60 Msg {61 call,62 caller,63 value,64 },65 )?))66 }67 CollectionMode::NFT => {68 let call = match UniqueNFTCall::parse(method_id, &mut input)? {69 Some(v) => v,70 None => return Ok(None),71 };72 Ok(Some(<CollectionHandle<T> as UniqueNFT>::call(73 collection,74 Msg {75 call,76 caller,77 value,78 },79 )?))80 }81 _ => Err("erc calls only supported to fungible and nft collections for now".into()),82 }83}*/841985impl<T: Config> pallet_evm::OnMethodCall<T> for NftErcSupport<T> {20impl<T: Config> pallet_evm::OnMethodCall<T> for NftErcSupport<T> {86 fn is_reserved(target: &H160) -> bool {21 fn is_reserved(target: &H160) -> bool {92 .unwrap_or(false)27 .unwrap_or(false)93 }28 }94 fn get_code(target: &H160) -> Option<Vec<u8>> {29 fn get_code(target: &H160) -> Option<Vec<u8>> {95 map_eth_to_id(target)30 if let Some(collection_id) = map_eth_to_id(target) {96 .and_then(<CollectionById<T>>::get)31 let collection = <CollectionById<T>>::get(collection_id)?;97 .map(|collection| {32 Some(98 match collection.mode {33 match collection.mode {99 CollectionMode::NFT => include_bytes!("stubs/UniqueNFT.raw") as &[u8],34 CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,100 CollectionMode::Fungible(_) => {35 CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,101 include_bytes!("stubs/UniqueFungible.raw") as &[u8]102 }103 CollectionMode::ReFungible => {36 CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,104 include_bytes!("stubs/UniqueRefungible.raw") as &[u8]105 }106 }37 }107 .to_owned()38 .to_owned(),108 })39 )40 } else if let Some((collection_id, _token_id)) = map_eth_to_token_id(target) {41 let collection = <CollectionById<T>>::get(collection_id)?;42 if collection.mode != CollectionMode::ReFungible {43 return None;44 }45 // TODO: check token existence46 Some(<RefungibleTokenHandle<T>>::CODE.to_owned())47 } else {48 None49 }109 }50 }110 fn call(51 fn call(111 source: &H160,52 source: &H160,114 input: &[u8],55 input: &[u8],115 value: U256,56 value: U256,116 ) -> Option<PrecompileOutput> {57 ) -> Option<PrecompileOutput> {58 if let Some(collection_id) = map_eth_to_id(target) {117 let mut collection = map_eth_to_id(target)59 let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;118 .and_then(|id| <CollectionHandle<T>>::get_with_gas_limit(id, gas_limit))?;119 let result = match collection.mode {60 let dispatched = Dispatched::dispatch(collection);6162 match dispatched {120 CollectionMode::NFT => {63 Dispatched::Fungible(h) => h.call(source, input, value),121 call_internal::<UniqueNFTCall, _>(*source, &mut collection, value, input)122 }123 CollectionMode::Fungible(_) => {64 Dispatched::Nonfungible(h) => h.call(source, input, value),124 call_internal::<UniqueFungibleCall, _>(*source, &mut collection, value, input)125 }126 _ => return None,65 Dispatched::Refungible(h) => h.call(source, input, value),127 };66 }67 } else if let Some((collection_id, token_id)) = map_eth_to_token_id(target) {68 let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;128 collection.recorder.evm_to_precompile_output(result)69 if collection.mode != CollectionMode::ReFungible {70 return None;71 }7273 let handle = RefungibleHandle::cast(collection);74 // TODO: check token existence75 RefungibleTokenHandle(handle, token_id).call(source, input, value)76 } else {77 None78 }129 }79 }130}80}13181pallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth1//! Implements EVM sponsoring logic via OnChargeEVMTransaction1//! Implements EVM sponsoring logic via OnChargeEVMTransaction223use crate::{3use crate::{Collection, Config, FungibleTransferBasket, NftTransferBasket};4 Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket,5 eth::{account::EvmBackwardsAddressMapping, map_eth_to_id},6};7use evm_coder::{Call, abi::AbiReader};4use evm_coder::{Call, abi::AbiReader};8use frame_support::{5use frame_support::{9 storage::{StorageMap, StorageDoubleMap},6 storage::{StorageDoubleMap},10};7};8use pallet_common::eth::map_eth_to_id;11use sp_core::H160;9use sp_core::H160;12use sp_std::prelude::*;10use sp_std::prelude::*;13use up_sponsorship::SponsorshipHandler;11use up_sponsorship::SponsorshipHandler;14use super::{12use core::marker::PhantomData;15 account::CrossAccountId,16 erc::{UniqueFungibleCall, UniqueNFTCall, ERC721Call, ERC20Call, ERC721UniqueExtensionsCall},17};18use core::convert::TryInto;13use core::convert::TryInto;14use nft_data_structs::{CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT};15use pallet_common::{16 CollectionById,17 account::{CrossAccountId, EvmBackwardsAddressMapping},18};1919use core::marker::PhantomData;20use pallet_nonfungible::erc::{UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721Call};20use nft_data_structs::{NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT};21use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};212222struct AnyError;23struct AnyError;232424fn try_sponsor<T: Config>(25fn try_sponsor<T: Config>(25 caller: &H160,26 caller: &H160,26 collection_id: u32,27 collection_id: CollectionId,27 collection: &Collection<T>,28 collection: &Collection<T>,28 call: &[u8],29 call: &[u8],29) -> Result<(), AnyError> {30) -> Result<(), AnyError> {pallets/nft/src/eth/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/nft/src/eth/stubs/UniqueFungible.soldiffbeforeafterbothno changes
pallets/nft/src/eth/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nft/src/eth/stubs/UniqueNFT.soldiffbeforeafterbothno changes
pallets/nft/src/eth/stubs/UniqueRefungible.rawdiffbeforeafterbothno changes
pallets/nft/src/lib.rsdiffbeforeafterboth69decl_error! {69decl_error! {70 /// Error for non-fungible-token module.70 /// Error for non-fungible-token module.71 pub enum Error for Module<T: Config> {71 pub enum Error for Module<T: Config> {72 /// Total collections bound exceeded.73 TotalCollectionsLimitExceeded,74 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.72 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.75 CollectionDecimalPointLimitExceeded,73 CollectionDecimalPointLimitExceeded,76 /// Collection name can not be longer than 63 char.77 CollectionNameLimitExceeded,78 /// Collection description can not be longer than 255 char.79 CollectionDescriptionLimitExceeded,80 /// Token prefix can not be longer than 15 char.81 CollectionTokenPrefixLimitExceeded,82 /// This collection does not exist.83 CollectionNotFound,84 /// Item not exists.85 TokenNotFound,86 /// Admin not found87 AdminNotFound,88 /// Arithmetic calculation overflow.89 NumOverflow,90 /// Account already has admin role.91 AlreadyAdmin,92 /// You do not own this collection.93 NoPermission,94 /// This address is not set as sponsor, use setCollectionSponsor first.74 /// This address is not set as sponsor, use setCollectionSponsor first.95 ConfirmUnsetSponsorFail,75 ConfirmUnsetSponsorFail,96 /// Collection is not in mint mode.97 PublicMintingNotAllowed,98 /// Sender parameter and item owner must be equal.99 MustBeTokenOwner,100 /// Item balance not enough.101 TokenValueTooLow,102 /// Size of item is too large.103 NftSizeLimitExceeded,104 /// No approve found105 ApproveNotFound,106 /// Requested value more than approved.107 TokenValueNotEnough,108 /// Only approved addresses can call this method.109 ApproveRequired,110 /// Address is not in white list.111 AddresNotInWhiteList,112 /// Number of collection admins bound exceeded.113 CollectionAdminsLimitExceeded,114 /// Owned tokens by a single address bound exceeded.115 AddressOwnershipLimitExceeded,116 /// Length of items properties must be greater than 0.76 /// Length of items properties must be greater than 0.117 EmptyArgument,77 EmptyArgument,118 /// const_data exceeded data limit.119 TokenConstDataLimitExceeded,120 /// variable_data exceeded data limit.121 TokenVariableDataLimitExceeded,122 /// Not NFT item data used to mint in NFT collection.123 NotNftDataUsedToMintNftCollectionToken,124 /// Not Fungible item data used to mint in Fungible collection.125 NotFungibleDataUsedToMintFungibleCollectionToken,126 /// Not Re Fungible item data used to mint in Re Fungible collection.127 NotReFungibleDataUsedToMintReFungibleCollectionToken,128 /// Unexpected collection type.129 UnexpectedCollectionType,130 /// Can't store metadata in fungible tokens.131 CantStoreMetadataInFungibleTokens,132 /// Collection token limit exceeded133 CollectionTokenLimitExceeded,134 /// Account token limit exceeded per collection135 AccountTokenLimitExceeded,136 /// Collection limit bounds per collection exceeded78 /// Collection limit bounds per collection exceeded137 CollectionLimitBoundsExceeded,79 CollectionLimitBoundsExceeded,138 /// Tried to enable permissions which are only permitted to be disabled80 /// Tried to enable permissions which are only permitted to be disabled139 OwnerPermissionsCantBeReverted,81 OwnerPermissionsCantBeReverted,140 /// Schema data size limit bound exceeded141 SchemaDataLimitExceeded,142 /// Maximum refungibility exceeded143 WrongRefungiblePieces,144 /// createRefungible should be called with one owner145 BadCreateRefungibleCall,146 /// Gas limit exceeded147 OutOfGas,148 /// Metadata update denied by collection settings149 MetadataUpdateDenied,150 /// Metadata update flag become unmutable with None option151 MetadataFlagFrozen,152 /// Collection settings not allowing items transferring153 TransferNotAllowed,154 /// Can't transfer tokens to ethereum zero address155 AddressIsZero,156 }82 }157}83}158159#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]160pub struct CollectionHandle<T: Config> {161 pub id: CollectionId,162 collection: Collection<T>,163 recorder: pallet_evm_coder_substrate::SubstrateRecorder<T>,164}165impl<T: Config> CollectionHandle<T> {166 pub fn get_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {167 <CollectionById<T>>::get(id).map(|collection| Self {168 id,169 collection,170 recorder: pallet_evm_coder_substrate::SubstrateRecorder::new(171 eth::collection_id_to_address(id),172 gas_limit,173 ),174 })175 }176 pub fn get(id: CollectionId) -> Option<Self> {177 Self::get_with_gas_limit(id, u64::MAX)178 }179 pub fn log(&self, log: impl evm_coder::ToLog) -> DispatchResult {180 self.recorder.log_sub(log)181 }182 #[allow(dead_code)]183 fn consume_gas(&self, gas: u64) -> DispatchResult {184 self.recorder.consume_gas_sub(gas)185 }186 fn consume_sload(&self) -> DispatchResult {187 self.recorder.consume_sload_sub()188 }189 fn consume_sstore(&self) -> DispatchResult {190 self.recorder.consume_sstore_sub()191 }192 pub fn submit_logs(self) -> DispatchResult {193 self.recorder.submit_logs()194 }195 pub fn save(self) -> DispatchResult {196 self.recorder.submit_logs()?;197 <CollectionById<T>>::insert(self.id, self.collection);198 Ok(())199 }200}201impl<T: Config> Deref for CollectionHandle<T> {202 type Target = Collection<T>;203204 fn deref(&self) -> &Self::Target {205 &self.collection206 }207}208209impl<T: Config> DerefMut for CollectionHandle<T> {210 fn deref_mut(&mut self) -> &mut Self::Target {211 &mut self.collection212 }213}214215pub trait Config: system::Config + pallet_evm_coder_substrate::Config + Sized {84pub trait Config:85 system::Config86 + pallet_evm_coder_substrate::Config87 + pallet_common::Config216 type Event: From<Event<Self>> + Into<<Self as system::Config>::Event>;88 + pallet_nonfungible::Config21789 + pallet_refungible::Config90 + pallet_fungible::Config91 + Sized92{218 /// Weight information for extrinsics in this pallet.93 /// Weight information for extrinsics in this pallet.219 type WeightInfo: WeightInfo;94 type WeightInfo: WeightInfo;22095}221 type EvmAddressMapping: pallet_evm::AddressMapping<Self::AccountId>;222 type EvmBackwardsAddressMapping: EvmBackwardsAddressMapping<Self::AccountId>;223224 type CrossAccountId: CrossAccountId<Self::AccountId>;225 type Currency: Currency<Self::AccountId>;226 type CollectionCreationPrice: Get<227 <<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,228 >;229 type TreasuryAccountId: Get<Self::AccountId>;230}23196232type SelfWeightOf<T> = <T as Config>::WeightInfo;97type SelfWeightOf<T> = <T as Config>::WeightInfo;23398293 trait Store for Module<T: Config> as Nft {158 trait Store for Module<T: Config> as Nft {294159295 //#region Private members160 //#region Private members296 /// Id of next collection297 CreatedCollectionCount: u32;298 /// Used for migrations161 /// Used for migrations299 ChainVersion: u64;162 ChainVersion: u64;300 /// Id of last collection token301 /// Collection id (controlled?1)302 ItemListIndex: map hasher(blake2_128_concat) CollectionId => TokenId;303 //#endregion163 //#endregion304305 //#region Bound counters306 /// Amount of collections destroyed, used for total amount tracking with307 /// CreatedCollectionCount308 DestroyedCollectionCount: u32;309 //#endregion310311 //#region Basic collections312 /// Collection info313 /// Collection id (controlled?1)314 pub CollectionById get(fn collection_id) config(): map hasher(blake2_128_concat) CollectionId => Option<Collection<T>> = None;315 /// List of collection admins316 /// Collection id (controlled?2)317 pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::CrossAccountId>;318 /// Whitelisted collection users319 /// Collection id (controlled?2), user id (controlled?3)320 pub WhiteList get(fn white_list): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => bool;321 //#endregion322323 /// How many of collection items user have324 /// Collection id (controlled?2), account id (real)325 pub Balance get(fn balance_count): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => u128;326327 /// Amount of items which spender can transfer out of owners account (via transferFrom)328 /// Collection id (controlled?2), (token id (controlled ?2) + owner account id (real) + spender account id (controlled?3))329 /// TODO: Off chain worker should remove from this map when token gets removed330 pub Allowances get(fn approved): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) (TokenId, T::AccountId, T::AccountId) => u128;331332 //#region Item collections333 /// Collection id (controlled?2), token id (controlled?1)334 pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<NftItemType<T::CrossAccountId>>;335 /// Collection id (controlled?2), owner (controlled?2)336 pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => FungibleItemType;337 /// Collection id (controlled?2), token id (controlled?1)338 pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<ReFungibleItemType<T::CrossAccountId>>;339 //#endregion340341 //#region Index list342 /// Collection id (controlled?2), tokens owner (controlled?2)343 pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => Vec<TokenId>;344 //#endregion345164346 //#region Tokens transfer rate limit baskets165 //#region Tokens transfer rate limit baskets347 /// (Collection id (controlled?2), who created (real))166 /// (Collection id (controlled?2), who created (real))359 /// Collection id (controlled?2), token id (controlled?2)178 /// Collection id (controlled?2), token id (controlled?2)360 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber> = None;179 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber> = None;361 }180 }362 add_extra_genesis {363 build(|config: &GenesisConfig<T>| {364 // Modification of storage365 for (_num, _c) in &config.collection_id {366 <Module<T>>::init_collection(_c);367 }368369 for (_num, _c, _i) in &config.nft_item_id {370 <Module<T>>::init_nft_token(*_c, _i);371 }372373 for (collection_id, account_id, fungible_item) in &config.fungible_item_id {374 <Module<T>>::init_fungible_token(*collection_id, &T::CrossAccountId::from_sub(account_id.clone()), fungible_item);375 }376377 for (_num, _c, _i) in &config.refungible_item_id {378 <Module<T>>::init_refungible_token(*_c, _i);379 }380 })381 }382}181}383384decl_event!(385 pub enum Event<T>386 where387 AccountId = <T as frame_system::Config>::AccountId,388 CrossAccountId = <T as Config>::CrossAccountId,389 {390 /// New collection was created391 ///392 /// # Arguments393 ///394 /// * collection_id: Globally unique identifier of newly created collection.395 ///396 /// * mode: [CollectionMode] converted into u8.397 ///398 /// * account_id: Collection owner.399 CollectionCreated(CollectionId, u8, AccountId),400401 /// New item was created.402 ///403 /// # Arguments404 ///405 /// * collection_id: Id of the collection where item was created.406 ///407 /// * item_id: Id of an item. Unique within the collection.408 ///409 /// * recipient: Owner of newly created item410 ItemCreated(CollectionId, TokenId, CrossAccountId),411412 /// Collection item was burned.413 ///414 /// # Arguments415 ///416 /// collection_id.417 ///418 /// item_id: Identifier of burned NFT.419 ItemDestroyed(CollectionId, TokenId),420421 /// Item was transferred422 ///423 /// * collection_id: Id of collection to which item is belong424 ///425 /// * item_id: Id of an item426 ///427 /// * sender: Original owner of item428 ///429 /// * recipient: New owner of item430 ///431 /// * amount: Always 1 for NFT432 Transfer(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),433434 /// * collection_id435 ///436 /// * item_id437 ///438 /// * sender439 ///440 /// * spender441 ///442 /// * amount443 Approved(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),444 }445);446182447decl_module! {183decl_module! {448 pub struct Module<T: Config> for enum Call184 pub struct Module<T: Config> for enum Call449 where185 where450 origin: T::Origin186 origin: T::Origin451 {187 {452 fn deposit_event() = default;453 const CollectionAdminsLimit: u64 = COLLECTION_ADMINS_LIMIT;188 const CollectionAdminsLimit: u64 = COLLECTION_ADMINS_LIMIT;454 type Error = Error<T>;189 type Error = Error<T>;455190