1use evm_coder::{abi::AbiType, generate_stubgen, solidity_interface, types::*};2use pallet_balances::WeightInfo;3use pallet_common::{4 erc::{CommonEvmHandler, CrossAccountId, PrecompileHandle, PrecompileResult},5 eth::CrossAddress,6};7use pallet_evm_coder_substrate::{8 call, dispatch_to_evm,9 execution::{PreDispatch, Result},10 frontier_contract, WithRecorder,11};12use pallet_structure::{weights::WeightInfo as _, SelfWeightOf as StructureWeight};13use sp_core::{Get, U256};1415use crate::{Config, NativeFungibleHandle, Pallet, SelfWeightOf};1617frontier_contract! {18 macro_rules! NativeFungibleHandle_result {...}19 impl<T: Config> Contract for NativeFungibleHandle<T> {...}20}2122#[solidity_interface(name = ERC20, enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x942e8b22)]23impl<T: Config> NativeFungibleHandle<T> {24 fn allowance(&self, _owner: Address, _spender: Address) -> Result<U256> {25 Ok(U256::zero())26 }2728 fn approve(&mut self, _caller: Caller, _spender: Address, _amount: U256) -> Result<bool> {29 Err("approve not supported".into())30 }3132 fn balance_of(&self, owner: Address) -> Result<U256> {33 self.consume_store_reads(1)?;34 let owner = T::CrossAccountId::from_eth(owner);35 let balance = <Pallet<T>>::balance_of(&owner);36 Ok(balance.into())37 }3839 fn decimals(&self) -> Result<u8> {40 Ok(T::Decimals::get())41 }4243 fn name(&self) -> Result<String> {44 Ok(T::Name::get())45 }4647 fn symbol(&self) -> Result<String> {48 Ok(T::Symbol::get())49 }5051 fn total_supply(&self) -> Result<U256> {52 self.consume_store_reads(1)?;53 Ok(<Pallet<T>>::total_issuance().into())54 }5556 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]57 fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {58 let caller = T::CrossAccountId::from_eth(caller);59 let to = T::CrossAccountId::from_eth(to);60 let amount = amount.try_into().map_err(|_| "amount overflow")?;6162 <Pallet<T>>::transfer(&caller, &to, amount).map_err(|e| dispatch_to_evm::<T>(e.error))?;63 Ok(true)64 }6566 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]67 fn transfer_from(68 &mut self,69 caller: Caller,70 from: Address,71 to: Address,72 amount: U256,73 ) -> Result<bool> {74 let caller = T::CrossAccountId::from_eth(caller);75 let from = T::CrossAccountId::from_eth(from);76 let to = T::CrossAccountId::from_eth(to);77 let amount = amount.try_into().map_err(|_| "amount overflow")?;78 let budget = self79 .recorder()80 .weight_calls_budget(<StructureWeight<T>>::find_parent());8182 <Pallet<T>>::transfer_from(&caller, &from, &to, amount, &budget)83 .map_err(|e| dispatch_to_evm::<T>(e.error))?;84 Ok(true)85 }86}8788#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]89impl<T: Config> NativeFungibleHandle<T>90where91 T::AccountId: From<[u8; 32]>,92{93 fn balance_of_cross(&self, owner: CrossAddress) -> Result<U256> {94 self.consume_store_reads(1)?;95 let owner = owner.into_sub_cross_account::<T>()?;96 let balance = <Pallet<T>>::balance_of(&owner);97 Ok(balance.into())98 }99100 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]101 fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {102 let caller = T::CrossAccountId::from_eth(caller);103 let to = to.into_sub_cross_account::<T>()?;104 let amount = amount.try_into().map_err(|_| "amount overflow")?;105106 <Pallet<T>>::transfer(&caller, &to, amount).map_err(|e| dispatch_to_evm::<T>(e.error))?;107108 Ok(true)109 }110111 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]112 fn transfer_from_cross(113 &mut self,114 caller: Caller,115 from: CrossAddress,116 to: CrossAddress,117 amount: U256,118 ) -> Result<bool> {119 let caller = T::CrossAccountId::from_eth(caller);120 let from = from.into_sub_cross_account::<T>()?;121 let to = to.into_sub_cross_account::<T>()?;122 let amount = amount.try_into().map_err(|_| "amount overflow")?;123124 if from != caller {125 return Err("no permission".into());126 }127128 let budget = self129 .recorder()130 .weight_calls_budget(<StructureWeight<T>>::find_parent());131132 <Pallet<T>>::transfer_from(&caller, &from, &to, amount, &budget)133 .map_err(|e| dispatch_to_evm::<T>(e.error))?;134135 Ok(true)136 }137}138139#[solidity_interface(140 name = UniqueNativeFungible,141 is(ERC20, ERC20UniqueExtensions),142 enum(derive(PreDispatch))143)]144impl<T: Config> NativeFungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}145146generate_stubgen!(gen_impl, UniqueNativeFungibleCall<()>, true);147generate_stubgen!(gen_iface, UniqueNativeFungibleCall<()>, false);148149impl<T: Config> CommonEvmHandler for NativeFungibleHandle<T>150where151 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,152{153 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNativeFungible.raw");154155 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {156 call::<T, UniqueNativeFungibleCall<T>, _, _>(handle, self)157 }158}