git.delta.rocks / unique-network / refs/commits / d08f39622829

difftreelog

source

pallets/nft/src/eth/erc_impl.rs8.2 KiBsourcehistory
1use core::char::{decode_utf16, REPLACEMENT_CHARACTER};2use evm_coder::{3	abi::{AbiWriter, StringError},4	types::*,5};6use core::convert::TryInto;7use alloc::format;8use crate::{Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList};9use frame_support::storage::StorageDoubleMap;10use pallet_evm::AddressMapping;11use super::erc::*;12use super::account::CrossAccountId;1314type Result<T> = core::result::Result<T, StringError>;1516impl<T: Config> InlineNameSymbol for CollectionHandle<T> {17	type Error = StringError;1819	fn name(&self) -> Result<string> {20		Ok(decode_utf16(self.name.iter().copied())21			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))22			.collect::<string>())23	}2425	fn symbol(&self) -> Result<string> {26		Ok(string::from_utf8_lossy(&self.token_prefix).into())27	}28}2930impl<T: Config> InlineTotalSupply for CollectionHandle<T> {31	type Error = StringError;3233	fn total_supply(&self) -> Result<uint256> {34		// TODO: we do not track total amount of all tokens35		Ok(0.into())36	}37}3839impl<T: Config> ERC721Metadata for CollectionHandle<T> {40	type Error = StringError;4142	fn token_uri(&self, token_id: uint256) -> Result<string> {43		// TODO: We should standartize url prefix, maybe via offchain schema?44		Ok(format!("unique.network/{}/{}", self.id, token_id))45	}4647	fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {48		<Self as InlineNameSymbol>::call(self, c)49	}50}5152impl<T: Config> ERC721Enumerable for CollectionHandle<T> {53	type Error = StringError;5455	fn token_by_index(&self, index: uint256) -> Result<uint256> {56		Ok(index)57	}5859	fn token_of_owner_by_index(&self, owner: address, index: uint256) -> Result<uint256> {60		// TODO: Not implemetable61		Err("not implemented".into())62	}6364	fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {65		<Self as InlineTotalSupply>::call(self, c)66	}67}6869impl<T: Config> ERC721 for CollectionHandle<T> {70	type Error = StringError;7172	fn balance_of(&self, owner: address) -> Result<uint256> {73		let owner = T::EvmAddressMapping::into_account_id(owner);74		let balance = <Balance<T>>::get(self.id, owner);75		Ok(balance.into())76	}77	fn owner_of(&self, token_id: uint256) -> Result<address> {78		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;79		let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;80		Ok(token.owner.as_eth().clone())81	}82	fn safe_transfer_from_with_data(83		&mut self,84		_from: address,85		_to: address,86		_token_id: uint256,87		_data: bytes,88		_value: value,89	) -> Result<void> {90		// TODO: Not implemetable91		Err("not implemented".into())92	}93	fn safe_transfer_from(94		&mut self,95		_from: address,96		_to: address,97		_token_id: uint256,98		_value: value,99	) -> Result<void> {100		// TODO: Not implemetable101		Err("not implemented".into())102	}103104	fn transfer_from(105		&mut self,106		caller: caller,107		from: address,108		to: address,109		token_id: uint256,110		_value: value,111	) -> Result<void> {112		let caller = T::CrossAccountId::from_eth(caller);113		let from = T::CrossAccountId::from_eth(from);114		let to = T::CrossAccountId::from_eth(to);115		let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;116117		<Module<T>>::transfer_from_internal(&caller, &from, &to, &self, token_id, 1)118			.map_err(|_| "transferFrom error")?;119		Ok(())120	}121122	fn approve(123		&mut self,124		caller: caller,125		approved: address,126		token_id: uint256,127		_value: value,128	) -> Result<void> {129		let caller = T::CrossAccountId::from_eth(caller);130		let approved = T::CrossAccountId::from_eth(approved);131		let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;132133		<Module<T>>::approve_internal(&caller, &approved, &self, token_id, 1)134			.map_err(|_| "approve internal")?;135		Ok(())136	}137138	fn set_approval_for_all(139		&mut self,140		_caller: caller,141		_operator: address,142		_approved: bool,143	) -> Result<void> {144		// TODO: Not implemetable145		Err("not implemented".into())146	}147148	fn get_approved(&self, _token_id: uint256) -> Result<address> {149		// TODO: Not implemetable150		Err("not implemented".into())151	}152153	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {154		// TODO: Not implemetable155		Err("not implemented".into())156	}157158	fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {159		let ERC165Call::SupportsInterface { interface_id } = c.call;160		Ok(evm_coder::abi_encode!(bool(161			&ERC721Call::supports_interface(interface_id)162		)))163	}164}165166impl<T: Config> ERC721UniqueExtensions for CollectionHandle<T> {167	type Error = StringError;168	fn transfer(169		&mut self,170		caller: caller,171		to: address,172		token_id: uint256,173		value: value,174	) -> Result<void> {175		let caller = T::CrossAccountId::from_eth(caller);176		let to = T::CrossAccountId::from_eth(to);177		let token_id = token_id.try_into().map_err(|_| "amount overflow")?;178179		<Module<T>>::transfer_internal(&caller, &to, &self, token_id, 1)180			.map_err(|_| "transfer error")?;181		Ok(())182	}183}184185impl<T: Config> UniqueNFT for CollectionHandle<T> {186	type Error = StringError;187	fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {188		let ERC165Call::SupportsInterface { interface_id } = c.call;189		Ok(evm_coder::abi_encode!(bool(190			&UniqueNFTCall::supports_interface(interface_id)191		)))192	}193	fn call_erc721(&mut self, c: Msg<ERC721Call>) -> Result<AbiWriter> {194		<Self as ERC721>::call(self, c)195	}196	fn call_erc721_metadata(&mut self, c: Msg<ERC721MetadataCall>) -> Result<AbiWriter> {197		<Self as ERC721Metadata>::call(self, c)198	}199	fn call_erc721_enumerable(&mut self, c: Msg<ERC721EnumerableCall>) -> Result<AbiWriter> {200		<Self as ERC721Enumerable>::call(self, c)201	}202	fn call_erc721_unique_extensions(203		&mut self,204		c: Msg<ERC721UniqueExtensionsCall>,205	) -> Result<AbiWriter> {206		<Self as ERC721UniqueExtensions>::call(self, c)207	}208}209210impl<T: Config> ERC20 for CollectionHandle<T> {211	type Error = StringError;212	fn decimals(&self) -> Result<uint8> {213		Ok(if let CollectionMode::Fungible(decimals) = &self.mode {214			*decimals215		} else {216			unreachable!()217		})218	}219	fn balance_of(&self, owner: address) -> Result<uint256> {220		let owner = T::EvmAddressMapping::into_account_id(owner);221		let balance = <Balance<T>>::get(self.id, owner);222		Ok(balance.into())223	}224	fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {225		let caller = T::CrossAccountId::from_eth(caller);226		let to = T::CrossAccountId::from_eth(to);227		let amount = amount.try_into().map_err(|_| "amount overflow")?;228229		<Module<T>>::transfer_internal(&caller, &to, &self, 1, amount)230			.map_err(|_| "transfer error")?;231		Ok(true)232	}233	fn transfer_from(234		&mut self,235		caller: caller,236		from: address,237		to: address,238		amount: uint256,239	) -> Result<bool> {240		let caller = T::CrossAccountId::from_eth(caller);241		let from = T::CrossAccountId::from_eth(from);242		let to = T::CrossAccountId::from_eth(to);243		let amount = amount.try_into().map_err(|_| "amount overflow")?;244245		<Module<T>>::transfer_from_internal(&caller, &from, &to, &self, 1, amount)246			.map_err(|_| "transferFrom error")?;247		Ok(true)248	}249	fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {250		let caller = T::CrossAccountId::from_eth(caller);251		let spender = T::CrossAccountId::from_eth(spender);252		let amount = amount.try_into().map_err(|_| "amount overflow")?;253254		<Module<T>>::approve_internal(&caller, &spender, &self, 1, amount)255			.map_err(|_| "approve internal")?;256		Ok(true)257	}258	fn allowance(&self, owner: address, spender: address) -> Result<uint256> {259		let owner = T::CrossAccountId::from_eth(owner);260		let spender = T::CrossAccountId::from_eth(spender);261262		Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())263	}264	fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {265		<Self as InlineNameSymbol>::call(self, c)266	}267	fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {268		<Self as InlineTotalSupply>::call(self, c)269	}270}271272impl<T: Config> UniqueFungible for CollectionHandle<T> {273	type Error = StringError;274	fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {275		let ERC165Call::SupportsInterface { interface_id } = c.call;276		Ok(evm_coder::abi_encode!(bool(277			&UniqueNFTCall::supports_interface(interface_id)278		)))279	}280	fn call_erc20(&mut self, c: Msg<ERC20Call>) -> Result<AbiWriter> {281		<Self as ERC20>::call(self, c)282	}283}