git.delta.rocks / unique-network / refs/commits / 00a765656f26

difftreelog

source

pallets/fungible/src/erc.rs5.4 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 core::char::{REPLACEMENT_CHARACTER, decode_utf16};18use core::convert::TryInto;19use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};20use up_data_structs::CollectionMode;21use pallet_common::erc::{CommonEvmHandler, PrecompileResult};22use sp_std::vec::Vec;23use pallet_evm::{account::CrossAccountId, PrecompileHandle};24use pallet_evm_coder_substrate::{call, dispatch_to_evm};25use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};26use pallet_common::{CollectionHandle, erc::CollectionCall};2728use crate::{29	Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,30	weights::WeightInfo,31};3233#[derive(ToLog)]34pub enum ERC20Events {35	Transfer {36		#[indexed]37		from: address,38		#[indexed]39		to: address,40		value: uint256,41	},42	Approval {43		#[indexed]44		owner: address,45		#[indexed]46		spender: address,47		value: uint256,48	},49}5051#[solidity_interface(name = "ERC20", events(ERC20Events))]52impl<T: Config> FungibleHandle<T> {53	fn name(&self) -> Result<string> {54		Ok(decode_utf16(self.name.iter().copied())55			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))56			.collect::<string>())57	}58	fn symbol(&self) -> Result<string> {59		Ok(string::from_utf8_lossy(&self.token_prefix).into())60	}61	fn total_supply(&self) -> Result<uint256> {62		self.consume_store_reads(1)?;63		Ok(<TotalSupply<T>>::get(self.id).into())64	}6566	fn decimals(&self) -> Result<uint8> {67		Ok(if let CollectionMode::Fungible(decimals) = &self.mode {68			*decimals69		} else {70			unreachable!()71		})72	}73	fn balance_of(&self, owner: address) -> Result<uint256> {74		self.consume_store_reads(1)?;75		let owner = T::CrossAccountId::from_eth(owner);76		let balance = <Balance<T>>::get((self.id, owner));77		Ok(balance.into())78	}79	#[weight(<SelfWeightOf<T>>::transfer())]80	fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {81		let caller = T::CrossAccountId::from_eth(caller);82		let to = T::CrossAccountId::from_eth(to);83		let amount = amount.try_into().map_err(|_| "amount overflow")?;84		let budget = self85			.recorder86			.weight_calls_budget(<StructureWeight<T>>::find_parent());8788		<Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;89		Ok(true)90	}91	#[weight(<SelfWeightOf<T>>::transfer_from())]92	fn transfer_from(93		&mut self,94		caller: caller,95		from: address,96		to: address,97		amount: uint256,98	) -> Result<bool> {99		let caller = T::CrossAccountId::from_eth(caller);100		let from = T::CrossAccountId::from_eth(from);101		let to = T::CrossAccountId::from_eth(to);102		let amount = amount.try_into().map_err(|_| "amount overflow")?;103		let budget = self104			.recorder105			.weight_calls_budget(<StructureWeight<T>>::find_parent());106107		<Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)108			.map_err(dispatch_to_evm::<T>)?;109		Ok(true)110	}111	#[weight(<SelfWeightOf<T>>::approve())]112	fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {113		let caller = T::CrossAccountId::from_eth(caller);114		let spender = T::CrossAccountId::from_eth(spender);115		let amount = amount.try_into().map_err(|_| "amount overflow")?;116117		<Pallet<T>>::set_allowance(self, &caller, &spender, amount)118			.map_err(dispatch_to_evm::<T>)?;119		Ok(true)120	}121	fn allowance(&self, owner: address, spender: address) -> Result<uint256> {122		self.consume_store_reads(1)?;123		let owner = T::CrossAccountId::from_eth(owner);124		let spender = T::CrossAccountId::from_eth(spender);125126		Ok(<Allowance<T>>::get((self.id, owner, spender)).into())127	}128}129130#[solidity_interface(name = "ERC20UniqueExtensions")]131impl<T: Config> FungibleHandle<T> {132	#[weight(<SelfWeightOf<T>>::burn_from())]133	fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {134		let caller = T::CrossAccountId::from_eth(caller);135		let from = T::CrossAccountId::from_eth(from);136		let amount = amount.try_into().map_err(|_| "amount overflow")?;137		let budget = self138			.recorder139			.weight_calls_budget(<StructureWeight<T>>::find_parent());140141		<Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)142			.map_err(dispatch_to_evm::<T>)?;143		Ok(true)144	}145}146147#[solidity_interface(148	name = "UniqueFungible",149	is(150		ERC20,151		ERC20UniqueExtensions,152		via("CollectionHandle<T>", common_mut, Collection)153	)154)]155impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> {}156157generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);158generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);159160impl<T: Config> CommonEvmHandler for FungibleHandle<T>161where162	T::AccountId: From<[u8; 32]>,163{164	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");165166	fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {167		call::<T, UniqueFungibleCall<T>, _, _>(handle, self)168	}169}