git.delta.rocks / unique-network / refs/commits / 2f9c8d434e2f

difftreelog

source

pallets/fungible/src/erc.rs4.8 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};2627use crate::{28	Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,29	weights::WeightInfo,30};3132#[derive(ToLog)]33pub enum ERC20Events {34	Transfer {35		#[indexed]36		from: address,37		#[indexed]38		to: address,39		value: uint256,40	},41	Approval {42		#[indexed]43		owner: address,44		#[indexed]45		spender: address,46		value: uint256,47	},48}4950#[solidity_interface(name = "ERC20", events(ERC20Events))]51impl<T: Config> FungibleHandle<T> {52	fn name(&self) -> Result<string> {53		Ok(decode_utf16(self.name.iter().copied())54			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))55			.collect::<string>())56	}57	fn symbol(&self) -> Result<string> {58		Ok(string::from_utf8_lossy(&self.token_prefix).into())59	}60	fn total_supply(&self) -> Result<uint256> {61		self.consume_store_reads(1)?;62		Ok(<TotalSupply<T>>::get(self.id).into())63	}6465	fn decimals(&self) -> Result<uint8> {66		Ok(if let CollectionMode::Fungible(decimals) = &self.mode {67			*decimals68		} else {69			unreachable!()70		})71	}72	fn balance_of(&self, owner: address) -> Result<uint256> {73		self.consume_store_reads(1)?;74		let owner = T::CrossAccountId::from_eth(owner);75		let balance = <Balance<T>>::get((self.id, owner));76		Ok(balance.into())77	}78	#[weight(<SelfWeightOf<T>>::transfer())]79	fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {80		let caller = T::CrossAccountId::from_eth(caller);81		let to = T::CrossAccountId::from_eth(to);82		let amount = amount.try_into().map_err(|_| "amount overflow")?;8384		<Pallet<T>>::transfer(self, &caller, &to, amount).map_err(|_| "transfer error")?;85		Ok(true)86	}87	#[weight(<SelfWeightOf<T>>::transfer_from())]88	fn transfer_from(89		&mut self,90		caller: caller,91		from: address,92		to: address,93		amount: uint256,94	) -> Result<bool> {95		let caller = T::CrossAccountId::from_eth(caller);96		let from = T::CrossAccountId::from_eth(from);97		let to = T::CrossAccountId::from_eth(to);98		let amount = amount.try_into().map_err(|_| "amount overflow")?;99100		<Pallet<T>>::transfer_from(self, &caller, &from, &to, amount)101			.map_err(dispatch_to_evm::<T>)?;102		Ok(true)103	}104	#[weight(<SelfWeightOf<T>>::approve())]105	fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {106		let caller = T::CrossAccountId::from_eth(caller);107		let spender = T::CrossAccountId::from_eth(spender);108		let amount = amount.try_into().map_err(|_| "amount overflow")?;109110		<Pallet<T>>::set_allowance(self, &caller, &spender, amount)111			.map_err(dispatch_to_evm::<T>)?;112		Ok(true)113	}114	fn allowance(&self, owner: address, spender: address) -> Result<uint256> {115		self.consume_store_reads(1)?;116		let owner = T::CrossAccountId::from_eth(owner);117		let spender = T::CrossAccountId::from_eth(spender);118119		Ok(<Allowance<T>>::get((self.id, owner, spender)).into())120	}121}122123#[solidity_interface(name = "ERC20UniqueExtensions")]124impl<T: Config> FungibleHandle<T> {125	#[weight(<SelfWeightOf<T>>::burn_from())]126	fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {127		let caller = T::CrossAccountId::from_eth(caller);128		let from = T::CrossAccountId::from_eth(from);129		let amount = amount.try_into().map_err(|_| "amount overflow")?;130131		<Pallet<T>>::burn_from(self, &caller, &from, amount).map_err(dispatch_to_evm::<T>)?;132		Ok(true)133	}134}135136#[solidity_interface(name = "UniqueFungible", is(ERC20))]137impl<T: Config> FungibleHandle<T> {}138139generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);140generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);141142impl<T: Config> CommonEvmHandler for FungibleHandle<T> {143	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");144145	fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult> {146		call::<T, UniqueFungibleCall<T>, _>(*source, self, value, input)147	}148}