difftreelog
fix after rebase
in: master
4 files changed
pallets/nonfungible/expand.rsdiffbeforeafterboth1#![feature(prelude_import)]2//! # Nonfungible Pallet3//!4//! The Nonfungible pallet provides functionality for handling nonfungible collections and tokens.5//!6//! - [`Config`]7//! - [`NonfungibleHandle`]8//! - [`Pallet`]9//! - [`CommonWeights`](common::CommonWeights)10//!11//! ## Overview12//!13//! The Nonfungible pallet provides functions for:14//!15//! - NFT collection creation and removal16//! - Minting and burning of NFT tokens17//! - Retrieving account balances18//! - Transfering NFT tokens19//! - Setting and checking allowance for NFT tokens20//! - Setting properties and permissions for NFT collections and tokens21//! - Nesting and unnesting tokens22//!23//! ### Terminology24//!25//! - **NFT token:** Non fungible token.26//!27//! - **NFT Collection:** A collection of NFT tokens. All NFT tokens are part of a collection.28//! Each collection can define it's own properties, properties for it's tokens and set of permissions.29//!30//! - **Balance:** Number of NFT tokens owned by an account31//!32//! - **Allowance:** NFT tokens owned by one account that another account is allowed to make operations on33//!34//! - **Burning:** The process of “deleting” a token from a collection and from35//! an account balance of the owner.36//!37//! - **Nesting:** Setting up parent-child relationship between tokens. Nested tokens are inhereting38//! owner from their parent. There could be multiple levels of nesting. Token couldn't be nested in39//! it's child token i.e. parent-child relationship graph shouldn't have cycles.40//!41//! - **Properties:** Key-Values pairs. Token properties are attached to a token. Collection properties are42//! attached to a collection. Set of permissions could be defined for each property.43//!44//! ### Implementations45//!46//! The Nonfungible pallet provides implementations for the following traits. If these traits provide47//! the functionality that you need, then you can avoid coupling with the Nonfungible pallet.48//!49//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight50//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing51//! with collections52//!53//! ## Interface54//!55//! ### Dispatchable Functions56//!57//! - `init_collection` - Create NFT collection. NFT collection can be configured to allow or deny access for58//! some accounts.59//! - `destroy_collection` - Destroy exising NFT collection. There should be no tokens in the collection.60//! - `burn` - Burn NFT token owned by account.61//! - `transfer` - Transfer NFT token. Transfers should be enabled for NFT collection.62//! Nests the NFT token if it is sent to another token.63//! - `create_item` - Mint NFT token in collection. Sender should have permission to mint tokens.64//! - `set_allowance` - Set allowance for another account.65//! - `set_token_property` - Set token property value.66//! - `delete_token_property` - Remove property from the token.67//! - `set_collection_properties` - Set collection properties.68//! - `delete_collection_properties` - Remove properties from the collection.69//! - `set_property_permission` - Set collection property permission.70//! - `set_token_property_permissions` - Set token property permissions.71//!72//! ## Assumptions73//!74//! * To perform operations on tokens sender should be in collection's allow list if collection access mode is `AllowList`.75#[prelude_import]76use std::prelude::rust_2021::*;77#[macro_use]78extern crate std;79use erc::ERC721Events;80use evm_coder::ToLog;81use frame_support::{82 BoundedVec, ensure, fail, transactional, storage::with_transaction,83 pallet_prelude::DispatchResultWithPostInfo, pallet_prelude::Weight,84 weights::{PostDispatchInfo, Pays},85};86use up_data_structs::{87 AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId,88 CreateCollectionData, CreateNftExData, mapping::TokenAddressMapping, budget::Budget,89 Property, PropertyPermission, PropertyKey, PropertyValue, PropertyKeyPermission,90 Properties, PropertyScope, TrySetProperty, TokenChild, AuxPropertyValue,91};92use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};93use pallet_common::{94 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,95 eth::collection_id_to_address,96};97use pallet_structure::{Pallet as PalletStructure, Error as StructureError};98use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};99use sp_core::H160;100use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};101use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};102use core::ops::Deref;103use codec::{Encode, Decode, MaxEncodedLen};104use scale_info::TypeInfo;105pub use pallet::*;106use weights::WeightInfo;107pub mod common {108 use core::marker::PhantomData;109 use frame_support::{110 dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight,111 };112 use up_data_structs::{113 TokenId, CreateItemExData, CollectionId, budget::Budget, Property, PropertyKey,114 PropertyKeyPermission, PropertyValue,115 };116 use pallet_common::{117 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,118 weights::WeightInfo as _,119 };120 use sp_runtime::DispatchError;121 use sp_std::{vec::Vec, vec};122 use crate::{123 AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle,124 Owned, Pallet, SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,125 };126 pub struct CommonWeights<T: Config>(PhantomData<T>);127 impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {128 fn create_item() -> Weight {129 <SelfWeightOf<T>>::create_item()130 }131 fn create_multiple_items_ex(132 data: &CreateItemExData<T::CrossAccountId>,133 ) -> Weight {134 match data {135 CreateItemExData::NFT(t) => {136 <SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32)137 + t138 .iter()139 .filter_map(|t| {140 if t.properties.len() > 0 {141 Some(Self::set_token_properties(t.properties.len() as u32))142 } else {143 None144 }145 })146 .fold(Weight::zero(), |a, b| a.saturating_add(b))147 }148 _ => Weight::zero(),149 }150 }151 fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {152 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32)153 + data154 .iter()155 .filter_map(|t| match t {156 up_data_structs::CreateItemData::NFT(157 n,158 ) if n.properties.len() > 0 => {159 Some(Self::set_token_properties(n.properties.len() as u32))160 }161 _ => None,162 })163 .fold(Weight::zero(), |a, b| a.saturating_add(b))164 }165 fn burn_item() -> Weight {166 <SelfWeightOf<T>>::burn_item()167 }168 fn set_collection_properties(amount: u32) -> Weight {169 <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)170 }171 fn delete_collection_properties(amount: u32) -> Weight {172 <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)173 }174 fn set_token_properties(amount: u32) -> Weight {175 <SelfWeightOf<T>>::set_token_properties(amount)176 }177 fn delete_token_properties(amount: u32) -> Weight {178 <SelfWeightOf<T>>::delete_token_properties(amount)179 }180 fn set_token_property_permissions(amount: u32) -> Weight {181 <SelfWeightOf<T>>::set_token_property_permissions(amount)182 }183 fn transfer() -> Weight {184 <SelfWeightOf<T>>::transfer()185 }186 fn approve() -> Weight {187 <SelfWeightOf<T>>::approve()188 }189 fn transfer_from() -> Weight {190 <SelfWeightOf<T>>::transfer_from()191 }192 fn burn_from() -> Weight {193 <SelfWeightOf<T>>::burn_from()194 }195 fn burn_recursively_self_raw() -> Weight {196 <SelfWeightOf<T>>::burn_recursively_self_raw()197 }198 fn burn_recursively_breadth_raw(amount: u32) -> Weight {199 <SelfWeightOf<200 T,201 >>::burn_recursively_breadth_plus_self_plus_self_per_each_raw(amount)202 .saturating_sub(203 Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1),204 )205 }206 fn token_owner() -> Weight {207 <SelfWeightOf<T>>::token_owner()208 }209 }210 fn map_create_data<T: Config>(211 data: up_data_structs::CreateItemData,212 to: &T::CrossAccountId,213 ) -> Result<CreateItemData<T>, DispatchError> {214 match data {215 up_data_structs::CreateItemData::NFT(data) => {216 Ok(CreateItemData::<T> {217 properties: data.properties,218 owner: to.clone(),219 })220 }221 _ => {222 return Err(223 <Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken224 .into(),225 );226 }227 }228 }229 /// Implementation of `CommonCollectionOperations` for `NonfungibleHandle`. It wraps Nonfungible Pallete230 /// methods and adds weight info.231 impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {232 fn create_item(233 &self,234 sender: T::CrossAccountId,235 to: T::CrossAccountId,236 data: up_data_structs::CreateItemData,237 nesting_budget: &dyn Budget,238 ) -> DispatchResultWithPostInfo {239 with_weight(240 <Pallet<241 T,242 >>::create_item(243 self,244 &sender,245 map_create_data::<T>(data, &to)?,246 nesting_budget,247 ),248 <CommonWeights<T>>::create_item(),249 )250 }251 fn create_multiple_items(252 &self,253 sender: T::CrossAccountId,254 to: T::CrossAccountId,255 data: Vec<up_data_structs::CreateItemData>,256 nesting_budget: &dyn Budget,257 ) -> DispatchResultWithPostInfo {258 let weight = <CommonWeights<T>>::create_multiple_items(&data);259 let data = data260 .into_iter()261 .map(|d| map_create_data::<T>(d, &to))262 .collect::<Result<Vec<_>, DispatchError>>()?;263 with_weight(264 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),265 weight,266 )267 }268 fn create_multiple_items_ex(269 &self,270 sender: <T>::CrossAccountId,271 data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,272 nesting_budget: &dyn Budget,273 ) -> DispatchResultWithPostInfo {274 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);275 let data = match data {276 up_data_structs::CreateItemExData::NFT(nft) => nft,277 _ => {278 return Err(279 Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken280 .into(),281 );282 }283 };284 with_weight(285 <Pallet<286 T,287 >>::create_multiple_items(288 self,289 &sender,290 data.into_inner(),291 nesting_budget,292 ),293 weight,294 )295 }296 fn set_collection_properties(297 &self,298 sender: T::CrossAccountId,299 properties: Vec<Property>,300 ) -> DispatchResultWithPostInfo {301 let weight = <CommonWeights<302 T,303 >>::set_collection_properties(properties.len() as u32);304 with_weight(305 <Pallet<T>>::set_collection_properties(self, &sender, properties),306 weight,307 )308 }309 fn delete_collection_properties(310 &self,311 sender: &T::CrossAccountId,312 property_keys: Vec<PropertyKey>,313 ) -> DispatchResultWithPostInfo {314 let weight = <CommonWeights<315 T,316 >>::delete_collection_properties(property_keys.len() as u32);317 with_weight(318 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),319 weight,320 )321 }322 fn set_token_properties(323 &self,324 sender: T::CrossAccountId,325 token_id: TokenId,326 properties: Vec<Property>,327 nesting_budget: &dyn Budget,328 ) -> DispatchResultWithPostInfo {329 let weight = <CommonWeights<330 T,331 >>::set_token_properties(properties.len() as u32);332 with_weight(333 <Pallet<334 T,335 >>::set_token_properties(336 self,337 &sender,338 token_id,339 properties.into_iter(),340 false,341 nesting_budget,342 ),343 weight,344 )345 }346 fn delete_token_properties(347 &self,348 sender: T::CrossAccountId,349 token_id: TokenId,350 property_keys: Vec<PropertyKey>,351 nesting_budget: &dyn Budget,352 ) -> DispatchResultWithPostInfo {353 let weight = <CommonWeights<354 T,355 >>::delete_token_properties(property_keys.len() as u32);356 with_weight(357 <Pallet<358 T,359 >>::delete_token_properties(360 self,361 &sender,362 token_id,363 property_keys.into_iter(),364 nesting_budget,365 ),366 weight,367 )368 }369 fn set_token_property_permissions(370 &self,371 sender: &T::CrossAccountId,372 property_permissions: Vec<PropertyKeyPermission>,373 ) -> DispatchResultWithPostInfo {374 let weight = <CommonWeights<375 T,376 >>::set_token_property_permissions(property_permissions.len() as u32);377 with_weight(378 <Pallet<379 T,380 >>::set_token_property_permissions(self, sender, property_permissions),381 weight,382 )383 }384 fn burn_item(385 &self,386 sender: T::CrossAccountId,387 token: TokenId,388 amount: u128,389 ) -> DispatchResultWithPostInfo {390 {391 if !(amount <= 1) {392 { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };393 }394 };395 if amount == 1 {396 with_weight(397 <Pallet<T>>::burn(self, &sender, token),398 <CommonWeights<T>>::burn_item(),399 )400 } else {401 Ok(().into())402 }403 }404 fn burn_item_recursively(405 &self,406 sender: T::CrossAccountId,407 token: TokenId,408 self_budget: &dyn Budget,409 breadth_budget: &dyn Budget,410 ) -> DispatchResultWithPostInfo {411 <Pallet<412 T,413 >>::burn_recursively(self, &sender, token, self_budget, breadth_budget)414 }415 fn transfer(416 &self,417 from: T::CrossAccountId,418 to: T::CrossAccountId,419 token: TokenId,420 amount: u128,421 nesting_budget: &dyn Budget,422 ) -> DispatchResultWithPostInfo {423 {424 if !(amount <= 1) {425 { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };426 }427 };428 if amount == 1 {429 with_weight(430 <Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),431 <CommonWeights<T>>::transfer(),432 )433 } else {434 Ok(().into())435 }436 }437 fn approve(438 &self,439 sender: T::CrossAccountId,440 spender: T::CrossAccountId,441 token: TokenId,442 amount: u128,443 ) -> DispatchResultWithPostInfo {444 {445 if !(amount <= 1) {446 { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };447 }448 };449 with_weight(450 if amount == 1 {451 <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))452 } else {453 <Pallet<T>>::set_allowance(self, &sender, token, None)454 },455 <CommonWeights<T>>::approve(),456 )457 }458 fn transfer_from(459 &self,460 sender: T::CrossAccountId,461 from: T::CrossAccountId,462 to: T::CrossAccountId,463 token: TokenId,464 amount: u128,465 nesting_budget: &dyn Budget,466 ) -> DispatchResultWithPostInfo {467 {468 if !(amount <= 1) {469 { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };470 }471 };472 if amount == 1 {473 with_weight(474 <Pallet<475 T,476 >>::transfer_from(self, &sender, &from, &to, token, nesting_budget),477 <CommonWeights<T>>::transfer_from(),478 )479 } else {480 Ok(().into())481 }482 }483 fn burn_from(484 &self,485 sender: T::CrossAccountId,486 from: T::CrossAccountId,487 token: TokenId,488 amount: u128,489 nesting_budget: &dyn Budget,490 ) -> DispatchResultWithPostInfo {491 {492 if !(amount <= 1) {493 { return Err(<Error<T>>::NonfungibleItemsHaveNoAmount.into()) };494 }495 };496 if amount == 1 {497 with_weight(498 <Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),499 <CommonWeights<T>>::burn_from(),500 )501 } else {502 Ok(().into())503 }504 }505 fn check_nesting(506 &self,507 sender: T::CrossAccountId,508 from: (CollectionId, TokenId),509 under: TokenId,510 nesting_budget: &dyn Budget,511 ) -> sp_runtime::DispatchResult {512 <Pallet<T>>::check_nesting(self, sender, from, under, nesting_budget)513 }514 fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId)) {515 <Pallet<T>>::nest((self.id, under), to_nest);516 }517 fn unnest(&self, under: TokenId, to_unnest: (CollectionId, TokenId)) {518 <Pallet<T>>::unnest((self.id, under), to_unnest);519 }520 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {521 <Owned<T>>::iter_prefix((self.id, account)).map(|(id, _)| id).collect()522 }523 fn collection_tokens(&self) -> Vec<TokenId> {524 <TokenData<T>>::iter_prefix((self.id,)).map(|(id, _)| id).collect()525 }526 fn token_exists(&self, token: TokenId) -> bool {527 <Pallet<T>>::token_exists(self, token)528 }529 fn last_token_id(&self) -> TokenId {530 TokenId(<TokensMinted<T>>::get(self.id))531 }532 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {533 <TokenData<T>>::get((self.id, token)).map(|t| t.owner)534 }535 /// Returns token owners.536 fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {537 self.token_owner(token)538 .map_or_else(539 || ::alloc::vec::Vec::new(),540 |t| <[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([t])),541 )542 }543 fn token_property(544 &self,545 token_id: TokenId,546 key: &PropertyKey,547 ) -> Option<PropertyValue> {548 <Pallet<T>>::token_properties((self.id, token_id)).get(key).cloned()549 }550 fn token_properties(551 &self,552 token_id: TokenId,553 keys: Option<Vec<PropertyKey>>,554 ) -> Vec<Property> {555 let properties = <Pallet<T>>::token_properties((self.id, token_id));556 keys.map(|keys| {557 keys.into_iter()558 .filter_map(|key| {559 properties560 .get(&key)561 .map(|value| Property {562 key,563 value: value.clone(),564 })565 })566 .collect()567 })568 .unwrap_or_else(|| {569 properties570 .into_iter()571 .map(|(key, value)| Property { key, value })572 .collect()573 })574 }575 fn total_supply(&self) -> u32 {576 <Pallet<T>>::total_supply(self)577 }578 fn account_balance(&self, account: T::CrossAccountId) -> u32 {579 <AccountBalance<T>>::get((self.id, account))580 }581 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {582 if <TokenData<T>>::get((self.id, token))583 .map(|a| a.owner == account)584 .unwrap_or(false)585 {586 1587 } else {588 0589 }590 }591 fn allowance(592 &self,593 sender: T::CrossAccountId,594 spender: T::CrossAccountId,595 token: TokenId,596 ) -> u128 {597 if <TokenData<T>>::get((self.id, token))598 .map(|a| a.owner != sender)599 .unwrap_or(true)600 {601 0602 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {603 1604 } else {605 0606 }607 }608 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {609 None610 }611 fn total_pieces(&self, token: TokenId) -> Option<u128> {612 if <TokenData<T>>::contains_key((self.id, token)) { Some(1) } else { None }613 }614 }615}616pub mod erc {617 //! # Nonfungible Pallet EVM API618 //!619 //! Provides ERC-721 standart support implementation and EVM API for unique extensions for Nonfungible Pallet.620 //! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.621 extern crate alloc;622 use alloc::{format, string::ToString};623 use core::{624 char::{REPLACEMENT_CHARACTER, decode_utf16},625 convert::TryInto,626 };627 use evm_coder::{628 ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,629 weight, custom_signature::{FunctionName, FunctionSignature},630 make_signature,631 };632 use frame_support::BoundedVec;633 use up_data_structs::{634 TokenId, PropertyPermission, PropertyKeyPermission, Property, CollectionId,635 PropertyKey, CollectionPropertiesVec,636 };637 use pallet_evm_coder_substrate::dispatch_to_evm;638 use sp_std::vec::Vec;639 use pallet_common::{640 erc::{641 CommonEvmHandler, PrecompileResult, CollectionCall,642 static_property::{key, value as property_value},643 },644 CollectionHandle, CollectionPropertyPermissions,645 eth::convert_tuple_to_cross_account,646 };647 use pallet_evm::{account::CrossAccountId, PrecompileHandle};648 use pallet_evm_coder_substrate::call;649 use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};650 use crate::{651 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData,652 TokensMinted, SelfWeightOf, weights::WeightInfo, TokenProperties,653 };654 /// @title A contract that allows to set and delete token properties and change token property permissions.655 impl<T: Config> NonfungibleHandle<T> {656 /// @notice Set permissions for token property.657 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.658 /// @param key Property key.659 /// @param isMutable Permission to mutate property.660 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.661 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.662 fn set_token_property_permission(663 &mut self,664 caller: caller,665 key: string,666 is_mutable: bool,667 collection_admin: bool,668 token_owner: bool,669 ) -> Result<()> {670 let caller = T::CrossAccountId::from_eth(caller);671 <Pallet<672 T,673 >>::set_property_permission(674 self,675 &caller,676 PropertyKeyPermission {677 key: <Vec<u8>>::from(key)678 .try_into()679 .map_err(|_| "too long key")?,680 permission: PropertyPermission {681 mutable: is_mutable,682 collection_admin,683 token_owner,684 },685 },686 )687 .map_err(dispatch_to_evm::<T>)688 }689 /// @notice Set token property value.690 /// @dev Throws error if `msg.sender` has no permission to edit the property.691 /// @param tokenId ID of the token.692 /// @param key Property key.693 /// @param value Property value.694 fn set_property(695 &mut self,696 caller: caller,697 token_id: uint256,698 key: string,699 value: bytes,700 ) -> Result<()> {701 let caller = T::CrossAccountId::from_eth(caller);702 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;703 let key = <Vec<u8>>::from(key).try_into().map_err(|_| "key too long")?;704 let value = value.0.try_into().map_err(|_| "value too long")?;705 let nesting_budget = self706 .recorder707 .weight_calls_budget(<StructureWeight<T>>::find_parent());708 <Pallet<709 T,710 >>::set_token_property(711 self,712 &caller,713 TokenId(token_id),714 Property { key, value },715 &nesting_budget,716 )717 .map_err(dispatch_to_evm::<T>)718 }719 /// @notice Delete token property value.720 /// @dev Throws error if `msg.sender` has no permission to edit the property.721 /// @param tokenId ID of the token.722 /// @param key Property key.723 fn delete_property(724 &mut self,725 token_id: uint256,726 caller: caller,727 key: string,728 ) -> Result<()> {729 let caller = T::CrossAccountId::from_eth(caller);730 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;731 let key = <Vec<u8>>::from(key).try_into().map_err(|_| "key too long")?;732 let nesting_budget = self733 .recorder734 .weight_calls_budget(<StructureWeight<T>>::find_parent());735 <Pallet<736 T,737 >>::delete_token_property(738 self,739 &caller,740 TokenId(token_id),741 key,742 &nesting_budget,743 )744 .map_err(dispatch_to_evm::<T>)745 }746 /// @notice Get token property value.747 /// @dev Throws error if key not found748 /// @param tokenId ID of the token.749 /// @param key Property key.750 /// @return Property value bytes751 fn property(&self, token_id: uint256, key: string) -> Result<bytes> {752 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;753 let key = <Vec<u8>>::from(key).try_into().map_err(|_| "key too long")?;754 let props = <TokenProperties<T>>::get((self.id, token_id));755 let prop = props.get(&key).ok_or("key not found")?;756 Ok(prop.to_vec().into())757 }758 }759 /// @title A contract that allows to set and delete token properties and change token property permissions.760 pub enum TokenPropertiesCall<T> {761 /// Inherited method762 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),763 /// @notice Set permissions for token property.764 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.765 /// @param key Property key.766 /// @param isMutable Permission to mutate property.767 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.768 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.769 #[allow(missing_docs)]770 SetTokenPropertyPermission {771 key: string,772 is_mutable: bool,773 collection_admin: bool,774 token_owner: bool,775 },776 /// @notice Set token property value.777 /// @dev Throws error if `msg.sender` has no permission to edit the property.778 /// @param tokenId ID of the token.779 /// @param key Property key.780 /// @param value Property value.781 #[allow(missing_docs)]782 SetProperty { token_id: uint256, key: string, value: bytes },783 /// @notice Delete token property value.784 /// @dev Throws error if `msg.sender` has no permission to edit the property.785 /// @param tokenId ID of the token.786 /// @param key Property key.787 #[allow(missing_docs)]788 DeleteProperty { token_id: uint256, key: string },789 /// @notice Get token property value.790 /// @dev Throws error if key not found791 /// @param tokenId ID of the token.792 /// @param key Property key.793 /// @return Property value bytes794 #[allow(missing_docs)]795 Property { token_id: uint256, key: string },796 }797 #[automatically_derived]798 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for TokenPropertiesCall<T> {799 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {800 match self {801 TokenPropertiesCall::ERC165Call(__self_0, __self_1) => {802 ::core::fmt::Formatter::debug_tuple_field2_finish(803 f,804 "ERC165Call",805 &__self_0,806 &__self_1,807 )808 }809 TokenPropertiesCall::SetTokenPropertyPermission {810 key: __self_0,811 is_mutable: __self_1,812 collection_admin: __self_2,813 token_owner: __self_3,814 } => {815 ::core::fmt::Formatter::debug_struct_field4_finish(816 f,817 "SetTokenPropertyPermission",818 "key",819 &__self_0,820 "is_mutable",821 &__self_1,822 "collection_admin",823 &__self_2,824 "token_owner",825 &__self_3,826 )827 }828 TokenPropertiesCall::SetProperty {829 token_id: __self_0,830 key: __self_1,831 value: __self_2,832 } => {833 ::core::fmt::Formatter::debug_struct_field3_finish(834 f,835 "SetProperty",836 "token_id",837 &__self_0,838 "key",839 &__self_1,840 "value",841 &__self_2,842 )843 }844 TokenPropertiesCall::DeleteProperty {845 token_id: __self_0,846 key: __self_1,847 } => {848 ::core::fmt::Formatter::debug_struct_field2_finish(849 f,850 "DeleteProperty",851 "token_id",852 &__self_0,853 "key",854 &__self_1,855 )856 }857 TokenPropertiesCall::Property { token_id: __self_0, key: __self_1 } => {858 ::core::fmt::Formatter::debug_struct_field2_finish(859 f,860 "Property",861 "token_id",862 &__self_0,863 "key",864 &__self_1,865 )866 }867 }868 }869 }870 impl<T> TokenPropertiesCall<T> {871 const SET_TOKEN_PROPERTY_PERMISSION_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {872 {873 let fs = FunctionSignature::new(874 &&FunctionName::new("setTokenPropertyPermission"),875 );876 let fs = FunctionSignature::done(877 FunctionSignature::add_param(878 FunctionSignature::add_param(879 FunctionSignature::add_param(880 FunctionSignature::add_param(881 fs,882 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),883 ),884 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),885 ),886 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),887 ),888 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),889 ),890 true,891 );892 fs893 }894 };895 ///setTokenPropertyPermission(string,bool,bool,bool)896 const SET_TOKEN_PROPERTY_PERMISSION: ::evm_coder::types::bytes4 = {897 let a = ::evm_coder::sha3_const::Keccak256::new()898 .update_with_size(899 &Self::SET_TOKEN_PROPERTY_PERMISSION_SIGNATURE.signature,900 Self::SET_TOKEN_PROPERTY_PERMISSION_SIGNATURE.signature_len,901 )902 .finalize();903 [a[0], a[1], a[2], a[3]]904 };905 const SET_PROPERTY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {906 {907 let fs = FunctionSignature::new(&&FunctionName::new("setProperty"));908 let fs = FunctionSignature::done(909 FunctionSignature::add_param(910 FunctionSignature::add_param(911 FunctionSignature::add_param(912 fs,913 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),914 ),915 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),916 ),917 (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),918 ),919 true,920 );921 fs922 }923 };924 ///setProperty(uint256,string,bytes)925 const SET_PROPERTY: ::evm_coder::types::bytes4 = {926 let a = ::evm_coder::sha3_const::Keccak256::new()927 .update_with_size(928 &Self::SET_PROPERTY_SIGNATURE.signature,929 Self::SET_PROPERTY_SIGNATURE.signature_len,930 )931 .finalize();932 [a[0], a[1], a[2], a[3]]933 };934 const DELETE_PROPERTY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {935 {936 let fs = FunctionSignature::new(&&FunctionName::new("deleteProperty"));937 let fs = FunctionSignature::done(938 FunctionSignature::add_param(939 FunctionSignature::add_param(940 fs,941 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),942 ),943 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),944 ),945 true,946 );947 fs948 }949 };950 ///deleteProperty(uint256,string)951 const DELETE_PROPERTY: ::evm_coder::types::bytes4 = {952 let a = ::evm_coder::sha3_const::Keccak256::new()953 .update_with_size(954 &Self::DELETE_PROPERTY_SIGNATURE.signature,955 Self::DELETE_PROPERTY_SIGNATURE.signature_len,956 )957 .finalize();958 [a[0], a[1], a[2], a[3]]959 };960 const PROPERTY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {961 {962 let fs = FunctionSignature::new(&&FunctionName::new("property"));963 let fs = FunctionSignature::done(964 FunctionSignature::add_param(965 FunctionSignature::add_param(966 fs,967 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),968 ),969 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),970 ),971 true,972 );973 fs974 }975 };976 ///property(uint256,string)977 const PROPERTY: ::evm_coder::types::bytes4 = {978 let a = ::evm_coder::sha3_const::Keccak256::new()979 .update_with_size(980 &Self::PROPERTY_SIGNATURE.signature,981 Self::PROPERTY_SIGNATURE.signature_len,982 )983 .finalize();984 [a[0], a[1], a[2], a[3]]985 };986 /// Return this call ERC165 selector987 pub fn interface_id() -> ::evm_coder::types::bytes4 {988 let mut interface_id = 0;989 interface_id ^= u32::from_be_bytes(Self::SET_TOKEN_PROPERTY_PERMISSION);990 interface_id ^= u32::from_be_bytes(Self::SET_PROPERTY);991 interface_id ^= u32::from_be_bytes(Self::DELETE_PROPERTY);992 interface_id ^= u32::from_be_bytes(Self::PROPERTY);993 u32::to_be_bytes(interface_id)994 }995 /// Generate solidity definitions for methods described in this interface996 pub fn generate_solidity_interface(997 tc: &evm_coder::solidity::TypeCollector,998 is_impl: bool,999 ) {1000 use evm_coder::solidity::*;1001 use core::fmt::Write;1002 let interface = SolidityInterface {1003 docs: &[1004 " @title A contract that allows to set and delete token properties and change token property permissions.",1005 ],1006 name: "TokenProperties",1007 selector: Self::interface_id(),1008 is: &["Dummy", "ERC165"],1009 functions: (1010 SolidityFunction {1011 docs: &[1012 " @notice Set permissions for token property.",1013 " @dev Throws error if `msg.sender` is not admin or owner of the collection.",1014 " @param key Property key.",1015 " @param isMutable Permission to mutate property.",1016 " @param collectionAdmin Permission to mutate property by collection admin if property is mutable.",1017 " @param tokenOwner Permission to mutate property by token owner if property is mutable.",1018 ],1019 selector_str: "setTokenPropertyPermission(string,bool,bool,bool)",1020 selector: u32::from_be_bytes(1021 Self::SET_TOKEN_PROPERTY_PERMISSION,1022 ),1023 custom_signature: {1024 const cs: FunctionSignature = {1025 {1026 let fs = FunctionSignature::new(1027 &&FunctionName::new("setTokenPropertyPermission"),1028 );1029 let fs = FunctionSignature::done(1030 FunctionSignature::add_param(1031 FunctionSignature::add_param(1032 FunctionSignature::add_param(1033 FunctionSignature::add_param(1034 fs,1035 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),1036 ),1037 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),1038 ),1039 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),1040 ),1041 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),1042 ),1043 true,1044 );1045 fs1046 }1047 };1048 cs1049 },1050 name: "setTokenPropertyPermission",1051 mutability: SolidityMutability::Mutable,1052 is_payable: false,1053 args: (1054 <NamedArgument<string>>::new("key"),1055 <NamedArgument<bool>>::new("isMutable"),1056 <NamedArgument<bool>>::new("collectionAdmin"),1057 <NamedArgument<bool>>::new("tokenOwner"),1058 ),1059 result: <UnnamedArgument<()>>::default(),1060 },1061 SolidityFunction {1062 docs: &[1063 " @notice Set token property value.",1064 " @dev Throws error if `msg.sender` has no permission to edit the property.",1065 " @param tokenId ID of the token.",1066 " @param key Property key.",1067 " @param value Property value.",1068 ],1069 selector_str: "setProperty(uint256,string,bytes)",1070 selector: u32::from_be_bytes(Self::SET_PROPERTY),1071 custom_signature: {1072 const cs: FunctionSignature = {1073 {1074 let fs = FunctionSignature::new(1075 &&FunctionName::new("setProperty"),1076 );1077 let fs = FunctionSignature::done(1078 FunctionSignature::add_param(1079 FunctionSignature::add_param(1080 FunctionSignature::add_param(1081 fs,1082 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),1083 ),1084 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),1085 ),1086 (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),1087 ),1088 true,1089 );1090 fs1091 }1092 };1093 cs1094 },1095 name: "setProperty",1096 mutability: SolidityMutability::Mutable,1097 is_payable: false,1098 args: (1099 <NamedArgument<uint256>>::new("tokenId"),1100 <NamedArgument<string>>::new("key"),1101 <NamedArgument<bytes>>::new("value"),1102 ),1103 result: <UnnamedArgument<()>>::default(),1104 },1105 SolidityFunction {1106 docs: &[1107 " @notice Delete token property value.",1108 " @dev Throws error if `msg.sender` has no permission to edit the property.",1109 " @param tokenId ID of the token.",1110 " @param key Property key.",1111 ],1112 selector_str: "deleteProperty(uint256,string)",1113 selector: u32::from_be_bytes(Self::DELETE_PROPERTY),1114 custom_signature: {1115 const cs: FunctionSignature = {1116 {1117 let fs = FunctionSignature::new(1118 &&FunctionName::new("deleteProperty"),1119 );1120 let fs = FunctionSignature::done(1121 FunctionSignature::add_param(1122 FunctionSignature::add_param(1123 fs,1124 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),1125 ),1126 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),1127 ),1128 true,1129 );1130 fs1131 }1132 };1133 cs1134 },1135 name: "deleteProperty",1136 mutability: SolidityMutability::Mutable,1137 is_payable: false,1138 args: (1139 <NamedArgument<uint256>>::new("tokenId"),1140 <NamedArgument<string>>::new("key"),1141 ),1142 result: <UnnamedArgument<()>>::default(),1143 },1144 SolidityFunction {1145 docs: &[1146 " @notice Get token property value.",1147 " @dev Throws error if key not found",1148 " @param tokenId ID of the token.",1149 " @param key Property key.",1150 " @return Property value bytes",1151 ],1152 selector_str: "property(uint256,string)",1153 selector: u32::from_be_bytes(Self::PROPERTY),1154 custom_signature: {1155 const cs: FunctionSignature = {1156 {1157 let fs = FunctionSignature::new(1158 &&FunctionName::new("property"),1159 );1160 let fs = FunctionSignature::done(1161 FunctionSignature::add_param(1162 FunctionSignature::add_param(1163 fs,1164 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),1165 ),1166 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),1167 ),1168 true,1169 );1170 fs1171 }1172 };1173 cs1174 },1175 name: "property",1176 mutability: SolidityMutability::View,1177 is_payable: false,1178 args: (1179 <NamedArgument<uint256>>::new("tokenId"),1180 <NamedArgument<string>>::new("key"),1181 ),1182 result: <UnnamedArgument<bytes>>::default(),1183 },1184 ),1185 };1186 let mut out = ::evm_coder::types::string::new();1187 if "TokenProperties".starts_with("Inline") {1188 out.push_str("/// @dev inlined interface\n");1189 }1190 let _ = interface.format(is_impl, &mut out, tc);1191 tc.collect(out);1192 if is_impl {1193 tc.collect(1194 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"1195 .into(),1196 );1197 } else {1198 tc.collect(1199 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"1200 .into(),1201 );1202 }1203 }1204 }1205 impl<T> ::evm_coder::Call for TokenPropertiesCall<T> {1206 fn parse(1207 method_id: ::evm_coder::types::bytes4,1208 reader: &mut ::evm_coder::abi::AbiReader,1209 ) -> ::evm_coder::execution::Result<Option<Self>> {1210 use ::evm_coder::abi::AbiRead;1211 match method_id {1212 ::evm_coder::ERC165Call::INTERFACE_ID => {1213 return Ok(1214 ::evm_coder::ERC165Call::parse(method_id, reader)?1215 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),1216 );1217 }1218 Self::SET_TOKEN_PROPERTY_PERMISSION => {1219 return Ok(1220 Some(Self::SetTokenPropertyPermission {1221 key: reader.abi_read()?,1222 is_mutable: reader.abi_read()?,1223 collection_admin: reader.abi_read()?,1224 token_owner: reader.abi_read()?,1225 }),1226 );1227 }1228 Self::SET_PROPERTY => {1229 return Ok(1230 Some(Self::SetProperty {1231 token_id: reader.abi_read()?,1232 key: reader.abi_read()?,1233 value: reader.abi_read()?,1234 }),1235 );1236 }1237 Self::DELETE_PROPERTY => {1238 return Ok(1239 Some(Self::DeleteProperty {1240 token_id: reader.abi_read()?,1241 key: reader.abi_read()?,1242 }),1243 );1244 }1245 Self::PROPERTY => {1246 return Ok(1247 Some(Self::Property {1248 token_id: reader.abi_read()?,1249 key: reader.abi_read()?,1250 }),1251 );1252 }1253 _ => {}1254 }1255 return Ok(None);1256 }1257 }1258 impl<T: Config> TokenPropertiesCall<T> {1259 /// Is this contract implements specified ERC165 selector1260 pub fn supports_interface(1261 this: &NonfungibleHandle<T>,1262 interface_id: ::evm_coder::types::bytes4,1263 ) -> bool {1264 interface_id != u32::to_be_bytes(0xffffff)1265 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID1266 || interface_id == Self::interface_id())1267 }1268 }1269 impl<T: Config> ::evm_coder::Weighted for TokenPropertiesCall<T> {1270 #[allow(unused_variables)]1271 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {1272 match self {1273 Self::ERC165Call(1274 ::evm_coder::ERC165Call::SupportsInterface { .. },1275 _,1276 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),1277 Self::SetTokenPropertyPermission { .. } => ().into(),1278 Self::SetProperty { .. } => ().into(),1279 Self::DeleteProperty { .. } => ().into(),1280 Self::Property { .. } => ().into(),1281 }1282 }1283 }1284 impl<T: Config> ::evm_coder::Callable<TokenPropertiesCall<T>>1285 for NonfungibleHandle<T> {1286 #[allow(unreachable_code)]1287 fn call(1288 &mut self,1289 c: Msg<TokenPropertiesCall<T>>,1290 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {1291 use ::evm_coder::abi::AbiWrite;1292 match c.call {1293 TokenPropertiesCall::ERC165Call(1294 ::evm_coder::ERC165Call::SupportsInterface { interface_id },1295 _,1296 ) => {1297 let mut writer = ::evm_coder::abi::AbiWriter::default();1298 writer1299 .bool(1300 &<TokenPropertiesCall<1301 T,1302 >>::supports_interface(self, interface_id),1303 );1304 return Ok(writer.into());1305 }1306 _ => {}1307 }1308 let mut writer = ::evm_coder::abi::AbiWriter::default();1309 match c.call {1310 TokenPropertiesCall::SetTokenPropertyPermission {1311 key,1312 is_mutable,1313 collection_admin,1314 token_owner,1315 } => {1316 let result = self1317 .set_token_property_permission(1318 c.caller.clone(),1319 key,1320 is_mutable,1321 collection_admin,1322 token_owner,1323 )?;1324 (&result).to_result()1325 }1326 TokenPropertiesCall::SetProperty { token_id, key, value } => {1327 let result = self1328 .set_property(c.caller.clone(), token_id, key, value)?;1329 (&result).to_result()1330 }1331 TokenPropertiesCall::DeleteProperty { token_id, key } => {1332 let result = self.delete_property(token_id, c.caller.clone(), key)?;1333 (&result).to_result()1334 }1335 TokenPropertiesCall::Property { token_id, key } => {1336 let result = self.property(token_id, key)?;1337 (&result).to_result()1338 }1339 _ => {1340 Err(1341 ::evm_coder::execution::Error::from("method is not available")1342 .into(),1343 )1344 }1345 }1346 }1347 }1348 pub enum ERC721Events {1349 /// @dev This emits when ownership of any NFT changes by any mechanism.1350 /// This event emits when NFTs are created (`from` == 0) and destroyed1351 /// (`to` == 0). Exception: during contract creation, any number of NFTs1352 /// may be created and assigned without emitting Transfer. At the time of1353 /// any transfer, the approved address for that NFT (if any) is reset to none.1354 Transfer {1355 #[indexed]1356 from: address,1357 #[indexed]1358 to: address,1359 #[indexed]1360 token_id: uint256,1361 },1362 /// @dev This emits when the approved address for an NFT is changed or1363 /// reaffirmed. The zero address indicates there is no approved address.1364 /// When a Transfer event emits, this also indicates that the approved1365 /// address for that NFT (if any) is reset to none.1366 Approval {1367 #[indexed]1368 owner: address,1369 #[indexed]1370 approved: address,1371 #[indexed]1372 token_id: uint256,1373 },1374 /// @dev This emits when an operator is enabled or disabled for an owner.1375 /// The operator can manage all NFTs of the owner.1376 #[allow(dead_code)]1377 ApprovalForAll {1378 #[indexed]1379 owner: address,1380 #[indexed]1381 operator: address,1382 approved: bool,1383 },1384 }1385 impl ERC721Events {1386 ///Transfer(address,address,uint256)1387 const TRANSFER: [u8; 32] = [1388 221u8,1389 242u8,1390 82u8,1391 173u8,1392 27u8,1393 226u8,1394 200u8,1395 155u8,1396 105u8,1397 194u8,1398 176u8,1399 104u8,1400 252u8,1401 55u8,1402 141u8,1403 170u8,1404 149u8,1405 43u8,1406 167u8,1407 241u8,1408 99u8,1409 196u8,1410 161u8,1411 22u8,1412 40u8,1413 245u8,1414 90u8,1415 77u8,1416 245u8,1417 35u8,1418 179u8,1419 239u8,1420 ];1421 ///Approval(address,address,uint256)1422 const APPROVAL: [u8; 32] = [1423 140u8,1424 91u8,1425 225u8,1426 229u8,1427 235u8,1428 236u8,1429 125u8,1430 91u8,1431 209u8,1432 79u8,1433 113u8,1434 66u8,1435 125u8,1436 30u8,1437 132u8,1438 243u8,1439 221u8,1440 3u8,1441 20u8,1442 192u8,1443 247u8,1444 178u8,1445 41u8,1446 30u8,1447 91u8,1448 32u8,1449 10u8,1450 200u8,1451 199u8,1452 195u8,1453 185u8,1454 37u8,1455 ];1456 ///ApprovalForAll(address,address,bool)1457 const APPROVAL_FOR_ALL: [u8; 32] = [1458 23u8,1459 48u8,1460 126u8,1461 171u8,1462 57u8,1463 171u8,1464 97u8,1465 7u8,1466 232u8,1467 137u8,1468 152u8,1469 69u8,1470 173u8,1471 61u8,1472 89u8,1473 189u8,1474 150u8,1475 83u8,1476 242u8,1477 0u8,1478 242u8,1479 32u8,1480 146u8,1481 4u8,1482 137u8,1483 202u8,1484 43u8,1485 89u8,1486 55u8,1487 105u8,1488 108u8,1489 49u8,1490 ];1491 pub fn generate_solidity_interface(1492 tc: &evm_coder::solidity::TypeCollector,1493 is_impl: bool,1494 ) {1495 use evm_coder::solidity::*;1496 use core::fmt::Write;1497 let interface = SolidityInterface {1498 docs: &[],1499 selector: [0; 4],1500 name: "ERC721Events",1501 is: &[],1502 functions: (1503 SolidityEvent {1504 name: "Transfer",1505 args: (1506 <SolidityEventArgument<address>>::new(true, "from"),1507 <SolidityEventArgument<address>>::new(true, "to"),1508 <SolidityEventArgument<uint256>>::new(true, "tokenId"),1509 ),1510 },1511 SolidityEvent {1512 name: "Approval",1513 args: (1514 <SolidityEventArgument<address>>::new(true, "owner"),1515 <SolidityEventArgument<address>>::new(true, "approved"),1516 <SolidityEventArgument<uint256>>::new(true, "tokenId"),1517 ),1518 },1519 SolidityEvent {1520 name: "ApprovalForAll",1521 args: (1522 <SolidityEventArgument<address>>::new(true, "owner"),1523 <SolidityEventArgument<address>>::new(true, "operator"),1524 <SolidityEventArgument<bool>>::new(false, "approved"),1525 ),1526 },1527 ),1528 };1529 let mut out = string::new();1530 out.push_str("/// @dev inlined interface\n");1531 let _ = interface.format(is_impl, &mut out, tc);1532 tc.collect(out);1533 }1534 }1535 #[automatically_derived]1536 impl ::evm_coder::events::ToLog for ERC721Events {1537 fn to_log(&self, contract: address) -> ::ethereum::Log {1538 use ::evm_coder::events::ToTopic;1539 use ::evm_coder::abi::AbiWrite;1540 let mut writer = ::evm_coder::abi::AbiWriter::new();1541 let mut topics = Vec::new();1542 match self {1543 Self::Transfer { from, to, token_id } => {1544 topics.push(topic::from(Self::TRANSFER));1545 topics.push(from.to_topic());1546 topics.push(to.to_topic());1547 topics.push(token_id.to_topic());1548 }1549 Self::Approval { owner, approved, token_id } => {1550 topics.push(topic::from(Self::APPROVAL));1551 topics.push(owner.to_topic());1552 topics.push(approved.to_topic());1553 topics.push(token_id.to_topic());1554 }1555 Self::ApprovalForAll { owner, operator, approved } => {1556 topics.push(topic::from(Self::APPROVAL_FOR_ALL));1557 topics.push(owner.to_topic());1558 topics.push(operator.to_topic());1559 approved.abi_write(&mut writer);1560 }1561 }1562 ::ethereum::Log {1563 address: contract,1564 topics,1565 data: writer.finish(),1566 }1567 }1568 }1569 pub enum ERC721MintableEvents {1570 #[allow(dead_code)]1571 MintingFinished {},1572 }1573 impl ERC721MintableEvents {1574 ///MintingFinished()1575 const MINTING_FINISHED: [u8; 32] = [1576 184u8,1577 40u8,1578 217u8,1579 181u8,1580 199u8,1581 128u8,1582 149u8,1583 222u8,1584 238u8,1585 239u8,1586 242u8,1587 236u8,1588 162u8,1589 229u8,1590 212u8,1591 254u8,1592 4u8,1593 108u8,1594 227u8,1595 254u8,1596 180u8,1597 201u8,1598 151u8,1599 2u8,1600 98u8,1601 74u8,1602 63u8,1603 211u8,1604 132u8,1605 173u8,1606 45u8,1607 188u8,1608 ];1609 pub fn generate_solidity_interface(1610 tc: &evm_coder::solidity::TypeCollector,1611 is_impl: bool,1612 ) {1613 use evm_coder::solidity::*;1614 use core::fmt::Write;1615 let interface = SolidityInterface {1616 docs: &[],1617 selector: [0; 4],1618 name: "ERC721MintableEvents",1619 is: &[],1620 functions: (1621 SolidityEvent {1622 name: "MintingFinished",1623 args: (),1624 },1625 ),1626 };1627 let mut out = string::new();1628 out.push_str("/// @dev inlined interface\n");1629 let _ = interface.format(is_impl, &mut out, tc);1630 tc.collect(out);1631 }1632 }1633 #[automatically_derived]1634 impl ::evm_coder::events::ToLog for ERC721MintableEvents {1635 fn to_log(&self, contract: address) -> ::ethereum::Log {1636 use ::evm_coder::events::ToTopic;1637 use ::evm_coder::abi::AbiWrite;1638 let mut writer = ::evm_coder::abi::AbiWriter::new();1639 let mut topics = Vec::new();1640 match self {1641 Self::MintingFinished {} => {1642 topics.push(topic::from(Self::MINTING_FINISHED));1643 }1644 }1645 ::ethereum::Log {1646 address: contract,1647 topics,1648 data: writer.finish(),1649 }1650 }1651 }1652 /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension1653 /// @dev See https://eips.ethereum.org/EIPS/eip-7211654 impl<T: Config> NonfungibleHandle<T> {1655 /// @notice A descriptive name for a collection of NFTs in this contract1656 fn name(&self) -> Result<string> {1657 Ok(1658 decode_utf16(self.name.iter().copied())1659 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))1660 .collect::<string>(),1661 )1662 }1663 /// @notice An abbreviated name for NFTs in this contract1664 fn symbol(&self) -> Result<string> {1665 Ok(string::from_utf8_lossy(&self.token_prefix).into())1666 }1667 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.1668 ///1669 /// @dev If the token has a `url` property and it is not empty, it is returned.1670 /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.1671 /// If the collection property `baseURI` is empty or absent, return "" (empty string)1672 /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix1673 /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).1674 ///1675 /// @return token's const_metadata1676 fn token_uri(&self, token_id: uint256) -> Result<string> {1677 let token_id_u32: u32 = token_id1678 .try_into()1679 .map_err(|_| "token id overflow")?;1680 if let Ok(url) = get_token_property(self, token_id_u32, &key::url()) {1681 if !url.is_empty() {1682 return Ok(url);1683 }1684 } else if !is_erc721_metadata_compatible::<T>(self.id) {1685 return Err("tokenURI not set".into());1686 }1687 if let Some(base_uri)1688 = pallet_common::Pallet::<1689 T,1690 >::get_collection_property(self.id, &key::base_uri()) {1691 if !base_uri.is_empty() {1692 let base_uri = string::from_utf8(base_uri.into_inner())1693 .map_err(|e| {1694 Error::Revert({1695 let res = ::alloc::fmt::format(1696 ::core::fmt::Arguments::new_v1(1697 &[1698 "Can not convert value \"baseURI\" to string with error \"",1699 "\"",1700 ],1701 &[::core::fmt::ArgumentV1::new_display(&e)],1702 ),1703 );1704 res1705 })1706 })?;1707 if let Ok(suffix)1708 = get_token_property(self, token_id_u32, &key::suffix()) {1709 if !suffix.is_empty() {1710 return Ok(base_uri + suffix.as_str());1711 }1712 }1713 return Ok(base_uri + token_id.to_string().as_str());1714 }1715 }1716 Ok("".into())1717 }1718 }1719 /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension1720 /// @dev See https://eips.ethereum.org/EIPS/eip-7211721 pub enum ERC721MetadataCall<T> {1722 /// Inherited method1723 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),1724 Name,1725 Symbol,1726 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.1727 ///1728 /// @dev If the token has a `url` property and it is not empty, it is returned.1729 /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.1730 /// If the collection property `baseURI` is empty or absent, return "" (empty string)1731 /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix1732 /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).1733 ///1734 /// @return token's const_metadata1735 #[allow(missing_docs)]1736 TokenUri { token_id: uint256 },1737 }1738 #[automatically_derived]1739 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721MetadataCall<T> {1740 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {1741 match self {1742 ERC721MetadataCall::ERC165Call(__self_0, __self_1) => {1743 ::core::fmt::Formatter::debug_tuple_field2_finish(1744 f,1745 "ERC165Call",1746 &__self_0,1747 &__self_1,1748 )1749 }1750 ERC721MetadataCall::Name => ::core::fmt::Formatter::write_str(f, "Name"),1751 ERC721MetadataCall::Symbol => {1752 ::core::fmt::Formatter::write_str(f, "Symbol")1753 }1754 ERC721MetadataCall::TokenUri { token_id: __self_0 } => {1755 ::core::fmt::Formatter::debug_struct_field1_finish(1756 f,1757 "TokenUri",1758 "token_id",1759 &__self_0,1760 )1761 }1762 }1763 }1764 }1765 impl<T> ERC721MetadataCall<T> {1766 const NAME_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {1767 {1768 let fs = FunctionSignature::new(&&FunctionName::new("name"));1769 let fs = FunctionSignature::done(fs, false);1770 fs1771 }1772 };1773 ///name()1774 const NAME: ::evm_coder::types::bytes4 = {1775 let a = ::evm_coder::sha3_const::Keccak256::new()1776 .update_with_size(1777 &Self::NAME_SIGNATURE.signature,1778 Self::NAME_SIGNATURE.signature_len,1779 )1780 .finalize();1781 [a[0], a[1], a[2], a[3]]1782 };1783 const SYMBOL_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {1784 {1785 let fs = FunctionSignature::new(&&FunctionName::new("symbol"));1786 let fs = FunctionSignature::done(fs, false);1787 fs1788 }1789 };1790 ///symbol()1791 const SYMBOL: ::evm_coder::types::bytes4 = {1792 let a = ::evm_coder::sha3_const::Keccak256::new()1793 .update_with_size(1794 &Self::SYMBOL_SIGNATURE.signature,1795 Self::SYMBOL_SIGNATURE.signature_len,1796 )1797 .finalize();1798 [a[0], a[1], a[2], a[3]]1799 };1800 const TOKEN_URI_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {1801 {1802 let fs = FunctionSignature::new(&&FunctionName::new("tokenURI"));1803 let fs = FunctionSignature::done(1804 FunctionSignature::add_param(1805 fs,1806 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),1807 ),1808 true,1809 );1810 fs1811 }1812 };1813 ///tokenURI(uint256)1814 const TOKEN_URI: ::evm_coder::types::bytes4 = {1815 let a = ::evm_coder::sha3_const::Keccak256::new()1816 .update_with_size(1817 &Self::TOKEN_URI_SIGNATURE.signature,1818 Self::TOKEN_URI_SIGNATURE.signature_len,1819 )1820 .finalize();1821 [a[0], a[1], a[2], a[3]]1822 };1823 /// Return this call ERC165 selector1824 pub fn interface_id() -> ::evm_coder::types::bytes4 {1825 let mut interface_id = 0;1826 interface_id ^= u32::from_be_bytes(Self::NAME);1827 interface_id ^= u32::from_be_bytes(Self::SYMBOL);1828 interface_id ^= u32::from_be_bytes(Self::TOKEN_URI);1829 u32::to_be_bytes(interface_id)1830 }1831 /// Generate solidity definitions for methods described in this interface1832 pub fn generate_solidity_interface(1833 tc: &evm_coder::solidity::TypeCollector,1834 is_impl: bool,1835 ) {1836 use evm_coder::solidity::*;1837 use core::fmt::Write;1838 let interface = SolidityInterface {1839 docs: &[1840 " @title ERC-721 Non-Fungible Token Standard, optional metadata extension",1841 " @dev See https://eips.ethereum.org/EIPS/eip-721",1842 ],1843 name: "ERC721Metadata",1844 selector: Self::interface_id(),1845 is: &["Dummy", "ERC165"],1846 functions: (1847 SolidityFunction {1848 docs: &[1849 " @notice A descriptive name for a collection of NFTs in this contract",1850 ],1851 selector_str: "name()",1852 selector: u32::from_be_bytes(Self::NAME),1853 custom_signature: {1854 const cs: FunctionSignature = {1855 {1856 let fs = FunctionSignature::new(1857 &&FunctionName::new("name"),1858 );1859 let fs = FunctionSignature::done(fs, false);1860 fs1861 }1862 };1863 cs1864 },1865 name: "name",1866 mutability: SolidityMutability::View,1867 is_payable: false,1868 args: (),1869 result: <UnnamedArgument<string>>::default(),1870 },1871 SolidityFunction {1872 docs: &[1873 " @notice An abbreviated name for NFTs in this contract",1874 ],1875 selector_str: "symbol()",1876 selector: u32::from_be_bytes(Self::SYMBOL),1877 custom_signature: {1878 const cs: FunctionSignature = {1879 {1880 let fs = FunctionSignature::new(1881 &&FunctionName::new("symbol"),1882 );1883 let fs = FunctionSignature::done(fs, false);1884 fs1885 }1886 };1887 cs1888 },1889 name: "symbol",1890 mutability: SolidityMutability::View,1891 is_payable: false,1892 args: (),1893 result: <UnnamedArgument<string>>::default(),1894 },1895 SolidityFunction {1896 docs: &[1897 " @notice A distinct Uniform Resource Identifier (URI) for a given asset.",1898 "",1899 " @dev If the token has a `url` property and it is not empty, it is returned.",1900 " Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.",1901 " If the collection property `baseURI` is empty or absent, return \"\" (empty string)",1902 " otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix",1903 " otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).",1904 "",1905 " @return token's const_metadata",1906 ],1907 selector_str: "tokenURI(uint256)",1908 selector: u32::from_be_bytes(Self::TOKEN_URI),1909 custom_signature: {1910 const cs: FunctionSignature = {1911 {1912 let fs = FunctionSignature::new(1913 &&FunctionName::new("tokenURI"),1914 );1915 let fs = FunctionSignature::done(1916 FunctionSignature::add_param(1917 fs,1918 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),1919 ),1920 true,1921 );1922 fs1923 }1924 };1925 cs1926 },1927 name: "tokenURI",1928 mutability: SolidityMutability::View,1929 is_payable: false,1930 args: (<NamedArgument<uint256>>::new("tokenId"),),1931 result: <UnnamedArgument<string>>::default(),1932 },1933 ),1934 };1935 let mut out = ::evm_coder::types::string::new();1936 if "ERC721Metadata".starts_with("Inline") {1937 out.push_str("/// @dev inlined interface\n");1938 }1939 let _ = interface.format(is_impl, &mut out, tc);1940 tc.collect(out);1941 if is_impl {1942 tc.collect(1943 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"1944 .into(),1945 );1946 } else {1947 tc.collect(1948 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"1949 .into(),1950 );1951 }1952 }1953 }1954 impl<T> ::evm_coder::Call for ERC721MetadataCall<T> {1955 fn parse(1956 method_id: ::evm_coder::types::bytes4,1957 reader: &mut ::evm_coder::abi::AbiReader,1958 ) -> ::evm_coder::execution::Result<Option<Self>> {1959 use ::evm_coder::abi::AbiRead;1960 match method_id {1961 ::evm_coder::ERC165Call::INTERFACE_ID => {1962 return Ok(1963 ::evm_coder::ERC165Call::parse(method_id, reader)?1964 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),1965 );1966 }1967 Self::NAME => return Ok(Some(Self::Name)),1968 Self::SYMBOL => return Ok(Some(Self::Symbol)),1969 Self::TOKEN_URI => {1970 return Ok(1971 Some(Self::TokenUri {1972 token_id: reader.abi_read()?,1973 }),1974 );1975 }1976 _ => {}1977 }1978 return Ok(None);1979 }1980 }1981 impl<T: Config> ERC721MetadataCall<T> {1982 /// Is this contract implements specified ERC165 selector1983 pub fn supports_interface(1984 this: &NonfungibleHandle<T>,1985 interface_id: ::evm_coder::types::bytes4,1986 ) -> bool {1987 interface_id != u32::to_be_bytes(0xffffff)1988 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID1989 || interface_id == Self::interface_id())1990 }1991 }1992 impl<T: Config> ::evm_coder::Weighted for ERC721MetadataCall<T> {1993 #[allow(unused_variables)]1994 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {1995 match self {1996 Self::ERC165Call(1997 ::evm_coder::ERC165Call::SupportsInterface { .. },1998 _,1999 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),2000 Self::Name => ().into(),2001 Self::Symbol => ().into(),2002 Self::TokenUri { .. } => ().into(),2003 }2004 }2005 }2006 impl<T: Config> ::evm_coder::Callable<ERC721MetadataCall<T>>2007 for NonfungibleHandle<T> {2008 #[allow(unreachable_code)]2009 fn call(2010 &mut self,2011 c: Msg<ERC721MetadataCall<T>>,2012 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {2013 use ::evm_coder::abi::AbiWrite;2014 match c.call {2015 ERC721MetadataCall::ERC165Call(2016 ::evm_coder::ERC165Call::SupportsInterface { interface_id },2017 _,2018 ) => {2019 let mut writer = ::evm_coder::abi::AbiWriter::default();2020 writer2021 .bool(2022 &<ERC721MetadataCall<2023 T,2024 >>::supports_interface(self, interface_id),2025 );2026 return Ok(writer.into());2027 }2028 _ => {}2029 }2030 let mut writer = ::evm_coder::abi::AbiWriter::default();2031 match c.call {2032 ERC721MetadataCall::Name => {2033 let result = self.name()?;2034 (&result).to_result()2035 }2036 ERC721MetadataCall::Symbol => {2037 let result = self.symbol()?;2038 (&result).to_result()2039 }2040 ERC721MetadataCall::TokenUri { token_id } => {2041 let result = self.token_uri(token_id)?;2042 (&result).to_result()2043 }2044 _ => {2045 Err(2046 ::evm_coder::execution::Error::from("method is not available")2047 .into(),2048 )2049 }2050 }2051 }2052 }2053 /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension2054 /// @dev See https://eips.ethereum.org/EIPS/eip-7212055 impl<T: Config> NonfungibleHandle<T> {2056 /// @notice Enumerate valid NFTs2057 /// @param index A counter less than `totalSupply()`2058 /// @return The token identifier for the `index`th NFT,2059 /// (sort order not specified)2060 fn token_by_index(&self, index: uint256) -> Result<uint256> {2061 Ok(index)2062 }2063 /// @dev Not implemented2064 fn token_of_owner_by_index(2065 &self,2066 _owner: address,2067 _index: uint256,2068 ) -> Result<uint256> {2069 Err("not implemented".into())2070 }2071 /// @notice Count NFTs tracked by this contract2072 /// @return A count of valid NFTs tracked by this contract, where each one of2073 /// them has an assigned and queryable owner not equal to the zero address2074 fn total_supply(&self) -> Result<uint256> {2075 self.consume_store_reads(1)?;2076 Ok(<Pallet<T>>::total_supply(self).into())2077 }2078 }2079 /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension2080 /// @dev See https://eips.ethereum.org/EIPS/eip-7212081 pub enum ERC721EnumerableCall<T> {2082 /// Inherited method2083 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),2084 /// @notice Enumerate valid NFTs2085 /// @param index A counter less than `totalSupply()`2086 /// @return The token identifier for the `index`th NFT,2087 /// (sort order not specified)2088 #[allow(missing_docs)]2089 TokenByIndex { index: uint256 },2090 /// @dev Not implemented2091 #[allow(missing_docs)]2092 TokenOfOwnerByIndex { _owner: address, _index: uint256 },2093 TotalSupply,2094 }2095 #[automatically_derived]2096 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721EnumerableCall<T> {2097 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {2098 match self {2099 ERC721EnumerableCall::ERC165Call(__self_0, __self_1) => {2100 ::core::fmt::Formatter::debug_tuple_field2_finish(2101 f,2102 "ERC165Call",2103 &__self_0,2104 &__self_1,2105 )2106 }2107 ERC721EnumerableCall::TokenByIndex { index: __self_0 } => {2108 ::core::fmt::Formatter::debug_struct_field1_finish(2109 f,2110 "TokenByIndex",2111 "index",2112 &__self_0,2113 )2114 }2115 ERC721EnumerableCall::TokenOfOwnerByIndex {2116 _owner: __self_0,2117 _index: __self_1,2118 } => {2119 ::core::fmt::Formatter::debug_struct_field2_finish(2120 f,2121 "TokenOfOwnerByIndex",2122 "_owner",2123 &__self_0,2124 "_index",2125 &__self_1,2126 )2127 }2128 ERC721EnumerableCall::TotalSupply => {2129 ::core::fmt::Formatter::write_str(f, "TotalSupply")2130 }2131 }2132 }2133 }2134 impl<T> ERC721EnumerableCall<T> {2135 const TOKEN_BY_INDEX_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2136 {2137 let fs = FunctionSignature::new(&&FunctionName::new("tokenByIndex"));2138 let fs = FunctionSignature::done(2139 FunctionSignature::add_param(2140 fs,2141 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2142 ),2143 true,2144 );2145 fs2146 }2147 };2148 ///tokenByIndex(uint256)2149 const TOKEN_BY_INDEX: ::evm_coder::types::bytes4 = {2150 let a = ::evm_coder::sha3_const::Keccak256::new()2151 .update_with_size(2152 &Self::TOKEN_BY_INDEX_SIGNATURE.signature,2153 Self::TOKEN_BY_INDEX_SIGNATURE.signature_len,2154 )2155 .finalize();2156 [a[0], a[1], a[2], a[3]]2157 };2158 const TOKEN_OF_OWNER_BY_INDEX_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2159 {2160 let fs = FunctionSignature::new(2161 &&FunctionName::new("tokenOfOwnerByIndex"),2162 );2163 let fs = FunctionSignature::done(2164 FunctionSignature::add_param(2165 FunctionSignature::add_param(2166 fs,2167 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2168 ),2169 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2170 ),2171 true,2172 );2173 fs2174 }2175 };2176 ///tokenOfOwnerByIndex(address,uint256)2177 const TOKEN_OF_OWNER_BY_INDEX: ::evm_coder::types::bytes4 = {2178 let a = ::evm_coder::sha3_const::Keccak256::new()2179 .update_with_size(2180 &Self::TOKEN_OF_OWNER_BY_INDEX_SIGNATURE.signature,2181 Self::TOKEN_OF_OWNER_BY_INDEX_SIGNATURE.signature_len,2182 )2183 .finalize();2184 [a[0], a[1], a[2], a[3]]2185 };2186 const TOTAL_SUPPLY_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2187 {2188 let fs = FunctionSignature::new(&&FunctionName::new("totalSupply"));2189 let fs = FunctionSignature::done(fs, false);2190 fs2191 }2192 };2193 ///totalSupply()2194 const TOTAL_SUPPLY: ::evm_coder::types::bytes4 = {2195 let a = ::evm_coder::sha3_const::Keccak256::new()2196 .update_with_size(2197 &Self::TOTAL_SUPPLY_SIGNATURE.signature,2198 Self::TOTAL_SUPPLY_SIGNATURE.signature_len,2199 )2200 .finalize();2201 [a[0], a[1], a[2], a[3]]2202 };2203 /// Return this call ERC165 selector2204 pub fn interface_id() -> ::evm_coder::types::bytes4 {2205 let mut interface_id = 0;2206 interface_id ^= u32::from_be_bytes(Self::TOKEN_BY_INDEX);2207 interface_id ^= u32::from_be_bytes(Self::TOKEN_OF_OWNER_BY_INDEX);2208 interface_id ^= u32::from_be_bytes(Self::TOTAL_SUPPLY);2209 u32::to_be_bytes(interface_id)2210 }2211 /// Generate solidity definitions for methods described in this interface2212 pub fn generate_solidity_interface(2213 tc: &evm_coder::solidity::TypeCollector,2214 is_impl: bool,2215 ) {2216 use evm_coder::solidity::*;2217 use core::fmt::Write;2218 let interface = SolidityInterface {2219 docs: &[2220 " @title ERC-721 Non-Fungible Token Standard, optional enumeration extension",2221 " @dev See https://eips.ethereum.org/EIPS/eip-721",2222 ],2223 name: "ERC721Enumerable",2224 selector: Self::interface_id(),2225 is: &["Dummy", "ERC165"],2226 functions: (2227 SolidityFunction {2228 docs: &[2229 " @notice Enumerate valid NFTs",2230 " @param index A counter less than `totalSupply()`",2231 " @return The token identifier for the `index`th NFT,",2232 " (sort order not specified)",2233 ],2234 selector_str: "tokenByIndex(uint256)",2235 selector: u32::from_be_bytes(Self::TOKEN_BY_INDEX),2236 custom_signature: {2237 const cs: FunctionSignature = {2238 {2239 let fs = FunctionSignature::new(2240 &&FunctionName::new("tokenByIndex"),2241 );2242 let fs = FunctionSignature::done(2243 FunctionSignature::add_param(2244 fs,2245 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2246 ),2247 true,2248 );2249 fs2250 }2251 };2252 cs2253 },2254 name: "tokenByIndex",2255 mutability: SolidityMutability::View,2256 is_payable: false,2257 args: (<NamedArgument<uint256>>::new("index"),),2258 result: <UnnamedArgument<uint256>>::default(),2259 },2260 SolidityFunction {2261 docs: &[" @dev Not implemented"],2262 selector_str: "tokenOfOwnerByIndex(address,uint256)",2263 selector: u32::from_be_bytes(Self::TOKEN_OF_OWNER_BY_INDEX),2264 custom_signature: {2265 const cs: FunctionSignature = {2266 {2267 let fs = FunctionSignature::new(2268 &&FunctionName::new("tokenOfOwnerByIndex"),2269 );2270 let fs = FunctionSignature::done(2271 FunctionSignature::add_param(2272 FunctionSignature::add_param(2273 fs,2274 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2275 ),2276 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2277 ),2278 true,2279 );2280 fs2281 }2282 };2283 cs2284 },2285 name: "tokenOfOwnerByIndex",2286 mutability: SolidityMutability::View,2287 is_payable: false,2288 args: (2289 <NamedArgument<address>>::new("owner"),2290 <NamedArgument<uint256>>::new("index"),2291 ),2292 result: <UnnamedArgument<uint256>>::default(),2293 },2294 SolidityFunction {2295 docs: &[2296 " @notice Count NFTs tracked by this contract",2297 " @return A count of valid NFTs tracked by this contract, where each one of",2298 " them has an assigned and queryable owner not equal to the zero address",2299 ],2300 selector_str: "totalSupply()",2301 selector: u32::from_be_bytes(Self::TOTAL_SUPPLY),2302 custom_signature: {2303 const cs: FunctionSignature = {2304 {2305 let fs = FunctionSignature::new(2306 &&FunctionName::new("totalSupply"),2307 );2308 let fs = FunctionSignature::done(fs, false);2309 fs2310 }2311 };2312 cs2313 },2314 name: "totalSupply",2315 mutability: SolidityMutability::View,2316 is_payable: false,2317 args: (),2318 result: <UnnamedArgument<uint256>>::default(),2319 },2320 ),2321 };2322 let mut out = ::evm_coder::types::string::new();2323 if "ERC721Enumerable".starts_with("Inline") {2324 out.push_str("/// @dev inlined interface\n");2325 }2326 let _ = interface.format(is_impl, &mut out, tc);2327 tc.collect(out);2328 if is_impl {2329 tc.collect(2330 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"2331 .into(),2332 );2333 } else {2334 tc.collect(2335 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"2336 .into(),2337 );2338 }2339 }2340 }2341 impl<T> ::evm_coder::Call for ERC721EnumerableCall<T> {2342 fn parse(2343 method_id: ::evm_coder::types::bytes4,2344 reader: &mut ::evm_coder::abi::AbiReader,2345 ) -> ::evm_coder::execution::Result<Option<Self>> {2346 use ::evm_coder::abi::AbiRead;2347 match method_id {2348 ::evm_coder::ERC165Call::INTERFACE_ID => {2349 return Ok(2350 ::evm_coder::ERC165Call::parse(method_id, reader)?2351 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),2352 );2353 }2354 Self::TOKEN_BY_INDEX => {2355 return Ok(2356 Some(Self::TokenByIndex {2357 index: reader.abi_read()?,2358 }),2359 );2360 }2361 Self::TOKEN_OF_OWNER_BY_INDEX => {2362 return Ok(2363 Some(Self::TokenOfOwnerByIndex {2364 _owner: reader.abi_read()?,2365 _index: reader.abi_read()?,2366 }),2367 );2368 }2369 Self::TOTAL_SUPPLY => return Ok(Some(Self::TotalSupply)),2370 _ => {}2371 }2372 return Ok(None);2373 }2374 }2375 impl<T: Config> ERC721EnumerableCall<T> {2376 /// Is this contract implements specified ERC165 selector2377 pub fn supports_interface(2378 this: &NonfungibleHandle<T>,2379 interface_id: ::evm_coder::types::bytes4,2380 ) -> bool {2381 interface_id != u32::to_be_bytes(0xffffff)2382 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID2383 || interface_id == Self::interface_id())2384 }2385 }2386 impl<T: Config> ::evm_coder::Weighted for ERC721EnumerableCall<T> {2387 #[allow(unused_variables)]2388 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {2389 match self {2390 Self::ERC165Call(2391 ::evm_coder::ERC165Call::SupportsInterface { .. },2392 _,2393 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),2394 Self::TokenByIndex { .. } => ().into(),2395 Self::TokenOfOwnerByIndex { .. } => ().into(),2396 Self::TotalSupply => ().into(),2397 }2398 }2399 }2400 impl<T: Config> ::evm_coder::Callable<ERC721EnumerableCall<T>>2401 for NonfungibleHandle<T> {2402 #[allow(unreachable_code)]2403 fn call(2404 &mut self,2405 c: Msg<ERC721EnumerableCall<T>>,2406 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {2407 use ::evm_coder::abi::AbiWrite;2408 match c.call {2409 ERC721EnumerableCall::ERC165Call(2410 ::evm_coder::ERC165Call::SupportsInterface { interface_id },2411 _,2412 ) => {2413 let mut writer = ::evm_coder::abi::AbiWriter::default();2414 writer2415 .bool(2416 &<ERC721EnumerableCall<2417 T,2418 >>::supports_interface(self, interface_id),2419 );2420 return Ok(writer.into());2421 }2422 _ => {}2423 }2424 let mut writer = ::evm_coder::abi::AbiWriter::default();2425 match c.call {2426 ERC721EnumerableCall::TokenByIndex { index } => {2427 let result = self.token_by_index(index)?;2428 (&result).to_result()2429 }2430 ERC721EnumerableCall::TokenOfOwnerByIndex { _owner, _index } => {2431 let result = self.token_of_owner_by_index(_owner, _index)?;2432 (&result).to_result()2433 }2434 ERC721EnumerableCall::TotalSupply => {2435 let result = self.total_supply()?;2436 (&result).to_result()2437 }2438 _ => {2439 Err(2440 ::evm_coder::execution::Error::from("method is not available")2441 .into(),2442 )2443 }2444 }2445 }2446 }2447 /// @title ERC-721 Non-Fungible Token Standard2448 /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md2449 impl<T: Config> NonfungibleHandle<T> {2450 /// @notice Count all NFTs assigned to an owner2451 /// @dev NFTs assigned to the zero address are considered invalid, and this2452 /// function throws for queries about the zero address.2453 /// @param owner An address for whom to query the balance2454 /// @return The number of NFTs owned by `owner`, possibly zero2455 fn balance_of(&self, owner: address) -> Result<uint256> {2456 self.consume_store_reads(1)?;2457 let owner = T::CrossAccountId::from_eth(owner);2458 let balance = <AccountBalance<T>>::get((self.id, owner));2459 Ok(balance.into())2460 }2461 /// @notice Find the owner of an NFT2462 /// @dev NFTs assigned to zero address are considered invalid, and queries2463 /// about them do throw.2464 /// @param tokenId The identifier for an NFT2465 /// @return The address of the owner of the NFT2466 fn owner_of(&self, token_id: uint256) -> Result<address> {2467 self.consume_store_reads(1)?;2468 let token: TokenId = token_id.try_into()?;2469 Ok(2470 *<TokenData<T>>::get((self.id, token))2471 .ok_or("token not found")?2472 .owner2473 .as_eth(),2474 )2475 }2476 /// @dev Not implemented2477 fn safe_transfer_from_with_data(2478 &mut self,2479 _from: address,2480 _to: address,2481 _token_id: uint256,2482 _data: bytes,2483 ) -> Result<void> {2484 Err("not implemented".into())2485 }2486 /// @dev Not implemented2487 fn safe_transfer_from(2488 &mut self,2489 _from: address,2490 _to: address,2491 _token_id: uint256,2492 ) -> Result<void> {2493 Err("not implemented".into())2494 }2495 /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE2496 /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE2497 /// THEY MAY BE PERMANENTLY LOST2498 /// @dev Throws unless `msg.sender` is the current owner or an authorized2499 /// operator for this NFT. Throws if `from` is not the current owner. Throws2500 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.2501 /// @param from The current owner of the NFT2502 /// @param to The new owner2503 /// @param tokenId The NFT to transfer2504 fn transfer_from(2505 &mut self,2506 caller: caller,2507 from: address,2508 to: address,2509 token_id: uint256,2510 ) -> Result<void> {2511 let caller = T::CrossAccountId::from_eth(caller);2512 let from = T::CrossAccountId::from_eth(from);2513 let to = T::CrossAccountId::from_eth(to);2514 let token = token_id.try_into()?;2515 let budget = self2516 .recorder2517 .weight_calls_budget(<StructureWeight<T>>::find_parent());2518 <Pallet<T>>::transfer_from(self, &caller, &from, &to, token, &budget)2519 .map_err(dispatch_to_evm::<T>)?;2520 Ok(())2521 }2522 /// @notice Set or reaffirm the approved address for an NFT2523 /// @dev The zero address indicates there is no approved address.2524 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized2525 /// operator of the current owner.2526 /// @param approved The new approved NFT controller2527 /// @param tokenId The NFT to approve2528 fn approve(2529 &mut self,2530 caller: caller,2531 approved: address,2532 token_id: uint256,2533 ) -> Result<void> {2534 let caller = T::CrossAccountId::from_eth(caller);2535 let approved = T::CrossAccountId::from_eth(approved);2536 let token = token_id.try_into()?;2537 <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))2538 .map_err(dispatch_to_evm::<T>)?;2539 Ok(())2540 }2541 /// @dev Not implemented2542 fn set_approval_for_all(2543 &mut self,2544 _caller: caller,2545 _operator: address,2546 _approved: bool,2547 ) -> Result<void> {2548 Err("not implemented".into())2549 }2550 /// @dev Not implemented2551 fn get_approved(&self, _token_id: uint256) -> Result<address> {2552 Err("not implemented".into())2553 }2554 /// @dev Not implemented2555 fn is_approved_for_all(2556 &self,2557 _owner: address,2558 _operator: address,2559 ) -> Result<address> {2560 Err("not implemented".into())2561 }2562 }2563 /// @title ERC-721 Non-Fungible Token Standard2564 /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md2565 pub enum ERC721Call<T> {2566 /// Inherited method2567 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),2568 /// @notice Count all NFTs assigned to an owner2569 /// @dev NFTs assigned to the zero address are considered invalid, and this2570 /// function throws for queries about the zero address.2571 /// @param owner An address for whom to query the balance2572 /// @return The number of NFTs owned by `owner`, possibly zero2573 #[allow(missing_docs)]2574 BalanceOf { owner: address },2575 /// @notice Find the owner of an NFT2576 /// @dev NFTs assigned to zero address are considered invalid, and queries2577 /// about them do throw.2578 /// @param tokenId The identifier for an NFT2579 /// @return The address of the owner of the NFT2580 #[allow(missing_docs)]2581 OwnerOf { token_id: uint256 },2582 /// @dev Not implemented2583 #[allow(missing_docs)]2584 SafeTransferFromWithData {2585 _from: address,2586 _to: address,2587 _token_id: uint256,2588 _data: bytes,2589 },2590 /// @dev Not implemented2591 #[allow(missing_docs)]2592 SafeTransferFrom { _from: address, _to: address, _token_id: uint256 },2593 /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE2594 /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE2595 /// THEY MAY BE PERMANENTLY LOST2596 /// @dev Throws unless `msg.sender` is the current owner or an authorized2597 /// operator for this NFT. Throws if `from` is not the current owner. Throws2598 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.2599 /// @param from The current owner of the NFT2600 /// @param to The new owner2601 /// @param tokenId The NFT to transfer2602 #[allow(missing_docs)]2603 TransferFrom { from: address, to: address, token_id: uint256 },2604 /// @notice Set or reaffirm the approved address for an NFT2605 /// @dev The zero address indicates there is no approved address.2606 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized2607 /// operator of the current owner.2608 /// @param approved The new approved NFT controller2609 /// @param tokenId The NFT to approve2610 #[allow(missing_docs)]2611 Approve { approved: address, token_id: uint256 },2612 /// @dev Not implemented2613 #[allow(missing_docs)]2614 SetApprovalForAll { _operator: address, _approved: bool },2615 /// @dev Not implemented2616 #[allow(missing_docs)]2617 GetApproved { _token_id: uint256 },2618 /// @dev Not implemented2619 #[allow(missing_docs)]2620 IsApprovedForAll { _owner: address, _operator: address },2621 }2622 #[automatically_derived]2623 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721Call<T> {2624 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {2625 match self {2626 ERC721Call::ERC165Call(__self_0, __self_1) => {2627 ::core::fmt::Formatter::debug_tuple_field2_finish(2628 f,2629 "ERC165Call",2630 &__self_0,2631 &__self_1,2632 )2633 }2634 ERC721Call::BalanceOf { owner: __self_0 } => {2635 ::core::fmt::Formatter::debug_struct_field1_finish(2636 f,2637 "BalanceOf",2638 "owner",2639 &__self_0,2640 )2641 }2642 ERC721Call::OwnerOf { token_id: __self_0 } => {2643 ::core::fmt::Formatter::debug_struct_field1_finish(2644 f,2645 "OwnerOf",2646 "token_id",2647 &__self_0,2648 )2649 }2650 ERC721Call::SafeTransferFromWithData {2651 _from: __self_0,2652 _to: __self_1,2653 _token_id: __self_2,2654 _data: __self_3,2655 } => {2656 ::core::fmt::Formatter::debug_struct_field4_finish(2657 f,2658 "SafeTransferFromWithData",2659 "_from",2660 &__self_0,2661 "_to",2662 &__self_1,2663 "_token_id",2664 &__self_2,2665 "_data",2666 &__self_3,2667 )2668 }2669 ERC721Call::SafeTransferFrom {2670 _from: __self_0,2671 _to: __self_1,2672 _token_id: __self_2,2673 } => {2674 ::core::fmt::Formatter::debug_struct_field3_finish(2675 f,2676 "SafeTransferFrom",2677 "_from",2678 &__self_0,2679 "_to",2680 &__self_1,2681 "_token_id",2682 &__self_2,2683 )2684 }2685 ERC721Call::TransferFrom {2686 from: __self_0,2687 to: __self_1,2688 token_id: __self_2,2689 } => {2690 ::core::fmt::Formatter::debug_struct_field3_finish(2691 f,2692 "TransferFrom",2693 "from",2694 &__self_0,2695 "to",2696 &__self_1,2697 "token_id",2698 &__self_2,2699 )2700 }2701 ERC721Call::Approve { approved: __self_0, token_id: __self_1 } => {2702 ::core::fmt::Formatter::debug_struct_field2_finish(2703 f,2704 "Approve",2705 "approved",2706 &__self_0,2707 "token_id",2708 &__self_1,2709 )2710 }2711 ERC721Call::SetApprovalForAll {2712 _operator: __self_0,2713 _approved: __self_1,2714 } => {2715 ::core::fmt::Formatter::debug_struct_field2_finish(2716 f,2717 "SetApprovalForAll",2718 "_operator",2719 &__self_0,2720 "_approved",2721 &__self_1,2722 )2723 }2724 ERC721Call::GetApproved { _token_id: __self_0 } => {2725 ::core::fmt::Formatter::debug_struct_field1_finish(2726 f,2727 "GetApproved",2728 "_token_id",2729 &__self_0,2730 )2731 }2732 ERC721Call::IsApprovedForAll {2733 _owner: __self_0,2734 _operator: __self_1,2735 } => {2736 ::core::fmt::Formatter::debug_struct_field2_finish(2737 f,2738 "IsApprovedForAll",2739 "_owner",2740 &__self_0,2741 "_operator",2742 &__self_1,2743 )2744 }2745 }2746 }2747 }2748 impl<T> ERC721Call<T> {2749 const BALANCE_OF_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2750 {2751 let fs = FunctionSignature::new(&&FunctionName::new("balanceOf"));2752 let fs = FunctionSignature::done(2753 FunctionSignature::add_param(2754 fs,2755 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2756 ),2757 true,2758 );2759 fs2760 }2761 };2762 ///balanceOf(address)2763 const BALANCE_OF: ::evm_coder::types::bytes4 = {2764 let a = ::evm_coder::sha3_const::Keccak256::new()2765 .update_with_size(2766 &Self::BALANCE_OF_SIGNATURE.signature,2767 Self::BALANCE_OF_SIGNATURE.signature_len,2768 )2769 .finalize();2770 [a[0], a[1], a[2], a[3]]2771 };2772 const OWNER_OF_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2773 {2774 let fs = FunctionSignature::new(&&FunctionName::new("ownerOf"));2775 let fs = FunctionSignature::done(2776 FunctionSignature::add_param(2777 fs,2778 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2779 ),2780 true,2781 );2782 fs2783 }2784 };2785 ///ownerOf(uint256)2786 const OWNER_OF: ::evm_coder::types::bytes4 = {2787 let a = ::evm_coder::sha3_const::Keccak256::new()2788 .update_with_size(2789 &Self::OWNER_OF_SIGNATURE.signature,2790 Self::OWNER_OF_SIGNATURE.signature_len,2791 )2792 .finalize();2793 [a[0], a[1], a[2], a[3]]2794 };2795 const SAFE_TRANSFER_FROM_WITH_DATA_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2796 {2797 let fs = FunctionSignature::new(&&FunctionName::new("safeTransferFrom"));2798 let fs = FunctionSignature::done(2799 FunctionSignature::add_param(2800 FunctionSignature::add_param(2801 FunctionSignature::add_param(2802 FunctionSignature::add_param(2803 fs,2804 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2805 ),2806 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2807 ),2808 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2809 ),2810 (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),2811 ),2812 true,2813 );2814 fs2815 }2816 };2817 ///safeTransferFrom(address,address,uint256,bytes)2818 const SAFE_TRANSFER_FROM_WITH_DATA: ::evm_coder::types::bytes4 = {2819 let a = ::evm_coder::sha3_const::Keccak256::new()2820 .update_with_size(2821 &Self::SAFE_TRANSFER_FROM_WITH_DATA_SIGNATURE.signature,2822 Self::SAFE_TRANSFER_FROM_WITH_DATA_SIGNATURE.signature_len,2823 )2824 .finalize();2825 [a[0], a[1], a[2], a[3]]2826 };2827 const SAFE_TRANSFER_FROM_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2828 {2829 let fs = FunctionSignature::new(&&FunctionName::new("safeTransferFrom"));2830 let fs = FunctionSignature::done(2831 FunctionSignature::add_param(2832 FunctionSignature::add_param(2833 FunctionSignature::add_param(2834 fs,2835 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2836 ),2837 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2838 ),2839 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2840 ),2841 true,2842 );2843 fs2844 }2845 };2846 ///safeTransferFrom(address,address,uint256)2847 const SAFE_TRANSFER_FROM: ::evm_coder::types::bytes4 = {2848 let a = ::evm_coder::sha3_const::Keccak256::new()2849 .update_with_size(2850 &Self::SAFE_TRANSFER_FROM_SIGNATURE.signature,2851 Self::SAFE_TRANSFER_FROM_SIGNATURE.signature_len,2852 )2853 .finalize();2854 [a[0], a[1], a[2], a[3]]2855 };2856 const TRANSFER_FROM_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2857 {2858 let fs = FunctionSignature::new(&&FunctionName::new("transferFrom"));2859 let fs = FunctionSignature::done(2860 FunctionSignature::add_param(2861 FunctionSignature::add_param(2862 FunctionSignature::add_param(2863 fs,2864 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2865 ),2866 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2867 ),2868 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2869 ),2870 true,2871 );2872 fs2873 }2874 };2875 ///transferFrom(address,address,uint256)2876 const TRANSFER_FROM: ::evm_coder::types::bytes4 = {2877 let a = ::evm_coder::sha3_const::Keccak256::new()2878 .update_with_size(2879 &Self::TRANSFER_FROM_SIGNATURE.signature,2880 Self::TRANSFER_FROM_SIGNATURE.signature_len,2881 )2882 .finalize();2883 [a[0], a[1], a[2], a[3]]2884 };2885 const APPROVE_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2886 {2887 let fs = FunctionSignature::new(&&FunctionName::new("approve"));2888 let fs = FunctionSignature::done(2889 FunctionSignature::add_param(2890 FunctionSignature::add_param(2891 fs,2892 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2893 ),2894 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2895 ),2896 true,2897 );2898 fs2899 }2900 };2901 ///approve(address,uint256)2902 const APPROVE: ::evm_coder::types::bytes4 = {2903 let a = ::evm_coder::sha3_const::Keccak256::new()2904 .update_with_size(2905 &Self::APPROVE_SIGNATURE.signature,2906 Self::APPROVE_SIGNATURE.signature_len,2907 )2908 .finalize();2909 [a[0], a[1], a[2], a[3]]2910 };2911 const SET_APPROVAL_FOR_ALL_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2912 {2913 let fs = FunctionSignature::new(2914 &&FunctionName::new("setApprovalForAll"),2915 );2916 let fs = FunctionSignature::done(2917 FunctionSignature::add_param(2918 FunctionSignature::add_param(2919 fs,2920 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2921 ),2922 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),2923 ),2924 true,2925 );2926 fs2927 }2928 };2929 ///setApprovalForAll(address,bool)2930 const SET_APPROVAL_FOR_ALL: ::evm_coder::types::bytes4 = {2931 let a = ::evm_coder::sha3_const::Keccak256::new()2932 .update_with_size(2933 &Self::SET_APPROVAL_FOR_ALL_SIGNATURE.signature,2934 Self::SET_APPROVAL_FOR_ALL_SIGNATURE.signature_len,2935 )2936 .finalize();2937 [a[0], a[1], a[2], a[3]]2938 };2939 const GET_APPROVED_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2940 {2941 let fs = FunctionSignature::new(&&FunctionName::new("getApproved"));2942 let fs = FunctionSignature::done(2943 FunctionSignature::add_param(2944 fs,2945 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),2946 ),2947 true,2948 );2949 fs2950 }2951 };2952 ///getApproved(uint256)2953 const GET_APPROVED: ::evm_coder::types::bytes4 = {2954 let a = ::evm_coder::sha3_const::Keccak256::new()2955 .update_with_size(2956 &Self::GET_APPROVED_SIGNATURE.signature,2957 Self::GET_APPROVED_SIGNATURE.signature_len,2958 )2959 .finalize();2960 [a[0], a[1], a[2], a[3]]2961 };2962 const IS_APPROVED_FOR_ALL_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {2963 {2964 let fs = FunctionSignature::new(&&FunctionName::new("isApprovedForAll"));2965 let fs = FunctionSignature::done(2966 FunctionSignature::add_param(2967 FunctionSignature::add_param(2968 fs,2969 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2970 ),2971 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),2972 ),2973 true,2974 );2975 fs2976 }2977 };2978 ///isApprovedForAll(address,address)2979 const IS_APPROVED_FOR_ALL: ::evm_coder::types::bytes4 = {2980 let a = ::evm_coder::sha3_const::Keccak256::new()2981 .update_with_size(2982 &Self::IS_APPROVED_FOR_ALL_SIGNATURE.signature,2983 Self::IS_APPROVED_FOR_ALL_SIGNATURE.signature_len,2984 )2985 .finalize();2986 [a[0], a[1], a[2], a[3]]2987 };2988 /// Return this call ERC165 selector2989 pub fn interface_id() -> ::evm_coder::types::bytes4 {2990 let mut interface_id = 0;2991 interface_id ^= u32::from_be_bytes(Self::BALANCE_OF);2992 interface_id ^= u32::from_be_bytes(Self::OWNER_OF);2993 interface_id ^= u32::from_be_bytes(Self::SAFE_TRANSFER_FROM_WITH_DATA);2994 interface_id ^= u32::from_be_bytes(Self::SAFE_TRANSFER_FROM);2995 interface_id ^= u32::from_be_bytes(Self::TRANSFER_FROM);2996 interface_id ^= u32::from_be_bytes(Self::APPROVE);2997 interface_id ^= u32::from_be_bytes(Self::SET_APPROVAL_FOR_ALL);2998 interface_id ^= u32::from_be_bytes(Self::GET_APPROVED);2999 interface_id ^= u32::from_be_bytes(Self::IS_APPROVED_FOR_ALL);3000 u32::to_be_bytes(interface_id)3001 }3002 /// Generate solidity definitions for methods described in this interface3003 pub fn generate_solidity_interface(3004 tc: &evm_coder::solidity::TypeCollector,3005 is_impl: bool,3006 ) {3007 use evm_coder::solidity::*;3008 use core::fmt::Write;3009 let interface = SolidityInterface {3010 docs: &[3011 " @title ERC-721 Non-Fungible Token Standard",3012 " @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md",3013 ],3014 name: "ERC721",3015 selector: Self::interface_id(),3016 is: &["Dummy", "ERC165", "ERC721Events"],3017 functions: (3018 SolidityFunction {3019 docs: &[3020 " @notice Count all NFTs assigned to an owner",3021 " @dev NFTs assigned to the zero address are considered invalid, and this",3022 " function throws for queries about the zero address.",3023 " @param owner An address for whom to query the balance",3024 " @return The number of NFTs owned by `owner`, possibly zero",3025 ],3026 selector_str: "balanceOf(address)",3027 selector: u32::from_be_bytes(Self::BALANCE_OF),3028 custom_signature: {3029 const cs: FunctionSignature = {3030 {3031 let fs = FunctionSignature::new(3032 &&FunctionName::new("balanceOf"),3033 );3034 let fs = FunctionSignature::done(3035 FunctionSignature::add_param(3036 fs,3037 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3038 ),3039 true,3040 );3041 fs3042 }3043 };3044 cs3045 },3046 name: "balanceOf",3047 mutability: SolidityMutability::View,3048 is_payable: false,3049 args: (<NamedArgument<address>>::new("owner"),),3050 result: <UnnamedArgument<uint256>>::default(),3051 },3052 SolidityFunction {3053 docs: &[3054 " @notice Find the owner of an NFT",3055 " @dev NFTs assigned to zero address are considered invalid, and queries",3056 " about them do throw.",3057 " @param tokenId The identifier for an NFT",3058 " @return The address of the owner of the NFT",3059 ],3060 selector_str: "ownerOf(uint256)",3061 selector: u32::from_be_bytes(Self::OWNER_OF),3062 custom_signature: {3063 const cs: FunctionSignature = {3064 {3065 let fs = FunctionSignature::new(3066 &&FunctionName::new("ownerOf"),3067 );3068 let fs = FunctionSignature::done(3069 FunctionSignature::add_param(3070 fs,3071 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3072 ),3073 true,3074 );3075 fs3076 }3077 };3078 cs3079 },3080 name: "ownerOf",3081 mutability: SolidityMutability::View,3082 is_payable: false,3083 args: (<NamedArgument<uint256>>::new("tokenId"),),3084 result: <UnnamedArgument<address>>::default(),3085 },3086 SolidityFunction {3087 docs: &[" @dev Not implemented"],3088 selector_str: "safeTransferFrom(address,address,uint256,bytes)",3089 selector: u32::from_be_bytes(Self::SAFE_TRANSFER_FROM_WITH_DATA),3090 custom_signature: {3091 const cs: FunctionSignature = {3092 {3093 let fs = FunctionSignature::new(3094 &&FunctionName::new("safeTransferFrom"),3095 );3096 let fs = FunctionSignature::done(3097 FunctionSignature::add_param(3098 FunctionSignature::add_param(3099 FunctionSignature::add_param(3100 FunctionSignature::add_param(3101 fs,3102 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3103 ),3104 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3105 ),3106 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3107 ),3108 (<bytes>::SIGNATURE, <bytes>::SIGNATURE_LEN),3109 ),3110 true,3111 );3112 fs3113 }3114 };3115 cs3116 },3117 name: "safeTransferFrom",3118 mutability: SolidityMutability::Mutable,3119 is_payable: false,3120 args: (3121 <NamedArgument<address>>::new("from"),3122 <NamedArgument<address>>::new("to"),3123 <NamedArgument<uint256>>::new("tokenId"),3124 <NamedArgument<bytes>>::new("data"),3125 ),3126 result: <UnnamedArgument<void>>::default(),3127 },3128 SolidityFunction {3129 docs: &[" @dev Not implemented"],3130 selector_str: "safeTransferFrom(address,address,uint256)",3131 selector: u32::from_be_bytes(Self::SAFE_TRANSFER_FROM),3132 custom_signature: {3133 const cs: FunctionSignature = {3134 {3135 let fs = FunctionSignature::new(3136 &&FunctionName::new("safeTransferFrom"),3137 );3138 let fs = FunctionSignature::done(3139 FunctionSignature::add_param(3140 FunctionSignature::add_param(3141 FunctionSignature::add_param(3142 fs,3143 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3144 ),3145 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3146 ),3147 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3148 ),3149 true,3150 );3151 fs3152 }3153 };3154 cs3155 },3156 name: "safeTransferFrom",3157 mutability: SolidityMutability::Mutable,3158 is_payable: false,3159 args: (3160 <NamedArgument<address>>::new("from"),3161 <NamedArgument<address>>::new("to"),3162 <NamedArgument<uint256>>::new("tokenId"),3163 ),3164 result: <UnnamedArgument<void>>::default(),3165 },3166 SolidityFunction {3167 docs: &[3168 " @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE",3169 " TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE",3170 " THEY MAY BE PERMANENTLY LOST",3171 " @dev Throws unless `msg.sender` is the current owner or an authorized",3172 " operator for this NFT. Throws if `from` is not the current owner. Throws",3173 " if `to` is the zero address. Throws if `tokenId` is not a valid NFT.",3174 " @param from The current owner of the NFT",3175 " @param to The new owner",3176 " @param tokenId The NFT to transfer",3177 ],3178 selector_str: "transferFrom(address,address,uint256)",3179 selector: u32::from_be_bytes(Self::TRANSFER_FROM),3180 custom_signature: {3181 const cs: FunctionSignature = {3182 {3183 let fs = FunctionSignature::new(3184 &&FunctionName::new("transferFrom"),3185 );3186 let fs = FunctionSignature::done(3187 FunctionSignature::add_param(3188 FunctionSignature::add_param(3189 FunctionSignature::add_param(3190 fs,3191 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3192 ),3193 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3194 ),3195 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3196 ),3197 true,3198 );3199 fs3200 }3201 };3202 cs3203 },3204 name: "transferFrom",3205 mutability: SolidityMutability::Mutable,3206 is_payable: false,3207 args: (3208 <NamedArgument<address>>::new("from"),3209 <NamedArgument<address>>::new("to"),3210 <NamedArgument<uint256>>::new("tokenId"),3211 ),3212 result: <UnnamedArgument<void>>::default(),3213 },3214 SolidityFunction {3215 docs: &[3216 " @notice Set or reaffirm the approved address for an NFT",3217 " @dev The zero address indicates there is no approved address.",3218 " @dev Throws unless `msg.sender` is the current NFT owner, or an authorized",3219 " operator of the current owner.",3220 " @param approved The new approved NFT controller",3221 " @param tokenId The NFT to approve",3222 ],3223 selector_str: "approve(address,uint256)",3224 selector: u32::from_be_bytes(Self::APPROVE),3225 custom_signature: {3226 const cs: FunctionSignature = {3227 {3228 let fs = FunctionSignature::new(3229 &&FunctionName::new("approve"),3230 );3231 let fs = FunctionSignature::done(3232 FunctionSignature::add_param(3233 FunctionSignature::add_param(3234 fs,3235 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3236 ),3237 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3238 ),3239 true,3240 );3241 fs3242 }3243 };3244 cs3245 },3246 name: "approve",3247 mutability: SolidityMutability::Mutable,3248 is_payable: false,3249 args: (3250 <NamedArgument<address>>::new("approved"),3251 <NamedArgument<uint256>>::new("tokenId"),3252 ),3253 result: <UnnamedArgument<void>>::default(),3254 },3255 SolidityFunction {3256 docs: &[" @dev Not implemented"],3257 selector_str: "setApprovalForAll(address,bool)",3258 selector: u32::from_be_bytes(Self::SET_APPROVAL_FOR_ALL),3259 custom_signature: {3260 const cs: FunctionSignature = {3261 {3262 let fs = FunctionSignature::new(3263 &&FunctionName::new("setApprovalForAll"),3264 );3265 let fs = FunctionSignature::done(3266 FunctionSignature::add_param(3267 FunctionSignature::add_param(3268 fs,3269 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3270 ),3271 (<bool>::SIGNATURE, <bool>::SIGNATURE_LEN),3272 ),3273 true,3274 );3275 fs3276 }3277 };3278 cs3279 },3280 name: "setApprovalForAll",3281 mutability: SolidityMutability::Mutable,3282 is_payable: false,3283 args: (3284 <NamedArgument<address>>::new("operator"),3285 <NamedArgument<bool>>::new("approved"),3286 ),3287 result: <UnnamedArgument<void>>::default(),3288 },3289 SolidityFunction {3290 docs: &[" @dev Not implemented"],3291 selector_str: "getApproved(uint256)",3292 selector: u32::from_be_bytes(Self::GET_APPROVED),3293 custom_signature: {3294 const cs: FunctionSignature = {3295 {3296 let fs = FunctionSignature::new(3297 &&FunctionName::new("getApproved"),3298 );3299 let fs = FunctionSignature::done(3300 FunctionSignature::add_param(3301 fs,3302 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3303 ),3304 true,3305 );3306 fs3307 }3308 };3309 cs3310 },3311 name: "getApproved",3312 mutability: SolidityMutability::View,3313 is_payable: false,3314 args: (<NamedArgument<uint256>>::new("tokenId"),),3315 result: <UnnamedArgument<address>>::default(),3316 },3317 SolidityFunction {3318 docs: &[" @dev Not implemented"],3319 selector_str: "isApprovedForAll(address,address)",3320 selector: u32::from_be_bytes(Self::IS_APPROVED_FOR_ALL),3321 custom_signature: {3322 const cs: FunctionSignature = {3323 {3324 let fs = FunctionSignature::new(3325 &&FunctionName::new("isApprovedForAll"),3326 );3327 let fs = FunctionSignature::done(3328 FunctionSignature::add_param(3329 FunctionSignature::add_param(3330 fs,3331 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3332 ),3333 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),3334 ),3335 true,3336 );3337 fs3338 }3339 };3340 cs3341 },3342 name: "isApprovedForAll",3343 mutability: SolidityMutability::View,3344 is_payable: false,3345 args: (3346 <NamedArgument<address>>::new("owner"),3347 <NamedArgument<address>>::new("operator"),3348 ),3349 result: <UnnamedArgument<address>>::default(),3350 },3351 ),3352 };3353 let mut out = ::evm_coder::types::string::new();3354 if "ERC721".starts_with("Inline") {3355 out.push_str("/// @dev inlined interface\n");3356 }3357 let _ = interface.format(is_impl, &mut out, tc);3358 tc.collect(out);3359 ERC721Events::generate_solidity_interface(tc, is_impl);3360 if is_impl {3361 tc.collect(3362 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"3363 .into(),3364 );3365 } else {3366 tc.collect(3367 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"3368 .into(),3369 );3370 }3371 }3372 }3373 impl<T> ::evm_coder::Call for ERC721Call<T> {3374 fn parse(3375 method_id: ::evm_coder::types::bytes4,3376 reader: &mut ::evm_coder::abi::AbiReader,3377 ) -> ::evm_coder::execution::Result<Option<Self>> {3378 use ::evm_coder::abi::AbiRead;3379 match method_id {3380 ::evm_coder::ERC165Call::INTERFACE_ID => {3381 return Ok(3382 ::evm_coder::ERC165Call::parse(method_id, reader)?3383 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),3384 );3385 }3386 Self::BALANCE_OF => {3387 return Ok(3388 Some(Self::BalanceOf {3389 owner: reader.abi_read()?,3390 }),3391 );3392 }3393 Self::OWNER_OF => {3394 return Ok(3395 Some(Self::OwnerOf {3396 token_id: reader.abi_read()?,3397 }),3398 );3399 }3400 Self::SAFE_TRANSFER_FROM_WITH_DATA => {3401 return Ok(3402 Some(Self::SafeTransferFromWithData {3403 _from: reader.abi_read()?,3404 _to: reader.abi_read()?,3405 _token_id: reader.abi_read()?,3406 _data: reader.abi_read()?,3407 }),3408 );3409 }3410 Self::SAFE_TRANSFER_FROM => {3411 return Ok(3412 Some(Self::SafeTransferFrom {3413 _from: reader.abi_read()?,3414 _to: reader.abi_read()?,3415 _token_id: reader.abi_read()?,3416 }),3417 );3418 }3419 Self::TRANSFER_FROM => {3420 return Ok(3421 Some(Self::TransferFrom {3422 from: reader.abi_read()?,3423 to: reader.abi_read()?,3424 token_id: reader.abi_read()?,3425 }),3426 );3427 }3428 Self::APPROVE => {3429 return Ok(3430 Some(Self::Approve {3431 approved: reader.abi_read()?,3432 token_id: reader.abi_read()?,3433 }),3434 );3435 }3436 Self::SET_APPROVAL_FOR_ALL => {3437 return Ok(3438 Some(Self::SetApprovalForAll {3439 _operator: reader.abi_read()?,3440 _approved: reader.abi_read()?,3441 }),3442 );3443 }3444 Self::GET_APPROVED => {3445 return Ok(3446 Some(Self::GetApproved {3447 _token_id: reader.abi_read()?,3448 }),3449 );3450 }3451 Self::IS_APPROVED_FOR_ALL => {3452 return Ok(3453 Some(Self::IsApprovedForAll {3454 _owner: reader.abi_read()?,3455 _operator: reader.abi_read()?,3456 }),3457 );3458 }3459 _ => {}3460 }3461 return Ok(None);3462 }3463 }3464 impl<T: Config> ERC721Call<T> {3465 /// Is this contract implements specified ERC165 selector3466 pub fn supports_interface(3467 this: &NonfungibleHandle<T>,3468 interface_id: ::evm_coder::types::bytes4,3469 ) -> bool {3470 interface_id != u32::to_be_bytes(0xffffff)3471 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID3472 || interface_id == Self::interface_id())3473 }3474 }3475 impl<T: Config> ::evm_coder::Weighted for ERC721Call<T> {3476 #[allow(unused_variables)]3477 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {3478 match self {3479 Self::ERC165Call(3480 ::evm_coder::ERC165Call::SupportsInterface { .. },3481 _,3482 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),3483 Self::BalanceOf { .. } => ().into(),3484 Self::OwnerOf { .. } => ().into(),3485 Self::SafeTransferFromWithData { .. } => ().into(),3486 Self::SafeTransferFrom { .. } => ().into(),3487 Self::TransferFrom { from, to, token_id } => {3488 (<SelfWeightOf<T>>::transfer_from()).into()3489 }3490 Self::Approve { approved, token_id } => {3491 (<SelfWeightOf<T>>::approve()).into()3492 }3493 Self::SetApprovalForAll { .. } => ().into(),3494 Self::GetApproved { .. } => ().into(),3495 Self::IsApprovedForAll { .. } => ().into(),3496 }3497 }3498 }3499 impl<T: Config> ::evm_coder::Callable<ERC721Call<T>> for NonfungibleHandle<T> {3500 #[allow(unreachable_code)]3501 fn call(3502 &mut self,3503 c: Msg<ERC721Call<T>>,3504 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {3505 use ::evm_coder::abi::AbiWrite;3506 match c.call {3507 ERC721Call::ERC165Call(3508 ::evm_coder::ERC165Call::SupportsInterface { interface_id },3509 _,3510 ) => {3511 let mut writer = ::evm_coder::abi::AbiWriter::default();3512 writer3513 .bool(&<ERC721Call<T>>::supports_interface(self, interface_id));3514 return Ok(writer.into());3515 }3516 _ => {}3517 }3518 let mut writer = ::evm_coder::abi::AbiWriter::default();3519 match c.call {3520 ERC721Call::BalanceOf { owner } => {3521 let result = self.balance_of(owner)?;3522 (&result).to_result()3523 }3524 ERC721Call::OwnerOf { token_id } => {3525 let result = self.owner_of(token_id)?;3526 (&result).to_result()3527 }3528 ERC721Call::SafeTransferFromWithData {3529 _from,3530 _to,3531 _token_id,3532 _data,3533 } => {3534 let result = self3535 .safe_transfer_from_with_data(_from, _to, _token_id, _data)?;3536 (&result).to_result()3537 }3538 ERC721Call::SafeTransferFrom { _from, _to, _token_id } => {3539 let result = self.safe_transfer_from(_from, _to, _token_id)?;3540 (&result).to_result()3541 }3542 ERC721Call::TransferFrom { from, to, token_id } => {3543 let result = self3544 .transfer_from(c.caller.clone(), from, to, token_id)?;3545 (&result).to_result()3546 }3547 ERC721Call::Approve { approved, token_id } => {3548 let result = self.approve(c.caller.clone(), approved, token_id)?;3549 (&result).to_result()3550 }3551 ERC721Call::SetApprovalForAll { _operator, _approved } => {3552 let result = self3553 .set_approval_for_all(c.caller.clone(), _operator, _approved)?;3554 (&result).to_result()3555 }3556 ERC721Call::GetApproved { _token_id } => {3557 let result = self.get_approved(_token_id)?;3558 (&result).to_result()3559 }3560 ERC721Call::IsApprovedForAll { _owner, _operator } => {3561 let result = self.is_approved_for_all(_owner, _operator)?;3562 (&result).to_result()3563 }3564 _ => {3565 Err(3566 ::evm_coder::execution::Error::from("method is not available")3567 .into(),3568 )3569 }3570 }3571 }3572 }3573 /// @title ERC721 Token that can be irreversibly burned (destroyed).3574 impl<T: Config> NonfungibleHandle<T> {3575 /// @notice Burns a specific ERC721 token.3576 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized3577 /// operator of the current owner.3578 /// @param tokenId The NFT to approve3579 fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {3580 let caller = T::CrossAccountId::from_eth(caller);3581 let token = token_id.try_into()?;3582 <Pallet<T>>::burn(self, &caller, token).map_err(dispatch_to_evm::<T>)?;3583 Ok(())3584 }3585 }3586 /// @title ERC721 Token that can be irreversibly burned (destroyed).3587 pub enum ERC721BurnableCall<T> {3588 /// Inherited method3589 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),3590 /// @notice Burns a specific ERC721 token.3591 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized3592 /// operator of the current owner.3593 /// @param tokenId The NFT to approve3594 #[allow(missing_docs)]3595 Burn { token_id: uint256 },3596 }3597 #[automatically_derived]3598 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721BurnableCall<T> {3599 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {3600 match self {3601 ERC721BurnableCall::ERC165Call(__self_0, __self_1) => {3602 ::core::fmt::Formatter::debug_tuple_field2_finish(3603 f,3604 "ERC165Call",3605 &__self_0,3606 &__self_1,3607 )3608 }3609 ERC721BurnableCall::Burn { token_id: __self_0 } => {3610 ::core::fmt::Formatter::debug_struct_field1_finish(3611 f,3612 "Burn",3613 "token_id",3614 &__self_0,3615 )3616 }3617 }3618 }3619 }3620 impl<T> ERC721BurnableCall<T> {3621 const BURN_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {3622 {3623 let fs = FunctionSignature::new(&&FunctionName::new("burn"));3624 let fs = FunctionSignature::done(3625 FunctionSignature::add_param(3626 fs,3627 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3628 ),3629 true,3630 );3631 fs3632 }3633 };3634 ///burn(uint256)3635 const BURN: ::evm_coder::types::bytes4 = {3636 let a = ::evm_coder::sha3_const::Keccak256::new()3637 .update_with_size(3638 &Self::BURN_SIGNATURE.signature,3639 Self::BURN_SIGNATURE.signature_len,3640 )3641 .finalize();3642 [a[0], a[1], a[2], a[3]]3643 };3644 /// Return this call ERC165 selector3645 pub fn interface_id() -> ::evm_coder::types::bytes4 {3646 let mut interface_id = 0;3647 interface_id ^= u32::from_be_bytes(Self::BURN);3648 u32::to_be_bytes(interface_id)3649 }3650 /// Generate solidity definitions for methods described in this interface3651 pub fn generate_solidity_interface(3652 tc: &evm_coder::solidity::TypeCollector,3653 is_impl: bool,3654 ) {3655 use evm_coder::solidity::*;3656 use core::fmt::Write;3657 let interface = SolidityInterface {3658 docs: &[3659 " @title ERC721 Token that can be irreversibly burned (destroyed).",3660 ],3661 name: "ERC721Burnable",3662 selector: Self::interface_id(),3663 is: &["Dummy", "ERC165"],3664 functions: (3665 SolidityFunction {3666 docs: &[3667 " @notice Burns a specific ERC721 token.",3668 " @dev Throws unless `msg.sender` is the current NFT owner, or an authorized",3669 " operator of the current owner.",3670 " @param tokenId The NFT to approve",3671 ],3672 selector_str: "burn(uint256)",3673 selector: u32::from_be_bytes(Self::BURN),3674 custom_signature: {3675 const cs: FunctionSignature = {3676 {3677 let fs = FunctionSignature::new(3678 &&FunctionName::new("burn"),3679 );3680 let fs = FunctionSignature::done(3681 FunctionSignature::add_param(3682 fs,3683 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),3684 ),3685 true,3686 );3687 fs3688 }3689 };3690 cs3691 },3692 name: "burn",3693 mutability: SolidityMutability::Mutable,3694 is_payable: false,3695 args: (<NamedArgument<uint256>>::new("tokenId"),),3696 result: <UnnamedArgument<void>>::default(),3697 },3698 ),3699 };3700 let mut out = ::evm_coder::types::string::new();3701 if "ERC721Burnable".starts_with("Inline") {3702 out.push_str("/// @dev inlined interface\n");3703 }3704 let _ = interface.format(is_impl, &mut out, tc);3705 tc.collect(out);3706 if is_impl {3707 tc.collect(3708 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"3709 .into(),3710 );3711 } else {3712 tc.collect(3713 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"3714 .into(),3715 );3716 }3717 }3718 }3719 impl<T> ::evm_coder::Call for ERC721BurnableCall<T> {3720 fn parse(3721 method_id: ::evm_coder::types::bytes4,3722 reader: &mut ::evm_coder::abi::AbiReader,3723 ) -> ::evm_coder::execution::Result<Option<Self>> {3724 use ::evm_coder::abi::AbiRead;3725 match method_id {3726 ::evm_coder::ERC165Call::INTERFACE_ID => {3727 return Ok(3728 ::evm_coder::ERC165Call::parse(method_id, reader)?3729 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),3730 );3731 }3732 Self::BURN => {3733 return Ok(3734 Some(Self::Burn {3735 token_id: reader.abi_read()?,3736 }),3737 );3738 }3739 _ => {}3740 }3741 return Ok(None);3742 }3743 }3744 impl<T: Config> ERC721BurnableCall<T> {3745 /// Is this contract implements specified ERC165 selector3746 pub fn supports_interface(3747 this: &NonfungibleHandle<T>,3748 interface_id: ::evm_coder::types::bytes4,3749 ) -> bool {3750 interface_id != u32::to_be_bytes(0xffffff)3751 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID3752 || interface_id == Self::interface_id())3753 }3754 }3755 impl<T: Config> ::evm_coder::Weighted for ERC721BurnableCall<T> {3756 #[allow(unused_variables)]3757 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {3758 match self {3759 Self::ERC165Call(3760 ::evm_coder::ERC165Call::SupportsInterface { .. },3761 _,3762 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),3763 Self::Burn { token_id } => (<SelfWeightOf<T>>::burn_item()).into(),3764 }3765 }3766 }3767 impl<T: Config> ::evm_coder::Callable<ERC721BurnableCall<T>>3768 for NonfungibleHandle<T> {3769 #[allow(unreachable_code)]3770 fn call(3771 &mut self,3772 c: Msg<ERC721BurnableCall<T>>,3773 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {3774 use ::evm_coder::abi::AbiWrite;3775 match c.call {3776 ERC721BurnableCall::ERC165Call(3777 ::evm_coder::ERC165Call::SupportsInterface { interface_id },3778 _,3779 ) => {3780 let mut writer = ::evm_coder::abi::AbiWriter::default();3781 writer3782 .bool(3783 &<ERC721BurnableCall<3784 T,3785 >>::supports_interface(self, interface_id),3786 );3787 return Ok(writer.into());3788 }3789 _ => {}3790 }3791 let mut writer = ::evm_coder::abi::AbiWriter::default();3792 match c.call {3793 ERC721BurnableCall::Burn { token_id } => {3794 let result = self.burn(c.caller.clone(), token_id)?;3795 (&result).to_result()3796 }3797 _ => {3798 Err(3799 ::evm_coder::execution::Error::from("method is not available")3800 .into(),3801 )3802 }3803 }3804 }3805 }3806 /// @title ERC721 minting logic.3807 impl<T: Config> NonfungibleHandle<T> {3808 fn minting_finished(&self) -> Result<bool> {3809 Ok(false)3810 }3811 /// @notice Function to mint token.3812 /// @dev `tokenId` should be obtained with `nextTokenId` method,3813 /// unlike standard, you can't specify it manually3814 /// @param to The new owner3815 /// @param tokenId ID of the minted NFT3816 fn mint(3817 &mut self,3818 caller: caller,3819 to: address,3820 token_id: uint256,3821 ) -> Result<bool> {3822 let caller = T::CrossAccountId::from_eth(caller);3823 let to = T::CrossAccountId::from_eth(to);3824 let token_id: u32 = token_id.try_into()?;3825 let budget = self3826 .recorder3827 .weight_calls_budget(<StructureWeight<T>>::find_parent());3828 if <TokensMinted<T>>::get(self.id).checked_add(1).ok_or("item id overflow")?3829 != token_id3830 {3831 return Err("item id should be next".into());3832 }3833 <Pallet<3834 T,3835 >>::create_item(3836 self,3837 &caller,3838 CreateItemData::<T> {3839 properties: BoundedVec::default(),3840 owner: to,3841 },3842 &budget,3843 )3844 .map_err(dispatch_to_evm::<T>)?;3845 Ok(true)3846 }3847 /// @notice Function to mint token with the given tokenUri.3848 /// @dev `tokenId` should be obtained with `nextTokenId` method,3849 /// unlike standard, you can't specify it manually3850 /// @param to The new owner3851 /// @param tokenId ID of the minted NFT3852 /// @param tokenUri Token URI that would be stored in the NFT properties3853 fn mint_with_token_uri(3854 &mut self,3855 caller: caller,3856 to: address,3857 token_id: uint256,3858 token_uri: string,3859 ) -> Result<bool> {3860 let key = key::url();3861 let permission = get_token_permission::<T>(self.id, &key)?;3862 if !permission.collection_admin {3863 return Err("Operation is not allowed".into());3864 }3865 let caller = T::CrossAccountId::from_eth(caller);3866 let to = T::CrossAccountId::from_eth(to);3867 let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;3868 let budget = self3869 .recorder3870 .weight_calls_budget(<StructureWeight<T>>::find_parent());3871 if <TokensMinted<T>>::get(self.id).checked_add(1).ok_or("item id overflow")?3872 != token_id3873 {3874 return Err("item id should be next".into());3875 }3876 let mut properties = CollectionPropertiesVec::default();3877 properties3878 .try_push(Property {3879 key,3880 value: token_uri3881 .into_bytes()3882 .try_into()3883 .map_err(|_| "token uri is too long")?,3884 })3885 .map_err(|e| Error::Revert({3886 let res = ::alloc::fmt::format(3887 ::core::fmt::Arguments::new_v1(3888 &["Can\'t add property: "],3889 &[::core::fmt::ArgumentV1::new_debug(&e)],3890 ),3891 );3892 res3893 }))?;3894 <Pallet<3895 T,3896 >>::create_item(3897 self,3898 &caller,3899 CreateItemData::<T> {3900 properties,3901 owner: to,3902 },3903 &budget,3904 )3905 .map_err(dispatch_to_evm::<T>)?;3906 Ok(true)3907 }3908 /// @dev Not implemented3909 fn finish_minting(&mut self, _caller: caller) -> Result<bool> {3910 Err("not implementable".into())3911 }3912 }3913 /// @title ERC721 minting logic.3914 pub enum ERC721MintableCall<T> {3915 /// Inherited method3916 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),3917 MintingFinished,3918 /// @notice Function to mint token.3919 /// @dev `tokenId` should be obtained with `nextTokenId` method,3920 /// unlike standard, you can't specify it manually3921 /// @param to The new owner3922 /// @param tokenId ID of the minted NFT3923 #[allow(missing_docs)]3924 Mint { to: address, token_id: uint256 },3925 /// @notice Function to mint token with the given tokenUri.3926 /// @dev `tokenId` should be obtained with `nextTokenId` method,3927 /// unlike standard, you can't specify it manually3928 /// @param to The new owner3929 /// @param tokenId ID of the minted NFT3930 /// @param tokenUri Token URI that would be stored in the NFT properties3931 #[allow(missing_docs)]3932 MintWithTokenUri { to: address, token_id: uint256, token_uri: string },3933 FinishMinting,3934 }3935 #[automatically_derived]3936 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721MintableCall<T> {3937 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {3938 match self {3939 ERC721MintableCall::ERC165Call(__self_0, __self_1) => {3940 ::core::fmt::Formatter::debug_tuple_field2_finish(3941 f,3942 "ERC165Call",3943 &__self_0,3944 &__self_1,3945 )3946 }3947 ERC721MintableCall::MintingFinished => {3948 ::core::fmt::Formatter::write_str(f, "MintingFinished")3949 }3950 ERC721MintableCall::Mint { to: __self_0, token_id: __self_1 } => {3951 ::core::fmt::Formatter::debug_struct_field2_finish(3952 f,3953 "Mint",3954 "to",3955 &__self_0,3956 "token_id",3957 &__self_1,3958 )3959 }3960 ERC721MintableCall::MintWithTokenUri {3961 to: __self_0,3962 token_id: __self_1,3963 token_uri: __self_2,3964 } => {3965 ::core::fmt::Formatter::debug_struct_field3_finish(3966 f,3967 "MintWithTokenUri",3968 "to",3969 &__self_0,3970 "token_id",3971 &__self_1,3972 "token_uri",3973 &__self_2,3974 )3975 }3976 ERC721MintableCall::FinishMinting => {3977 ::core::fmt::Formatter::write_str(f, "FinishMinting")3978 }3979 }3980 }3981 }3982 impl<T> ERC721MintableCall<T> {3983 const MINTING_FINISHED_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {3984 {3985 let fs = FunctionSignature::new(&&FunctionName::new("mintingFinished"));3986 let fs = FunctionSignature::done(fs, false);3987 fs3988 }3989 };3990 ///mintingFinished()3991 const MINTING_FINISHED: ::evm_coder::types::bytes4 = {3992 let a = ::evm_coder::sha3_const::Keccak256::new()3993 .update_with_size(3994 &Self::MINTING_FINISHED_SIGNATURE.signature,3995 Self::MINTING_FINISHED_SIGNATURE.signature_len,3996 )3997 .finalize();3998 [a[0], a[1], a[2], a[3]]3999 };4000 const MINT_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4001 {4002 let fs = FunctionSignature::new(&&FunctionName::new("mint"));4003 let fs = FunctionSignature::done(4004 FunctionSignature::add_param(4005 FunctionSignature::add_param(4006 fs,4007 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),4008 ),4009 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4010 ),4011 true,4012 );4013 fs4014 }4015 };4016 ///mint(address,uint256)4017 const MINT: ::evm_coder::types::bytes4 = {4018 let a = ::evm_coder::sha3_const::Keccak256::new()4019 .update_with_size(4020 &Self::MINT_SIGNATURE.signature,4021 Self::MINT_SIGNATURE.signature_len,4022 )4023 .finalize();4024 [a[0], a[1], a[2], a[3]]4025 };4026 const MINT_WITH_TOKEN_URI_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4027 {4028 let fs = FunctionSignature::new(&&FunctionName::new("mintWithTokenURI"));4029 let fs = FunctionSignature::done(4030 FunctionSignature::add_param(4031 FunctionSignature::add_param(4032 FunctionSignature::add_param(4033 fs,4034 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),4035 ),4036 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4037 ),4038 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),4039 ),4040 true,4041 );4042 fs4043 }4044 };4045 ///mintWithTokenURI(address,uint256,string)4046 const MINT_WITH_TOKEN_URI: ::evm_coder::types::bytes4 = {4047 let a = ::evm_coder::sha3_const::Keccak256::new()4048 .update_with_size(4049 &Self::MINT_WITH_TOKEN_URI_SIGNATURE.signature,4050 Self::MINT_WITH_TOKEN_URI_SIGNATURE.signature_len,4051 )4052 .finalize();4053 [a[0], a[1], a[2], a[3]]4054 };4055 const FINISH_MINTING_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4056 {4057 let fs = FunctionSignature::new(&&FunctionName::new("finishMinting"));4058 let fs = FunctionSignature::done(fs, false);4059 fs4060 }4061 };4062 ///finishMinting()4063 const FINISH_MINTING: ::evm_coder::types::bytes4 = {4064 let a = ::evm_coder::sha3_const::Keccak256::new()4065 .update_with_size(4066 &Self::FINISH_MINTING_SIGNATURE.signature,4067 Self::FINISH_MINTING_SIGNATURE.signature_len,4068 )4069 .finalize();4070 [a[0], a[1], a[2], a[3]]4071 };4072 /// Return this call ERC165 selector4073 pub fn interface_id() -> ::evm_coder::types::bytes4 {4074 let mut interface_id = 0;4075 interface_id ^= u32::from_be_bytes(Self::MINTING_FINISHED);4076 interface_id ^= u32::from_be_bytes(Self::MINT);4077 interface_id ^= u32::from_be_bytes(Self::MINT_WITH_TOKEN_URI);4078 interface_id ^= u32::from_be_bytes(Self::FINISH_MINTING);4079 u32::to_be_bytes(interface_id)4080 }4081 /// Generate solidity definitions for methods described in this interface4082 pub fn generate_solidity_interface(4083 tc: &evm_coder::solidity::TypeCollector,4084 is_impl: bool,4085 ) {4086 use evm_coder::solidity::*;4087 use core::fmt::Write;4088 let interface = SolidityInterface {4089 docs: &[" @title ERC721 minting logic."],4090 name: "ERC721Mintable",4091 selector: Self::interface_id(),4092 is: &["Dummy", "ERC165", "ERC721MintableEvents"],4093 functions: (4094 SolidityFunction {4095 docs: &[],4096 selector_str: "mintingFinished()",4097 selector: u32::from_be_bytes(Self::MINTING_FINISHED),4098 custom_signature: {4099 const cs: FunctionSignature = {4100 {4101 let fs = FunctionSignature::new(4102 &&FunctionName::new("mintingFinished"),4103 );4104 let fs = FunctionSignature::done(fs, false);4105 fs4106 }4107 };4108 cs4109 },4110 name: "mintingFinished",4111 mutability: SolidityMutability::View,4112 is_payable: false,4113 args: (),4114 result: <UnnamedArgument<bool>>::default(),4115 },4116 SolidityFunction {4117 docs: &[4118 " @notice Function to mint token.",4119 " @dev `tokenId` should be obtained with `nextTokenId` method,",4120 " unlike standard, you can't specify it manually",4121 " @param to The new owner",4122 " @param tokenId ID of the minted NFT",4123 ],4124 selector_str: "mint(address,uint256)",4125 selector: u32::from_be_bytes(Self::MINT),4126 custom_signature: {4127 const cs: FunctionSignature = {4128 {4129 let fs = FunctionSignature::new(4130 &&FunctionName::new("mint"),4131 );4132 let fs = FunctionSignature::done(4133 FunctionSignature::add_param(4134 FunctionSignature::add_param(4135 fs,4136 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),4137 ),4138 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4139 ),4140 true,4141 );4142 fs4143 }4144 };4145 cs4146 },4147 name: "mint",4148 mutability: SolidityMutability::Mutable,4149 is_payable: false,4150 args: (4151 <NamedArgument<address>>::new("to"),4152 <NamedArgument<uint256>>::new("tokenId"),4153 ),4154 result: <UnnamedArgument<bool>>::default(),4155 },4156 SolidityFunction {4157 docs: &[4158 " @notice Function to mint token with the given tokenUri.",4159 " @dev `tokenId` should be obtained with `nextTokenId` method,",4160 " unlike standard, you can't specify it manually",4161 " @param to The new owner",4162 " @param tokenId ID of the minted NFT",4163 " @param tokenUri Token URI that would be stored in the NFT properties",4164 ],4165 selector_str: "mintWithTokenURI(address,uint256,string)",4166 selector: u32::from_be_bytes(Self::MINT_WITH_TOKEN_URI),4167 custom_signature: {4168 const cs: FunctionSignature = {4169 {4170 let fs = FunctionSignature::new(4171 &&FunctionName::new("mintWithTokenURI"),4172 );4173 let fs = FunctionSignature::done(4174 FunctionSignature::add_param(4175 FunctionSignature::add_param(4176 FunctionSignature::add_param(4177 fs,4178 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),4179 ),4180 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4181 ),4182 (<string>::SIGNATURE, <string>::SIGNATURE_LEN),4183 ),4184 true,4185 );4186 fs4187 }4188 };4189 cs4190 },4191 name: "mintWithTokenURI",4192 mutability: SolidityMutability::Mutable,4193 is_payable: false,4194 args: (4195 <NamedArgument<address>>::new("to"),4196 <NamedArgument<uint256>>::new("tokenId"),4197 <NamedArgument<string>>::new("tokenUri"),4198 ),4199 result: <UnnamedArgument<bool>>::default(),4200 },4201 SolidityFunction {4202 docs: &[" @dev Not implemented"],4203 selector_str: "finishMinting()",4204 selector: u32::from_be_bytes(Self::FINISH_MINTING),4205 custom_signature: {4206 const cs: FunctionSignature = {4207 {4208 let fs = FunctionSignature::new(4209 &&FunctionName::new("finishMinting"),4210 );4211 let fs = FunctionSignature::done(fs, false);4212 fs4213 }4214 };4215 cs4216 },4217 name: "finishMinting",4218 mutability: SolidityMutability::Mutable,4219 is_payable: false,4220 args: (),4221 result: <UnnamedArgument<bool>>::default(),4222 },4223 ),4224 };4225 let mut out = ::evm_coder::types::string::new();4226 if "ERC721Mintable".starts_with("Inline") {4227 out.push_str("/// @dev inlined interface\n");4228 }4229 let _ = interface.format(is_impl, &mut out, tc);4230 tc.collect(out);4231 ERC721MintableEvents::generate_solidity_interface(tc, is_impl);4232 if is_impl {4233 tc.collect(4234 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"4235 .into(),4236 );4237 } else {4238 tc.collect(4239 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"4240 .into(),4241 );4242 }4243 }4244 }4245 impl<T> ::evm_coder::Call for ERC721MintableCall<T> {4246 fn parse(4247 method_id: ::evm_coder::types::bytes4,4248 reader: &mut ::evm_coder::abi::AbiReader,4249 ) -> ::evm_coder::execution::Result<Option<Self>> {4250 use ::evm_coder::abi::AbiRead;4251 match method_id {4252 ::evm_coder::ERC165Call::INTERFACE_ID => {4253 return Ok(4254 ::evm_coder::ERC165Call::parse(method_id, reader)?4255 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),4256 );4257 }4258 Self::MINTING_FINISHED => return Ok(Some(Self::MintingFinished)),4259 Self::MINT => {4260 return Ok(4261 Some(Self::Mint {4262 to: reader.abi_read()?,4263 token_id: reader.abi_read()?,4264 }),4265 );4266 }4267 Self::MINT_WITH_TOKEN_URI => {4268 return Ok(4269 Some(Self::MintWithTokenUri {4270 to: reader.abi_read()?,4271 token_id: reader.abi_read()?,4272 token_uri: reader.abi_read()?,4273 }),4274 );4275 }4276 Self::FINISH_MINTING => return Ok(Some(Self::FinishMinting)),4277 _ => {}4278 }4279 return Ok(None);4280 }4281 }4282 impl<T: Config> ERC721MintableCall<T> {4283 /// Is this contract implements specified ERC165 selector4284 pub fn supports_interface(4285 this: &NonfungibleHandle<T>,4286 interface_id: ::evm_coder::types::bytes4,4287 ) -> bool {4288 interface_id != u32::to_be_bytes(0xffffff)4289 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID4290 || interface_id == Self::interface_id())4291 }4292 }4293 impl<T: Config> ::evm_coder::Weighted for ERC721MintableCall<T> {4294 #[allow(unused_variables)]4295 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {4296 match self {4297 Self::ERC165Call(4298 ::evm_coder::ERC165Call::SupportsInterface { .. },4299 _,4300 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),4301 Self::MintingFinished => ().into(),4302 Self::Mint { to, token_id } => (<SelfWeightOf<T>>::create_item()).into(),4303 Self::MintWithTokenUri { to, token_id, token_uri } => {4304 (<SelfWeightOf<T>>::create_item()).into()4305 }4306 Self::FinishMinting => ().into(),4307 }4308 }4309 }4310 impl<T: Config> ::evm_coder::Callable<ERC721MintableCall<T>>4311 for NonfungibleHandle<T> {4312 #[allow(unreachable_code)]4313 fn call(4314 &mut self,4315 c: Msg<ERC721MintableCall<T>>,4316 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {4317 use ::evm_coder::abi::AbiWrite;4318 match c.call {4319 ERC721MintableCall::ERC165Call(4320 ::evm_coder::ERC165Call::SupportsInterface { interface_id },4321 _,4322 ) => {4323 let mut writer = ::evm_coder::abi::AbiWriter::default();4324 writer4325 .bool(4326 &<ERC721MintableCall<4327 T,4328 >>::supports_interface(self, interface_id),4329 );4330 return Ok(writer.into());4331 }4332 _ => {}4333 }4334 let mut writer = ::evm_coder::abi::AbiWriter::default();4335 match c.call {4336 ERC721MintableCall::MintingFinished => {4337 let result = self.minting_finished()?;4338 (&result).to_result()4339 }4340 ERC721MintableCall::Mint { to, token_id } => {4341 let result = self.mint(c.caller.clone(), to, token_id)?;4342 (&result).to_result()4343 }4344 ERC721MintableCall::MintWithTokenUri { to, token_id, token_uri } => {4345 let result = self4346 .mint_with_token_uri(c.caller.clone(), to, token_id, token_uri)?;4347 (&result).to_result()4348 }4349 ERC721MintableCall::FinishMinting => {4350 let result = self.finish_minting(c.caller.clone())?;4351 (&result).to_result()4352 }4353 _ => {4354 Err(4355 ::evm_coder::execution::Error::from("method is not available")4356 .into(),4357 )4358 }4359 }4360 }4361 }4362 fn get_token_property<T: Config>(4363 collection: &CollectionHandle<T>,4364 token_id: u32,4365 key: &up_data_structs::PropertyKey,4366 ) -> Result<string> {4367 collection.consume_store_reads(1)?;4368 let properties = <TokenProperties<T>>::try_get((collection.id, token_id))4369 .map_err(|_| Error::Revert("Token properties not found".into()))?;4370 if let Some(property) = properties.get(key) {4371 return Ok(string::from_utf8_lossy(property).into());4372 }4373 Err("Property tokenURI not found".into())4374 }4375 fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {4376 if let Some(shema_name)4377 = pallet_common::Pallet::<4378 T,4379 >::get_collection_property(collection_id, &key::schema_name()) {4380 let shema_name = shema_name.into_inner();4381 shema_name == property_value::ERC721_METADATA4382 } else {4383 false4384 }4385 }4386 fn get_token_permission<T: Config>(4387 collection_id: CollectionId,4388 key: &PropertyKey,4389 ) -> Result<PropertyPermission> {4390 let token_property_permissions = CollectionPropertyPermissions::<4391 T,4392 >::try_get(collection_id)4393 .map_err(|_| Error::Revert("No permissions for collection".into()))?;4394 let a = token_property_permissions4395 .get(key)4396 .map(Clone::clone)4397 .ok_or_else(|| {4398 let key = string::from_utf8(key.clone().into_inner())4399 .unwrap_or_default();4400 Error::Revert({4401 let res = ::alloc::fmt::format(4402 ::core::fmt::Arguments::new_v1(4403 &["No permission for key "],4404 &[::core::fmt::ArgumentV1::new_display(&key)],4405 ),4406 );4407 res4408 })4409 })?;4410 Ok(a)4411 }4412 fn has_token_permission<T: Config>(4413 collection_id: CollectionId,4414 key: &PropertyKey,4415 ) -> bool {4416 if let Ok(token_property_permissions)4417 = CollectionPropertyPermissions::<T>::try_get(collection_id) {4418 return token_property_permissions.contains_key(key);4419 }4420 false4421 }4422 /// @title Unique extensions for ERC721.4423 impl<T: Config> NonfungibleHandle<T>4424 where4425 T::AccountId: From<[u8; 32]>,4426 {4427 /// @notice Set or reaffirm the approved address for an NFT4428 /// @dev The zero address indicates there is no approved address.4429 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized4430 /// operator of the current owner.4431 /// @param approved The new substrate address approved NFT controller4432 /// @param tokenId The NFT to approve4433 fn approve_cross(4434 &mut self,4435 caller: caller,4436 approved: (address, uint256),4437 token_id: uint256,4438 ) -> Result<void> {4439 let caller = T::CrossAccountId::from_eth(caller);4440 let approved = convert_tuple_to_cross_account::<T>(approved)?;4441 let token = token_id.try_into()?;4442 <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))4443 .map_err(dispatch_to_evm::<T>)?;4444 Ok(())4445 }4446 /// @notice Transfer ownership of an NFT4447 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`4448 /// is the zero address. Throws if `tokenId` is not a valid NFT.4449 /// @param to The new owner4450 /// @param tokenId The NFT to transfer4451 fn transfer(4452 &mut self,4453 caller: caller,4454 to: address,4455 token_id: uint256,4456 ) -> Result<void> {4457 let caller = T::CrossAccountId::from_eth(caller);4458 let to = T::CrossAccountId::from_eth(to);4459 let token = token_id.try_into()?;4460 let budget = self4461 .recorder4462 .weight_calls_budget(<StructureWeight<T>>::find_parent());4463 <Pallet<T>>::transfer(self, &caller, &to, token, &budget)4464 .map_err(dispatch_to_evm::<T>)?;4465 Ok(())4466 }4467 /// @notice Transfer ownership of an NFT from cross account address to cross account address4468 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`4469 /// is the zero address. Throws if `tokenId` is not a valid NFT.4470 /// @param from Cross acccount address of current owner4471 /// @param to Cross acccount address of new owner4472 /// @param tokenId The NFT to transfer4473 fn transfer_from_cross(4474 &mut self,4475 caller: caller,4476 from: EthCrossAccount,4477 to: EthCrossAccount,4478 token_id: uint256,4479 ) -> Result<void> {4480 let caller = T::CrossAccountId::from_eth(caller);4481 let from = from.into_sub_cross_account::<T>()?;4482 let to = to.into_sub_cross_account::<T>()?;4483 let token_id = token_id.try_into()?;4484 let budget = self4485 .recorder4486 .weight_calls_budget(<StructureWeight<T>>::find_parent());4487 Pallet::<T>::transfer_from(self, &caller, &from, &to, token_id, &budget)4488 .map_err(dispatch_to_evm::<T>)?;4489 Ok(())4490 }4491 /// @notice Burns a specific ERC721 token.4492 /// @dev Throws unless `msg.sender` is the current owner or an authorized4493 /// operator for this NFT. Throws if `from` is not the current owner. Throws4494 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.4495 /// @param from The current owner of the NFT4496 /// @param tokenId The NFT to transfer4497 fn burn_from(4498 &mut self,4499 caller: caller,4500 from: address,4501 token_id: uint256,4502 ) -> Result<void> {4503 let caller = T::CrossAccountId::from_eth(caller);4504 let from = T::CrossAccountId::from_eth(from);4505 let token = token_id.try_into()?;4506 let budget = self4507 .recorder4508 .weight_calls_budget(<StructureWeight<T>>::find_parent());4509 <Pallet<T>>::burn_from(self, &caller, &from, token, &budget)4510 .map_err(dispatch_to_evm::<T>)?;4511 Ok(())4512 }4513 /// @notice Burns a specific ERC721 token.4514 /// @dev Throws unless `msg.sender` is the current owner or an authorized4515 /// operator for this NFT. Throws if `from` is not the current owner. Throws4516 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.4517 /// @param from The current owner of the NFT4518 /// @param tokenId The NFT to transfer4519 fn burn_from_cross(4520 &mut self,4521 caller: caller,4522 from: (address, uint256),4523 token_id: uint256,4524 ) -> Result<void> {4525 let caller = T::CrossAccountId::from_eth(caller);4526 let from = convert_tuple_to_cross_account::<T>(from)?;4527 let token = token_id.try_into()?;4528 let budget = self4529 .recorder4530 .weight_calls_budget(<StructureWeight<T>>::find_parent());4531 <Pallet<T>>::burn_from(self, &caller, &from, token, &budget)4532 .map_err(dispatch_to_evm::<T>)?;4533 Ok(())4534 }4535 /// @notice Returns next free NFT ID.4536 fn next_token_id(&self) -> Result<uint256> {4537 self.consume_store_reads(1)?;4538 Ok(4539 <TokensMinted<T>>::get(self.id)4540 .checked_add(1)4541 .ok_or("item id overflow")?4542 .into(),4543 )4544 }4545 /// @notice Function to mint multiple tokens.4546 /// @dev `tokenIds` should be an array of consecutive numbers and first number4547 /// should be obtained with `nextTokenId` method4548 /// @param to The new owner4549 /// @param tokenIds IDs of the minted NFTs4550 fn mint_bulk(4551 &mut self,4552 caller: caller,4553 to: address,4554 token_ids: Vec<uint256>,4555 ) -> Result<bool> {4556 let caller = T::CrossAccountId::from_eth(caller);4557 let to = T::CrossAccountId::from_eth(to);4558 let mut expected_index = <TokensMinted<T>>::get(self.id)4559 .checked_add(1)4560 .ok_or("item id overflow")?;4561 let budget = self4562 .recorder4563 .weight_calls_budget(<StructureWeight<T>>::find_parent());4564 let total_tokens = token_ids.len();4565 for id in token_ids.into_iter() {4566 let id: u32 = id.try_into().map_err(|_| "token id overflow")?;4567 if id != expected_index {4568 return Err("item id should be next".into());4569 }4570 expected_index = expected_index4571 .checked_add(1)4572 .ok_or("item id overflow")?;4573 }4574 let data = (0..total_tokens)4575 .map(|_| CreateItemData::<T> {4576 properties: BoundedVec::default(),4577 owner: to.clone(),4578 })4579 .collect();4580 <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)4581 .map_err(dispatch_to_evm::<T>)?;4582 Ok(true)4583 }4584 /// @notice Function to mint multiple tokens with the given tokenUris.4585 /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive4586 /// numbers and first number should be obtained with `nextTokenId` method4587 /// @param to The new owner4588 /// @param tokens array of pairs of token ID and token URI for minted tokens4589 fn mint_bulk_with_token_uri(4590 &mut self,4591 caller: caller,4592 to: address,4593 tokens: Vec<(uint256, string)>,4594 ) -> Result<bool> {4595 let key = key::url();4596 let caller = T::CrossAccountId::from_eth(caller);4597 let to = T::CrossAccountId::from_eth(to);4598 let mut expected_index = <TokensMinted<T>>::get(self.id)4599 .checked_add(1)4600 .ok_or("item id overflow")?;4601 let budget = self4602 .recorder4603 .weight_calls_budget(<StructureWeight<T>>::find_parent());4604 let mut data = Vec::with_capacity(tokens.len());4605 for (id, token_uri) in tokens {4606 let id: u32 = id.try_into().map_err(|_| "token id overflow")?;4607 if id != expected_index {4608 return Err("item id should be next".into());4609 }4610 expected_index = expected_index4611 .checked_add(1)4612 .ok_or("item id overflow")?;4613 let mut properties = CollectionPropertiesVec::default();4614 properties4615 .try_push(Property {4616 key: key.clone(),4617 value: token_uri4618 .into_bytes()4619 .try_into()4620 .map_err(|_| "token uri is too long")?,4621 })4622 .map_err(|e| Error::Revert({4623 let res = ::alloc::fmt::format(4624 ::core::fmt::Arguments::new_v1(4625 &["Can\'t add property: "],4626 &[::core::fmt::ArgumentV1::new_debug(&e)],4627 ),4628 );4629 res4630 }))?;4631 data.push(CreateItemData::<T> {4632 properties,4633 owner: to.clone(),4634 });4635 }4636 <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)4637 .map_err(dispatch_to_evm::<T>)?;4638 Ok(true)4639 }4640 }4641 /// @title Unique extensions for ERC721.4642 pub enum ERC721UniqueExtensionsCall<T> {4643 /// Inherited method4644 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),4645 /// @notice Set or reaffirm the approved address for an NFT4646 /// @dev The zero address indicates there is no approved address.4647 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized4648 /// operator of the current owner.4649 /// @param approved The new substrate address approved NFT controller4650 /// @param tokenId The NFT to approve4651 #[allow(missing_docs)]4652 ApproveCross { approved: (address, uint256), token_id: uint256 },4653 /// @notice Transfer ownership of an NFT4654 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`4655 /// is the zero address. Throws if `tokenId` is not a valid NFT.4656 /// @param to The new owner4657 /// @param tokenId The NFT to transfer4658 #[allow(missing_docs)]4659 Transfer { to: address, token_id: uint256 },4660 /// @notice Transfer ownership of an NFT from cross account address to cross account address4661 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`4662 /// is the zero address. Throws if `tokenId` is not a valid NFT.4663 /// @param from Cross acccount address of current owner4664 /// @param to Cross acccount address of new owner4665 /// @param tokenId The NFT to transfer4666 #[allow(missing_docs)]4667 TransferFromCross {4668 from: EthCrossAccount,4669 to: EthCrossAccount,4670 token_id: uint256,4671 },4672 /// @notice Burns a specific ERC721 token.4673 /// @dev Throws unless `msg.sender` is the current owner or an authorized4674 /// operator for this NFT. Throws if `from` is not the current owner. Throws4675 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.4676 /// @param from The current owner of the NFT4677 /// @param tokenId The NFT to transfer4678 #[allow(missing_docs)]4679 BurnFrom { from: address, token_id: uint256 },4680 /// @notice Burns a specific ERC721 token.4681 /// @dev Throws unless `msg.sender` is the current owner or an authorized4682 /// operator for this NFT. Throws if `from` is not the current owner. Throws4683 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.4684 /// @param from The current owner of the NFT4685 /// @param tokenId The NFT to transfer4686 #[allow(missing_docs)]4687 BurnFromCross { from: (address, uint256), token_id: uint256 },4688 NextTokenId,4689 /// @notice Function to mint multiple tokens.4690 /// @dev `tokenIds` should be an array of consecutive numbers and first number4691 /// should be obtained with `nextTokenId` method4692 /// @param to The new owner4693 /// @param tokenIds IDs of the minted NFTs4694 #[allow(missing_docs)]4695 MintBulk { to: address, token_ids: Vec<uint256> },4696 /// @notice Function to mint multiple tokens with the given tokenUris.4697 /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive4698 /// numbers and first number should be obtained with `nextTokenId` method4699 /// @param to The new owner4700 /// @param tokens array of pairs of token ID and token URI for minted tokens4701 #[allow(missing_docs)]4702 MintBulkWithTokenUri { to: address, tokens: Vec<(uint256, string)> },4703 }4704 #[automatically_derived]4705 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ERC721UniqueExtensionsCall<T> {4706 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {4707 match self {4708 ERC721UniqueExtensionsCall::ERC165Call(__self_0, __self_1) => {4709 ::core::fmt::Formatter::debug_tuple_field2_finish(4710 f,4711 "ERC165Call",4712 &__self_0,4713 &__self_1,4714 )4715 }4716 ERC721UniqueExtensionsCall::ApproveCross {4717 approved: __self_0,4718 token_id: __self_1,4719 } => {4720 ::core::fmt::Formatter::debug_struct_field2_finish(4721 f,4722 "ApproveCross",4723 "approved",4724 &__self_0,4725 "token_id",4726 &__self_1,4727 )4728 }4729 ERC721UniqueExtensionsCall::Transfer {4730 to: __self_0,4731 token_id: __self_1,4732 } => {4733 ::core::fmt::Formatter::debug_struct_field2_finish(4734 f,4735 "Transfer",4736 "to",4737 &__self_0,4738 "token_id",4739 &__self_1,4740 )4741 }4742 ERC721UniqueExtensionsCall::TransferFromCross {4743 from: __self_0,4744 to: __self_1,4745 token_id: __self_2,4746 } => {4747 ::core::fmt::Formatter::debug_struct_field3_finish(4748 f,4749 "TransferFromCross",4750 "from",4751 &__self_0,4752 "to",4753 &__self_1,4754 "token_id",4755 &__self_2,4756 )4757 }4758 ERC721UniqueExtensionsCall::BurnFrom {4759 from: __self_0,4760 token_id: __self_1,4761 } => {4762 ::core::fmt::Formatter::debug_struct_field2_finish(4763 f,4764 "BurnFrom",4765 "from",4766 &__self_0,4767 "token_id",4768 &__self_1,4769 )4770 }4771 ERC721UniqueExtensionsCall::BurnFromCross {4772 from: __self_0,4773 token_id: __self_1,4774 } => {4775 ::core::fmt::Formatter::debug_struct_field2_finish(4776 f,4777 "BurnFromCross",4778 "from",4779 &__self_0,4780 "token_id",4781 &__self_1,4782 )4783 }4784 ERC721UniqueExtensionsCall::NextTokenId => {4785 ::core::fmt::Formatter::write_str(f, "NextTokenId")4786 }4787 ERC721UniqueExtensionsCall::MintBulk {4788 to: __self_0,4789 token_ids: __self_1,4790 } => {4791 ::core::fmt::Formatter::debug_struct_field2_finish(4792 f,4793 "MintBulk",4794 "to",4795 &__self_0,4796 "token_ids",4797 &__self_1,4798 )4799 }4800 ERC721UniqueExtensionsCall::MintBulkWithTokenUri {4801 to: __self_0,4802 tokens: __self_1,4803 } => {4804 ::core::fmt::Formatter::debug_struct_field2_finish(4805 f,4806 "MintBulkWithTokenUri",4807 "to",4808 &__self_0,4809 "tokens",4810 &__self_1,4811 )4812 }4813 }4814 }4815 }4816 impl<T> ERC721UniqueExtensionsCall<T> {4817 const APPROVE_CROSS_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4818 {4819 let fs = FunctionSignature::new(&&FunctionName::new("approveCross"));4820 let fs = FunctionSignature::done(4821 FunctionSignature::add_param(4822 fs,4823 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4824 ),4825 true,4826 );4827 fs4828 }4829 };4830 ///approveCross((address,uint256),uint256)4831 const APPROVE_CROSS: ::evm_coder::types::bytes4 = {4832 let a = ::evm_coder::sha3_const::Keccak256::new()4833 .update_with_size(4834 &Self::APPROVE_CROSS_SIGNATURE.signature,4835 Self::APPROVE_CROSS_SIGNATURE.signature_len,4836 )4837 .finalize();4838 [a[0], a[1], a[2], a[3]]4839 };4840 const TRANSFER_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4841 {4842 let fs = FunctionSignature::new(&&FunctionName::new("transfer"));4843 let fs = FunctionSignature::done(4844 FunctionSignature::add_param(4845 FunctionSignature::add_param(4846 fs,4847 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),4848 ),4849 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4850 ),4851 true,4852 );4853 fs4854 }4855 };4856 ///transfer(address,uint256)4857 const TRANSFER: ::evm_coder::types::bytes4 = {4858 let a = ::evm_coder::sha3_const::Keccak256::new()4859 .update_with_size(4860 &Self::TRANSFER_SIGNATURE.signature,4861 Self::TRANSFER_SIGNATURE.signature_len,4862 )4863 .finalize();4864 [a[0], a[1], a[2], a[3]]4865 };4866 const TRANSFER_FROM_CROSS_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4867 {4868 let fs = FunctionSignature::new(4869 &&FunctionName::new("transferFromCross"),4870 );4871 let fs = FunctionSignature::done(4872 FunctionSignature::add_param(4873 FunctionSignature::add_param(4874 FunctionSignature::add_param(4875 fs,4876 (4877 <EthCrossAccount>::SIGNATURE,4878 <EthCrossAccount>::SIGNATURE_LEN,4879 ),4880 ),4881 (4882 <EthCrossAccount>::SIGNATURE,4883 <EthCrossAccount>::SIGNATURE_LEN,4884 ),4885 ),4886 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4887 ),4888 true,4889 );4890 fs4891 }4892 };4893 ///transferFromCross(EthCrossAccount,EthCrossAccount,uint256)4894 const TRANSFER_FROM_CROSS: ::evm_coder::types::bytes4 = {4895 let a = ::evm_coder::sha3_const::Keccak256::new()4896 .update_with_size(4897 &Self::TRANSFER_FROM_CROSS_SIGNATURE.signature,4898 Self::TRANSFER_FROM_CROSS_SIGNATURE.signature_len,4899 )4900 .finalize();4901 [a[0], a[1], a[2], a[3]]4902 };4903 const BURN_FROM_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4904 {4905 let fs = FunctionSignature::new(&&FunctionName::new("burnFrom"));4906 let fs = FunctionSignature::done(4907 FunctionSignature::add_param(4908 FunctionSignature::add_param(4909 fs,4910 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),4911 ),4912 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4913 ),4914 true,4915 );4916 fs4917 }4918 };4919 ///burnFrom(address,uint256)4920 const BURN_FROM: ::evm_coder::types::bytes4 = {4921 let a = ::evm_coder::sha3_const::Keccak256::new()4922 .update_with_size(4923 &Self::BURN_FROM_SIGNATURE.signature,4924 Self::BURN_FROM_SIGNATURE.signature_len,4925 )4926 .finalize();4927 [a[0], a[1], a[2], a[3]]4928 };4929 const BURN_FROM_CROSS_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4930 {4931 let fs = FunctionSignature::new(&&FunctionName::new("burnFromCross"));4932 let fs = FunctionSignature::done(4933 FunctionSignature::add_param(4934 fs,4935 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),4936 ),4937 true,4938 );4939 fs4940 }4941 };4942 ///burnFromCross((address,uint256),uint256)4943 const BURN_FROM_CROSS: ::evm_coder::types::bytes4 = {4944 let a = ::evm_coder::sha3_const::Keccak256::new()4945 .update_with_size(4946 &Self::BURN_FROM_CROSS_SIGNATURE.signature,4947 Self::BURN_FROM_CROSS_SIGNATURE.signature_len,4948 )4949 .finalize();4950 [a[0], a[1], a[2], a[3]]4951 };4952 const NEXT_TOKEN_ID_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4953 {4954 let fs = FunctionSignature::new(&&FunctionName::new("nextTokenId"));4955 let fs = FunctionSignature::done(fs, false);4956 fs4957 }4958 };4959 ///nextTokenId()4960 const NEXT_TOKEN_ID: ::evm_coder::types::bytes4 = {4961 let a = ::evm_coder::sha3_const::Keccak256::new()4962 .update_with_size(4963 &Self::NEXT_TOKEN_ID_SIGNATURE.signature,4964 Self::NEXT_TOKEN_ID_SIGNATURE.signature_len,4965 )4966 .finalize();4967 [a[0], a[1], a[2], a[3]]4968 };4969 const MINT_BULK_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4970 {4971 let fs = FunctionSignature::new(&&FunctionName::new("mintBulk"));4972 let fs = FunctionSignature::done(4973 FunctionSignature::add_param(4974 fs,4975 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),4976 ),4977 true,4978 );4979 fs4980 }4981 };4982 ///mintBulk(address,uint256[])4983 const MINT_BULK: ::evm_coder::types::bytes4 = {4984 let a = ::evm_coder::sha3_const::Keccak256::new()4985 .update_with_size(4986 &Self::MINT_BULK_SIGNATURE.signature,4987 Self::MINT_BULK_SIGNATURE.signature_len,4988 )4989 .finalize();4990 [a[0], a[1], a[2], a[3]]4991 };4992 const MINT_BULK_WITH_TOKEN_URI_SIGNATURE: ::evm_coder::custom_signature::FunctionSignature = {4993 {4994 let fs = FunctionSignature::new(4995 &&FunctionName::new("mintBulkWithTokenURI"),4996 );4997 let fs = FunctionSignature::done(4998 FunctionSignature::add_param(4999 fs,5000 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),5001 ),5002 true,5003 );5004 fs5005 }5006 };5007 ///mintBulkWithTokenURI(address,(uint256,string)[])5008 const MINT_BULK_WITH_TOKEN_URI: ::evm_coder::types::bytes4 = {5009 let a = ::evm_coder::sha3_const::Keccak256::new()5010 .update_with_size(5011 &Self::MINT_BULK_WITH_TOKEN_URI_SIGNATURE.signature,5012 Self::MINT_BULK_WITH_TOKEN_URI_SIGNATURE.signature_len,5013 )5014 .finalize();5015 [a[0], a[1], a[2], a[3]]5016 };5017 /// Return this call ERC165 selector5018 pub fn interface_id() -> ::evm_coder::types::bytes4 {5019 let mut interface_id = 0;5020 interface_id ^= u32::from_be_bytes(Self::APPROVE_CROSS);5021 interface_id ^= u32::from_be_bytes(Self::TRANSFER);5022 interface_id ^= u32::from_be_bytes(Self::TRANSFER_FROM_CROSS);5023 interface_id ^= u32::from_be_bytes(Self::BURN_FROM);5024 interface_id ^= u32::from_be_bytes(Self::BURN_FROM_CROSS);5025 interface_id ^= u32::from_be_bytes(Self::NEXT_TOKEN_ID);5026 interface_id ^= u32::from_be_bytes(Self::MINT_BULK);5027 interface_id ^= u32::from_be_bytes(Self::MINT_BULK_WITH_TOKEN_URI);5028 u32::to_be_bytes(interface_id)5029 }5030 /// Generate solidity definitions for methods described in this interface5031 pub fn generate_solidity_interface(5032 tc: &evm_coder::solidity::TypeCollector,5033 is_impl: bool,5034 ) {5035 use evm_coder::solidity::*;5036 use core::fmt::Write;5037 let interface = SolidityInterface {5038 docs: &[" @title Unique extensions for ERC721."],5039 name: "ERC721UniqueExtensions",5040 selector: Self::interface_id(),5041 is: &["Dummy", "ERC165"],5042 functions: (5043 SolidityFunction {5044 docs: &[5045 " @notice Set or reaffirm the approved address for an NFT",5046 " @dev The zero address indicates there is no approved address.",5047 " @dev Throws unless `msg.sender` is the current NFT owner, or an authorized",5048 " operator of the current owner.",5049 " @param approved The new substrate address approved NFT controller",5050 " @param tokenId The NFT to approve",5051 ],5052 selector_str: "approveCross((address,uint256),uint256)",5053 selector: u32::from_be_bytes(Self::APPROVE_CROSS),5054 custom_signature: {5055 const cs: FunctionSignature = {5056 {5057 let fs = FunctionSignature::new(5058 &&FunctionName::new("approveCross"),5059 );5060 let fs = FunctionSignature::done(5061 FunctionSignature::add_param(5062 fs,5063 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),5064 ),5065 true,5066 );5067 fs5068 }5069 };5070 cs5071 },5072 name: "approveCross",5073 mutability: SolidityMutability::Mutable,5074 is_payable: false,5075 args: (5076 <NamedArgument<(address, uint256)>>::new("approved"),5077 <NamedArgument<uint256>>::new("tokenId"),5078 ),5079 result: <UnnamedArgument<void>>::default(),5080 },5081 SolidityFunction {5082 docs: &[5083 " @notice Transfer ownership of an NFT",5084 " @dev Throws unless `msg.sender` is the current owner. Throws if `to`",5085 " is the zero address. Throws if `tokenId` is not a valid NFT.",5086 " @param to The new owner",5087 " @param tokenId The NFT to transfer",5088 ],5089 selector_str: "transfer(address,uint256)",5090 selector: u32::from_be_bytes(Self::TRANSFER),5091 custom_signature: {5092 const cs: FunctionSignature = {5093 {5094 let fs = FunctionSignature::new(5095 &&FunctionName::new("transfer"),5096 );5097 let fs = FunctionSignature::done(5098 FunctionSignature::add_param(5099 FunctionSignature::add_param(5100 fs,5101 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),5102 ),5103 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),5104 ),5105 true,5106 );5107 fs5108 }5109 };5110 cs5111 },5112 name: "transfer",5113 mutability: SolidityMutability::Mutable,5114 is_payable: false,5115 args: (5116 <NamedArgument<address>>::new("to"),5117 <NamedArgument<uint256>>::new("tokenId"),5118 ),5119 result: <UnnamedArgument<void>>::default(),5120 },5121 SolidityFunction {5122 docs: &[5123 " @notice Transfer ownership of an NFT from cross account address to cross account address",5124 " @dev Throws unless `msg.sender` is the current owner. Throws if `to`",5125 " is the zero address. Throws if `tokenId` is not a valid NFT.",5126 " @param from Cross acccount address of current owner",5127 " @param to Cross acccount address of new owner",5128 " @param tokenId The NFT to transfer",5129 ],5130 selector_str: "transferFromCross(EthCrossAccount,EthCrossAccount,uint256)",5131 selector: u32::from_be_bytes(Self::TRANSFER_FROM_CROSS),5132 custom_signature: {5133 const cs: FunctionSignature = {5134 {5135 let fs = FunctionSignature::new(5136 &&FunctionName::new("transferFromCross"),5137 );5138 let fs = FunctionSignature::done(5139 FunctionSignature::add_param(5140 FunctionSignature::add_param(5141 FunctionSignature::add_param(5142 fs,5143 (5144 <EthCrossAccount>::SIGNATURE,5145 <EthCrossAccount>::SIGNATURE_LEN,5146 ),5147 ),5148 (5149 <EthCrossAccount>::SIGNATURE,5150 <EthCrossAccount>::SIGNATURE_LEN,5151 ),5152 ),5153 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),5154 ),5155 true,5156 );5157 fs5158 }5159 };5160 cs5161 },5162 name: "transferFromCross",5163 mutability: SolidityMutability::Mutable,5164 is_payable: false,5165 args: (5166 <NamedArgument<EthCrossAccount>>::new("from"),5167 <NamedArgument<EthCrossAccount>>::new("to"),5168 <NamedArgument<uint256>>::new("tokenId"),5169 ),5170 result: <UnnamedArgument<void>>::default(),5171 },5172 SolidityFunction {5173 docs: &[5174 " @notice Burns a specific ERC721 token.",5175 " @dev Throws unless `msg.sender` is the current owner or an authorized",5176 " operator for this NFT. Throws if `from` is not the current owner. Throws",5177 " if `to` is the zero address. Throws if `tokenId` is not a valid NFT.",5178 " @param from The current owner of the NFT",5179 " @param tokenId The NFT to transfer",5180 ],5181 selector_str: "burnFrom(address,uint256)",5182 selector: u32::from_be_bytes(Self::BURN_FROM),5183 custom_signature: {5184 const cs: FunctionSignature = {5185 {5186 let fs = FunctionSignature::new(5187 &&FunctionName::new("burnFrom"),5188 );5189 let fs = FunctionSignature::done(5190 FunctionSignature::add_param(5191 FunctionSignature::add_param(5192 fs,5193 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),5194 ),5195 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),5196 ),5197 true,5198 );5199 fs5200 }5201 };5202 cs5203 },5204 name: "burnFrom",5205 mutability: SolidityMutability::Mutable,5206 is_payable: false,5207 args: (5208 <NamedArgument<address>>::new("from"),5209 <NamedArgument<uint256>>::new("tokenId"),5210 ),5211 result: <UnnamedArgument<void>>::default(),5212 },5213 SolidityFunction {5214 docs: &[5215 " @notice Burns a specific ERC721 token.",5216 " @dev Throws unless `msg.sender` is the current owner or an authorized",5217 " operator for this NFT. Throws if `from` is not the current owner. Throws",5218 " if `to` is the zero address. Throws if `tokenId` is not a valid NFT.",5219 " @param from The current owner of the NFT",5220 " @param tokenId The NFT to transfer",5221 ],5222 selector_str: "burnFromCross((address,uint256),uint256)",5223 selector: u32::from_be_bytes(Self::BURN_FROM_CROSS),5224 custom_signature: {5225 const cs: FunctionSignature = {5226 {5227 let fs = FunctionSignature::new(5228 &&FunctionName::new("burnFromCross"),5229 );5230 let fs = FunctionSignature::done(5231 FunctionSignature::add_param(5232 fs,5233 (<uint256>::SIGNATURE, <uint256>::SIGNATURE_LEN),5234 ),5235 true,5236 );5237 fs5238 }5239 };5240 cs5241 },5242 name: "burnFromCross",5243 mutability: SolidityMutability::Mutable,5244 is_payable: false,5245 args: (5246 <NamedArgument<(address, uint256)>>::new("from"),5247 <NamedArgument<uint256>>::new("tokenId"),5248 ),5249 result: <UnnamedArgument<void>>::default(),5250 },5251 SolidityFunction {5252 docs: &[" @notice Returns next free NFT ID."],5253 selector_str: "nextTokenId()",5254 selector: u32::from_be_bytes(Self::NEXT_TOKEN_ID),5255 custom_signature: {5256 const cs: FunctionSignature = {5257 {5258 let fs = FunctionSignature::new(5259 &&FunctionName::new("nextTokenId"),5260 );5261 let fs = FunctionSignature::done(fs, false);5262 fs5263 }5264 };5265 cs5266 },5267 name: "nextTokenId",5268 mutability: SolidityMutability::View,5269 is_payable: false,5270 args: (),5271 result: <UnnamedArgument<uint256>>::default(),5272 },5273 SolidityFunction {5274 docs: &[5275 " @notice Function to mint multiple tokens.",5276 " @dev `tokenIds` should be an array of consecutive numbers and first number",5277 " should be obtained with `nextTokenId` method",5278 " @param to The new owner",5279 " @param tokenIds IDs of the minted NFTs",5280 ],5281 selector_str: "mintBulk(address,uint256[])",5282 selector: u32::from_be_bytes(Self::MINT_BULK),5283 custom_signature: {5284 const cs: FunctionSignature = {5285 {5286 let fs = FunctionSignature::new(5287 &&FunctionName::new("mintBulk"),5288 );5289 let fs = FunctionSignature::done(5290 FunctionSignature::add_param(5291 fs,5292 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),5293 ),5294 true,5295 );5296 fs5297 }5298 };5299 cs5300 },5301 name: "mintBulk",5302 mutability: SolidityMutability::Mutable,5303 is_payable: false,5304 args: (5305 <NamedArgument<address>>::new("to"),5306 <NamedArgument<Vec<uint256>>>::new("tokenIds"),5307 ),5308 result: <UnnamedArgument<bool>>::default(),5309 },5310 SolidityFunction {5311 docs: &[5312 " @notice Function to mint multiple tokens with the given tokenUris.",5313 " @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive",5314 " numbers and first number should be obtained with `nextTokenId` method",5315 " @param to The new owner",5316 " @param tokens array of pairs of token ID and token URI for minted tokens",5317 ],5318 selector_str: "mintBulkWithTokenURI(address,(uint256,string)[])",5319 selector: u32::from_be_bytes(Self::MINT_BULK_WITH_TOKEN_URI),5320 custom_signature: {5321 const cs: FunctionSignature = {5322 {5323 let fs = FunctionSignature::new(5324 &&FunctionName::new("mintBulkWithTokenURI"),5325 );5326 let fs = FunctionSignature::done(5327 FunctionSignature::add_param(5328 fs,5329 (<address>::SIGNATURE, <address>::SIGNATURE_LEN),5330 ),5331 true,5332 );5333 fs5334 }5335 };5336 cs5337 },5338 name: "mintBulkWithTokenURI",5339 mutability: SolidityMutability::Mutable,5340 is_payable: false,5341 args: (5342 <NamedArgument<address>>::new("to"),5343 <NamedArgument<Vec<(uint256, string)>>>::new("tokens"),5344 ),5345 result: <UnnamedArgument<bool>>::default(),5346 },5347 ),5348 };5349 let mut out = ::evm_coder::types::string::new();5350 if "ERC721UniqueExtensions".starts_with("Inline") {5351 out.push_str("/// @dev inlined interface\n");5352 }5353 let _ = interface.format(is_impl, &mut out, tc);5354 tc.collect(out);5355 if is_impl {5356 tc.collect(5357 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"5358 .into(),5359 );5360 } else {5361 tc.collect(5362 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"5363 .into(),5364 );5365 }5366 }5367 }5368 impl<T> ::evm_coder::Call for ERC721UniqueExtensionsCall<T> {5369 fn parse(5370 method_id: ::evm_coder::types::bytes4,5371 reader: &mut ::evm_coder::abi::AbiReader,5372 ) -> ::evm_coder::execution::Result<Option<Self>> {5373 use ::evm_coder::abi::AbiRead;5374 match method_id {5375 ::evm_coder::ERC165Call::INTERFACE_ID => {5376 return Ok(5377 ::evm_coder::ERC165Call::parse(method_id, reader)?5378 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),5379 );5380 }5381 Self::APPROVE_CROSS => {5382 return Ok(5383 Some(Self::ApproveCross {5384 approved: reader.abi_read()?,5385 token_id: reader.abi_read()?,5386 }),5387 );5388 }5389 Self::TRANSFER => {5390 return Ok(5391 Some(Self::Transfer {5392 to: reader.abi_read()?,5393 token_id: reader.abi_read()?,5394 }),5395 );5396 }5397 Self::TRANSFER_FROM_CROSS => {5398 return Ok(5399 Some(Self::TransferFromCross {5400 from: reader.abi_read()?,5401 to: reader.abi_read()?,5402 token_id: reader.abi_read()?,5403 }),5404 );5405 }5406 Self::BURN_FROM => {5407 return Ok(5408 Some(Self::BurnFrom {5409 from: reader.abi_read()?,5410 token_id: reader.abi_read()?,5411 }),5412 );5413 }5414 Self::BURN_FROM_CROSS => {5415 return Ok(5416 Some(Self::BurnFromCross {5417 from: reader.abi_read()?,5418 token_id: reader.abi_read()?,5419 }),5420 );5421 }5422 Self::NEXT_TOKEN_ID => return Ok(Some(Self::NextTokenId)),5423 Self::MINT_BULK => {5424 return Ok(5425 Some(Self::MintBulk {5426 to: reader.abi_read()?,5427 token_ids: reader.abi_read()?,5428 }),5429 );5430 }5431 Self::MINT_BULK_WITH_TOKEN_URI => {5432 return Ok(5433 Some(Self::MintBulkWithTokenUri {5434 to: reader.abi_read()?,5435 tokens: reader.abi_read()?,5436 }),5437 );5438 }5439 _ => {}5440 }5441 return Ok(None);5442 }5443 }5444 impl<T: Config> ERC721UniqueExtensionsCall<T>5445 where5446 T::AccountId: From<[u8; 32]>,5447 {5448 /// Is this contract implements specified ERC165 selector5449 pub fn supports_interface(5450 this: &NonfungibleHandle<T>,5451 interface_id: ::evm_coder::types::bytes4,5452 ) -> bool {5453 interface_id != u32::to_be_bytes(0xffffff)5454 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID5455 || interface_id == Self::interface_id())5456 }5457 }5458 impl<T: Config> ::evm_coder::Weighted for ERC721UniqueExtensionsCall<T>5459 where5460 T::AccountId: From<[u8; 32]>,5461 {5462 #[allow(unused_variables)]5463 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {5464 match self {5465 Self::ERC165Call(5466 ::evm_coder::ERC165Call::SupportsInterface { .. },5467 _,5468 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),5469 Self::ApproveCross { approved, token_id } => {5470 (<SelfWeightOf<T>>::approve()).into()5471 }5472 Self::Transfer { to, token_id } => (<SelfWeightOf<T>>::transfer()).into(),5473 Self::TransferFromCross { from, to, token_id } => {5474 (<SelfWeightOf<T>>::transfer()).into()5475 }5476 Self::BurnFrom { from, token_id } => {5477 (<SelfWeightOf<T>>::burn_from()).into()5478 }5479 Self::BurnFromCross { from, token_id } => {5480 (<SelfWeightOf<T>>::burn_from()).into()5481 }5482 Self::NextTokenId => ().into(),5483 Self::MintBulk { to, token_ids } => {5484 (<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))5485 .into()5486 }5487 Self::MintBulkWithTokenUri { to, tokens } => {5488 (<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))5489 .into()5490 }5491 }5492 }5493 }5494 impl<T: Config> ::evm_coder::Callable<ERC721UniqueExtensionsCall<T>>5495 for NonfungibleHandle<T>5496 where5497 T::AccountId: From<[u8; 32]>,5498 {5499 #[allow(unreachable_code)]5500 fn call(5501 &mut self,5502 c: Msg<ERC721UniqueExtensionsCall<T>>,5503 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {5504 use ::evm_coder::abi::AbiWrite;5505 match c.call {5506 ERC721UniqueExtensionsCall::ERC165Call(5507 ::evm_coder::ERC165Call::SupportsInterface { interface_id },5508 _,5509 ) => {5510 let mut writer = ::evm_coder::abi::AbiWriter::default();5511 writer5512 .bool(5513 &<ERC721UniqueExtensionsCall<5514 T,5515 >>::supports_interface(self, interface_id),5516 );5517 return Ok(writer.into());5518 }5519 _ => {}5520 }5521 let mut writer = ::evm_coder::abi::AbiWriter::default();5522 match c.call {5523 ERC721UniqueExtensionsCall::ApproveCross { approved, token_id } => {5524 let result = self5525 .approve_cross(c.caller.clone(), approved, token_id)?;5526 (&result).to_result()5527 }5528 ERC721UniqueExtensionsCall::Transfer { to, token_id } => {5529 let result = self.transfer(c.caller.clone(), to, token_id)?;5530 (&result).to_result()5531 }5532 ERC721UniqueExtensionsCall::TransferFromCross { from, to, token_id } => {5533 let result = self5534 .transfer_from_cross(c.caller.clone(), from, to, token_id)?;5535 (&result).to_result()5536 }5537 ERC721UniqueExtensionsCall::BurnFrom { from, token_id } => {5538 let result = self.burn_from(c.caller.clone(), from, token_id)?;5539 (&result).to_result()5540 }5541 ERC721UniqueExtensionsCall::BurnFromCross { from, token_id } => {5542 let result = self.burn_from_cross(c.caller.clone(), from, token_id)?;5543 (&result).to_result()5544 }5545 ERC721UniqueExtensionsCall::NextTokenId => {5546 let result = self.next_token_id()?;5547 (&result).to_result()5548 }5549 ERC721UniqueExtensionsCall::MintBulk { to, token_ids } => {5550 let result = self.mint_bulk(c.caller.clone(), to, token_ids)?;5551 (&result).to_result()5552 }5553 ERC721UniqueExtensionsCall::MintBulkWithTokenUri { to, tokens } => {5554 let result = self5555 .mint_bulk_with_token_uri(c.caller.clone(), to, tokens)?;5556 (&result).to_result()5557 }5558 _ => {5559 Err(5560 ::evm_coder::execution::Error::from("method is not available")5561 .into(),5562 )5563 }5564 }5565 }5566 }5567 impl<T: Config> NonfungibleHandle<T>5568 where5569 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,5570 {}5571 pub enum UniqueNFTCall<T> {5572 /// Inherited method5573 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<T>),5574 ERC721(ERC721Call<T>),5575 ERC721Metadata(ERC721MetadataCall<T>),5576 ERC721Enumerable(ERC721EnumerableCall<T>),5577 ERC721UniqueExtensions(ERC721UniqueExtensionsCall<T>),5578 ERC721Mintable(ERC721MintableCall<T>),5579 ERC721Burnable(ERC721BurnableCall<T>),5580 Collection(CollectionCall<T>),5581 TokenProperties(TokenPropertiesCall<T>),5582 }5583 #[automatically_derived]5584 impl<T: ::core::fmt::Debug> ::core::fmt::Debug for UniqueNFTCall<T> {5585 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {5586 match self {5587 UniqueNFTCall::ERC165Call(__self_0, __self_1) => {5588 ::core::fmt::Formatter::debug_tuple_field2_finish(5589 f,5590 "ERC165Call",5591 &__self_0,5592 &__self_1,5593 )5594 }5595 UniqueNFTCall::ERC721(__self_0) => {5596 ::core::fmt::Formatter::debug_tuple_field1_finish(5597 f,5598 "ERC721",5599 &__self_0,5600 )5601 }5602 UniqueNFTCall::ERC721Metadata(__self_0) => {5603 ::core::fmt::Formatter::debug_tuple_field1_finish(5604 f,5605 "ERC721Metadata",5606 &__self_0,5607 )5608 }5609 UniqueNFTCall::ERC721Enumerable(__self_0) => {5610 ::core::fmt::Formatter::debug_tuple_field1_finish(5611 f,5612 "ERC721Enumerable",5613 &__self_0,5614 )5615 }5616 UniqueNFTCall::ERC721UniqueExtensions(__self_0) => {5617 ::core::fmt::Formatter::debug_tuple_field1_finish(5618 f,5619 "ERC721UniqueExtensions",5620 &__self_0,5621 )5622 }5623 UniqueNFTCall::ERC721Mintable(__self_0) => {5624 ::core::fmt::Formatter::debug_tuple_field1_finish(5625 f,5626 "ERC721Mintable",5627 &__self_0,5628 )5629 }5630 UniqueNFTCall::ERC721Burnable(__self_0) => {5631 ::core::fmt::Formatter::debug_tuple_field1_finish(5632 f,5633 "ERC721Burnable",5634 &__self_0,5635 )5636 }5637 UniqueNFTCall::Collection(__self_0) => {5638 ::core::fmt::Formatter::debug_tuple_field1_finish(5639 f,5640 "Collection",5641 &__self_0,5642 )5643 }5644 UniqueNFTCall::TokenProperties(__self_0) => {5645 ::core::fmt::Formatter::debug_tuple_field1_finish(5646 f,5647 "TokenProperties",5648 &__self_0,5649 )5650 }5651 }5652 }5653 }5654 impl<T> UniqueNFTCall<T> {5655 /// Return this call ERC165 selector5656 pub fn interface_id() -> ::evm_coder::types::bytes4 {5657 let mut interface_id = 0;5658 u32::to_be_bytes(interface_id)5659 }5660 /// Generate solidity definitions for methods described in this interface5661 pub fn generate_solidity_interface(5662 tc: &evm_coder::solidity::TypeCollector,5663 is_impl: bool,5664 ) {5665 use evm_coder::solidity::*;5666 use core::fmt::Write;5667 let interface = SolidityInterface {5668 docs: &[],5669 name: "UniqueNFT",5670 selector: Self::interface_id(),5671 is: &[5672 "Dummy",5673 "ERC165",5674 "ERC721",5675 "ERC721Metadata",5676 "ERC721Enumerable",5677 "ERC721UniqueExtensions",5678 "ERC721Mintable",5679 "ERC721Burnable",5680 "Collection",5681 "TokenProperties",5682 ],5683 functions: (),5684 };5685 let mut out = ::evm_coder::types::string::new();5686 if "UniqueNFT".starts_with("Inline") {5687 out.push_str("/// @dev inlined interface\n");5688 }5689 let _ = interface.format(is_impl, &mut out, tc);5690 tc.collect(out);5691 <ERC721Call<T>>::generate_solidity_interface(tc, is_impl);5692 <ERC721MetadataCall<T>>::generate_solidity_interface(tc, is_impl);5693 <ERC721EnumerableCall<T>>::generate_solidity_interface(tc, is_impl);5694 <ERC721UniqueExtensionsCall<T>>::generate_solidity_interface(tc, is_impl);5695 <ERC721MintableCall<T>>::generate_solidity_interface(tc, is_impl);5696 <ERC721BurnableCall<T>>::generate_solidity_interface(tc, is_impl);5697 <CollectionCall<T>>::generate_solidity_interface(tc, is_impl);5698 <TokenPropertiesCall<T>>::generate_solidity_interface(tc, is_impl);5699 if is_impl {5700 tc.collect(5701 "/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n"5702 .into(),5703 );5704 } else {5705 tc.collect(5706 "/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"5707 .into(),5708 );5709 }5710 }5711 }5712 impl<T> ::evm_coder::Call for UniqueNFTCall<T> {5713 fn parse(5714 method_id: ::evm_coder::types::bytes4,5715 reader: &mut ::evm_coder::abi::AbiReader,5716 ) -> ::evm_coder::execution::Result<Option<Self>> {5717 use ::evm_coder::abi::AbiRead;5718 match method_id {5719 ::evm_coder::ERC165Call::INTERFACE_ID => {5720 return Ok(5721 ::evm_coder::ERC165Call::parse(method_id, reader)?5722 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData)),5723 );5724 }5725 _ => {}5726 }5727 if let Some(parsed_call) = <ERC721Call<T>>::parse(method_id, reader)? {5728 return Ok(Some(Self::ERC721(parsed_call)))5729 } else if let Some(parsed_call)5730 = <ERC721MetadataCall<T>>::parse(method_id, reader)? {5731 return Ok(Some(Self::ERC721Metadata(parsed_call)))5732 } else if let Some(parsed_call)5733 = <ERC721EnumerableCall<T>>::parse(method_id, reader)? {5734 return Ok(Some(Self::ERC721Enumerable(parsed_call)))5735 } else if let Some(parsed_call)5736 = <ERC721UniqueExtensionsCall<T>>::parse(method_id, reader)? {5737 return Ok(Some(Self::ERC721UniqueExtensions(parsed_call)))5738 } else if let Some(parsed_call)5739 = <ERC721MintableCall<T>>::parse(method_id, reader)? {5740 return Ok(Some(Self::ERC721Mintable(parsed_call)))5741 } else if let Some(parsed_call)5742 = <ERC721BurnableCall<T>>::parse(method_id, reader)? {5743 return Ok(Some(Self::ERC721Burnable(parsed_call)))5744 } else if let Some(parsed_call)5745 = <CollectionCall<T>>::parse(method_id, reader)? {5746 return Ok(Some(Self::Collection(parsed_call)))5747 } else if let Some(parsed_call)5748 = <TokenPropertiesCall<T>>::parse(method_id, reader)? {5749 return Ok(Some(Self::TokenProperties(parsed_call)))5750 }5751 return Ok(None);5752 }5753 }5754 impl<T: Config> UniqueNFTCall<T>5755 where5756 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,5757 {5758 /// Is this contract implements specified ERC165 selector5759 pub fn supports_interface(5760 this: &NonfungibleHandle<T>,5761 interface_id: ::evm_coder::types::bytes4,5762 ) -> bool {5763 interface_id != u32::to_be_bytes(0xffffff)5764 && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID5765 || interface_id == Self::interface_id()5766 || <ERC721Call<T>>::supports_interface(this, interface_id)5767 || <ERC721MetadataCall<T>>::supports_interface(this, interface_id)5768 || <ERC721EnumerableCall<T>>::supports_interface(this, interface_id)5769 || <ERC721UniqueExtensionsCall<5770 T,5771 >>::supports_interface(this, interface_id)5772 || <ERC721MintableCall<T>>::supports_interface(this, interface_id)5773 || <ERC721BurnableCall<T>>::supports_interface(this, interface_id)5774 || <CollectionCall<T>>::supports_interface(this, interface_id)5775 || <TokenPropertiesCall<T>>::supports_interface(this, interface_id))5776 }5777 }5778 impl<T: Config> ::evm_coder::Weighted for UniqueNFTCall<T>5779 where5780 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,5781 {5782 #[allow(unused_variables)]5783 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {5784 match self {5785 Self::ERC721(call) => call.weight(),5786 Self::ERC721Metadata(call) => call.weight(),5787 Self::ERC721Enumerable(call) => call.weight(),5788 Self::ERC721UniqueExtensions(call) => call.weight(),5789 Self::ERC721Mintable(call) => call.weight(),5790 Self::ERC721Burnable(call) => call.weight(),5791 Self::Collection(call) => call.weight(),5792 Self::TokenProperties(call) => call.weight(),5793 Self::ERC165Call(5794 ::evm_coder::ERC165Call::SupportsInterface { .. },5795 _,5796 ) => ::frame_support::weights::Weight::from_ref_time(100).into(),5797 }5798 }5799 }5800 impl<T: Config> ::evm_coder::Callable<UniqueNFTCall<T>> for NonfungibleHandle<T>5801 where5802 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,5803 {5804 #[allow(unreachable_code)]5805 fn call(5806 &mut self,5807 c: Msg<UniqueNFTCall<T>>,5808 ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {5809 use ::evm_coder::abi::AbiWrite;5810 match c.call {5811 UniqueNFTCall::ERC721(call) => {5812 return <Self as ::evm_coder::Callable<5813 ERC721Call<T>,5814 >>::call(5815 self,5816 Msg {5817 call,5818 caller: c.caller,5819 value: c.value,5820 },5821 );5822 }5823 UniqueNFTCall::ERC721Metadata(call) => {5824 return <Self as ::evm_coder::Callable<5825 ERC721MetadataCall<T>,5826 >>::call(5827 self,5828 Msg {5829 call,5830 caller: c.caller,5831 value: c.value,5832 },5833 );5834 }5835 UniqueNFTCall::ERC721Enumerable(call) => {5836 return <Self as ::evm_coder::Callable<5837 ERC721EnumerableCall<T>,5838 >>::call(5839 self,5840 Msg {5841 call,5842 caller: c.caller,5843 value: c.value,5844 },5845 );5846 }5847 UniqueNFTCall::ERC721UniqueExtensions(call) => {5848 return <Self as ::evm_coder::Callable<5849 ERC721UniqueExtensionsCall<T>,5850 >>::call(5851 self,5852 Msg {5853 call,5854 caller: c.caller,5855 value: c.value,5856 },5857 );5858 }5859 UniqueNFTCall::ERC721Mintable(call) => {5860 return <Self as ::evm_coder::Callable<5861 ERC721MintableCall<T>,5862 >>::call(5863 self,5864 Msg {5865 call,5866 caller: c.caller,5867 value: c.value,5868 },5869 );5870 }5871 UniqueNFTCall::ERC721Burnable(call) => {5872 return <Self as ::evm_coder::Callable<5873 ERC721BurnableCall<T>,5874 >>::call(5875 self,5876 Msg {5877 call,5878 caller: c.caller,5879 value: c.value,5880 },5881 );5882 }5883 UniqueNFTCall::Collection(call) => {5884 return <CollectionHandle<5885 T,5886 > as ::evm_coder::Callable<5887 CollectionCall<T>,5888 >>::call(5889 self.common_mut(),5890 Msg {5891 call,5892 caller: c.caller,5893 value: c.value,5894 },5895 );5896 }5897 UniqueNFTCall::TokenProperties(call) => {5898 return <Self as ::evm_coder::Callable<5899 TokenPropertiesCall<T>,5900 >>::call(5901 self,5902 Msg {5903 call,5904 caller: c.caller,5905 value: c.value,5906 },5907 );5908 }5909 UniqueNFTCall::ERC165Call(5910 ::evm_coder::ERC165Call::SupportsInterface { interface_id },5911 _,5912 ) => {5913 let mut writer = ::evm_coder::abi::AbiWriter::default();5914 writer5915 .bool(5916 &<UniqueNFTCall<T>>::supports_interface(self, interface_id),5917 );5918 return Ok(writer.into());5919 }5920 _ => {}5921 }5922 let mut writer = ::evm_coder::abi::AbiWriter::default();5923 match c.call {5924 _ => {5925 Err(5926 ::evm_coder::execution::Error::from("method is not available")5927 .into(),5928 )5929 }5930 }5931 }5932 }5933 impl<T: Config> CommonEvmHandler for NonfungibleHandle<T>5934 where5935 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,5936 {5937 const CODE: &'static [u8] = b"`\xe0`@R`&`\x80\x81\x81R\x90b\x00\x138`\xa09`\x01\x90b\x00\x00\"\x90\x82b\x00\x00\xdcV[P4\x80\x15b\x00\x000W`\x00\x80\xfd[Pb\x00\x01\xa8V[cNH{q`\xe0\x1b`\x00R`A`\x04R`$`\x00\xfd[`\x01\x81\x81\x1c\x90\x82\x16\x80b\x00\x00bW`\x7f\x82\x16\x91P[` \x82\x10\x81\x03b\x00\x00\x83WcNH{q`\xe0\x1b`\x00R`\"`\x04R`$`\x00\xfd[P\x91\x90PV[`\x1f\x82\x11\x15b\x00\x00\xd7W`\x00\x81\x81R` \x81 `\x1f\x85\x01`\x05\x1c\x81\x01` \x86\x10\x15b\x00\x00\xb2WP\x80[`\x1f\x85\x01`\x05\x1c\x82\x01\x91P[\x81\x81\x10\x15b\x00\x00\xd3W\x82\x81U`\x01\x01b\x00\x00\xbeV[PPP[PPPV[\x81Q`\x01`\x01`@\x1b\x03\x81\x11\x15b\x00\x00\xf8Wb\x00\x00\xf8b\x00\x007V[b\x00\x01\x10\x81b\x00\x01\t\x84Tb\x00\x00MV[\x84b\x00\x00\x89V[` \x80`\x1f\x83\x11`\x01\x81\x14b\x00\x01HW`\x00\x84\x15b\x00\x01/WP\x85\x83\x01Q[`\x00\x19`\x03\x86\x90\x1b\x1c\x19\x16`\x01\x85\x90\x1b\x17\x85Ub\x00\x00\xd3V[`\x00\x85\x81R` \x81 `\x1f\x19\x86\x16\x91[\x82\x81\x10\x15b\x00\x01yW\x88\x86\x01Q\x82U\x94\x84\x01\x94`\x01\x90\x91\x01\x90\x84\x01b\x00\x01XV[P\x85\x82\x10\x15b\x00\x01\x98W\x87\x85\x01Q`\x00\x19`\x03\x88\x90\x1b`\xf8\x16\x1c\x19\x16\x81U[PPPPP`\x01\x90\x81\x1b\x01\x90UPV[a\x11\x80\x80b\x00\x01\xb8`\x009`\x00\xf3\xfe`\x80`@R4\x80\x15a\x00\x10W`\x00\x80\xfd[P`\x046\x10a\x03\xdaW`\x005`\xe0\x1c\x80cj8A\xdb\x11a\x02\nW\x80c\x98\x11\xb0\xc7\x11a\x01%W\x80c\xcf$\xfdm\x11a\x00\xb8W\x80c\xdfr};\x11a\x00\x87W\x80c\xdfr};\x14a\x05\xaaW\x80c\xe5\xc9\x91?\x14a\x04{W\x80c\xe9\x85\xe9\xc5\x14a\x06PW\x80c\xf6\xb4\xdf\xb4\x14a\x06^W\x80c\xfa\xfd{B\x14a\x04\x97W`\x00\x80\xfd[\x80c\xcf$\xfdm\x14a\x064W\x80c\xd3KU\xb8\x14a\x042W\x80c\xd5\xcfC\x0b\x14a\x06BW\x80c\xd6:\x8e\x11\x14a\x05\xeeW`\x00\x80\xfd[\x80c\xa9\x05\x9c\xbb\x11a\x00\xf4W\x80c\xa9\x05\x9c\xbb\x14a\x04mW\x80c\xb8\x8dO\xde\x14a\x06\x18W\x80c\xbb/ZX\x14a\x04\x89W\x80c\xc8{V\xdd\x14a\x06&W`\x00\x80\xfd[\x80c\x98\x11\xb0\xc7\x14a\x05\xeeW\x80c\x99;\x7f\xba\x14a\x05\xfcW\x80c\xa0\x18J:\x14a\x04{W\x80c\xa2,\xb4e\x14a\x06\nW`\x00\x80\xfd[\x80cy\xccg\x90\x11a\x01\x9dW\x80c\x85\x9a\xa7\xd6\x11a\x01lW\x80c\x85\x9a\xa7\xd6\x14a\x04{W\x80c\x85\xc5\x1a\xcb\x14a\x04\x97W\x80c\x92\xe4b\xc7\x14a\x04\x97W\x80c\x95\xd8\x9bA\x14a\x042W`\x00\x80\xfd[\x80cy\xccg\x90\x14a\x04mW\x80c{}\xeb\xce\x14a\x05\xe0W\x80c}d\xbc\xb4\x14a\x04\x1cW\x80c\x84\xa1\xd5\xa8\x14a\x04{W`\x00\x80\xfd[\x80cp\xa0\x821\x11a\x01\xd9W\x80cp\xa0\x821\x14a\x05\xbfW\x80cr(\xc3\'\x14a\x05\xcdW\x80cuyJ<\x14a\x04\xb3W\x80cv#@.\x14a\x04\x97W`\x00\x80\xfd[\x80cj8A\xdb\x14a\x05\x9cW\x80cl\x0c\xd1s\x14a\x04{W\x80cn\x03&\xa3\x14a\x05\x0fW\x80cn\xc0\xa9\xf1\x14a\x05\xaaW`\x00\x80\xfd[\x80c/\x07?f\x11a\x02\xfaW\x80cB\x96lh\x11a\x02\x8dW\x80cX\x13!k\x11a\x02\\W\x80cX\x13!k\x14a\x05yW\x80ccR!\x1e\x14a\x04GW\x80cd\x87#\x96\x14a\x05\x8eW\x80cg\x84O\xe6\x14a\x04\x97W`\x00\x80\xfd[\x80cB\x96lh\x14a\x05AW\x80cD\xa9\x94^\x14a\x05OW\x80cOl\xcc\xe7\x14a\x05]W\x80cP\xbbN\x7f\x14a\x05kW`\x00\x80\xfd[\x80c>u\xa9\x05\x11a\x02\xc9W\x80c>u\xa9\x05\x14a\x05\x17W\x80c@\xc1\x0f\x19\x14a\x05%W\x80cA\x83]L\x14a\x053W\x80cB\x84.\x0e\x14a\x04\xd7W`\x00\x80\xfd[\x80c/\x07?f\x14a\x04\xe5W\x80c/t\\Y\x14a\x04\xf3W\x80c6T0\x06\x14a\x05\x01W\x80c<P\xe9z\x14a\x05\x0fW`\x00\x80\xfd[\x80c\t\xbaE*\x11a\x03rW\x80c\x17R\xd6{\x11a\x03AW\x80c\x17R\xd6{\x14a\x04\xa5W\x80c\x18\x16\r\xdd\x14a\x04\xb3W\x80c\"-\x97\xfa\x14a\x04\xc9W\x80c#\xb8r\xdd\x14a\x04\xd7W`\x00\x80\xfd[\x80c\t\xbaE*\x14a\x04{W\x80c\x0e\xcd\n\xb0\x14a\x04\x89W\x80c\x11-E\x86\x14a\x03\xdfW\x80c\x13\xaf@5\x14a\x04\x97W`\x00\x80\xfd[\x80c\x06a\x11\xd1\x11a\x03\xaeW\x80c\x06a\x11\xd1\x14a\x04$W\x80c\x06\xfd\xde\x03\x14a\x042W\x80c\x08\x18\x12\xfc\x14a\x04GW\x80c\t^\xa7\xb3\x14a\x04mW`\x00\x80\xfd[\x80b\x01\x8e\x84\x14a\x03\xdfW\x80c\x01\xff\xc9\xa7\x14a\x03\xf4W\x80c\x05\x8a\xc1\x85\x14a\x04\x1cW\x80c\x05\xd2\x03[\x14a\x04\x1cW[`\x00\x80\xfd[a\x03\xf2a\x03\xed6`\x04a\x07$V[a\x06fV[\x00[a\x04\x07a\x04\x026`\x04a\x07FV[a\x06\x8aV[`@Q\x90\x15\x15\x81R` \x01[`@Q\x80\x91\x03\x90\xf3[a\x04\x07a\x06\x8aV[a\x03\xf2a\x03\xed6`\x04a\x08MV[a\x04:a\x06\xa7V[`@Qa\x04\x13\x91\x90a\x08\xd9V[a\x04Ua\x04\x026`\x04a\x08\xecV[`@Q`\x01`\x01`\xa0\x1b\x03\x90\x91\x16\x81R` \x01a\x04\x13V[a\x03\xf2a\x03\xed6`\x04a\t\x1cV[a\x03\xf2a\x03\xed6`\x04a\t\x9cV[a\x03\xf2a\x03\xed6`\x04a\t\xb8V[a\x03\xf2a\x03\xed6`\x04a\t\xe3V[a\x03\xf2a\x03\xed6`\x04a\t\xfeV[a\x04\xbba\x06\x8aV[`@Q\x90\x81R` \x01a\x04\x13V[a\x03\xf2a\x03\xed6`\x04a\njV[a\x03\xf2a\x03\xed6`\x04a\n\xd8V[a\x03\xf2a\x03\xed6`\x04a\x0b\x14V[a\x04\xbba\x04\x026`\x04a\t\x1cV[a\x04\x07a\x04\x026`\x04a\x0b\x90V[a\x03\xf2a\x06fV[a\x04\x07a\x04\x026`\x04a\t\x9cV[a\x04\x07a\x04\x026`\x04a\t\x1cV[a\x03\xf2a\x03\xed6`\x04a\x0c\x95V[a\x03\xf2a\x03\xed6`\x04a\x08\xecV[a\x04\x07a\x04\x026`\x04a\x0c\xb8V[a\x04\xbba\x04\x026`\x04a\x08\xecV[a\x04\x07a\x04\x026`\x04a\r[V[a\x05\x81a\x06\xa7V[`@Qa\x04\x13\x91\x90a\r\xa7V[a\x03\xf2a\x03\xed6`\x04a\x0e\x07V[a\x03\xf2a\x03\xed6`\x04a\x0e\xa2V[a\x05\xb2a\x06\xf6V[`@Qa\x04\x13\x91\x90a\x0e\xfcV[a\x04\xbba\x04\x026`\x04a\t\xe3V[a\x04:a\x05\xdb6`\x04a\x08MV[a\x06\xa7V[a\x03\xf2a\x03\xed6`\x04a\x0f\x1cV[a\x04\x07a\x04\x026`\x04a\t\xe3V[a\x03\xf2a\x03\xed6`\x04a\x0fXV[a\x03\xf2a\x03\xed6`\x04a\x0f\xa5V[a\x03\xf2a\x03\xed6`\x04a\x0f\xcfV[a\x04:a\x05\xdb6`\x04a\x08\xecV[a\x04:a\x05\xdb6`\x04a\x0f\x1cV[a\x03\xf2a\x03\xed6`\x04a\x106V[a\x04Ua\x04\x026`\x04a\x10tV[a\x04Ua\x06\x8aV[`\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x06\x81\x91\x90a\x10\x9eV[`@Q\x80\x91\x03\x90\xfd[`\x00`\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x06\x81\x91\x90a\x10\x9eV[```\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x06\x81\x91\x90a\x10\x9eV[\x92\x91PPV[`@\x80Q\x80\x82\x01\x90\x91R`\x00\x80\x82R` \x82\x01R\x81R` \x01\x90`\x01\x90\x03\x90\x81a\x06\xcaW\x90PP\x90P\x90V[`@\x80Q\x80\x82\x01\x90\x91R`\x00\x80\x82R` \x82\x01Ra\x06fV[\x805\x80\x15\x15\x81\x14a\x07\x1fW`\x00\x80\xfd[\x91\x90PV[`\x00` \x82\x84\x03\x12\x15a\x076W`\x00\x80\xfd[a\x07?\x82a\x07\x0fV[\x93\x92PPPV[`\x00` \x82\x84\x03\x12\x15a\x07XW`\x00\x80\xfd[\x815`\x01`\x01`\xe0\x1b\x03\x19\x81\x16\x81\x14a\x07?W`\x00\x80\xfd[cNH{q`\xe0\x1b`\x00R`A`\x04R`$`\x00\xfd[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1b\x03\x81\x11\x82\x82\x10\x17\x15a\x07\xa8Wa\x07\xa8a\x07pV[`@R\x90V[`@Q`\x1f\x82\x01`\x1f\x19\x16\x81\x01`\x01`\x01`@\x1b\x03\x81\x11\x82\x82\x10\x17\x15a\x07\xd6Wa\x07\xd6a\x07pV[`@R\x91\x90PV[`\x00\x82`\x1f\x83\x01\x12a\x07\xefW`\x00\x80\xfd[\x815`\x01`\x01`@\x1b\x03\x81\x11\x15a\x08\x08Wa\x08\x08a\x07pV[a\x08\x1b`\x1f\x82\x01`\x1f\x19\x16` \x01a\x07\xaeV[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x080W`\x00\x80\xfd[\x81` \x85\x01` \x83\x017`\x00\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[`\x00\x80`@\x83\x85\x03\x12\x15a\x08`W`\x00\x80\xfd[\x825\x91P` \x83\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x08}W`\x00\x80\xfd[a\x08\x89\x85\x82\x86\x01a\x07\xdeV[\x91PP\x92P\x92\x90PV[`\x00\x81Q\x80\x84R`\x00[\x81\x81\x10\x15a\x08\xb9W` \x81\x85\x01\x81\x01Q\x86\x83\x01\x82\x01R\x01a\x08\x9dV[P`\x00` \x82\x86\x01\x01R` `\x1f\x19`\x1f\x83\x01\x16\x85\x01\x01\x91PP\x92\x91PPV[` \x81R`\x00a\x07?` \x83\x01\x84a\x08\x93V[`\x00` \x82\x84\x03\x12\x15a\x08\xfeW`\x00\x80\xfd[P5\x91\x90PV[\x805`\x01`\x01`\xa0\x1b\x03\x81\x16\x81\x14a\x07\x1fW`\x00\x80\xfd[`\x00\x80`@\x83\x85\x03\x12\x15a\t/W`\x00\x80\xfd[a\t8\x83a\t\x05V[\x94` \x93\x90\x93\x015\x93PPPV[`\x00`@\x82\x84\x03\x12\x15a\tXW`\x00\x80\xfd[`@Q`@\x81\x01\x81\x81\x10`\x01`\x01`@\x1b\x03\x82\x11\x17\x15a\tzWa\tza\x07pV[`@R\x90P\x80a\t\x89\x83a\t\x05V[\x81R` \x83\x015` \x82\x01RP\x92\x91PPV[`\x00`@\x82\x84\x03\x12\x15a\t\xaeW`\x00\x80\xfd[a\x07?\x83\x83a\tFV[`\x00\x80``\x83\x85\x03\x12\x15a\t\xcbW`\x00\x80\xfd[a\t\xd5\x84\x84a\tFV[\x94`@\x93\x90\x93\x015\x93PPPV[`\x00` \x82\x84\x03\x12\x15a\t\xf5W`\x00\x80\xfd[a\x07?\x82a\t\x05V[`\x00\x80`\x00``\x84\x86\x03\x12\x15a\n\x13W`\x00\x80\xfd[\x835\x92P` \x84\x015`\x01`\x01`@\x1b\x03\x80\x82\x11\x15a\n1W`\x00\x80\xfd[a\n=\x87\x83\x88\x01a\x07\xdeV[\x93P`@\x86\x015\x91P\x80\x82\x11\x15a\nSW`\x00\x80\xfd[Pa\n`\x86\x82\x87\x01a\x07\xdeV[\x91PP\x92P\x92P\x92V[`\x00\x80`\x00\x80`\x80\x85\x87\x03\x12\x15a\n\x80W`\x00\x80\xfd[\x845`\x01`\x01`@\x1b\x03\x81\x11\x15a\n\x96W`\x00\x80\xfd[a\n\xa2\x87\x82\x88\x01a\x07\xdeV[\x94PPa\n\xb1` \x86\x01a\x07\x0fV[\x92Pa\n\xbf`@\x86\x01a\x07\x0fV[\x91Pa\n\xcd``\x86\x01a\x07\x0fV[\x90P\x92\x95\x91\x94P\x92PV[`\x00\x80`\x00``\x84\x86\x03\x12\x15a\n\xedW`\x00\x80\xfd[a\n\xf6\x84a\t\x05V[\x92Pa\x0b\x04` \x85\x01a\t\x05V[\x91P`@\x84\x015\x90P\x92P\x92P\x92V[`\x00\x80`@\x83\x85\x03\x12\x15a\x0b\'W`\x00\x80\xfd[\x825`\x01`\x01`@\x1b\x03\x80\x82\x11\x15a\x0b>W`\x00\x80\xfd[a\x0bJ\x86\x83\x87\x01a\x07\xdeV[\x93P` \x85\x015\x91P\x80\x82\x11\x15a\x0b`W`\x00\x80\xfd[Pa\x08\x89\x85\x82\x86\x01a\x07\xdeV[`\x00`\x01`\x01`@\x1b\x03\x82\x11\x15a\x0b\x86Wa\x0b\x86a\x07pV[P`\x05\x1b` \x01\x90V[`\x00\x80`@\x80\x84\x86\x03\x12\x15a\x0b\xa4W`\x00\x80\xfd[a\x0b\xad\x84a\t\x05V[\x92P` \x80\x85\x015`\x01`\x01`@\x1b\x03\x80\x82\x11\x15a\x0b\xcaW`\x00\x80\xfd[\x81\x87\x01\x91P\x87`\x1f\x83\x01\x12a\x0b\xdeW`\x00\x80\xfd[\x815a\x0b\xf1a\x0b\xec\x82a\x0bmV[a\x07\xaeV[\x81\x81R`\x05\x91\x90\x91\x1b\x83\x01\x84\x01\x90\x84\x81\x01\x90\x8a\x83\x11\x15a\x0c\x10W`\x00\x80\xfd[\x85\x85\x01[\x83\x81\x10\x15a\x0c\x83W\x805\x85\x81\x11\x15a\x0c,W`\x00\x80\x81\xfd[\x86\x01\x80\x8d\x03`\x1f\x19\x01\x89\x13\x15a\x0cBW`\x00\x80\x81\xfd[a\x0cJa\x07\x86V[\x88\x82\x015\x81R\x89\x82\x015\x87\x81\x11\x15a\x0cbW`\x00\x80\x81\xfd[a\x0cp\x8f\x8b\x83\x86\x01\x01a\x07\xdeV[\x82\x8b\x01RP\x84RP\x91\x86\x01\x91\x86\x01a\x0c\x14V[P\x80\x97PPPPPPPP\x92P\x92\x90PV[`\x00` \x82\x84\x03\x12\x15a\x0c\xa7W`\x00\x80\xfd[\x815`\xff\x81\x16\x81\x14a\x07?W`\x00\x80\xfd[`\x00\x80`@\x83\x85\x03\x12\x15a\x0c\xcbW`\x00\x80\xfd[a\x0c\xd4\x83a\t\x05V[\x91P` \x80\x84\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0c\xf0W`\x00\x80\xfd[\x84\x01`\x1f\x81\x01\x86\x13a\r\x01W`\x00\x80\xfd[\x805a\r\x0fa\x0b\xec\x82a\x0bmV[\x81\x81R`\x05\x91\x90\x91\x1b\x82\x01\x83\x01\x90\x83\x81\x01\x90\x88\x83\x11\x15a\r.W`\x00\x80\xfd[\x92\x84\x01\x92[\x82\x84\x10\x15a\rLW\x835\x82R\x92\x84\x01\x92\x90\x84\x01\x90a\r3V[\x80\x95PPPPPP\x92P\x92\x90PV[`\x00\x80`\x00``\x84\x86\x03\x12\x15a\rpW`\x00\x80\xfd[a\ry\x84a\t\x05V[\x92P` \x84\x015\x91P`@\x84\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\r\x9bW`\x00\x80\xfd[a\n`\x86\x82\x87\x01a\x07\xdeV[` \x80\x82R\x82Q\x82\x82\x01\x81\x90R`\x00\x91\x90`@\x90\x81\x85\x01\x90\x86\x84\x01\x85[\x82\x81\x10\x15a\r\xfaWa\r\xea\x84\x83Q\x80Q`\x01`\x01`\xa0\x1b\x03\x16\x82R` \x90\x81\x01Q\x91\x01RV[\x92\x84\x01\x92\x90\x85\x01\x90`\x01\x01a\r\xc4V[P\x91\x97\x96PPPPPPPV[`\x00\x80`@\x83\x85\x03\x12\x15a\x0e\x1aW`\x00\x80\xfd[a\x0e#\x83a\x07\x0fV[\x91P` \x80\x84\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0e?W`\x00\x80\xfd[\x84\x01`\x1f\x81\x01\x86\x13a\x0ePW`\x00\x80\xfd[\x805a\x0e^a\x0b\xec\x82a\x0bmV[\x81\x81R`\x05\x91\x90\x91\x1b\x82\x01\x83\x01\x90\x83\x81\x01\x90\x88\x83\x11\x15a\x0e}W`\x00\x80\xfd[\x92\x84\x01\x92[\x82\x84\x10\x15a\rLWa\x0e\x93\x84a\t\x05V[\x82R\x92\x84\x01\x92\x90\x84\x01\x90a\x0e\x82V[`\x00\x80`@\x83\x85\x03\x12\x15a\x0e\xb5W`\x00\x80\xfd[\x825`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0e\xcbW`\x00\x80\xfd[a\x0e\xd7\x85\x82\x86\x01a\x07\xdeV[\x92PP` \x83\x015c\xff\xff\xff\xff\x81\x16\x81\x14a\x0e\xf1W`\x00\x80\xfd[\x80\x91PP\x92P\x92\x90PV[\x81Q`\x01`\x01`\xa0\x1b\x03\x16\x81R` \x80\x83\x01Q\x90\x82\x01R`@\x81\x01a\x06\xc4V[`\x00` \x82\x84\x03\x12\x15a\x0f.W`\x00\x80\xfd[\x815`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0fDW`\x00\x80\xfd[a\x0fP\x84\x82\x85\x01a\x07\xdeV[\x94\x93PPPPV[`\x00\x80`@\x83\x85\x03\x12\x15a\x0fkW`\x00\x80\xfd[\x825`\x01`\x01`@\x1b\x03\x81\x11\x15a\x0f\x81W`\x00\x80\xfd[a\x0f\x8d\x85\x82\x86\x01a\x07\xdeV[\x92PPa\x0f\x9c` \x84\x01a\x07\x0fV[\x90P\x92P\x92\x90PV[`\x00\x80`@\x83\x85\x03\x12\x15a\x0f\xb8W`\x00\x80\xfd[a\x0f\xc1\x83a\t\x05V[\x91Pa\x0f\x9c` \x84\x01a\x07\x0fV[`\x00\x80`\x00\x80`\x80\x85\x87\x03\x12\x15a\x0f\xe5W`\x00\x80\xfd[a\x0f\xee\x85a\t\x05V[\x93Pa\x0f\xfc` \x86\x01a\t\x05V[\x92P`@\x85\x015\x91P``\x85\x015`\x01`\x01`@\x1b\x03\x81\x11\x15a\x10\x1eW`\x00\x80\xfd[a\x10*\x87\x82\x88\x01a\x07\xdeV[\x91PP\x92\x95\x91\x94P\x92PV[`\x00\x80`\x00`\xa0\x84\x86\x03\x12\x15a\x10KW`\x00\x80\xfd[a\x10U\x85\x85a\tFV[\x92Pa\x10d\x85`@\x86\x01a\tFV[\x91P`\x80\x84\x015\x90P\x92P\x92P\x92V[`\x00\x80`@\x83\x85\x03\x12\x15a\x10\x87W`\x00\x80\xfd[a\x10\x90\x83a\t\x05V[\x91Pa\x0f\x9c` \x84\x01a\t\x05V[`\x00` \x80\x83R`\x00\x84T\x81`\x01\x82\x81\x1c\x91P\x80\x83\x16\x80a\x10\xc0W`\x7f\x83\x16\x92P[\x85\x83\x10\x81\x03a\x10\xddWcNH{q`\xe0\x1b\x85R`\"`\x04R`$\x85\xfd[\x87\x86\x01\x83\x81R` \x01\x81\x80\x15a\x10\xfaW`\x01\x81\x14a\x11\x10Wa\x11;V[`\xff\x19\x86\x16\x82R\x84\x15\x15`\x05\x1b\x82\x01\x96Pa\x11;V[`\x00\x8b\x81R` \x90 `\x00[\x86\x81\x10\x15a\x115W\x81T\x84\x82\x01R\x90\x85\x01\x90\x89\x01a\x11\x1cV[\x83\x01\x97PP[P\x94\x99\x98PPPPPPPPPV\xfe\xa2dipfsX\"\x12 eT\x15\xcb|u\xb1F\x80}\xaa]\xc0#\xe0\xdeO$^\x96a\xfb1\xc5\xb0\xfa\t\x12\x00>F\xa8dsolcC\x00\x08\x10\x003this contract is implemented in native";5938 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {5939 call::<T, UniqueNFTCall<T>, _, _>(handle, self)5940 }5941 }5942}5943pub mod weights {5944 //! Autogenerated weights for pallet_nonfungible5945 //!5946 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev5947 //! DATE: 2022-08-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`5948 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 10245949 #![allow(unused_parens)]5950 #![allow(unused_imports)]5951 #![allow(clippy::unnecessary_cast)]5952 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};5953 use sp_std::marker::PhantomData;5954 /// Weight functions needed for pallet_nonfungible.5955 pub trait WeightInfo {5956 fn create_item() -> Weight;5957 fn create_multiple_items(b: u32) -> Weight;5958 fn create_multiple_items_ex(b: u32) -> Weight;5959 fn burn_item() -> Weight;5960 fn burn_recursively_self_raw() -> Weight;5961 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32) -> Weight;5962 fn transfer() -> Weight;5963 fn approve() -> Weight;5964 fn transfer_from() -> Weight;5965 fn burn_from() -> Weight;5966 fn set_token_property_permissions(b: u32) -> Weight;5967 fn set_token_properties(b: u32) -> Weight;5968 fn delete_token_properties(b: u32) -> Weight;5969 fn token_owner() -> Weight;5970 }5971 /// Weights for pallet_nonfungible using the Substrate node and recommended hardware.5972 pub struct SubstrateWeight<T>(PhantomData<T>);5973 impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {5974 fn create_item() -> Weight {5975 Weight::from_ref_time(25_905_000)5976 .saturating_add(T::DbWeight::get().reads(2 as u64))5977 .saturating_add(T::DbWeight::get().writes(4 as u64))5978 }5979 fn create_multiple_items(b: u32) -> Weight {5980 Weight::from_ref_time(24_955_000)5981 .saturating_add(5982 Weight::from_ref_time(5_340_000).saturating_mul(b as u64),5983 )5984 .saturating_add(T::DbWeight::get().reads(2 as u64))5985 .saturating_add(T::DbWeight::get().writes(2 as u64))5986 .saturating_add(5987 T::DbWeight::get().writes((2 as u64).saturating_mul(b as u64)),5988 )5989 }5990 fn create_multiple_items_ex(b: u32) -> Weight {5991 Weight::from_ref_time(13_666_000)5992 .saturating_add(5993 Weight::from_ref_time(8_299_000).saturating_mul(b as u64),5994 )5995 .saturating_add(T::DbWeight::get().reads(1 as u64))5996 .saturating_add(5997 T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64)),5998 )5999 .saturating_add(T::DbWeight::get().writes(1 as u64))6000 .saturating_add(6001 T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64)),6002 )6003 }6004 fn burn_item() -> Weight {6005 Weight::from_ref_time(36_205_000)6006 .saturating_add(T::DbWeight::get().reads(5 as u64))6007 .saturating_add(T::DbWeight::get().writes(5 as u64))6008 }6009 fn burn_recursively_self_raw() -> Weight {6010 Weight::from_ref_time(44_550_000)6011 .saturating_add(T::DbWeight::get().reads(5 as u64))6012 .saturating_add(T::DbWeight::get().writes(5 as u64))6013 }6014 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32) -> Weight {6015 (Weight::from_ref_time(0))6016 .saturating_add(6017 Weight::from_ref_time(312_125_000).saturating_mul(b as u64),6018 )6019 .saturating_add(T::DbWeight::get().reads(7 as u64))6020 .saturating_add(6021 T::DbWeight::get().reads((4 as u64).saturating_mul(b as u64)),6022 )6023 .saturating_add(T::DbWeight::get().writes(6 as u64))6024 .saturating_add(6025 T::DbWeight::get().writes((4 as u64).saturating_mul(b as u64)),6026 )6027 }6028 fn transfer() -> Weight {6029 Weight::from_ref_time(31_116_000)6030 .saturating_add(T::DbWeight::get().reads(4 as u64))6031 .saturating_add(T::DbWeight::get().writes(5 as u64))6032 }6033 fn approve() -> Weight {6034 Weight::from_ref_time(20_802_000)6035 .saturating_add(T::DbWeight::get().reads(2 as u64))6036 .saturating_add(T::DbWeight::get().writes(1 as u64))6037 }6038 fn transfer_from() -> Weight {6039 Weight::from_ref_time(36_083_000)6040 .saturating_add(T::DbWeight::get().reads(4 as u64))6041 .saturating_add(T::DbWeight::get().writes(6 as u64))6042 }6043 fn burn_from() -> Weight {6044 Weight::from_ref_time(41_781_000)6045 .saturating_add(T::DbWeight::get().reads(5 as u64))6046 .saturating_add(T::DbWeight::get().writes(6 as u64))6047 }6048 fn set_token_property_permissions(b: u32) -> Weight {6049 (Weight::from_ref_time(0))6050 .saturating_add(6051 Weight::from_ref_time(15_705_000).saturating_mul(b as u64),6052 )6053 .saturating_add(T::DbWeight::get().reads(1 as u64))6054 .saturating_add(T::DbWeight::get().writes(1 as u64))6055 }6056 fn set_token_properties(b: u32) -> Weight {6057 (Weight::from_ref_time(0))6058 .saturating_add(6059 Weight::from_ref_time(590_344_000).saturating_mul(b as u64),6060 )6061 .saturating_add(T::DbWeight::get().reads(2 as u64))6062 .saturating_add(T::DbWeight::get().writes(1 as u64))6063 }6064 fn delete_token_properties(b: u32) -> Weight {6065 (Weight::from_ref_time(0))6066 .saturating_add(6067 Weight::from_ref_time(605_836_000).saturating_mul(b as u64),6068 )6069 .saturating_add(T::DbWeight::get().reads(2 as u64))6070 .saturating_add(T::DbWeight::get().writes(1 as u64))6071 }6072 fn token_owner() -> Weight {6073 Weight::from_ref_time(4_366_000)6074 .saturating_add(T::DbWeight::get().reads(1 as u64))6075 }6076 }6077 impl WeightInfo for () {6078 fn create_item() -> Weight {6079 Weight::from_ref_time(25_905_000)6080 .saturating_add(RocksDbWeight::get().reads(2 as u64))6081 .saturating_add(RocksDbWeight::get().writes(4 as u64))6082 }6083 fn create_multiple_items(b: u32) -> Weight {6084 Weight::from_ref_time(24_955_000)6085 .saturating_add(6086 Weight::from_ref_time(5_340_000).saturating_mul(b as u64),6087 )6088 .saturating_add(RocksDbWeight::get().reads(2 as u64))6089 .saturating_add(RocksDbWeight::get().writes(2 as u64))6090 .saturating_add(6091 RocksDbWeight::get().writes((2 as u64).saturating_mul(b as u64)),6092 )6093 }6094 fn create_multiple_items_ex(b: u32) -> Weight {6095 Weight::from_ref_time(13_666_000)6096 .saturating_add(6097 Weight::from_ref_time(8_299_000).saturating_mul(b as u64),6098 )6099 .saturating_add(RocksDbWeight::get().reads(1 as u64))6100 .saturating_add(6101 RocksDbWeight::get().reads((1 as u64).saturating_mul(b as u64)),6102 )6103 .saturating_add(RocksDbWeight::get().writes(1 as u64))6104 .saturating_add(6105 RocksDbWeight::get().writes((3 as u64).saturating_mul(b as u64)),6106 )6107 }6108 fn burn_item() -> Weight {6109 Weight::from_ref_time(36_205_000)6110 .saturating_add(RocksDbWeight::get().reads(5 as u64))6111 .saturating_add(RocksDbWeight::get().writes(5 as u64))6112 }6113 fn burn_recursively_self_raw() -> Weight {6114 Weight::from_ref_time(44_550_000)6115 .saturating_add(RocksDbWeight::get().reads(5 as u64))6116 .saturating_add(RocksDbWeight::get().writes(5 as u64))6117 }6118 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32) -> Weight {6119 (Weight::from_ref_time(0))6120 .saturating_add(6121 Weight::from_ref_time(312_125_000).saturating_mul(b as u64),6122 )6123 .saturating_add(RocksDbWeight::get().reads(7 as u64))6124 .saturating_add(6125 RocksDbWeight::get().reads((4 as u64).saturating_mul(b as u64)),6126 )6127 .saturating_add(RocksDbWeight::get().writes(6 as u64))6128 .saturating_add(6129 RocksDbWeight::get().writes((4 as u64).saturating_mul(b as u64)),6130 )6131 }6132 fn transfer() -> Weight {6133 Weight::from_ref_time(31_116_000)6134 .saturating_add(RocksDbWeight::get().reads(4 as u64))6135 .saturating_add(RocksDbWeight::get().writes(5 as u64))6136 }6137 fn approve() -> Weight {6138 Weight::from_ref_time(20_802_000)6139 .saturating_add(RocksDbWeight::get().reads(2 as u64))6140 .saturating_add(RocksDbWeight::get().writes(1 as u64))6141 }6142 fn transfer_from() -> Weight {6143 Weight::from_ref_time(36_083_000)6144 .saturating_add(RocksDbWeight::get().reads(4 as u64))6145 .saturating_add(RocksDbWeight::get().writes(6 as u64))6146 }6147 fn burn_from() -> Weight {6148 Weight::from_ref_time(41_781_000)6149 .saturating_add(RocksDbWeight::get().reads(5 as u64))6150 .saturating_add(RocksDbWeight::get().writes(6 as u64))6151 }6152 fn set_token_property_permissions(b: u32) -> Weight {6153 (Weight::from_ref_time(0))6154 .saturating_add(6155 Weight::from_ref_time(15_705_000).saturating_mul(b as u64),6156 )6157 .saturating_add(RocksDbWeight::get().reads(1 as u64))6158 .saturating_add(RocksDbWeight::get().writes(1 as u64))6159 }6160 fn set_token_properties(b: u32) -> Weight {6161 (Weight::from_ref_time(0))6162 .saturating_add(6163 Weight::from_ref_time(590_344_000).saturating_mul(b as u64),6164 )6165 .saturating_add(RocksDbWeight::get().reads(2 as u64))6166 .saturating_add(RocksDbWeight::get().writes(1 as u64))6167 }6168 fn delete_token_properties(b: u32) -> Weight {6169 (Weight::from_ref_time(0))6170 .saturating_add(6171 Weight::from_ref_time(605_836_000).saturating_mul(b as u64),6172 )6173 .saturating_add(RocksDbWeight::get().reads(2 as u64))6174 .saturating_add(RocksDbWeight::get().writes(1 as u64))6175 }6176 fn token_owner() -> Weight {6177 Weight::from_ref_time(4_366_000)6178 .saturating_add(RocksDbWeight::get().reads(1 as u64))6179 }6180 }6181}6182pub type CreateItemData<T> = CreateNftExData<6183 <T as pallet_evm::account::Config>::CrossAccountId,6184>;6185pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;6186/// Token data, stored independently from other data used to describe it6187/// for the convenience of database access. Notably contains the owner account address.6188pub struct ItemDataVersion1<CrossAccountId> {6189 pub const_data: BoundedVec<u8, CustomDataLimit>,6190 pub variable_data: BoundedVec<u8, CustomDataLimit>,6191 pub owner: CrossAccountId,6192}6193#[allow(deprecated)]6194const _: () = {6195 #[automatically_derived]6196 impl<CrossAccountId> ::codec::Encode for ItemDataVersion1<CrossAccountId>6197 where6198 CrossAccountId: ::codec::Encode,6199 CrossAccountId: ::codec::Encode,6200 {6201 fn encode_to<__CodecOutputEdqy: ::codec::Output + ?::core::marker::Sized>(6202 &self,6203 __codec_dest_edqy: &mut __CodecOutputEdqy,6204 ) {6205 ::codec::Encode::encode_to(&self.const_data, __codec_dest_edqy);6206 ::codec::Encode::encode_to(&self.variable_data, __codec_dest_edqy);6207 ::codec::Encode::encode_to(&self.owner, __codec_dest_edqy);6208 }6209 }6210 #[automatically_derived]6211 impl<CrossAccountId> ::codec::EncodeLike for ItemDataVersion1<CrossAccountId>6212 where6213 CrossAccountId: ::codec::Encode,6214 CrossAccountId: ::codec::Encode,6215 {}6216};6217#[allow(deprecated)]6218const _: () = {6219 #[automatically_derived]6220 impl<CrossAccountId> ::codec::Decode for ItemDataVersion1<CrossAccountId>6221 where6222 CrossAccountId: ::codec::Decode,6223 CrossAccountId: ::codec::Decode,6224 {6225 fn decode<__CodecInputEdqy: ::codec::Input>(6226 __codec_input_edqy: &mut __CodecInputEdqy,6227 ) -> ::core::result::Result<Self, ::codec::Error> {6228 ::core::result::Result::Ok(ItemDataVersion1::<CrossAccountId> {6229 const_data: {6230 let __codec_res_edqy = <BoundedVec<6231 u8,6232 CustomDataLimit,6233 > as ::codec::Decode>::decode(__codec_input_edqy);6234 match __codec_res_edqy {6235 ::core::result::Result::Err(e) => {6236 return ::core::result::Result::Err(6237 e.chain("Could not decode `ItemDataVersion1::const_data`"),6238 );6239 }6240 ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,6241 }6242 },6243 variable_data: {6244 let __codec_res_edqy = <BoundedVec<6245 u8,6246 CustomDataLimit,6247 > as ::codec::Decode>::decode(__codec_input_edqy);6248 match __codec_res_edqy {6249 ::core::result::Result::Err(e) => {6250 return ::core::result::Result::Err(6251 e6252 .chain("Could not decode `ItemDataVersion1::variable_data`"),6253 );6254 }6255 ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,6256 }6257 },6258 owner: {6259 let __codec_res_edqy = <CrossAccountId as ::codec::Decode>::decode(6260 __codec_input_edqy,6261 );6262 match __codec_res_edqy {6263 ::core::result::Result::Err(e) => {6264 return ::core::result::Result::Err(6265 e.chain("Could not decode `ItemDataVersion1::owner`"),6266 );6267 }6268 ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,6269 }6270 },6271 })6272 }6273 }6274};6275#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]6276const _: () = {6277 impl<CrossAccountId> ::scale_info::TypeInfo for ItemDataVersion1<CrossAccountId>6278 where6279 CrossAccountId: ::scale_info::TypeInfo + 'static,6280 CrossAccountId: ::scale_info::TypeInfo + 'static,6281 {6282 type Identity = Self;6283 fn type_info() -> ::scale_info::Type {6284 ::scale_info::Type::builder()6285 .path(::scale_info::Path::new("ItemDataVersion1", "pallet_nonfungible"))6286 .type_params(6287 <[_]>::into_vec(6288 #[rustc_box]6289 ::alloc::boxed::Box::new([6290 ::scale_info::TypeParameter::new(6291 "CrossAccountId",6292 ::core::option::Option::Some(6293 ::scale_info::meta_type::<CrossAccountId>(),6294 ),6295 ),6296 ]),6297 ),6298 )6299 .docs(6300 &[6301 "Token data, stored independently from other data used to describe it",6302 "for the convenience of database access. Notably contains the owner account address.",6303 ],6304 )6305 .composite(6306 ::scale_info::build::Fields::named()6307 .field(|f| {6308 f6309 .ty::<BoundedVec<u8, CustomDataLimit>>()6310 .name("const_data")6311 .type_name("BoundedVec<u8, CustomDataLimit>")6312 .docs(&[])6313 })6314 .field(|f| {6315 f6316 .ty::<BoundedVec<u8, CustomDataLimit>>()6317 .name("variable_data")6318 .type_name("BoundedVec<u8, CustomDataLimit>")6319 .docs(&[])6320 })6321 .field(|f| {6322 f6323 .ty::<CrossAccountId>()6324 .name("owner")6325 .type_name("CrossAccountId")6326 .docs(&[])6327 }),6328 )6329 }6330 }6331};6332const _: () = {6333 impl<CrossAccountId> ::codec::MaxEncodedLen for ItemDataVersion1<CrossAccountId>6334 where6335 CrossAccountId: ::codec::MaxEncodedLen,6336 CrossAccountId: ::codec::MaxEncodedLen,6337 {6338 fn max_encoded_len() -> ::core::primitive::usize {6339 0_usize6340 .saturating_add(<BoundedVec<u8, CustomDataLimit>>::max_encoded_len())6341 .saturating_add(<BoundedVec<u8, CustomDataLimit>>::max_encoded_len())6342 .saturating_add(<CrossAccountId>::max_encoded_len())6343 }6344 }6345};6346/// Token data, stored independently from other data used to describe it6347/// for the convenience of database access. Notably contains the owner account address.6348/// # Versioning6349/// Changes between 1 and 2:6350/// - const_data: BoundedVec < u8, CustomDataLimit > was removed6351/// - variable_data: BoundedVec < u8, CustomDataLimit > was removed6352pub struct ItemData<CrossAccountId> {6353 pub owner: CrossAccountId,6354}6355#[allow(deprecated)]6356const _: () = {6357 #[automatically_derived]6358 impl<CrossAccountId> ::codec::Encode for ItemData<CrossAccountId>6359 where6360 CrossAccountId: ::codec::Encode,6361 CrossAccountId: ::codec::Encode,6362 {6363 fn encode_to<__CodecOutputEdqy: ::codec::Output + ?::core::marker::Sized>(6364 &self,6365 __codec_dest_edqy: &mut __CodecOutputEdqy,6366 ) {6367 ::codec::Encode::encode_to(&&self.owner, __codec_dest_edqy)6368 }6369 fn encode(&self) -> ::codec::alloc::vec::Vec<::core::primitive::u8> {6370 ::codec::Encode::encode(&&self.owner)6371 }6372 fn using_encoded<R, F: ::core::ops::FnOnce(&[::core::primitive::u8]) -> R>(6373 &self,6374 f: F,6375 ) -> R {6376 ::codec::Encode::using_encoded(&&self.owner, f)6377 }6378 }6379 #[automatically_derived]6380 impl<CrossAccountId> ::codec::EncodeLike for ItemData<CrossAccountId>6381 where6382 CrossAccountId: ::codec::Encode,6383 CrossAccountId: ::codec::Encode,6384 {}6385};6386#[allow(deprecated)]6387const _: () = {6388 #[automatically_derived]6389 impl<CrossAccountId> ::codec::Decode for ItemData<CrossAccountId>6390 where6391 CrossAccountId: ::codec::Decode,6392 CrossAccountId: ::codec::Decode,6393 {6394 fn decode<__CodecInputEdqy: ::codec::Input>(6395 __codec_input_edqy: &mut __CodecInputEdqy,6396 ) -> ::core::result::Result<Self, ::codec::Error> {6397 ::core::result::Result::Ok(ItemData::<CrossAccountId> {6398 owner: {6399 let __codec_res_edqy = <CrossAccountId as ::codec::Decode>::decode(6400 __codec_input_edqy,6401 );6402 match __codec_res_edqy {6403 ::core::result::Result::Err(e) => {6404 return ::core::result::Result::Err(6405 e.chain("Could not decode `ItemData::owner`"),6406 );6407 }6408 ::core::result::Result::Ok(__codec_res_edqy) => __codec_res_edqy,6409 }6410 },6411 })6412 }6413 }6414};6415#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]6416const _: () = {6417 impl<CrossAccountId> ::scale_info::TypeInfo for ItemData<CrossAccountId>6418 where6419 CrossAccountId: ::scale_info::TypeInfo + 'static,6420 CrossAccountId: ::scale_info::TypeInfo + 'static,6421 {6422 type Identity = Self;6423 fn type_info() -> ::scale_info::Type {6424 ::scale_info::Type::builder()6425 .path(::scale_info::Path::new("ItemData", "pallet_nonfungible"))6426 .type_params(6427 <[_]>::into_vec(6428 #[rustc_box]6429 ::alloc::boxed::Box::new([6430 ::scale_info::TypeParameter::new(6431 "CrossAccountId",6432 ::core::option::Option::Some(6433 ::scale_info::meta_type::<CrossAccountId>(),6434 ),6435 ),6436 ]),6437 ),6438 )6439 .docs(6440 &[6441 "Token data, stored independently from other data used to describe it",6442 "for the convenience of database access. Notably contains the owner account address.",6443 "# Versioning",6444 "Changes between 1 and 2:",6445 "- const_data: BoundedVec < u8, CustomDataLimit > was removed",6446 "- variable_data: BoundedVec < u8, CustomDataLimit > was removed",6447 ],6448 )6449 .composite(6450 ::scale_info::build::Fields::named()6451 .field(|f| {6452 f6453 .ty::<CrossAccountId>()6454 .name("owner")6455 .type_name("CrossAccountId")6456 .docs(&[])6457 }),6458 )6459 }6460 }6461};6462const _: () = {6463 impl<CrossAccountId> ::codec::MaxEncodedLen for ItemData<CrossAccountId>6464 where6465 CrossAccountId: ::codec::MaxEncodedLen,6466 CrossAccountId: ::codec::MaxEncodedLen,6467 {6468 fn max_encoded_len() -> ::core::primitive::usize {6469 0_usize.saturating_add(<CrossAccountId>::max_encoded_len())6470 }6471 }6472};6473impl<CrossAccountId> From<ItemDataVersion1<CrossAccountId>>6474for ItemData<CrossAccountId> {6475 fn from(old: ItemDataVersion1<CrossAccountId>) -> Self {6476 let ItemDataVersion1 { const_data, variable_data, owner } = old;6477 let _ = &const_data;6478 let _ = &variable_data;6479 Self { owner }6480 }6481}6482pub type ItemDataVersion2<CrossAccountId> = ItemData<CrossAccountId>;6483/**6484 The module that hosts all the6485 [FRAME](https://docs.substrate.io/main-docs/build/events-errors/)6486 types needed to add this pallet to a6487 runtime.6488 */6489pub mod pallet {6490 use super::*;6491 use frame_support::{6492 Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key,6493 traits::StorageVersion,6494 };6495 use frame_system::pallet_prelude::*;6496 use up_data_structs::{CollectionId, TokenId};6497 use super::weights::WeightInfo;6498 #[scale_info(skip_type_params(T), capture_docs = "always")]6499 /**6500 Custom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)6501 of this pallet.6502 */6503 pub enum Error<T> {6504 #[doc(hidden)]6505 #[codec(skip)]6506 __Ignore(frame_support::sp_std::marker::PhantomData<(T)>, frame_support::Never),6507 /// Not Nonfungible item data used to mint in Nonfungible collection.6508 NotNonfungibleDataUsedToMintFungibleCollectionToken,6509 /// Used amount > 1 with NFT6510 NonfungibleItemsHaveNoAmount,6511 /// Unable to burn NFT with children6512 CantBurnNftWithChildren,6513 }6514 #[allow(deprecated)]6515 const _: () = {6516 #[automatically_derived]6517 impl<T> ::codec::Encode for Error<T> {6518 fn encode_to<__CodecOutputEdqy: ::codec::Output + ?::core::marker::Sized>(6519 &self,6520 __codec_dest_edqy: &mut __CodecOutputEdqy,6521 ) {6522 match *self {6523 Error::NotNonfungibleDataUsedToMintFungibleCollectionToken => {6524 __codec_dest_edqy.push_byte(0usize as ::core::primitive::u8);6525 }6526 Error::NonfungibleItemsHaveNoAmount => {6527 __codec_dest_edqy.push_byte(1usize as ::core::primitive::u8);6528 }6529 Error::CantBurnNftWithChildren => {6530 __codec_dest_edqy.push_byte(2usize as ::core::primitive::u8);6531 }6532 _ => {}6533 }6534 }6535 }6536 #[automatically_derived]6537 impl<T> ::codec::EncodeLike for Error<T> {}6538 };6539 #[allow(deprecated)]6540 const _: () = {6541 #[automatically_derived]6542 impl<T> ::codec::Decode for Error<T> {6543 fn decode<__CodecInputEdqy: ::codec::Input>(6544 __codec_input_edqy: &mut __CodecInputEdqy,6545 ) -> ::core::result::Result<Self, ::codec::Error> {6546 match __codec_input_edqy6547 .read_byte()6548 .map_err(|e| {6549 e.chain("Could not decode `Error`, failed to read variant byte")6550 })?6551 {6552 __codec_x_edqy if __codec_x_edqy6553 == 0usize as ::core::primitive::u8 => {6554 ::core::result::Result::Ok(6555 Error::<6556 T,6557 >::NotNonfungibleDataUsedToMintFungibleCollectionToken,6558 )6559 }6560 __codec_x_edqy if __codec_x_edqy6561 == 1usize as ::core::primitive::u8 => {6562 ::core::result::Result::Ok(6563 Error::<T>::NonfungibleItemsHaveNoAmount,6564 )6565 }6566 __codec_x_edqy if __codec_x_edqy6567 == 2usize as ::core::primitive::u8 => {6568 ::core::result::Result::Ok(Error::<T>::CantBurnNftWithChildren)6569 }6570 _ => {6571 ::core::result::Result::Err(6572 <_ as ::core::convert::Into<6573 _,6574 >>::into("Could not decode `Error`, variant doesn't exist"),6575 )6576 }6577 }6578 }6579 }6580 };6581 #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]6582 const _: () = {6583 impl<T> ::scale_info::TypeInfo for Error<T>6584 where6585 frame_support::sp_std::marker::PhantomData<6586 (T),6587 >: ::scale_info::TypeInfo + 'static,6588 T: 'static,6589 {6590 type Identity = Self;6591 fn type_info() -> ::scale_info::Type {6592 ::scale_info::Type::builder()6593 .path(::scale_info::Path::new("Error", "pallet_nonfungible::pallet"))6594 .type_params(6595 <[_]>::into_vec(6596 #[rustc_box]6597 ::alloc::boxed::Box::new([6598 ::scale_info::TypeParameter::new(6599 "T",6600 ::core::option::Option::None,6601 ),6602 ]),6603 ),6604 )6605 .docs_always(6606 &[6607 "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t",6608 ],6609 )6610 .variant(6611 ::scale_info::build::Variants::new()6612 .variant(6613 "NotNonfungibleDataUsedToMintFungibleCollectionToken",6614 |v| {6615 v6616 .index(0usize as ::core::primitive::u8)6617 .docs_always(6618 &[6619 "Not Nonfungible item data used to mint in Nonfungible collection.",6620 ],6621 )6622 },6623 )6624 .variant(6625 "NonfungibleItemsHaveNoAmount",6626 |v| {6627 v6628 .index(1usize as ::core::primitive::u8)6629 .docs_always(&["Used amount > 1 with NFT"])6630 },6631 )6632 .variant(6633 "CantBurnNftWithChildren",6634 |v| {6635 v6636 .index(2usize as ::core::primitive::u8)6637 .docs_always(&["Unable to burn NFT with children"])6638 },6639 ),6640 )6641 }6642 }6643 };6644 const _: () = {6645 impl<T> frame_support::traits::PalletError for Error<T> {6646 const MAX_ENCODED_SIZE: usize = 1;6647 }6648 };6649 /**6650 Configuration trait of this pallet.66516652 Implement this type for a runtime in order to customize this pallet.6653 */6654 pub trait Config: frame_system::Config + pallet_common::Config + pallet_structure::Config + pallet_evm::Config {6655 type WeightInfo: WeightInfo;6656 }6657 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);6658 /**6659 The [pallet](https://docs.substrate.io/reference/frame-pallets/#pallets) implementing6660 the on-chain logic.6661 */6662 pub struct Pallet<T>(frame_support::sp_std::marker::PhantomData<(T)>);6663 const _: () = {6664 impl<T> core::clone::Clone for Pallet<T> {6665 fn clone(&self) -> Self {6666 Self(core::clone::Clone::clone(&self.0))6667 }6668 }6669 };6670 const _: () = {6671 impl<T> core::cmp::Eq for Pallet<T> {}6672 };6673 const _: () = {6674 impl<T> core::cmp::PartialEq for Pallet<T> {6675 fn eq(&self, other: &Self) -> bool {6676 true && self.0 == other.06677 }6678 }6679 };6680 const _: () = {6681 impl<T> core::fmt::Debug for Pallet<T> {6682 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {6683 fmt.debug_tuple("Pallet").field(&self.0).finish()6684 }6685 }6686 };6687 /// Total amount of minted tokens in a collection.6688 #[allow(type_alias_bounds)]6689 pub type TokensMinted<T: Config> = StorageMap<6690 _GeneratedPrefixForStorageTokensMinted<T>,6691 Twox64Concat,6692 CollectionId,6693 u32,6694 ValueQuery,6695 frame_support::traits::GetDefault,6696 frame_support::traits::GetDefault,6697 >;6698 /// Amount of burnt tokens in a collection.6699 #[allow(type_alias_bounds)]6700 pub type TokensBurnt<T: Config> = StorageMap<6701 _GeneratedPrefixForStorageTokensBurnt<T>,6702 Twox64Concat,6703 CollectionId,6704 u32,6705 ValueQuery,6706 frame_support::traits::GetDefault,6707 frame_support::traits::GetDefault,6708 >;6709 /// Token data, used to partially describe a token.6710 #[allow(type_alias_bounds)]6711 pub type TokenData<T: Config> = StorageNMap<6712 _GeneratedPrefixForStorageTokenData<T>,6713 (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),6714 ItemData<T::CrossAccountId>,6715 OptionQuery,6716 frame_support::traits::GetDefault,6717 frame_support::traits::GetDefault,6718 >;6719 /// Map of key-value pairs, describing the metadata of a token.6720 #[allow(type_alias_bounds)]6721 pub type TokenProperties<T: Config> = StorageNMap<6722 _GeneratedPrefixForStorageTokenProperties<T>,6723 (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),6724 Properties,6725 ValueQuery,6726 up_data_structs::TokenProperties,6727 frame_support::traits::GetDefault,6728 >;6729 /// Custom data of a token that is serialized to bytes,6730 /// primarily reserved for on-chain operations,6731 /// normally obscured from the external users.6732 ///6733 /// Auxiliary properties are slightly different from6734 /// usual [`TokenProperties`] due to an unlimited number6735 /// and separately stored and written-to key-value pairs.6736 ///6737 /// Currently used to store RMRK data.6738 #[allow(type_alias_bounds)]6739 pub type TokenAuxProperties<T: Config> = StorageNMap<6740 _GeneratedPrefixForStorageTokenAuxProperties<T>,6741 (6742 Key<Twox64Concat, CollectionId>,6743 Key<Twox64Concat, TokenId>,6744 Key<Twox64Concat, PropertyScope>,6745 Key<Twox64Concat, PropertyKey>,6746 ),6747 AuxPropertyValue,6748 OptionQuery,6749 frame_support::traits::GetDefault,6750 frame_support::traits::GetDefault,6751 >;6752 /// Used to enumerate tokens owned by account.6753 #[allow(type_alias_bounds)]6754 pub type Owned<T: Config> = StorageNMap<6755 _GeneratedPrefixForStorageOwned<T>,6756 (6757 Key<Twox64Concat, CollectionId>,6758 Key<Blake2_128Concat, T::CrossAccountId>,6759 Key<Twox64Concat, TokenId>,6760 ),6761 bool,6762 ValueQuery,6763 frame_support::traits::GetDefault,6764 frame_support::traits::GetDefault,6765 >;6766 /// Used to enumerate token's children.6767 #[allow(type_alias_bounds)]6768 pub type TokenChildren<T: Config> = StorageNMap<6769 _GeneratedPrefixForStorageTokenChildren<T>,6770 (6771 Key<Twox64Concat, CollectionId>,6772 Key<Twox64Concat, TokenId>,6773 Key<Twox64Concat, (CollectionId, TokenId)>,6774 ),6775 bool,6776 ValueQuery,6777 frame_support::traits::GetDefault,6778 frame_support::traits::GetDefault,6779 >;6780 /// Amount of tokens owned by an account in a collection.6781 #[allow(type_alias_bounds)]6782 pub type AccountBalance<T: Config> = StorageNMap<6783 _GeneratedPrefixForStorageAccountBalance<T>,6784 (Key<Twox64Concat, CollectionId>, Key<Blake2_128Concat, T::CrossAccountId>),6785 u32,6786 ValueQuery,6787 frame_support::traits::GetDefault,6788 frame_support::traits::GetDefault,6789 >;6790 /// Allowance set by a token owner for another user to perform one of certain transactions on a token.6791 #[allow(type_alias_bounds)]6792 pub type Allowance<T: Config> = StorageNMap<6793 _GeneratedPrefixForStorageAllowance<T>,6794 (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),6795 T::CrossAccountId,6796 OptionQuery,6797 frame_support::traits::GetDefault,6798 frame_support::traits::GetDefault,6799 >;6800 /// Upgrade from the old schema to properties.6801 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {6802 fn on_runtime_upgrade() -> Weight {6803 StorageVersion::new(1).put::<Pallet<T>>();6804 Weight::zero()6805 }6806 }6807 impl<T: Config> Pallet<T> {6808 #[doc(hidden)]6809 pub fn pallet_constants_metadata() -> frame_support::sp_std::vec::Vec<6810 frame_support::metadata::PalletConstantMetadata,6811 > {6812 ::alloc::vec::Vec::new()6813 }6814 }6815 impl<T: Config> Pallet<T> {6816 #[doc(hidden)]6817 pub fn error_metadata() -> Option<frame_support::metadata::PalletErrorMetadata> {6818 Some(frame_support::metadata::PalletErrorMetadata {6819 ty: frame_support::scale_info::meta_type::<Error<T>>(),6820 })6821 }6822 }6823 /// Type alias to `Pallet`, to be used by `construct_runtime`.6824 ///6825 /// Generated by `pallet` attribute macro.6826 #[deprecated(note = "use `Pallet` instead")]6827 #[allow(dead_code)]6828 pub type Module<T> = Pallet<T>;6829 impl<T: Config> frame_support::traits::GetStorageVersion for Pallet<T> {6830 fn current_storage_version() -> frame_support::traits::StorageVersion {6831 STORAGE_VERSION6832 }6833 fn on_chain_storage_version() -> frame_support::traits::StorageVersion {6834 frame_support::traits::StorageVersion::get::<Self>()6835 }6836 }6837 impl<T: Config> frame_support::traits::OnGenesis for Pallet<T> {6838 fn on_genesis() {6839 let storage_version = STORAGE_VERSION;6840 storage_version.put::<Self>();6841 }6842 }6843 impl<T: Config> frame_support::traits::PalletInfoAccess for Pallet<T> {6844 fn index() -> usize {6845 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::index::<6846 Self,6847 >()6848 .expect(6849 "Pallet is part of the runtime because pallet `Config` trait is \6850 implemented by the runtime",6851 )6852 }6853 fn name() -> &'static str {6854 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<6855 Self,6856 >()6857 .expect(6858 "Pallet is part of the runtime because pallet `Config` trait is \6859 implemented by the runtime",6860 )6861 }6862 fn module_name() -> &'static str {6863 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::module_name::<6864 Self,6865 >()6866 .expect(6867 "Pallet is part of the runtime because pallet `Config` trait is \6868 implemented by the runtime",6869 )6870 }6871 fn crate_version() -> frame_support::traits::CrateVersion {6872 frame_support::traits::CrateVersion {6873 major: 0u16,6874 minor: 1u8,6875 patch: 5u8,6876 }6877 }6878 }6879 impl<T: Config> frame_support::traits::PalletsInfoAccess for Pallet<T> {6880 fn count() -> usize {6881 16882 }6883 fn infos() -> frame_support::sp_std::vec::Vec<6884 frame_support::traits::PalletInfoData,6885 > {6886 use frame_support::traits::PalletInfoAccess;6887 let item = frame_support::traits::PalletInfoData {6888 index: Self::index(),6889 name: Self::name(),6890 module_name: Self::module_name(),6891 crate_version: Self::crate_version(),6892 };6893 <[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([item]))6894 }6895 }6896 impl<T: Config> frame_support::traits::StorageInfoTrait for Pallet<T> {6897 fn storage_info() -> frame_support::sp_std::vec::Vec<6898 frame_support::traits::StorageInfo,6899 > {6900 #[allow(unused_mut)]6901 let mut res = ::alloc::vec::Vec::new();6902 {6903 let mut storage_info = <TokensMinted<6904 T,6905 > as frame_support::traits::StorageInfoTrait>::storage_info();6906 res.append(&mut storage_info);6907 }6908 {6909 let mut storage_info = <TokensBurnt<6910 T,6911 > as frame_support::traits::StorageInfoTrait>::storage_info();6912 res.append(&mut storage_info);6913 }6914 {6915 let mut storage_info = <TokenData<6916 T,6917 > as frame_support::traits::StorageInfoTrait>::storage_info();6918 res.append(&mut storage_info);6919 }6920 {6921 let mut storage_info = <TokenProperties<6922 T,6923 > as frame_support::traits::StorageInfoTrait>::storage_info();6924 res.append(&mut storage_info);6925 }6926 {6927 let mut storage_info = <TokenAuxProperties<6928 T,6929 > as frame_support::traits::StorageInfoTrait>::storage_info();6930 res.append(&mut storage_info);6931 }6932 {6933 let mut storage_info = <Owned<6934 T,6935 > as frame_support::traits::StorageInfoTrait>::storage_info();6936 res.append(&mut storage_info);6937 }6938 {6939 let mut storage_info = <TokenChildren<6940 T,6941 > as frame_support::traits::StorageInfoTrait>::storage_info();6942 res.append(&mut storage_info);6943 }6944 {6945 let mut storage_info = <AccountBalance<6946 T,6947 > as frame_support::traits::StorageInfoTrait>::storage_info();6948 res.append(&mut storage_info);6949 }6950 {6951 let mut storage_info = <Allowance<6952 T,6953 > as frame_support::traits::StorageInfoTrait>::storage_info();6954 res.append(&mut storage_info);6955 }6956 res6957 }6958 }6959 #[doc(hidden)]6960 pub mod __substrate_call_check {6961 #[doc(hidden)]6962 pub use __is_call_part_defined_0 as is_call_part_defined;6963 }6964 ///Contains one variant per dispatchable that can be called by an extrinsic.6965 #[codec(encode_bound())]6966 #[codec(decode_bound())]6967 #[scale_info(skip_type_params(T), capture_docs = "always")]6968 #[allow(non_camel_case_types)]6969 pub enum Call<T: Config> {6970 #[doc(hidden)]6971 #[codec(skip)]6972 __Ignore(frame_support::sp_std::marker::PhantomData<(T,)>, frame_support::Never),6973 }6974 const _: () = {6975 impl<T: Config> core::fmt::Debug for Call<T> {6976 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {6977 match *self {6978 Self::__Ignore(ref _0, ref _1) => {6979 fmt.debug_tuple("Call::__Ignore").field(&_0).field(&_1).finish()6980 }6981 }6982 }6983 }6984 };6985 const _: () = {6986 impl<T: Config> core::clone::Clone for Call<T> {6987 fn clone(&self) -> Self {6988 match self {6989 Self::__Ignore(ref _0, ref _1) => {6990 Self::__Ignore(6991 core::clone::Clone::clone(_0),6992 core::clone::Clone::clone(_1),6993 )6994 }6995 }6996 }6997 }6998 };6999 const _: () = {7000 impl<T: Config> core::cmp::Eq for Call<T> {}7001 };7002 const _: () = {7003 impl<T: Config> core::cmp::PartialEq for Call<T> {7004 fn eq(&self, other: &Self) -> bool {7005 match (self, other) {7006 (Self::__Ignore(_0, _1), Self::__Ignore(_0_other, _1_other)) => {7007 true && _0 == _0_other && _1 == _1_other7008 }7009 }7010 }7011 }7012 };7013 #[allow(deprecated)]7014 const _: () = {7015 #[allow(non_camel_case_types)]7016 #[automatically_derived]7017 impl<T: Config> ::codec::Encode for Call<T> {}7018 #[automatically_derived]7019 impl<T: Config> ::codec::EncodeLike for Call<T> {}7020 };7021 #[allow(deprecated)]7022 const _: () = {7023 #[allow(non_camel_case_types)]7024 #[automatically_derived]7025 impl<T: Config> ::codec::Decode for Call<T> {7026 fn decode<__CodecInputEdqy: ::codec::Input>(7027 __codec_input_edqy: &mut __CodecInputEdqy,7028 ) -> ::core::result::Result<Self, ::codec::Error> {7029 match __codec_input_edqy7030 .read_byte()7031 .map_err(|e| {7032 e.chain("Could not decode `Call`, failed to read variant byte")7033 })?7034 {7035 _ => {7036 ::core::result::Result::Err(7037 <_ as ::core::convert::Into<7038 _,7039 >>::into("Could not decode `Call`, variant doesn't exist"),7040 )7041 }7042 }7043 }7044 }7045 };7046 #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]7047 const _: () = {7048 impl<T: Config> ::scale_info::TypeInfo for Call<T>7049 where7050 frame_support::sp_std::marker::PhantomData<7051 (T,),7052 >: ::scale_info::TypeInfo + 'static,7053 T: Config + 'static,7054 {7055 type Identity = Self;7056 fn type_info() -> ::scale_info::Type {7057 ::scale_info::Type::builder()7058 .path(::scale_info::Path::new("Call", "pallet_nonfungible::pallet"))7059 .type_params(7060 <[_]>::into_vec(7061 #[rustc_box]7062 ::alloc::boxed::Box::new([7063 ::scale_info::TypeParameter::new(7064 "T",7065 ::core::option::Option::None,7066 ),7067 ]),7068 ),7069 )7070 .docs_always(7071 &[7072 "Contains one variant per dispatchable that can be called by an extrinsic.",7073 ],7074 )7075 .variant(::scale_info::build::Variants::new())7076 }7077 }7078 };7079 impl<T: Config> Call<T> {}7080 impl<T: Config> frame_support::dispatch::GetDispatchInfo for Call<T> {7081 fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo {7082 match *self {7083 Self::__Ignore(_, _) => {7084 ::core::panicking::panic_fmt(7085 ::core::fmt::Arguments::new_v1(7086 &["internal error: entered unreachable code: "],7087 &[7088 ::core::fmt::ArgumentV1::new_display(7089 &::core::fmt::Arguments::new_v1(7090 &["__Ignore cannot be used"],7091 &[],7092 ),7093 ),7094 ],7095 ),7096 )7097 }7098 }7099 }7100 }7101 impl<T: Config> frame_support::dispatch::GetCallName for Call<T> {7102 fn get_call_name(&self) -> &'static str {7103 match *self {7104 Self::__Ignore(_, _) => {7105 ::core::panicking::panic_fmt(7106 ::core::fmt::Arguments::new_v1(7107 &["internal error: entered unreachable code: "],7108 &[7109 ::core::fmt::ArgumentV1::new_display(7110 &::core::fmt::Arguments::new_v1(7111 &["__PhantomItem cannot be used."],7112 &[],7113 ),7114 ),7115 ],7116 ),7117 )7118 }7119 }7120 }7121 fn get_call_names() -> &'static [&'static str] {7122 &[]7123 }7124 }7125 impl<T: Config> frame_support::traits::UnfilteredDispatchable for Call<T> {7126 type Origin = frame_system::pallet_prelude::OriginFor<T>;7127 fn dispatch_bypass_filter(7128 self,7129 origin: Self::Origin,7130 ) -> frame_support::dispatch::DispatchResultWithPostInfo {7131 match self {7132 Self::__Ignore(_, _) => {7133 let _ = origin;7134 ::core::panicking::panic_fmt(7135 ::core::fmt::Arguments::new_v1(7136 &["internal error: entered unreachable code: "],7137 &[7138 ::core::fmt::ArgumentV1::new_display(7139 &::core::fmt::Arguments::new_v1(7140 &["__PhantomItem cannot be used."],7141 &[],7142 ),7143 ),7144 ],7145 ),7146 );7147 }7148 }7149 }7150 }7151 impl<T: Config> frame_support::dispatch::Callable<T> for Pallet<T> {7152 type Call = Call<T>;7153 }7154 impl<T: Config> Pallet<T> {7155 #[doc(hidden)]7156 pub fn call_functions() -> frame_support::metadata::PalletCallMetadata {7157 frame_support::scale_info::meta_type::<Call<T>>().into()7158 }7159 }7160 impl<T: Config> frame_support::sp_std::fmt::Debug for Error<T> {7161 fn fmt(7162 &self,7163 f: &mut frame_support::sp_std::fmt::Formatter<'_>,7164 ) -> frame_support::sp_std::fmt::Result {7165 f.write_str(self.as_str())7166 }7167 }7168 impl<T: Config> Error<T> {7169 #[doc(hidden)]7170 pub fn as_str(&self) -> &'static str {7171 match &self {7172 Self::__Ignore(_, _) => {7173 ::core::panicking::panic_fmt(7174 ::core::fmt::Arguments::new_v1(7175 &["internal error: entered unreachable code: "],7176 &[7177 ::core::fmt::ArgumentV1::new_display(7178 &::core::fmt::Arguments::new_v1(7179 &["`__Ignore` can never be constructed"],7180 &[],7181 ),7182 ),7183 ],7184 ),7185 )7186 }7187 Self::NotNonfungibleDataUsedToMintFungibleCollectionToken => {7188 "NotNonfungibleDataUsedToMintFungibleCollectionToken"7189 }7190 Self::NonfungibleItemsHaveNoAmount => "NonfungibleItemsHaveNoAmount",7191 Self::CantBurnNftWithChildren => "CantBurnNftWithChildren",7192 }7193 }7194 }7195 impl<T: Config> From<Error<T>> for &'static str {7196 fn from(err: Error<T>) -> &'static str {7197 err.as_str()7198 }7199 }7200 impl<T: Config> From<Error<T>> for frame_support::sp_runtime::DispatchError {7201 fn from(err: Error<T>) -> Self {7202 use frame_support::codec::Encode;7203 let index = <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::index::<7204 Pallet<T>,7205 >()7206 .expect("Every active module has an index in the runtime; qed") as u8;7207 let mut encoded = err.encode();7208 encoded.resize(frame_support::MAX_MODULE_ERROR_ENCODED_SIZE, 0);7209 frame_support::sp_runtime::DispatchError::Module(frame_support::sp_runtime::ModuleError {7210 index,7211 error: TryInto::try_into(encoded)7212 .expect(7213 "encoded error is resized to be equal to the maximum encoded error size; qed",7214 ),7215 message: Some(err.as_str()),7216 })7217 }7218 }7219 pub use __tt_error_token_1 as tt_error_token;7220 #[doc(hidden)]7221 pub mod __substrate_event_check {7222 #[doc(hidden)]7223 pub use __is_event_part_defined_2 as is_event_part_defined;7224 }7225 impl<T: Config> Pallet<T> {7226 #[doc(hidden)]7227 pub fn storage_metadata() -> frame_support::metadata::PalletStorageMetadata {7228 frame_support::metadata::PalletStorageMetadata {7229 prefix: <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7230 Pallet<T>,7231 >()7232 .expect("Every active pallet has a name in the runtime; qed"),7233 entries: {7234 #[allow(unused_mut)]7235 let mut entries = ::alloc::vec::Vec::new();7236 {7237 <TokensMinted<7238 T,7239 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7240 <[_]>::into_vec(7241 #[rustc_box]7242 ::alloc::boxed::Box::new([7243 " Total amount of minted tokens in a collection.",7244 ]),7245 ),7246 &mut entries,7247 );7248 }7249 {7250 <TokensBurnt<7251 T,7252 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7253 <[_]>::into_vec(7254 #[rustc_box]7255 ::alloc::boxed::Box::new([7256 " Amount of burnt tokens in a collection.",7257 ]),7258 ),7259 &mut entries,7260 );7261 }7262 {7263 <TokenData<7264 T,7265 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7266 <[_]>::into_vec(7267 #[rustc_box]7268 ::alloc::boxed::Box::new([7269 " Token data, used to partially describe a token.",7270 ]),7271 ),7272 &mut entries,7273 );7274 }7275 {7276 <TokenProperties<7277 T,7278 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7279 <[_]>::into_vec(7280 #[rustc_box]7281 ::alloc::boxed::Box::new([7282 " Map of key-value pairs, describing the metadata of a token.",7283 ]),7284 ),7285 &mut entries,7286 );7287 }7288 {7289 <TokenAuxProperties<7290 T,7291 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7292 <[_]>::into_vec(7293 #[rustc_box]7294 ::alloc::boxed::Box::new([7295 " Custom data of a token that is serialized to bytes,",7296 " primarily reserved for on-chain operations,",7297 " normally obscured from the external users.",7298 "",7299 " Auxiliary properties are slightly different from",7300 " usual [`TokenProperties`] due to an unlimited number",7301 " and separately stored and written-to key-value pairs.",7302 "",7303 " Currently used to store RMRK data.",7304 ]),7305 ),7306 &mut entries,7307 );7308 }7309 {7310 <Owned<7311 T,7312 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7313 <[_]>::into_vec(7314 #[rustc_box]7315 ::alloc::boxed::Box::new([7316 " Used to enumerate tokens owned by account.",7317 ]),7318 ),7319 &mut entries,7320 );7321 }7322 {7323 <TokenChildren<7324 T,7325 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7326 <[_]>::into_vec(7327 #[rustc_box]7328 ::alloc::boxed::Box::new([7329 " Used to enumerate token\'s children.",7330 ]),7331 ),7332 &mut entries,7333 );7334 }7335 {7336 <AccountBalance<7337 T,7338 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7339 <[_]>::into_vec(7340 #[rustc_box]7341 ::alloc::boxed::Box::new([7342 " Amount of tokens owned by an account in a collection.",7343 ]),7344 ),7345 &mut entries,7346 );7347 }7348 {7349 <Allowance<7350 T,7351 > as frame_support::storage::StorageEntryMetadataBuilder>::build_metadata(7352 <[_]>::into_vec(7353 #[rustc_box]7354 ::alloc::boxed::Box::new([7355 " Allowance set by a token owner for another user to perform one of certain transactions on a token.",7356 ]),7357 ),7358 &mut entries,7359 );7360 }7361 entries7362 },7363 }7364 }7365 }7366 impl<T: Config> Pallet<T> {7367 /// Map of key-value pairs, describing the metadata of a token.7368 pub fn token_properties<KArg>(key: KArg) -> Properties7369 where7370 KArg: frame_support::storage::types::EncodeLikeTuple<7371 <(7372 Key<Twox64Concat, CollectionId>,7373 Key<Twox64Concat, TokenId>,7374 ) as frame_support::storage::types::KeyGenerator>::KArg,7375 > + frame_support::storage::types::TupleToEncodedIter,7376 {7377 <TokenProperties<7378 T,7379 > as frame_support::storage::StorageNMap<7380 (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),7381 Properties,7382 >>::get(key)7383 }7384 }7385 impl<T: Config> Pallet<T> {7386 /// Custom data of a token that is serialized to bytes,7387 /// primarily reserved for on-chain operations,7388 /// normally obscured from the external users.7389 ///7390 /// Auxiliary properties are slightly different from7391 /// usual [`TokenProperties`] due to an unlimited number7392 /// and separately stored and written-to key-value pairs.7393 ///7394 /// Currently used to store RMRK data.7395 pub fn token_aux_property<KArg>(key: KArg) -> Option<AuxPropertyValue>7396 where7397 KArg: frame_support::storage::types::EncodeLikeTuple<7398 <(7399 Key<Twox64Concat, CollectionId>,7400 Key<Twox64Concat, TokenId>,7401 Key<Twox64Concat, PropertyScope>,7402 Key<Twox64Concat, PropertyKey>,7403 ) as frame_support::storage::types::KeyGenerator>::KArg,7404 > + frame_support::storage::types::TupleToEncodedIter,7405 {7406 <TokenAuxProperties<7407 T,7408 > as frame_support::storage::StorageNMap<7409 (7410 Key<Twox64Concat, CollectionId>,7411 Key<Twox64Concat, TokenId>,7412 Key<Twox64Concat, PropertyScope>,7413 Key<Twox64Concat, PropertyKey>,7414 ),7415 AuxPropertyValue,7416 >>::get(key)7417 }7418 }7419 impl<T: Config> Pallet<T> {7420 /// Used to enumerate token's children.7421 pub fn token_children<KArg>(key: KArg) -> bool7422 where7423 KArg: frame_support::storage::types::EncodeLikeTuple<7424 <(7425 Key<Twox64Concat, CollectionId>,7426 Key<Twox64Concat, TokenId>,7427 Key<Twox64Concat, (CollectionId, TokenId)>,7428 ) as frame_support::storage::types::KeyGenerator>::KArg,7429 > + frame_support::storage::types::TupleToEncodedIter,7430 {7431 <TokenChildren<7432 T,7433 > as frame_support::storage::StorageNMap<7434 (7435 Key<Twox64Concat, CollectionId>,7436 Key<Twox64Concat, TokenId>,7437 Key<Twox64Concat, (CollectionId, TokenId)>,7438 ),7439 bool,7440 >>::get(key)7441 }7442 }7443 #[doc(hidden)]7444 pub struct _GeneratedPrefixForStorageTokensMinted<T>(7445 core::marker::PhantomData<(T,)>,7446 );7447 impl<T: Config> frame_support::traits::StorageInstance7448 for _GeneratedPrefixForStorageTokensMinted<T> {7449 fn pallet_prefix() -> &'static str {7450 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7451 Pallet<T>,7452 >()7453 .expect("Every active pallet has a name in the runtime; qed")7454 }7455 const STORAGE_PREFIX: &'static str = "TokensMinted";7456 }7457 #[doc(hidden)]7458 pub struct _GeneratedPrefixForStorageTokensBurnt<T>(core::marker::PhantomData<(T,)>);7459 impl<T: Config> frame_support::traits::StorageInstance7460 for _GeneratedPrefixForStorageTokensBurnt<T> {7461 fn pallet_prefix() -> &'static str {7462 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7463 Pallet<T>,7464 >()7465 .expect("Every active pallet has a name in the runtime; qed")7466 }7467 const STORAGE_PREFIX: &'static str = "TokensBurnt";7468 }7469 #[doc(hidden)]7470 pub struct _GeneratedPrefixForStorageTokenData<T>(core::marker::PhantomData<(T,)>);7471 impl<T: Config> frame_support::traits::StorageInstance7472 for _GeneratedPrefixForStorageTokenData<T> {7473 fn pallet_prefix() -> &'static str {7474 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7475 Pallet<T>,7476 >()7477 .expect("Every active pallet has a name in the runtime; qed")7478 }7479 const STORAGE_PREFIX: &'static str = "TokenData";7480 }7481 #[doc(hidden)]7482 pub struct _GeneratedPrefixForStorageTokenProperties<T>(7483 core::marker::PhantomData<(T,)>,7484 );7485 impl<T: Config> frame_support::traits::StorageInstance7486 for _GeneratedPrefixForStorageTokenProperties<T> {7487 fn pallet_prefix() -> &'static str {7488 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7489 Pallet<T>,7490 >()7491 .expect("Every active pallet has a name in the runtime; qed")7492 }7493 const STORAGE_PREFIX: &'static str = "TokenProperties";7494 }7495 #[doc(hidden)]7496 pub struct _GeneratedPrefixForStorageTokenAuxProperties<T>(7497 core::marker::PhantomData<(T,)>,7498 );7499 impl<T: Config> frame_support::traits::StorageInstance7500 for _GeneratedPrefixForStorageTokenAuxProperties<T> {7501 fn pallet_prefix() -> &'static str {7502 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7503 Pallet<T>,7504 >()7505 .expect("Every active pallet has a name in the runtime; qed")7506 }7507 const STORAGE_PREFIX: &'static str = "TokenAuxProperties";7508 }7509 #[doc(hidden)]7510 pub struct _GeneratedPrefixForStorageOwned<T>(core::marker::PhantomData<(T,)>);7511 impl<T: Config> frame_support::traits::StorageInstance7512 for _GeneratedPrefixForStorageOwned<T> {7513 fn pallet_prefix() -> &'static str {7514 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7515 Pallet<T>,7516 >()7517 .expect("Every active pallet has a name in the runtime; qed")7518 }7519 const STORAGE_PREFIX: &'static str = "Owned";7520 }7521 #[doc(hidden)]7522 pub struct _GeneratedPrefixForStorageTokenChildren<T>(7523 core::marker::PhantomData<(T,)>,7524 );7525 impl<T: Config> frame_support::traits::StorageInstance7526 for _GeneratedPrefixForStorageTokenChildren<T> {7527 fn pallet_prefix() -> &'static str {7528 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7529 Pallet<T>,7530 >()7531 .expect("Every active pallet has a name in the runtime; qed")7532 }7533 const STORAGE_PREFIX: &'static str = "TokenChildren";7534 }7535 #[doc(hidden)]7536 pub struct _GeneratedPrefixForStorageAccountBalance<T>(7537 core::marker::PhantomData<(T,)>,7538 );7539 impl<T: Config> frame_support::traits::StorageInstance7540 for _GeneratedPrefixForStorageAccountBalance<T> {7541 fn pallet_prefix() -> &'static str {7542 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7543 Pallet<T>,7544 >()7545 .expect("Every active pallet has a name in the runtime; qed")7546 }7547 const STORAGE_PREFIX: &'static str = "AccountBalance";7548 }7549 #[doc(hidden)]7550 pub struct _GeneratedPrefixForStorageAllowance<T>(core::marker::PhantomData<(T,)>);7551 impl<T: Config> frame_support::traits::StorageInstance7552 for _GeneratedPrefixForStorageAllowance<T> {7553 fn pallet_prefix() -> &'static str {7554 <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7555 Pallet<T>,7556 >()7557 .expect("Every active pallet has a name in the runtime; qed")7558 }7559 const STORAGE_PREFIX: &'static str = "Allowance";7560 }7561 #[doc(hidden)]7562 pub mod __substrate_inherent_check {7563 #[doc(hidden)]7564 pub use __is_inherent_part_defined_3 as is_inherent_part_defined;7565 }7566 /// Hidden instance generated to be internally used when module is used without7567 /// instance.7568 #[doc(hidden)]7569 pub type __InherentHiddenInstance = ();7570 pub(super) trait Store {7571 type TokensMinted;7572 type TokensBurnt;7573 type TokenData;7574 type TokenProperties;7575 type TokenAuxProperties;7576 type Owned;7577 type TokenChildren;7578 type AccountBalance;7579 type Allowance;7580 }7581 impl<T: Config> Store for Pallet<T> {7582 type TokensMinted = TokensMinted<T>;7583 type TokensBurnt = TokensBurnt<T>;7584 type TokenData = TokenData<T>;7585 type TokenProperties = TokenProperties<T>;7586 type TokenAuxProperties = TokenAuxProperties<T>;7587 type Owned = Owned<T>;7588 type TokenChildren = TokenChildren<T>;7589 type AccountBalance = AccountBalance<T>;7590 type Allowance = Allowance<T>;7591 }7592 impl<7593 T: Config,7594 > frame_support::traits::OnFinalize<<T as frame_system::Config>::BlockNumber>7595 for Pallet<T> {7596 fn on_finalize(n: <T as frame_system::Config>::BlockNumber) {7597 let __within_span__ = {7598 use ::tracing::__macro_support::Callsite as _;7599 static CALLSITE: ::tracing::callsite::DefaultCallsite = {7600 static META: ::tracing::Metadata<'static> = {7601 ::tracing_core::metadata::Metadata::new(7602 "on_finalize",7603 "pallet_nonfungible::pallet",7604 ::tracing::Level::TRACE,7605 Some("pallets/nonfungible/src/lib.rs"),7606 Some(147u32),7607 Some("pallet_nonfungible::pallet"),7608 ::tracing_core::field::FieldSet::new(7609 &[],7610 ::tracing_core::callsite::Identifier(&CALLSITE),7611 ),7612 ::tracing::metadata::Kind::SPAN,7613 )7614 };7615 ::tracing::callsite::DefaultCallsite::new(&META)7616 };7617 let mut interest = ::tracing::subscriber::Interest::never();7618 if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL7619 && ::tracing::Level::TRACE7620 <= ::tracing::level_filters::LevelFilter::current()7621 && {7622 interest = CALLSITE.interest();7623 !interest.is_never()7624 }7625 && ::tracing::__macro_support::__is_enabled(7626 CALLSITE.metadata(),7627 interest,7628 )7629 {7630 let meta = CALLSITE.metadata();7631 ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })7632 } else {7633 let span = ::tracing::__macro_support::__disabled_span(7634 CALLSITE.metadata(),7635 );7636 {};7637 span7638 }7639 };7640 let __tracing_guard__ = __within_span__.enter();7641 <Self as frame_support::traits::Hooks<7642 <T as frame_system::Config>::BlockNumber,7643 >>::on_finalize(n)7644 }7645 }7646 impl<7647 T: Config,7648 > frame_support::traits::OnIdle<<T as frame_system::Config>::BlockNumber>7649 for Pallet<T> {7650 fn on_idle(7651 n: <T as frame_system::Config>::BlockNumber,7652 remaining_weight: frame_support::weights::Weight,7653 ) -> frame_support::weights::Weight {7654 <Self as frame_support::traits::Hooks<7655 <T as frame_system::Config>::BlockNumber,7656 >>::on_idle(n, remaining_weight)7657 }7658 }7659 impl<7660 T: Config,7661 > frame_support::traits::OnInitialize<<T as frame_system::Config>::BlockNumber>7662 for Pallet<T> {7663 fn on_initialize(7664 n: <T as frame_system::Config>::BlockNumber,7665 ) -> frame_support::weights::Weight {7666 let __within_span__ = {7667 use ::tracing::__macro_support::Callsite as _;7668 static CALLSITE: ::tracing::callsite::DefaultCallsite = {7669 static META: ::tracing::Metadata<'static> = {7670 ::tracing_core::metadata::Metadata::new(7671 "on_initialize",7672 "pallet_nonfungible::pallet",7673 ::tracing::Level::TRACE,7674 Some("pallets/nonfungible/src/lib.rs"),7675 Some(147u32),7676 Some("pallet_nonfungible::pallet"),7677 ::tracing_core::field::FieldSet::new(7678 &[],7679 ::tracing_core::callsite::Identifier(&CALLSITE),7680 ),7681 ::tracing::metadata::Kind::SPAN,7682 )7683 };7684 ::tracing::callsite::DefaultCallsite::new(&META)7685 };7686 let mut interest = ::tracing::subscriber::Interest::never();7687 if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL7688 && ::tracing::Level::TRACE7689 <= ::tracing::level_filters::LevelFilter::current()7690 && {7691 interest = CALLSITE.interest();7692 !interest.is_never()7693 }7694 && ::tracing::__macro_support::__is_enabled(7695 CALLSITE.metadata(),7696 interest,7697 )7698 {7699 let meta = CALLSITE.metadata();7700 ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })7701 } else {7702 let span = ::tracing::__macro_support::__disabled_span(7703 CALLSITE.metadata(),7704 );7705 {};7706 span7707 }7708 };7709 let __tracing_guard__ = __within_span__.enter();7710 <Self as frame_support::traits::Hooks<7711 <T as frame_system::Config>::BlockNumber,7712 >>::on_initialize(n)7713 }7714 }7715 impl<T: Config> frame_support::traits::OnRuntimeUpgrade for Pallet<T> {7716 fn on_runtime_upgrade() -> frame_support::weights::Weight {7717 let __within_span__ = {7718 use ::tracing::__macro_support::Callsite as _;7719 static CALLSITE: ::tracing::callsite::DefaultCallsite = {7720 static META: ::tracing::Metadata<'static> = {7721 ::tracing_core::metadata::Metadata::new(7722 "on_runtime_update",7723 "pallet_nonfungible::pallet",7724 ::tracing::Level::TRACE,7725 Some("pallets/nonfungible/src/lib.rs"),7726 Some(147u32),7727 Some("pallet_nonfungible::pallet"),7728 ::tracing_core::field::FieldSet::new(7729 &[],7730 ::tracing_core::callsite::Identifier(&CALLSITE),7731 ),7732 ::tracing::metadata::Kind::SPAN,7733 )7734 };7735 ::tracing::callsite::DefaultCallsite::new(&META)7736 };7737 let mut interest = ::tracing::subscriber::Interest::never();7738 if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL7739 && ::tracing::Level::TRACE7740 <= ::tracing::level_filters::LevelFilter::current()7741 && {7742 interest = CALLSITE.interest();7743 !interest.is_never()7744 }7745 && ::tracing::__macro_support::__is_enabled(7746 CALLSITE.metadata(),7747 interest,7748 )7749 {7750 let meta = CALLSITE.metadata();7751 ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })7752 } else {7753 let span = ::tracing::__macro_support::__disabled_span(7754 CALLSITE.metadata(),7755 );7756 {};7757 span7758 }7759 };7760 let __tracing_guard__ = __within_span__.enter();7761 let pallet_name = <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<7762 Self,7763 >()7764 .unwrap_or("<unknown pallet name>");7765 {7766 let lvl = ::log::Level::Info;7767 if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level() {7768 ::log::__private_api_log(7769 ::core::fmt::Arguments::new_v1(7770 &[7771 "\u{26a0}\u{fe0f} ",7772 " declares internal migrations (which *might* execute). On-chain `",7773 "` vs current storage version `",7774 "`",7775 ],7776 &[7777 ::core::fmt::ArgumentV1::new_display(&pallet_name),7778 ::core::fmt::ArgumentV1::new_debug(7779 &<Self as frame_support::traits::GetStorageVersion>::on_chain_storage_version(),7780 ),7781 ::core::fmt::ArgumentV1::new_debug(7782 &<Self as frame_support::traits::GetStorageVersion>::current_storage_version(),7783 ),7784 ],7785 ),7786 lvl,7787 &(7788 frame_support::LOG_TARGET,7789 "pallet_nonfungible::pallet",7790 "pallets/nonfungible/src/lib.rs",7791 147u32,7792 ),7793 ::log::__private_api::Option::None,7794 );7795 }7796 };7797 <Self as frame_support::traits::Hooks<7798 <T as frame_system::Config>::BlockNumber,7799 >>::on_runtime_upgrade()7800 }7801 }7802 impl<7803 T: Config,7804 > frame_support::traits::OffchainWorker<<T as frame_system::Config>::BlockNumber>7805 for Pallet<T> {7806 fn offchain_worker(n: <T as frame_system::Config>::BlockNumber) {7807 <Self as frame_support::traits::Hooks<7808 <T as frame_system::Config>::BlockNumber,7809 >>::offchain_worker(n)7810 }7811 }7812 impl<T: Config> frame_support::traits::IntegrityTest for Pallet<T> {7813 fn integrity_test() {7814 <Self as frame_support::traits::Hooks<7815 <T as frame_system::Config>::BlockNumber,7816 >>::integrity_test()7817 }7818 }7819 #[doc(hidden)]7820 pub mod __substrate_genesis_config_check {7821 #[doc(hidden)]7822 pub use __is_genesis_config_defined_4 as is_genesis_config_defined;7823 #[doc(hidden)]7824 pub use __is_std_enabled_for_genesis_4 as is_std_enabled_for_genesis;7825 }7826 #[doc(hidden)]7827 pub mod __substrate_origin_check {7828 #[doc(hidden)]7829 pub use __is_origin_part_defined_5 as is_origin_part_defined;7830 }7831 #[doc(hidden)]7832 pub mod __substrate_validate_unsigned_check {7833 #[doc(hidden)]7834 pub use __is_validate_unsigned_part_defined_6 as is_validate_unsigned_part_defined;7835 }7836 pub use __tt_default_parts_7 as tt_default_parts;7837}7838pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);7839impl<T: Config> NonfungibleHandle<T> {7840 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {7841 Self(inner)7842 }7843 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {7844 self.07845 }7846 pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle<T> {7847 &mut self.07848 }7849}7850impl<T: Config> WithRecorder<T> for NonfungibleHandle<T> {7851 fn recorder(&self) -> &SubstrateRecorder<T> {7852 self.0.recorder()7853 }7854 fn into_recorder(self) -> SubstrateRecorder<T> {7855 self.0.into_recorder()7856 }7857}7858impl<T: Config> Deref for NonfungibleHandle<T> {7859 type Target = pallet_common::CollectionHandle<T>;7860 fn deref(&self) -> &Self::Target {7861 &self.07862 }7863}7864impl<T: Config> Pallet<T> {7865 /// Get number of NFT tokens in collection.7866 pub fn total_supply(collection: &NonfungibleHandle<T>) -> u32 {7867 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)7868 }7869 /// Check that NFT token exists.7870 ///7871 /// - `token`: Token ID.7872 pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {7873 <TokenData<T>>::contains_key((collection.id, token))7874 }7875 /// Set the token property with the scope.7876 ///7877 /// - `property`: Contains key-value pair.7878 pub fn set_scoped_token_property(7879 collection_id: CollectionId,7880 token_id: TokenId,7881 scope: PropertyScope,7882 property: Property,7883 ) -> DispatchResult {7884 TokenProperties::<7885 T,7886 >::try_mutate(7887 (collection_id, token_id),7888 |properties| {7889 properties.try_scoped_set(scope, property.key, property.value)7890 },7891 )7892 .map_err(<CommonError<T>>::from)?;7893 Ok(())7894 }7895 /// Batch operation to set multiple properties with the same scope.7896 pub fn set_scoped_token_properties(7897 collection_id: CollectionId,7898 token_id: TokenId,7899 scope: PropertyScope,7900 properties: impl Iterator<Item = Property>,7901 ) -> DispatchResult {7902 TokenProperties::<7903 T,7904 >::try_mutate(7905 (collection_id, token_id),7906 |stored_properties| {7907 stored_properties.try_scoped_set_from_iter(scope, properties)7908 },7909 )7910 .map_err(<CommonError<T>>::from)?;7911 Ok(())7912 }7913 /// Add or edit auxiliary data for the property.7914 ///7915 /// - `f`: function that adds or edits auxiliary data.7916 pub fn try_mutate_token_aux_property<R, E>(7917 collection_id: CollectionId,7918 token_id: TokenId,7919 scope: PropertyScope,7920 key: PropertyKey,7921 f: impl FnOnce(&mut Option<AuxPropertyValue>) -> Result<R, E>,7922 ) -> Result<R, E> {7923 <TokenAuxProperties<T>>::try_mutate((collection_id, token_id, scope, key), f)7924 }7925 /// Remove auxiliary data for the property.7926 pub fn remove_token_aux_property(7927 collection_id: CollectionId,7928 token_id: TokenId,7929 scope: PropertyScope,7930 key: PropertyKey,7931 ) {7932 <TokenAuxProperties<T>>::remove((collection_id, token_id, scope, key));7933 }7934 /// Get all auxiliary data in a given scope.7935 ///7936 /// Returns iterator over Property Key - Data pairs.7937 pub fn iterate_token_aux_properties(7938 collection_id: CollectionId,7939 token_id: TokenId,7940 scope: PropertyScope,7941 ) -> impl Iterator<Item = (PropertyKey, AuxPropertyValue)> {7942 <TokenAuxProperties<T>>::iter_prefix((collection_id, token_id, scope))7943 }7944 /// Get ID of the last minted token7945 pub fn current_token_id(collection_id: CollectionId) -> TokenId {7946 TokenId(<TokensMinted<T>>::get(collection_id))7947 }7948}7949impl<T: Config> Pallet<T> {7950 /// Create NFT collection7951 ///7952 /// `init_collection` will take non-refundable deposit for collection creation.7953 ///7954 /// - `data`: Contains settings for collection limits and permissions.7955 pub fn init_collection(7956 owner: T::CrossAccountId,7957 payer: T::CrossAccountId,7958 data: CreateCollectionData<T::AccountId>,7959 is_external: bool,7960 ) -> Result<CollectionId, DispatchError> {7961 <PalletCommon<7962 T,7963 >>::init_collection(7964 owner,7965 payer,7966 data,7967 CollectionFlags {7968 external: is_external,7969 ..Default::default()7970 },7971 )7972 }7973 /// Destroy NFT collection7974 ///7975 /// `destroy_collection` will throw error if collection contains any tokens.7976 /// Only owner can destroy collection.7977 pub fn destroy_collection(7978 collection: NonfungibleHandle<T>,7979 sender: &T::CrossAccountId,7980 ) -> DispatchResult {7981 let id = collection.id;7982 if Self::collection_has_tokens(id) {7983 return Err(<CommonError<T>>::CantDestroyNotEmptyCollection.into());7984 }7985 PalletCommon::destroy_collection(collection.0, sender)?;7986 let _ = <TokenData<T>>::clear_prefix((id,), u32::MAX, None);7987 let _ = <TokenChildren<T>>::clear_prefix((id,), u32::MAX, None);7988 let _ = <Owned<T>>::clear_prefix((id,), u32::MAX, None);7989 <TokensMinted<T>>::remove(id);7990 <TokensBurnt<T>>::remove(id);7991 let _ = <Allowance<T>>::clear_prefix((id,), u32::MAX, None);7992 let _ = <AccountBalance<T>>::clear_prefix((id,), u32::MAX, None);7993 Ok(())7994 }7995 /// Burn NFT token7996 ///7997 /// `burn` removes `token` from the `collection`, from it's owner and from the parent token7998 /// if the token is nested.7999 /// Only the owner can `burn` the token. The `token` shouldn't have any nested tokens.8000 /// Also removes all corresponding properties and auxiliary properties.8001 ///8002 /// - `token`: Token that should be burned8003 /// - `collection`: Collection that contains the token8004 pub fn burn(8005 collection: &NonfungibleHandle<T>,8006 sender: &T::CrossAccountId,8007 token: TokenId,8008 ) -> DispatchResult {8009 let token_data = <TokenData<T>>::get((collection.id, token))8010 .ok_or(<CommonError<T>>::TokenNotFound)?;8011 {8012 if !(&token_data.owner == sender) {8013 { return Err(<CommonError<T>>::NoPermission.into()) };8014 }8015 };8016 if collection.permissions.access() == AccessMode::AllowList {8017 collection.check_allowlist(sender)?;8018 }8019 if Self::token_has_children(collection.id, token) {8020 return Err(<Error<T>>::CantBurnNftWithChildren.into());8021 }8022 let burnt = <TokensBurnt<T>>::get(collection.id)8023 .checked_add(1)8024 .ok_or(ArithmeticError::Overflow)?;8025 let balance = <AccountBalance<T>>::get((collection.id, token_data.owner.clone()))8026 .checked_sub(1)8027 .ok_or(ArithmeticError::Overflow)?;8028 if balance == 0 {8029 <AccountBalance<T>>::remove((collection.id, token_data.owner.clone()));8030 } else {8031 <AccountBalance<8032 T,8033 >>::insert((collection.id, token_data.owner.clone()), balance);8034 }8035 <PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);8036 <Owned<T>>::remove((collection.id, &token_data.owner, token));8037 <TokensBurnt<T>>::insert(collection.id, burnt);8038 <TokenData<T>>::remove((collection.id, token));8039 <TokenProperties<T>>::remove((collection.id, token));8040 let _ = <TokenAuxProperties<8041 T,8042 >>::clear_prefix((collection.id, token), u32::MAX, None);8043 let old_spender = <Allowance<T>>::take((collection.id, token));8044 if let Some(old_spender) = old_spender {8045 <PalletCommon<8046 T,8047 >>::deposit_event(8048 CommonEvent::Approved(8049 collection.id,8050 token,8051 token_data.owner.clone(),8052 old_spender,8053 0,8054 ),8055 );8056 }8057 <PalletEvm<8058 T,8059 >>::deposit_log(8060 ERC721Events::Transfer {8061 from: *token_data.owner.as_eth(),8062 to: H160::default(),8063 token_id: token.into(),8064 }8065 .to_log(collection_id_to_address(collection.id)),8066 );8067 <PalletCommon<8068 T,8069 >>::deposit_event(8070 CommonEvent::ItemDestroyed(collection.id, token, token_data.owner, 1),8071 );8072 Ok(())8073 }8074 /// Same as [`burn`] but burns all the tokens that are nested in the token first8075 ///8076 /// - `self_budget`: Limit for searching children in depth.8077 /// - `breadth_budget`: Limit of breadth of searching children.8078 ///8079 /// [`burn`]: struct.Pallet.html#method.burn8080 pub fn burn_recursively(8081 collection: &NonfungibleHandle<T>,8082 sender: &T::CrossAccountId,8083 token: TokenId,8084 self_budget: &dyn Budget,8085 breadth_budget: &dyn Budget,8086 ) -> DispatchResultWithPostInfo {8087 use frame_support::storage::{with_transaction, TransactionOutcome};8088 with_transaction(|| {8089 let r = (|| {8090 {8091 {8092 if !self_budget.consume() {8093 { return Err(<StructureError<T>>::DepthLimit.into()) };8094 }8095 };8096 let current_token_account = T::CrossTokenAddressMapping::token_to_address(8097 collection.id,8098 token,8099 );8100 let mut weight = Weight::zero();8101 for ((collection, token), _) in <TokenChildren<8102 T,8103 >>::iter_prefix((collection.id, token)) {8104 {8105 if !breadth_budget.consume() {8106 { return Err(<StructureError<T>>::BreadthLimit.into()) };8107 }8108 };8109 let PostDispatchInfo { actual_weight, .. } = <PalletStructure<8110 T,8111 >>::burn_item_recursively(8112 current_token_account.clone(),8113 collection,8114 token,8115 self_budget,8116 breadth_budget,8117 )?;8118 if let Some(actual_weight) = actual_weight {8119 weight = weight.saturating_add(actual_weight);8120 }8121 }8122 Self::burn(collection, sender, token)?;8123 DispatchResultWithPostInfo::Ok(PostDispatchInfo {8124 actual_weight: Some(weight + <SelfWeightOf<T>>::burn_item()),8125 pays_fee: Pays::Yes,8126 })8127 }8128 })();8129 if r.is_ok() {8130 TransactionOutcome::Commit(r)8131 } else {8132 TransactionOutcome::Rollback(r)8133 }8134 })8135 }8136 /// Batch operation to add, edit or remove properties for the token8137 ///8138 /// All affected properties should have mutable permission and sender should have8139 /// permission to edit those properties.8140 ///8141 /// - `nesting_budget`: Limit for searching parents in depth to check ownership.8142 /// - `is_token_create`: Indicates that method is called during token initialization.8143 /// Allows to bypass ownership check.8144 fn modify_token_properties(8145 collection: &NonfungibleHandle<T>,8146 sender: &T::CrossAccountId,8147 token_id: TokenId,8148 properties: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,8149 is_token_create: bool,8150 nesting_budget: &dyn Budget,8151 ) -> DispatchResult {8152 use frame_support::storage::{with_transaction, TransactionOutcome};8153 with_transaction(|| {8154 let r = (|| {8155 {8156 let mut collection_admin_status = None;8157 let mut token_owner_result = None;8158 let mut is_collection_admin = || {8159 *collection_admin_status8160 .get_or_insert_with(|| collection.is_owner_or_admin(sender))8161 };8162 let mut is_token_owner = || {8163 *token_owner_result8164 .get_or_insert_with(|| -> Result<bool, DispatchError> {8165 let is_owned = <PalletStructure<8166 T,8167 >>::check_indirectly_owned(8168 sender.clone(),8169 collection.id,8170 token_id,8171 None,8172 nesting_budget,8173 )?;8174 Ok(is_owned)8175 })8176 };8177 for (key, value) in properties {8178 let permission = <PalletCommon<8179 T,8180 >>::property_permissions(collection.id)8181 .get(&key)8182 .cloned()8183 .unwrap_or_else(PropertyPermission::none);8184 let is_property_exists = TokenProperties::<8185 T,8186 >::get((collection.id, token_id))8187 .get(&key)8188 .is_some();8189 match permission {8190 PropertyPermission {8191 mutable: false,8192 ..8193 } if is_property_exists => {8194 return Err(<CommonError<T>>::NoPermission.into());8195 }8196 PropertyPermission { collection_admin, token_owner, .. } => {8197 if is_token_create && (collection_admin || token_owner)8198 && value.is_some()8199 {} else if collection_admin && is_collection_admin()8200 {} else if token_owner && is_token_owner()? {} else {8201 { return Err(<CommonError<T>>::NoPermission.into()) };8202 }8203 }8204 }8205 match value {8206 Some(value) => {8207 <TokenProperties<8208 T,8209 >>::try_mutate(8210 (collection.id, token_id),8211 |properties| { properties.try_set(key.clone(), value) },8212 )8213 .map_err(<CommonError<T>>::from)?;8214 <PalletCommon<8215 T,8216 >>::deposit_event(8217 CommonEvent::TokenPropertySet(collection.id, token_id, key),8218 );8219 }8220 None => {8221 <TokenProperties<8222 T,8223 >>::try_mutate(8224 (collection.id, token_id),8225 |properties| { properties.remove(&key) },8226 )8227 .map_err(<CommonError<T>>::from)?;8228 <PalletCommon<8229 T,8230 >>::deposit_event(8231 CommonEvent::TokenPropertyDeleted(8232 collection.id,8233 token_id,8234 key,8235 ),8236 );8237 }8238 }8239 }8240 Ok(())8241 }8242 })();8243 if r.is_ok() {8244 TransactionOutcome::Commit(r)8245 } else {8246 TransactionOutcome::Rollback(r)8247 }8248 })8249 }8250 /// Batch operation to add or edit properties for the token8251 ///8252 /// Same as [`modify_token_properties`] but doesn't allow to remove properties8253 ///8254 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties8255 pub fn set_token_properties(8256 collection: &NonfungibleHandle<T>,8257 sender: &T::CrossAccountId,8258 token_id: TokenId,8259 properties: impl Iterator<Item = Property>,8260 is_token_create: bool,8261 nesting_budget: &dyn Budget,8262 ) -> DispatchResult {8263 Self::modify_token_properties(8264 collection,8265 sender,8266 token_id,8267 properties.map(|p| (p.key, Some(p.value))),8268 is_token_create,8269 nesting_budget,8270 )8271 }8272 /// Add or edit single property for the token8273 ///8274 /// Calls [`set_token_properties`] internally8275 ///8276 /// [`set_token_properties`]: struct.Pallet.html#method.set_token_properties8277 pub fn set_token_property(8278 collection: &NonfungibleHandle<T>,8279 sender: &T::CrossAccountId,8280 token_id: TokenId,8281 property: Property,8282 nesting_budget: &dyn Budget,8283 ) -> DispatchResult {8284 let is_token_create = false;8285 Self::set_token_properties(8286 collection,8287 sender,8288 token_id,8289 [property].into_iter(),8290 is_token_create,8291 nesting_budget,8292 )8293 }8294 /// Batch operation to remove properties from the token8295 ///8296 /// Same as [`modify_token_properties`] but doesn't allow to add or edit properties8297 ///8298 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties8299 pub fn delete_token_properties(8300 collection: &NonfungibleHandle<T>,8301 sender: &T::CrossAccountId,8302 token_id: TokenId,8303 property_keys: impl Iterator<Item = PropertyKey>,8304 nesting_budget: &dyn Budget,8305 ) -> DispatchResult {8306 let is_token_create = false;8307 Self::modify_token_properties(8308 collection,8309 sender,8310 token_id,8311 property_keys.into_iter().map(|key| (key, None)),8312 is_token_create,8313 nesting_budget,8314 )8315 }8316 /// Remove single property from the token8317 ///8318 /// Calls [`delete_token_properties`] internally8319 ///8320 /// [`delete_token_properties`]: struct.Pallet.html#method.delete_token_properties8321 pub fn delete_token_property(8322 collection: &NonfungibleHandle<T>,8323 sender: &T::CrossAccountId,8324 token_id: TokenId,8325 property_key: PropertyKey,8326 nesting_budget: &dyn Budget,8327 ) -> DispatchResult {8328 Self::delete_token_properties(8329 collection,8330 sender,8331 token_id,8332 [property_key].into_iter(),8333 nesting_budget,8334 )8335 }8336 /// Add or edit properties for the collection8337 pub fn set_collection_properties(8338 collection: &NonfungibleHandle<T>,8339 sender: &T::CrossAccountId,8340 properties: Vec<Property>,8341 ) -> DispatchResult {8342 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)8343 }8344 /// Remove properties from the collection8345 pub fn delete_collection_properties(8346 collection: &CollectionHandle<T>,8347 sender: &T::CrossAccountId,8348 property_keys: Vec<PropertyKey>,8349 ) -> DispatchResult {8350 <PalletCommon<8351 T,8352 >>::delete_collection_properties(collection, sender, property_keys)8353 }8354 /// Set property permissions for the token.8355 ///8356 /// Sender should be the owner or admin of token's collection.8357 pub fn set_token_property_permissions(8358 collection: &CollectionHandle<T>,8359 sender: &T::CrossAccountId,8360 property_permissions: Vec<PropertyKeyPermission>,8361 ) -> DispatchResult {8362 <PalletCommon<8363 T,8364 >>::set_token_property_permissions(collection, sender, property_permissions)8365 }8366 /// Set property permissions for the token with scope.8367 ///8368 /// Sender should be the owner or admin of token's collection.8369 pub fn set_scoped_token_property_permissions(8370 collection: &CollectionHandle<T>,8371 sender: &T::CrossAccountId,8372 scope: PropertyScope,8373 property_permissions: Vec<PropertyKeyPermission>,8374 ) -> DispatchResult {8375 <PalletCommon<8376 T,8377 >>::set_scoped_token_property_permissions(8378 collection,8379 sender,8380 scope,8381 property_permissions,8382 )8383 }8384 /// Set property permissions for the collection.8385 ///8386 /// Sender should be the owner or admin of the collection.8387 pub fn set_property_permission(8388 collection: &CollectionHandle<T>,8389 sender: &T::CrossAccountId,8390 permission: PropertyKeyPermission,8391 ) -> DispatchResult {8392 <PalletCommon<T>>::set_property_permission(collection, sender, permission)8393 }8394 /// Transfer NFT token from one account to another.8395 ///8396 /// `from` account stops being the owner and `to` account becomes the owner of the token.8397 /// If `to` is token than `to` becomes owner of the token and the token become nested.8398 /// Unnests token from previous parent if it was nested before.8399 /// Removes allowance for the token if there was any.8400 /// Throws if transfers aren't allowed for collection or if receiver reached token ownership limit.8401 ///8402 /// - `nesting_budget`: Limit for token nesting depth8403 pub fn transfer(8404 collection: &NonfungibleHandle<T>,8405 from: &T::CrossAccountId,8406 to: &T::CrossAccountId,8407 token: TokenId,8408 nesting_budget: &dyn Budget,8409 ) -> DispatchResult {8410 {8411 if !collection.limits.transfers_enabled() {8412 { return Err(<CommonError<T>>::TransferNotAllowed.into()) };8413 }8414 };8415 let token_data = <TokenData<T>>::get((collection.id, token))8416 .ok_or(<CommonError<T>>::TokenNotFound)?;8417 {8418 if !(&token_data.owner == from) {8419 { return Err(<CommonError<T>>::NoPermission.into()) };8420 }8421 };8422 if collection.permissions.access() == AccessMode::AllowList {8423 collection.check_allowlist(from)?;8424 collection.check_allowlist(to)?;8425 }8426 <PalletCommon<T>>::ensure_correct_receiver(to)?;8427 let balance_from = <AccountBalance<T>>::get((collection.id, from))8428 .checked_sub(1)8429 .ok_or(<CommonError<T>>::TokenValueTooLow)?;8430 let balance_to = if from != to {8431 let balance_to = <AccountBalance<T>>::get((collection.id, to))8432 .checked_add(1)8433 .ok_or(ArithmeticError::Overflow)?;8434 {8435 if !(balance_to < collection.limits.account_token_ownership_limit()) {8436 { return Err(<CommonError<T>>::AccountTokenLimitExceeded.into()) };8437 }8438 };8439 Some(balance_to)8440 } else {8441 None8442 };8443 <PalletStructure<8444 T,8445 >>::nest_if_sent_to_token(8446 from.clone(),8447 to,8448 collection.id,8449 token,8450 nesting_budget,8451 )?;8452 <PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);8453 <TokenData<8454 T,8455 >>::insert(8456 (collection.id, token),8457 ItemData {8458 owner: to.clone(),8459 ..token_data8460 },8461 );8462 if let Some(balance_to) = balance_to {8463 if balance_from == 0 {8464 <AccountBalance<T>>::remove((collection.id, from));8465 } else {8466 <AccountBalance<T>>::insert((collection.id, from), balance_from);8467 }8468 <AccountBalance<T>>::insert((collection.id, to), balance_to);8469 <Owned<T>>::remove((collection.id, from, token));8470 <Owned<T>>::insert((collection.id, to, token), true);8471 }8472 Self::set_allowance_unchecked(collection, from, token, None, true);8473 <PalletEvm<8474 T,8475 >>::deposit_log(8476 ERC721Events::Transfer {8477 from: *from.as_eth(),8478 to: *to.as_eth(),8479 token_id: token.into(),8480 }8481 .to_log(collection_id_to_address(collection.id)),8482 );8483 <PalletCommon<8484 T,8485 >>::deposit_event(8486 CommonEvent::Transfer(collection.id, token, from.clone(), to.clone(), 1),8487 );8488 Ok(())8489 }8490 /// Batch operation to mint multiple NFT tokens.8491 ///8492 /// The sender should be the owner/admin of the collection or collection should be configured8493 /// to allow public minting.8494 /// Throws if amount of tokens reached it's limit for the collection or if caller reached8495 /// token ownership limit.8496 ///8497 /// - `data`: Contains list of token properties and users who will become the owners of the8498 /// corresponging tokens.8499 /// - `nesting_budget`: Limit for token nesting depth8500 pub fn create_multiple_items(8501 collection: &NonfungibleHandle<T>,8502 sender: &T::CrossAccountId,8503 data: Vec<CreateItemData<T>>,8504 nesting_budget: &dyn Budget,8505 ) -> DispatchResult {8506 if !collection.is_owner_or_admin(sender) {8507 {8508 if !collection.permissions.mint_mode() {8509 { return Err(<CommonError<T>>::PublicMintingNotAllowed.into()) };8510 }8511 };8512 collection.check_allowlist(sender)?;8513 for item in data.iter() {8514 collection.check_allowlist(&item.owner)?;8515 }8516 }8517 for data in data.iter() {8518 <PalletCommon<T>>::ensure_correct_receiver(&data.owner)?;8519 }8520 let first_token = <TokensMinted<T>>::get(collection.id);8521 let tokens_minted = first_token8522 .checked_add(data.len() as u32)8523 .ok_or(ArithmeticError::Overflow)?;8524 {8525 if !(tokens_minted <= collection.limits.token_limit()) {8526 { return Err(<CommonError<T>>::CollectionTokenLimitExceeded.into()) };8527 }8528 };8529 let mut balances = BTreeMap::new();8530 for data in &data {8531 let balance = balances8532 .entry(&data.owner)8533 .or_insert_with(|| <AccountBalance<8534 T,8535 >>::get((collection.id, &data.owner)));8536 *balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;8537 {8538 if !(*balance <= collection.limits.account_token_ownership_limit()) {8539 { return Err(<CommonError<T>>::AccountTokenLimitExceeded.into()) };8540 }8541 };8542 }8543 for (i, data) in data.iter().enumerate() {8544 let token = TokenId(first_token + i as u32 + 1);8545 <PalletStructure<8546 T,8547 >>::check_nesting(8548 sender.clone(),8549 &data.owner,8550 collection.id,8551 token,8552 nesting_budget,8553 )?;8554 }8555 with_transaction(|| {8556 for (i, data) in data.iter().enumerate() {8557 let token = first_token + i as u32 + 1;8558 <TokenData<8559 T,8560 >>::insert(8561 (collection.id, token),8562 ItemData {8563 owner: data.owner.clone(),8564 },8565 );8566 <PalletStructure<8567 T,8568 >>::nest_if_sent_to_token_unchecked(8569 &data.owner,8570 collection.id,8571 TokenId(token),8572 );8573 if let Err(e)8574 = Self::set_token_properties(8575 collection,8576 sender,8577 TokenId(token),8578 data.properties.clone().into_iter(),8579 true,8580 nesting_budget,8581 ) {8582 return TransactionOutcome::Rollback(Err(e));8583 }8584 }8585 TransactionOutcome::Commit(Ok(()))8586 })?;8587 <TokensMinted<T>>::insert(collection.id, tokens_minted);8588 for (account, balance) in balances {8589 <AccountBalance<T>>::insert((collection.id, account), balance);8590 }8591 for (i, data) in data.into_iter().enumerate() {8592 let token = first_token + i as u32 + 1;8593 <Owned<T>>::insert((collection.id, &data.owner, token), true);8594 <PalletEvm<8595 T,8596 >>::deposit_log(8597 ERC721Events::Transfer {8598 from: H160::default(),8599 to: *data.owner.as_eth(),8600 token_id: token.into(),8601 }8602 .to_log(collection_id_to_address(collection.id)),8603 );8604 <PalletCommon<8605 T,8606 >>::deposit_event(8607 CommonEvent::ItemCreated(8608 collection.id,8609 TokenId(token),8610 data.owner.clone(),8611 1,8612 ),8613 );8614 }8615 Ok(())8616 }8617 pub fn set_allowance_unchecked(8618 collection: &NonfungibleHandle<T>,8619 sender: &T::CrossAccountId,8620 token: TokenId,8621 spender: Option<&T::CrossAccountId>,8622 assume_implicit_eth: bool,8623 ) {8624 if let Some(spender) = spender {8625 let old_spender = <Allowance<T>>::get((collection.id, token));8626 <Allowance<T>>::insert((collection.id, token), spender);8627 <PalletEvm<8628 T,8629 >>::deposit_log(8630 ERC721Events::Approval {8631 owner: *sender.as_eth(),8632 approved: *spender.as_eth(),8633 token_id: token.into(),8634 }8635 .to_log(collection_id_to_address(collection.id)),8636 );8637 if old_spender.as_ref() != Some(spender) {8638 if let Some(old_owner) = old_spender {8639 <PalletCommon<8640 T,8641 >>::deposit_event(8642 CommonEvent::Approved(8643 collection.id,8644 token,8645 sender.clone(),8646 old_owner,8647 0,8648 ),8649 );8650 }8651 <PalletCommon<8652 T,8653 >>::deposit_event(8654 CommonEvent::Approved(8655 collection.id,8656 token,8657 sender.clone(),8658 spender.clone(),8659 1,8660 ),8661 );8662 }8663 } else {8664 let old_spender = <Allowance<T>>::take((collection.id, token));8665 if !assume_implicit_eth {8666 <PalletEvm<8667 T,8668 >>::deposit_log(8669 ERC721Events::Approval {8670 owner: *sender.as_eth(),8671 approved: H160::default(),8672 token_id: token.into(),8673 }8674 .to_log(collection_id_to_address(collection.id)),8675 );8676 }8677 if let Some(old_spender) = old_spender {8678 <PalletCommon<8679 T,8680 >>::deposit_event(8681 CommonEvent::Approved(8682 collection.id,8683 token,8684 sender.clone(),8685 old_spender,8686 0,8687 ),8688 );8689 }8690 }8691 }8692 /// Set allowance for the spender to `transfer` or `burn` sender's token.8693 ///8694 /// - `token`: Token the spender is allowed to `transfer` or `burn`.8695 pub fn set_allowance(8696 collection: &NonfungibleHandle<T>,8697 sender: &T::CrossAccountId,8698 token: TokenId,8699 spender: Option<&T::CrossAccountId>,8700 ) -> DispatchResult {8701 if collection.permissions.access() == AccessMode::AllowList {8702 collection.check_allowlist(sender)?;8703 if let Some(spender) = spender {8704 collection.check_allowlist(spender)?;8705 }8706 }8707 if let Some(spender) = spender {8708 <PalletCommon<T>>::ensure_correct_receiver(spender)?;8709 }8710 let token_data = <TokenData<T>>::get((collection.id, token))8711 .ok_or(<CommonError<T>>::TokenNotFound)?;8712 if &token_data.owner != sender {8713 {8714 if !collection.ignores_owned_amount(sender) {8715 { return Err(<CommonError<T>>::CantApproveMoreThanOwned.into()) };8716 }8717 };8718 }8719 Self::set_allowance_unchecked(collection, sender, token, spender, false);8720 Ok(())8721 }8722 /// Checks allowance for the spender to use the token.8723 fn check_allowed(8724 collection: &NonfungibleHandle<T>,8725 spender: &T::CrossAccountId,8726 from: &T::CrossAccountId,8727 token: TokenId,8728 nesting_budget: &dyn Budget,8729 ) -> DispatchResult {8730 if spender.conv_eq(from) {8731 return Ok(());8732 }8733 if collection.permissions.access() == AccessMode::AllowList {8734 collection.check_allowlist(spender)?;8735 }8736 if collection.limits.owner_can_transfer()8737 && collection.is_owner_or_admin(spender)8738 {8739 return Ok(());8740 }8741 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {8742 {8743 if !<PalletStructure<8744 T,8745 >>::check_indirectly_owned(8746 spender.clone(),8747 source.0,8748 source.1,8749 None,8750 nesting_budget,8751 )? {8752 { return Err(<CommonError<T>>::ApprovedValueTooLow.into()) };8753 }8754 };8755 return Ok(());8756 }8757 if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {8758 return Ok(());8759 }8760 {8761 if !collection.ignores_allowance(spender) {8762 { return Err(<CommonError<T>>::ApprovedValueTooLow.into()) };8763 }8764 };8765 Ok(())8766 }8767 /// Transfer NFT token from one account to another.8768 ///8769 /// Same as the [`transfer`] but spender doesn't needs to be the owner of the token.8770 /// The owner should set allowance for the spender to transfer token.8771 ///8772 /// [`transfer`]: struct.Pallet.html#method.transfer8773 pub fn transfer_from(8774 collection: &NonfungibleHandle<T>,8775 spender: &T::CrossAccountId,8776 from: &T::CrossAccountId,8777 to: &T::CrossAccountId,8778 token: TokenId,8779 nesting_budget: &dyn Budget,8780 ) -> DispatchResult {8781 Self::check_allowed(collection, spender, from, token, nesting_budget)?;8782 Self::transfer(collection, from, to, token, nesting_budget)8783 }8784 /// Burn NFT token for `from` account.8785 ///8786 /// Same as the [`burn`] but spender doesn't need to be an owner of the token. The owner should8787 /// set allowance for the spender to burn token.8788 ///8789 /// [`burn`]: struct.Pallet.html#method.burn8790 pub fn burn_from(8791 collection: &NonfungibleHandle<T>,8792 spender: &T::CrossAccountId,8793 from: &T::CrossAccountId,8794 token: TokenId,8795 nesting_budget: &dyn Budget,8796 ) -> DispatchResult {8797 Self::check_allowed(collection, spender, from, token, nesting_budget)?;8798 Self::burn(collection, from, token)8799 }8800 /// Check that `from` token could be nested in `under` token.8801 ///8802 pub fn check_nesting(8803 handle: &NonfungibleHandle<T>,8804 sender: T::CrossAccountId,8805 from: (CollectionId, TokenId),8806 under: TokenId,8807 nesting_budget: &dyn Budget,8808 ) -> DispatchResult {8809 let nesting = handle.permissions.nesting();8810 #[cfg(not(feature = "runtime-benchmarks"))]8811 let permissive = false;8812 if permissive {} else if nesting.token_owner8813 && <PalletStructure<8814 T,8815 >>::check_indirectly_owned(8816 sender.clone(),8817 handle.id,8818 under,8819 Some(from),8820 nesting_budget,8821 )?8822 {} else if nesting.collection_admin && handle.is_owner_or_admin(&sender)8823 {} else {8824 { return Err(<CommonError<T>>::UserIsNotAllowedToNest.into()) };8825 }8826 if let Some(whitelist) = &nesting.restricted {8827 {8828 if !whitelist.contains(&from.0) {8829 {8830 return Err(8831 <CommonError<T>>::SourceCollectionIsNotAllowedToNest.into(),8832 )8833 };8834 }8835 };8836 }8837 Ok(())8838 }8839 fn nest(under: (CollectionId, TokenId), to_nest: (CollectionId, TokenId)) {8840 <TokenChildren<T>>::insert((under.0, under.1, (to_nest.0, to_nest.1)), true);8841 }8842 fn unnest(under: (CollectionId, TokenId), to_unnest: (CollectionId, TokenId)) {8843 <TokenChildren<T>>::remove((under.0, under.1, to_unnest));8844 }8845 fn collection_has_tokens(collection_id: CollectionId) -> bool {8846 <TokenData<T>>::iter_prefix((collection_id,)).next().is_some()8847 }8848 fn token_has_children(collection_id: CollectionId, token_id: TokenId) -> bool {8849 <TokenChildren<T>>::iter_prefix((collection_id, token_id)).next().is_some()8850 }8851 pub fn token_children_ids(8852 collection_id: CollectionId,8853 token_id: TokenId,8854 ) -> Vec<TokenChild> {8855 <TokenChildren<T>>::iter_prefix((collection_id, token_id))8856 .map(|((child_collection_id, child_id), _)| TokenChild {8857 collection: child_collection_id,8858 token: child_id,8859 })8860 .collect()8861 }8862 /// Mint single NFT token.8863 ///8864 /// Delegated to [`create_multiple_items`]8865 ///8866 /// [`create_multiple_items`]: struct.Pallet.html#method.create_multiple_items8867 pub fn create_item(8868 collection: &NonfungibleHandle<T>,8869 sender: &T::CrossAccountId,8870 data: CreateItemData<T>,8871 nesting_budget: &dyn Budget,8872 ) -> DispatchResult {8873 Self::create_multiple_items(8874 collection,8875 sender,8876 <[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([data])),8877 nesting_budget,8878 )8879 }8880}pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -105,10 +105,14 @@
/// @title A contract that allows you to work with collections.
<<<<<<< HEAD
+<<<<<<< HEAD
/// @dev the ERC-165 identifier for this interface is 0xb3152af3
=======
/// @dev the ERC-165 identifier for this interface is 0x674be726
>>>>>>> feat: Add custum signature with unlimited nesting.
+=======
+/// @dev the ERC-165 identifier for this interface is 0x943ee094
+>>>>>>> fix: after rebase
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -126,9 +130,9 @@
/// Set collection properties.
///
/// @param properties Vector of properties key/value pair.
- /// @dev EVM selector for this function is: 0x50b26b2a,
+ /// @dev EVM selector for this function is: 0xf90c1ce9,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple19[] memory properties) public {
+ function setCollectionProperties(Tuple21[] memory properties) public {
require(false, stub_error);
properties;
dummy = 0;
@@ -148,7 +152,7 @@
/// Delete collection properties.
///
/// @param keys Properties keys.
- /// @dev EVM selector for this function is: 0xee206ee3,
+ /// @dev EVM selector for this function is: 0x56d4684a,
/// or in textual repr: deleteCollectionProperties(string[])
function deleteCollectionProperties(string[] memory keys) public {
require(false, stub_error);
@@ -175,13 +179,13 @@
///
/// @param keys Properties keys. Empty keys for all propertyes.
/// @return Vector of properties key/value pairs.
- /// @dev EVM selector for this function is: 0x285fb8e6,
+ /// @dev EVM selector for this function is: 0x5cad7311,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) public view returns (Tuple19[] memory) {
+ function collectionProperties(string[] memory keys) public view returns (Tuple21[] memory) {
require(false, stub_error);
keys;
dummy;
- return new Tuple19[](0);
+ return new Tuple21[](0);
}
/// Set the sponsor of the collection.
@@ -489,7 +493,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -551,6 +555,7 @@
}
<<<<<<< HEAD
+<<<<<<< HEAD
/// @dev anonymous struct
struct Tuple19 {
address field_0;
@@ -602,6 +607,14 @@
=======
>>>>>>> feat: Add custum signature with unlimited nesting.
+=======
+/// @dev anonymous struct
+struct Tuple21 {
+ string field_0;
+ bytes field_1;
+}
+
+>>>>>>> fix: after rebase
/// @title ERC721 Token that can be irreversibly burned (destroyed).
/// @dev the ERC-165 identifier for this interface is 0x42966c68
contract ERC721Burnable is Dummy, ERC165 {
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -71,10 +71,14 @@
/// @title A contract that allows you to work with collections.
<<<<<<< HEAD
+<<<<<<< HEAD
/// @dev the ERC-165 identifier for this interface is 0xb3152af3
=======
/// @dev the ERC-165 identifier for this interface is 0x674be726
>>>>>>> feat: Add custum signature with unlimited nesting.
+=======
+/// @dev the ERC-165 identifier for this interface is 0x943ee094
+>>>>>>> fix: after rebase
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -87,9 +91,9 @@
/// Set collection properties.
///
/// @param properties Vector of properties key/value pair.
- /// @dev EVM selector for this function is: 0x50b26b2a,
+ /// @dev EVM selector for this function is: 0xf90c1ce9,
/// or in textual repr: setCollectionProperties((string,bytes)[])
- function setCollectionProperties(Tuple19[] memory properties) external;
+ function setCollectionProperties(Tuple21[] memory properties) external;
/// Delete collection property.
///
@@ -101,7 +105,7 @@
/// Delete collection properties.
///
/// @param keys Properties keys.
- /// @dev EVM selector for this function is: 0xee206ee3,
+ /// @dev EVM selector for this function is: 0x56d4684a,
/// or in textual repr: deleteCollectionProperties(string[])
function deleteCollectionProperties(string[] memory keys) external;
@@ -119,9 +123,9 @@
///
/// @param keys Properties keys. Empty keys for all propertyes.
/// @return Vector of properties key/value pairs.
- /// @dev EVM selector for this function is: 0x285fb8e6,
+ /// @dev EVM selector for this function is: 0x5cad7311,
/// or in textual repr: collectionProperties(string[])
- function collectionProperties(string[] memory keys) external view returns (Tuple19[] memory);
+ function collectionProperties(string[] memory keys) external view returns (Tuple21[] memory);
/// Set the sponsor of the collection.
///
@@ -310,7 +314,7 @@
/// Get collection owner.
///
- /// @return Tuble with sponsor address and his substrate mirror.
+ /// @return Tuple with sponsor address and his substrate mirror.
/// If address is canonical then substrate mirror is zero and vice versa.
/// @dev EVM selector for this function is: 0xdf727d3b,
/// or in textual repr: collectionOwner()
@@ -348,6 +352,7 @@
uint256 field_1;
}
+<<<<<<< HEAD
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
@@ -380,6 +385,14 @@
=======
>>>>>>> feat: Add custum signature with unlimited nesting.
+=======
+/// @dev anonymous struct
+struct Tuple21 {
+ string field_0;
+ bytes field_1;
+}
+
+>>>>>>> fix: after rebase
/// @title ERC721 Token that can be irreversibly burned (destroyed).
/// @dev the ERC-165 identifier for this interface is 0x42966c68
interface ERC721Burnable is Dummy, ERC165 {
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -268,6 +268,9 @@
},
{
<<<<<<< HEAD
+<<<<<<< HEAD
+=======
+>>>>>>> fix: after rebase
"inputs": [
{ "internalType": "string[]", "name": "keys", "type": "string[]" }
],
@@ -278,16 +281,23 @@
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
+<<<<<<< HEAD
"internalType": "struct Tuple19[]",
+=======
+ "internalType": "struct Tuple21[]",
+>>>>>>> fix: after rebase
"name": "",
"type": "tuple[]"
}
],
+<<<<<<< HEAD
=======
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "collectionProperty",
"outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
>>>>>>> feat: Add custum signature with unlimited nesting.
+=======
+>>>>>>> fix: after rebase
"stateMutability": "view",
"type": "function"
},
@@ -339,6 +349,9 @@
},
{
<<<<<<< HEAD
+<<<<<<< HEAD
+=======
+>>>>>>> fix: after rebase
"inputs": [
{ "internalType": "string[]", "name": "keys", "type": "string[]" }
],
@@ -348,8 +361,11 @@
"type": "function"
},
{
+<<<<<<< HEAD
=======
>>>>>>> feat: Add custum signature with unlimited nesting.
+=======
+>>>>>>> fix: after rebase
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "deleteCollectionProperty",
"outputs": [],
@@ -677,11 +693,15 @@
{
"inputs": [
<<<<<<< HEAD
+<<<<<<< HEAD
+=======
+>>>>>>> fix: after rebase
{
"components": [
{ "internalType": "string", "name": "field_0", "type": "string" },
{ "internalType": "bytes", "name": "field_1", "type": "bytes" }
],
+<<<<<<< HEAD
"internalType": "struct Tuple19[]",
"name": "properties",
"type": "tuple[]"
@@ -690,6 +710,12 @@
{ "internalType": "string", "name": "key", "type": "string" },
{ "internalType": "bytes", "name": "value", "type": "bytes" }
>>>>>>> feat: Add custum signature with unlimited nesting.
+=======
+ "internalType": "struct Tuple21[]",
+ "name": "properties",
+ "type": "tuple[]"
+ }
+>>>>>>> fix: after rebase
],
"name": "setCollectionProperties",
"outputs": [],