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

difftreelog

source

pallets/common/src/erc.rs5.1 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use evm_coder::{solidity_interface, types::*, execution::{Result, Error}};18pub use pallet_evm::{PrecompileOutput, PrecompileResult, account::CrossAccountId};19use pallet_evm_coder_substrate::dispatch_to_evm;20use sp_core::{H160, U256};21use sp_std::vec::Vec;22use up_data_structs::{Property, SponsoringRateLimit};23use alloc::format;2425use crate::{Pallet, CollectionHandle, Config, CollectionProperties};2627/// Does not always represent a full collection, for RFT it is either28/// collection (Implementing ERC721), or specific collection token (Implementing ERC20)29pub trait CommonEvmHandler {30	const CODE: &'static [u8];3132	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult>;33}3435#[solidity_interface(name = "Collection")]36impl<T: Config> CollectionHandle<T> {37	fn set_collection_property(&mut self, caller: caller, key: string, value: bytes) -> Result<()> {38		let caller = T::CrossAccountId::from_eth(caller);39		let key = <Vec<u8>>::from(key)40			.try_into()41			.map_err(|_| "key too large")?;42		let value = value.try_into().map_err(|_| "value too large")?;4344		<Pallet<T>>::set_collection_property(self, &caller, Property { key, value })45			.map_err(dispatch_to_evm::<T>)46	}4748	fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {49		let caller = T::CrossAccountId::from_eth(caller);50		let key = <Vec<u8>>::from(key)51			.try_into()52			.map_err(|_| "key too large")?;5354		<Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)55	}5657	/// Throws error if key not found58	fn collection_property(&self, key: string) -> Result<bytes> {59		let key = <Vec<u8>>::from(key)60			.try_into()61			.map_err(|_| "key too large")?;6263		let props = <CollectionProperties<T>>::get(self.id);64		let prop = props.get(&key).ok_or("key not found")?;6566		Ok(prop.to_vec())67	}6869	fn eth_set_sponsor(70		&mut self,71		caller: caller,72		sponsor: address,73	) -> Result<void> {74		check_is_owner(caller, self)?;7576		let sponsor = T::CrossAccountId::from_eth(sponsor);77		self.set_sponsor(sponsor.as_sub().clone());78		save(self);79		Ok(())80	}8182	fn eth_confirm_sponsorship(&mut self, caller: caller) -> Result<void> {83		let caller = T::CrossAccountId::from_eth(caller);84		if !self.confirm_sponsorship(caller.as_sub()) {85			return Err(Error::Revert("Caller is not set as sponsor".into()));86		}87		save(self);88		Ok(())89	}9091	fn set_limit(92		&mut self,93		caller: caller,94		limit: string,95		value: string,96	) -> Result<void> {97		check_is_owner(caller, self)?;98		let mut limits = self.limits.clone();99100		match limit.as_str() {101			"accountTokenOwnershipLimit" => {102				limits.account_token_ownership_limit = parse_int(value)?;103			},104			"sponsoredDataSize" => {105				limits.sponsored_data_size = parse_int(value)?;106			},107			"sponsoredDataRateLimit" => {108				limits.sponsored_data_rate_limit = Some(SponsoringRateLimit::Blocks(parse_int(value)?.unwrap()));109			},110			"tokenLimit" => {111				limits.token_limit = parse_int(value)?;112			},113			"sponsorTransferTimeout" => {114				limits.sponsor_transfer_timeout = parse_int(value)?;115			},116			"sponsorApproveTimeout" => {117				limits.sponsor_approve_timeout = parse_int(value)?;118			},119			"ownerCanTransfer" => {120				limits.owner_can_transfer = parse_bool(value)?;121			},122			"ownerCanDestroy" => {123				limits.owner_can_destroy = parse_bool(value)?;124			},125			"transfersEnabled" => {126				limits.transfers_enabled = parse_bool(value)?;127			},128			_ => return Err(Error::Revert(format!("Unknown limit \"{}\"", limit)))129		}130		self.limits = limits;131		save(self);132		Ok(())133	}134135	fn contract_address(&self, _caller: caller) -> Result<address> {136		Ok(crate::eth::collection_id_to_address(self.id))137	}138}139140fn check_is_owner<T: Config>(caller: caller, collection: &CollectionHandle<T>) -> Result<()> {141	let caller = T::CrossAccountId::from_eth(caller);142	collection143		.check_is_owner(&caller)144		.map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;145	Ok(())146}147148fn save<T: Config>(collection: &CollectionHandle<T>) {149	<crate::CollectionById<T>>::insert(collection.id, collection.collection.clone());150}151152fn parse_int(value: string) -> Result<Option<u32>> {153	value.parse::<u32>()154		.map_err(|e| Error::Revert(format!("Int value \"{}\" parse error: {}", value, e)))155		.map(|value| Some(value))156}157158fn parse_bool(value: string) -> Result<Option<bool>> {159	value.parse::<bool>()160		.map_err(|e| Error::Revert(format!("Bool value \"{}\" parse error: {}", value, e)))161		.map(|value| Some(value))162}