git.delta.rocks / unique-network / refs/commits / 55c4d052d75c

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_core::{H160, U256};23use sp_std::vec::Vec;24use pallet_evm::account::CrossAccountId;25use pallet_evm_coder_substrate::{call, dispatch_to_evm};26use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};27use pallet_common::{CollectionHandle, erc::CollectionPropertiesCall};2829use crate::{30	Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,31	weights::WeightInfo,32};3334#[derive(ToLog)]35pub enum ERC20Events {36	Transfer {37		#[indexed]38		from: address,39		#[indexed]40		to: address,41		value: uint256,42	},43	Approval {44		#[indexed]45		owner: address,46		#[indexed]47		spender: address,48		value: uint256,49	},50}5152#[solidity_interface(name = "ERC20", events(ERC20Events))]53impl<T: Config> FungibleHandle<T> {54	fn name(&self) -> Result<string> {55		Ok(decode_utf16(self.name.iter().copied())56			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))57			.collect::<string>())58	}59	fn symbol(&self) -> Result<string> {60		Ok(string::from_utf8_lossy(&self.token_prefix).into())61	}62	fn total_supply(&self) -> Result<uint256> {63		self.consume_store_reads(1)?;64		Ok(<TotalSupply<T>>::get(self.id).into())65	}6667	fn decimals(&self) -> Result<uint8> {68		Ok(if let CollectionMode::Fungible(decimals) = &self.mode {69			*decimals70		} else {71			unreachable!()72		})73	}74	fn balance_of(&self, owner: address) -> Result<uint256> {75		self.consume_store_reads(1)?;76		let owner = T::CrossAccountId::from_eth(owner);77		let balance = <Balance<T>>::get((self.id, owner));78		Ok(balance.into())79	}80	#[weight(<SelfWeightOf<T>>::transfer())]81	fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {82		let caller = T::CrossAccountId::from_eth(caller);83		let to = T::CrossAccountId::from_eth(to);84		let amount = amount.try_into().map_err(|_| "amount overflow")?;85		let budget = self86			.recorder87			.weight_calls_budget(<StructureWeight<T>>::find_parent());8889		<Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;90		Ok(true)91	}92	#[weight(<SelfWeightOf<T>>::transfer_from())]93	fn transfer_from(94		&mut self,95		caller: caller,96		from: address,97		to: address,98		amount: uint256,99	) -> Result<bool> {100		let caller = T::CrossAccountId::from_eth(caller);101		let from = T::CrossAccountId::from_eth(from);102		let to = T::CrossAccountId::from_eth(to);103		let amount = amount.try_into().map_err(|_| "amount overflow")?;104		let budget = self105			.recorder106			.weight_calls_budget(<StructureWeight<T>>::find_parent());107108		<Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)109			.map_err(dispatch_to_evm::<T>)?;110		Ok(true)111	}112	#[weight(<SelfWeightOf<T>>::approve())]113	fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {114		let caller = T::CrossAccountId::from_eth(caller);115		let spender = T::CrossAccountId::from_eth(spender);116		let amount = amount.try_into().map_err(|_| "amount overflow")?;117118		<Pallet<T>>::set_allowance(self, &caller, &spender, amount)119			.map_err(dispatch_to_evm::<T>)?;120		Ok(true)121	}122	fn allowance(&self, owner: address, spender: address) -> Result<uint256> {123		self.consume_store_reads(1)?;124		let owner = T::CrossAccountId::from_eth(owner);125		let spender = T::CrossAccountId::from_eth(spender);126127		Ok(<Allowance<T>>::get((self.id, owner, spender)).into())128	}129}130131#[solidity_interface(name = "ERC20UniqueExtensions")]132impl<T: Config> FungibleHandle<T> {133	#[weight(<SelfWeightOf<T>>::burn_from())]134	fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {135		let caller = T::CrossAccountId::from_eth(caller);136		let from = T::CrossAccountId::from_eth(from);137		let amount = amount.try_into().map_err(|_| "amount overflow")?;138		let budget = self139			.recorder140			.weight_calls_budget(<StructureWeight<T>>::find_parent());141142		<Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)143			.map_err(dispatch_to_evm::<T>)?;144		Ok(true)145	}146}147148#[solidity_interface(149	name = "UniqueFungible",150	is(151		ERC20,152		ERC20UniqueExtensions,153		via("CollectionHandle<T>", common_mut, CollectionProperties)154	)155)]156impl<T: Config> FungibleHandle<T> {}157158generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);159generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);160161impl<T: Config> CommonEvmHandler for FungibleHandle<T> {162	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");163164	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult> {165		call::<T, UniqueFungibleCall<T>, _>(*source, self, value, input)166	}167}