difftreelog
Merge pull request #853 from UniqueNetwork/fix/erc20
in: master
9 files changed
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/erc.rsdiffbeforeafterboth1// 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/>.1617//! ERC-20 standart support implementation.1819extern crate alloc;20use core::char::{REPLACEMENT_CHARACTER, decode_utf16};21use core::convert::TryInto;22use evm_coder::{23 abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,24 weight,25};26use up_data_structs::CollectionMode;27use pallet_common::{28 CollectionHandle,29 erc::{CommonEvmHandler, PrecompileResult, CollectionCall},30};31use sp_std::vec::Vec;32use pallet_evm::{account::CrossAccountId, PrecompileHandle};33use pallet_evm_coder_substrate::{call, dispatch_to_evm};34use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};35use sp_core::{U256, Get};3637use crate::{38 Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,39 weights::WeightInfo,40};4142#[derive(ToLog)]43pub enum ERC20Events {44 Transfer {45 #[indexed]46 from: Address,47 #[indexed]48 to: Address,49 value: U256,50 },51 Approval {52 #[indexed]53 owner: Address,54 #[indexed]55 spender: Address,56 value: U256,57 },58}5960#[solidity_interface(name = ERC20, events(ERC20Events))]61impl<T: Config> FungibleHandle<T> {62 fn name(&self) -> Result<String> {63 Ok(decode_utf16(self.name.iter().copied())64 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))65 .collect::<String>())66 }67 fn symbol(&self) -> Result<String> {68 Ok(String::from_utf8_lossy(&self.token_prefix).into())69 }70 fn total_supply(&self) -> Result<U256> {71 self.consume_store_reads(1)?;72 Ok(<TotalSupply<T>>::get(self.id).into())73 }7475 fn decimals(&self) -> Result<u8> {76 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {77 *decimals78 } else {79 unreachable!()80 })81 }82 fn balance_of(&self, owner: Address) -> Result<U256> {83 self.consume_store_reads(1)?;84 let owner = T::CrossAccountId::from_eth(owner);85 let balance = <Balance<T>>::get((self.id, owner));86 Ok(balance.into())87 }88 #[weight(<SelfWeightOf<T>>::transfer())]89 fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {90 let caller = T::CrossAccountId::from_eth(caller);91 let to = T::CrossAccountId::from_eth(to);92 let amount = amount.try_into().map_err(|_| "amount overflow")?;93 let budget = self94 .recorder95 .weight_calls_budget(<StructureWeight<T>>::find_parent());9697 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;98 Ok(true)99 }100101 #[weight(<SelfWeightOf<T>>::transfer_from())]102 fn transfer_from(103 &mut self,104 caller: Caller,105 from: Address,106 to: Address,107 amount: U256,108 ) -> Result<bool> {109 let caller = T::CrossAccountId::from_eth(caller);110 let from = T::CrossAccountId::from_eth(from);111 let to = T::CrossAccountId::from_eth(to);112 let amount = amount.try_into().map_err(|_| "amount overflow")?;113 let budget = self114 .recorder115 .weight_calls_budget(<StructureWeight<T>>::find_parent());116117 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)118 .map_err(dispatch_to_evm::<T>)?;119 Ok(true)120 }121 #[weight(<SelfWeightOf<T>>::approve())]122 fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result<bool> {123 let caller = T::CrossAccountId::from_eth(caller);124 let spender = T::CrossAccountId::from_eth(spender);125 let amount = amount.try_into().map_err(|_| "amount overflow")?;126127 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)128 .map_err(dispatch_to_evm::<T>)?;129 Ok(true)130 }131 fn allowance(&self, owner: Address, spender: Address) -> Result<U256> {132 self.consume_store_reads(1)?;133 let owner = T::CrossAccountId::from_eth(owner);134 let spender = T::CrossAccountId::from_eth(spender);135136 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())137 }138139 /// @notice Returns collection helper contract address140 fn collection_helper_address(&self) -> Result<Address> {141 Ok(T::ContractAddress::get())142 }143}144145#[solidity_interface(name = ERC20Mintable)]146impl<T: Config> FungibleHandle<T> {147 /// Mint tokens for `to` account.148 /// @param to account that will receive minted tokens149 /// @param amount amount of tokens to mint150 #[weight(<SelfWeightOf<T>>::create_item())]151 fn mint(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {152 let caller = T::CrossAccountId::from_eth(caller);153 let to = T::CrossAccountId::from_eth(to);154 let amount = amount.try_into().map_err(|_| "amount overflow")?;155 let budget = self156 .recorder157 .weight_calls_budget(<StructureWeight<T>>::find_parent());158 <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)159 .map_err(dispatch_to_evm::<T>)?;160 Ok(true)161 }162}163164#[solidity_interface(name = ERC20UniqueExtensions)]165impl<T: Config> FungibleHandle<T>166where167 T::AccountId: From<[u8; 32]>,168{169 /// @notice A description for the collection.170 fn description(&self) -> Result<String> {171 Ok(decode_utf16(self.description.iter().copied())172 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))173 .collect::<String>())174 }175176 #[weight(<SelfWeightOf<T>>::create_item())]177 fn mint_cross(178 &mut self,179 caller: Caller,180 to: pallet_common::eth::CrossAddress,181 amount: U256,182 ) -> Result<bool> {183 let caller = T::CrossAccountId::from_eth(caller);184 let to = to.into_sub_cross_account::<T>()?;185 let amount = amount.try_into().map_err(|_| "amount overflow")?;186 let budget = self187 .recorder188 .weight_calls_budget(<StructureWeight<T>>::find_parent());189 <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)190 .map_err(dispatch_to_evm::<T>)?;191 Ok(true)192 }193194 #[weight(<SelfWeightOf<T>>::approve())]195 fn approve_cross(196 &mut self,197 caller: Caller,198 spender: pallet_common::eth::CrossAddress,199 amount: U256,200 ) -> Result<bool> {201 let caller = T::CrossAccountId::from_eth(caller);202 let spender = spender.into_sub_cross_account::<T>()?;203 let amount = amount.try_into().map_err(|_| "amount overflow")?;204205 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)206 .map_err(dispatch_to_evm::<T>)?;207 Ok(true)208 }209210 /// Burn tokens from account211 /// @dev Function that burns an `amount` of the tokens of a given account,212 /// deducting from the sender's allowance for said account.213 /// @param from The account whose tokens will be burnt.214 /// @param amount The amount that will be burnt.215 #[solidity(hide)]216 #[weight(<SelfWeightOf<T>>::burn_from())]217 fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result<bool> {218 let caller = T::CrossAccountId::from_eth(caller);219 let from = T::CrossAccountId::from_eth(from);220 let amount = amount.try_into().map_err(|_| "amount overflow")?;221 let budget = self222 .recorder223 .weight_calls_budget(<StructureWeight<T>>::find_parent());224225 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)226 .map_err(dispatch_to_evm::<T>)?;227 Ok(true)228 }229230 /// Burn tokens from account231 /// @dev Function that burns an `amount` of the tokens of a given account,232 /// deducting from the sender's allowance for said account.233 /// @param from The account whose tokens will be burnt.234 /// @param amount The amount that will be burnt.235 #[weight(<SelfWeightOf<T>>::burn_from())]236 fn burn_from_cross(237 &mut self,238 caller: Caller,239 from: pallet_common::eth::CrossAddress,240 amount: U256,241 ) -> Result<bool> {242 let caller = T::CrossAccountId::from_eth(caller);243 let from = from.into_sub_cross_account::<T>()?;244 let amount = amount.try_into().map_err(|_| "amount overflow")?;245 let budget = self246 .recorder247 .weight_calls_budget(<StructureWeight<T>>::find_parent());248249 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)250 .map_err(dispatch_to_evm::<T>)?;251 Ok(true)252 }253254 /// Mint tokens for multiple accounts.255 /// @param amounts array of pairs of account address and amount256 #[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]257 fn mint_bulk(&mut self, caller: Caller, amounts: Vec<(Address, U256)>) -> Result<bool> {258 let caller = T::CrossAccountId::from_eth(caller);259 let budget = self260 .recorder261 .weight_calls_budget(<StructureWeight<T>>::find_parent());262 let amounts = amounts263 .into_iter()264 .map(|(to, amount)| {265 Ok((266 T::CrossAccountId::from_eth(to),267 amount.try_into().map_err(|_| "amount overflow")?,268 ))269 })270 .collect::<Result<_>>()?;271272 <Pallet<T>>::create_multiple_items(&self, &caller, amounts, &budget)273 .map_err(dispatch_to_evm::<T>)?;274 Ok(true)275 }276277 #[weight(<SelfWeightOf<T>>::transfer())]278 fn transfer_cross(279 &mut self,280 caller: Caller,281 to: pallet_common::eth::CrossAddress,282 amount: U256,283 ) -> Result<bool> {284 let caller = T::CrossAccountId::from_eth(caller);285 let to = to.into_sub_cross_account::<T>()?;286 let amount = amount.try_into().map_err(|_| "amount overflow")?;287 let budget = self288 .recorder289 .weight_calls_budget(<StructureWeight<T>>::find_parent());290291 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;292 Ok(true)293 }294295 #[weight(<SelfWeightOf<T>>::transfer_from())]296 fn transfer_from_cross(297 &mut self,298 caller: Caller,299 from: pallet_common::eth::CrossAddress,300 to: pallet_common::eth::CrossAddress,301 amount: U256,302 ) -> Result<bool> {303 let caller = T::CrossAccountId::from_eth(caller);304 let from = from.into_sub_cross_account::<T>()?;305 let to = to.into_sub_cross_account::<T>()?;306 let amount = amount.try_into().map_err(|_| "amount overflow")?;307 let budget = self308 .recorder309 .weight_calls_budget(<StructureWeight<T>>::find_parent());310311 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)312 .map_err(dispatch_to_evm::<T>)?;313 Ok(true)314 }315}316317#[solidity_interface(318 name = UniqueFungible,319 is(320 ERC20,321 ERC20Mintable,322 ERC20UniqueExtensions,323 Collection(via(common_mut returns CollectionHandle<T>)),324 )325)]326impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}327328generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);329generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);330331impl<T: Config> CommonEvmHandler for FungibleHandle<T>332where333 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,334{335 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");336337 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {338 call::<T, UniqueFungibleCall<T>, _, _>(handle, self)339 }340}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/>.1617//! ERC-20 standart support implementation.1819extern crate alloc;20use core::char::{REPLACEMENT_CHARACTER, decode_utf16};21use core::convert::TryInto;22use evm_coder::{23 abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,24 weight,25};26use up_data_structs::CollectionMode;27use pallet_common::{28 CollectionHandle,29 erc::{CommonEvmHandler, PrecompileResult, CollectionCall},30};31use sp_std::vec::Vec;32use pallet_evm::{account::CrossAccountId, PrecompileHandle};33use pallet_evm_coder_substrate::{call, dispatch_to_evm};34use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};35use sp_core::{U256, Get};3637use crate::{38 Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,39 weights::WeightInfo,40};4142#[derive(ToLog)]43pub enum ERC20Events {44 Transfer {45 #[indexed]46 from: Address,47 #[indexed]48 to: Address,49 value: U256,50 },51 Approval {52 #[indexed]53 owner: Address,54 #[indexed]55 spender: Address,56 value: U256,57 },58}5960#[solidity_interface(name = ERC20, events(ERC20Events), expect_selector = 0x942e8b22)]61impl<T: Config> FungibleHandle<T> {62 fn name(&self) -> Result<String> {63 Ok(decode_utf16(self.name.iter().copied())64 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))65 .collect::<String>())66 }67 fn symbol(&self) -> Result<String> {68 Ok(String::from_utf8_lossy(&self.token_prefix).into())69 }70 fn total_supply(&self) -> Result<U256> {71 self.consume_store_reads(1)?;72 Ok(<TotalSupply<T>>::get(self.id).into())73 }7475 fn decimals(&self) -> Result<u8> {76 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {77 *decimals78 } else {79 unreachable!()80 })81 }82 fn balance_of(&self, owner: Address) -> Result<U256> {83 self.consume_store_reads(1)?;84 let owner = T::CrossAccountId::from_eth(owner);85 let balance = <Balance<T>>::get((self.id, owner));86 Ok(balance.into())87 }88 #[weight(<SelfWeightOf<T>>::transfer())]89 fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {90 let caller = T::CrossAccountId::from_eth(caller);91 let to = T::CrossAccountId::from_eth(to);92 let amount = amount.try_into().map_err(|_| "amount overflow")?;93 let budget = self94 .recorder95 .weight_calls_budget(<StructureWeight<T>>::find_parent());9697 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;98 Ok(true)99 }100101 #[weight(<SelfWeightOf<T>>::transfer_from())]102 fn transfer_from(103 &mut self,104 caller: Caller,105 from: Address,106 to: Address,107 amount: U256,108 ) -> Result<bool> {109 let caller = T::CrossAccountId::from_eth(caller);110 let from = T::CrossAccountId::from_eth(from);111 let to = T::CrossAccountId::from_eth(to);112 let amount = amount.try_into().map_err(|_| "amount overflow")?;113 let budget = self114 .recorder115 .weight_calls_budget(<StructureWeight<T>>::find_parent());116117 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)118 .map_err(dispatch_to_evm::<T>)?;119 Ok(true)120 }121 #[weight(<SelfWeightOf<T>>::approve())]122 fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result<bool> {123 let caller = T::CrossAccountId::from_eth(caller);124 let spender = T::CrossAccountId::from_eth(spender);125 let amount = amount.try_into().map_err(|_| "amount overflow")?;126127 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)128 .map_err(dispatch_to_evm::<T>)?;129 Ok(true)130 }131 fn allowance(&self, owner: Address, spender: Address) -> Result<U256> {132 self.consume_store_reads(1)?;133 let owner = T::CrossAccountId::from_eth(owner);134 let spender = T::CrossAccountId::from_eth(spender);135136 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())137 }138}139140#[solidity_interface(name = ERC20Mintable)]141impl<T: Config> FungibleHandle<T> {142 /// Mint tokens for `to` account.143 /// @param to account that will receive minted tokens144 /// @param amount amount of tokens to mint145 #[weight(<SelfWeightOf<T>>::create_item())]146 fn mint(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {147 let caller = T::CrossAccountId::from_eth(caller);148 let to = T::CrossAccountId::from_eth(to);149 let amount = amount.try_into().map_err(|_| "amount overflow")?;150 let budget = self151 .recorder152 .weight_calls_budget(<StructureWeight<T>>::find_parent());153 <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)154 .map_err(dispatch_to_evm::<T>)?;155 Ok(true)156 }157}158159#[solidity_interface(name = ERC20UniqueExtensions)]160impl<T: Config> FungibleHandle<T>161where162 T::AccountId: From<[u8; 32]>,163{164 /// @notice A description for the collection.165 fn description(&self) -> Result<String> {166 Ok(decode_utf16(self.description.iter().copied())167 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))168 .collect::<String>())169 }170171 #[weight(<SelfWeightOf<T>>::create_item())]172 fn mint_cross(173 &mut self,174 caller: Caller,175 to: pallet_common::eth::CrossAddress,176 amount: U256,177 ) -> Result<bool> {178 let caller = T::CrossAccountId::from_eth(caller);179 let to = to.into_sub_cross_account::<T>()?;180 let amount = amount.try_into().map_err(|_| "amount overflow")?;181 let budget = self182 .recorder183 .weight_calls_budget(<StructureWeight<T>>::find_parent());184 <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)185 .map_err(dispatch_to_evm::<T>)?;186 Ok(true)187 }188189 #[weight(<SelfWeightOf<T>>::approve())]190 fn approve_cross(191 &mut self,192 caller: Caller,193 spender: pallet_common::eth::CrossAddress,194 amount: U256,195 ) -> Result<bool> {196 let caller = T::CrossAccountId::from_eth(caller);197 let spender = spender.into_sub_cross_account::<T>()?;198 let amount = amount.try_into().map_err(|_| "amount overflow")?;199200 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)201 .map_err(dispatch_to_evm::<T>)?;202 Ok(true)203 }204205 /// Burn tokens from account206 /// @dev Function that burns an `amount` of the tokens of a given account,207 /// deducting from the sender's allowance for said account.208 /// @param from The account whose tokens will be burnt.209 /// @param amount The amount that will be burnt.210 #[solidity(hide)]211 #[weight(<SelfWeightOf<T>>::burn_from())]212 fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result<bool> {213 let caller = T::CrossAccountId::from_eth(caller);214 let from = T::CrossAccountId::from_eth(from);215 let amount = amount.try_into().map_err(|_| "amount overflow")?;216 let budget = self217 .recorder218 .weight_calls_budget(<StructureWeight<T>>::find_parent());219220 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)221 .map_err(dispatch_to_evm::<T>)?;222 Ok(true)223 }224225 /// Burn tokens from account226 /// @dev Function that burns an `amount` of the tokens of a given account,227 /// deducting from the sender's allowance for said account.228 /// @param from The account whose tokens will be burnt.229 /// @param amount The amount that will be burnt.230 #[weight(<SelfWeightOf<T>>::burn_from())]231 fn burn_from_cross(232 &mut self,233 caller: Caller,234 from: pallet_common::eth::CrossAddress,235 amount: U256,236 ) -> Result<bool> {237 let caller = T::CrossAccountId::from_eth(caller);238 let from = from.into_sub_cross_account::<T>()?;239 let amount = amount.try_into().map_err(|_| "amount overflow")?;240 let budget = self241 .recorder242 .weight_calls_budget(<StructureWeight<T>>::find_parent());243244 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)245 .map_err(dispatch_to_evm::<T>)?;246 Ok(true)247 }248249 /// Mint tokens for multiple accounts.250 /// @param amounts array of pairs of account address and amount251 #[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]252 fn mint_bulk(&mut self, caller: Caller, amounts: Vec<(Address, U256)>) -> Result<bool> {253 let caller = T::CrossAccountId::from_eth(caller);254 let budget = self255 .recorder256 .weight_calls_budget(<StructureWeight<T>>::find_parent());257 let amounts = amounts258 .into_iter()259 .map(|(to, amount)| {260 Ok((261 T::CrossAccountId::from_eth(to),262 amount.try_into().map_err(|_| "amount overflow")?,263 ))264 })265 .collect::<Result<_>>()?;266267 <Pallet<T>>::create_multiple_items(&self, &caller, amounts, &budget)268 .map_err(dispatch_to_evm::<T>)?;269 Ok(true)270 }271272 #[weight(<SelfWeightOf<T>>::transfer())]273 fn transfer_cross(274 &mut self,275 caller: Caller,276 to: pallet_common::eth::CrossAddress,277 amount: U256,278 ) -> Result<bool> {279 let caller = T::CrossAccountId::from_eth(caller);280 let to = to.into_sub_cross_account::<T>()?;281 let amount = amount.try_into().map_err(|_| "amount overflow")?;282 let budget = self283 .recorder284 .weight_calls_budget(<StructureWeight<T>>::find_parent());285286 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;287 Ok(true)288 }289290 #[weight(<SelfWeightOf<T>>::transfer_from())]291 fn transfer_from_cross(292 &mut self,293 caller: Caller,294 from: pallet_common::eth::CrossAddress,295 to: pallet_common::eth::CrossAddress,296 amount: U256,297 ) -> Result<bool> {298 let caller = T::CrossAccountId::from_eth(caller);299 let from = from.into_sub_cross_account::<T>()?;300 let to = to.into_sub_cross_account::<T>()?;301 let amount = amount.try_into().map_err(|_| "amount overflow")?;302 let budget = self303 .recorder304 .weight_calls_budget(<StructureWeight<T>>::find_parent());305306 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)307 .map_err(dispatch_to_evm::<T>)?;308 Ok(true)309 }310311 /// @notice Returns collection helper contract address312 fn collection_helper_address(&self) -> Result<Address> {313 Ok(T::ContractAddress::get())314 }315}316317#[solidity_interface(318 name = UniqueFungible,319 is(320 ERC20,321 ERC20Mintable,322 ERC20UniqueExtensions,323 Collection(via(common_mut returns CollectionHandle<T>)),324 )325)]326impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}327328generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);329generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);330331impl<T: Config> CommonEvmHandler for FungibleHandle<T>332where333 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,334{335 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");336337 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {338 call::<T, UniqueFungibleCall<T>, _, _>(handle, self)339 }340}pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -511,7 +511,7 @@
bytes value;
}
-/// @dev the ERC-165 identifier for this interface is 0x7dee5997
+/// @dev the ERC-165 identifier for this interface is 0x65789571
contract ERC20UniqueExtensions is Dummy, ERC165 {
/// @notice A description for the collection.
/// @dev EVM selector for this function is: 0x7284e416,
@@ -607,6 +607,15 @@
dummy = 0;
return false;
}
+
+ /// @notice Returns collection helper contract address
+ /// @dev EVM selector for this function is: 0x1896cce6,
+ /// or in textual repr: collectionHelperAddress()
+ function collectionHelperAddress() public view returns (address) {
+ require(false, stub_error);
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
}
/// @dev anonymous struct
@@ -637,7 +646,7 @@
event Approval(address indexed owner, address indexed spender, uint256 value);
}
-/// @dev the ERC-165 identifier for this interface is 0x8cb847c4
+/// @dev the ERC-165 identifier for this interface is 0x942e8b22
contract ERC20 is Dummy, ERC165, ERC20Events {
/// @dev EVM selector for this function is: 0x06fdde03,
/// or in textual repr: name()
@@ -723,15 +732,6 @@
spender;
dummy;
return 0;
- }
-
- /// @notice Returns collection helper contract address
- /// @dev EVM selector for this function is: 0x1896cce6,
- /// or in textual repr: collectionHelperAddress()
- function collectionHelperAddress() public view returns (address) {
- require(false, stub_error);
- dummy;
- return 0x0000000000000000000000000000000000000000;
}
}
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -353,7 +353,7 @@
bytes value;
}
-/// @dev the ERC-165 identifier for this interface is 0x7dee5997
+/// @dev the ERC-165 identifier for this interface is 0x65789571
interface ERC20UniqueExtensions is Dummy, ERC165 {
/// @notice A description for the collection.
/// @dev EVM selector for this function is: 0x7284e416,
@@ -403,6 +403,11 @@
CrossAddress memory to,
uint256 amount
) external returns (bool);
+
+ /// @notice Returns collection helper contract address
+ /// @dev EVM selector for this function is: 0x1896cce6,
+ /// or in textual repr: collectionHelperAddress()
+ function collectionHelperAddress() external view returns (address);
}
/// @dev anonymous struct
@@ -427,7 +432,7 @@
event Approval(address indexed owner, address indexed spender, uint256 value);
}
-/// @dev the ERC-165 identifier for this interface is 0x8cb847c4
+/// @dev the ERC-165 identifier for this interface is 0x942e8b22
interface ERC20 is Dummy, ERC165, ERC20Events {
/// @dev EVM selector for this function is: 0x06fdde03,
/// or in textual repr: name()
@@ -468,11 +473,6 @@
/// @dev EVM selector for this function is: 0xdd62ed3e,
/// or in textual repr: allowance(address,address)
function allowance(address owner, address spender) external view returns (uint256);
-
- /// @notice Returns collection helper contract address
- /// @dev EVM selector for this function is: 0x1896cce6,
- /// or in textual repr: collectionHelperAddress()
- function collectionHelperAddress() external view returns (address);
}
interface UniqueFungible is Dummy, ERC165, ERC20, ERC20Mintable, ERC20UniqueExtensions, Collection {}