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

difftreelog

source

pallets/fungible/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 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 _};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")?;8485		<Pallet<T>>::transfer(self, &caller, &to, amount).map_err(|_| "transfer error")?;86		Ok(true)87	}88	#[weight(<SelfWeightOf<T>>::transfer_from())]89	fn transfer_from(90		&mut self,91		caller: caller,92		from: address,93		to: address,94		amount: uint256,95	) -> Result<bool> {96		let caller = T::CrossAccountId::from_eth(caller);97		let from = T::CrossAccountId::from_eth(from);98		let to = T::CrossAccountId::from_eth(to);99		let amount = amount.try_into().map_err(|_| "amount overflow")?;100		let budget = self101			.recorder102			.weight_calls_budget(<StructureWeight<T>>::find_parent());103104		<Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)105			.map_err(dispatch_to_evm::<T>)?;106		Ok(true)107	}108	#[weight(<SelfWeightOf<T>>::approve())]109	fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {110		let caller = T::CrossAccountId::from_eth(caller);111		let spender = T::CrossAccountId::from_eth(spender);112		let amount = amount.try_into().map_err(|_| "amount overflow")?;113114		<Pallet<T>>::set_allowance(self, &caller, &spender, amount)115			.map_err(dispatch_to_evm::<T>)?;116		Ok(true)117	}118	fn allowance(&self, owner: address, spender: address) -> Result<uint256> {119		self.consume_store_reads(1)?;120		let owner = T::CrossAccountId::from_eth(owner);121		let spender = T::CrossAccountId::from_eth(spender);122123		Ok(<Allowance<T>>::get((self.id, owner, spender)).into())124	}125}126127#[solidity_interface(name = "ERC20UniqueExtensions")]128impl<T: Config> FungibleHandle<T> {129	#[weight(<SelfWeightOf<T>>::burn_from())]130	fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {131		let caller = T::CrossAccountId::from_eth(caller);132		let from = T::CrossAccountId::from_eth(from);133		let amount = amount.try_into().map_err(|_| "amount overflow")?;134		let budget = self135			.recorder136			.weight_calls_budget(<StructureWeight<T>>::find_parent());137138		<Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)139			.map_err(dispatch_to_evm::<T>)?;140		Ok(true)141	}142}143144#[solidity_interface(name = "UniqueFungible", is(ERC20))]145impl<T: Config> FungibleHandle<T> {}146147generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);148generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);149150impl<T: Config> CommonEvmHandler for FungibleHandle<T> {151	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");152153	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult> {154		call::<T, UniqueFungibleCall<T>, _>(*source, self, value, input)155	}156}