difftreelog
fix PR
in: master
4 files changed
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::AbiCoder;23use evm_coder::{24 abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,25 weight,26};27use up_data_structs::CollectionMode;28use pallet_common::{29 CollectionHandle,30 erc::{CommonEvmHandler, PrecompileResult, CollectionCall},31 eth::CrossAddress,32};33use sp_std::vec::Vec;34use pallet_evm::{account::CrossAccountId, PrecompileHandle};35use pallet_evm_coder_substrate::{call, dispatch_to_evm};36use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};37use sp_core::{U256, Get};3839use crate::{40 Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,41 weights::WeightInfo,42};4344#[derive(ToLog)]45pub enum ERC20Events {46 Transfer {47 #[indexed]48 from: Address,49 #[indexed]50 to: Address,51 value: U256,52 },53 Approval {54 #[indexed]55 owner: Address,56 #[indexed]57 spender: Address,58 value: U256,59 },60}6162#[derive(AbiCoder, Debug)]63pub struct AmountForAddress {64 to: Address,65 amount: U256,66}6768#[solidity_interface(name = ERC20, events(ERC20Events), expect_selector = 0x942e8b22)]69impl<T: Config> FungibleHandle<T> {70 fn name(&self) -> Result<String> {71 Ok(decode_utf16(self.name.iter().copied())72 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))73 .collect::<String>())74 }75 fn symbol(&self) -> Result<String> {76 Ok(String::from_utf8_lossy(&self.token_prefix).into())77 }78 fn total_supply(&self) -> Result<U256> {79 self.consume_store_reads(1)?;80 Ok(<TotalSupply<T>>::get(self.id).into())81 }8283 fn decimals(&self) -> Result<u8> {84 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {85 *decimals86 } else {87 unreachable!()88 })89 }90 fn balance_of(&self, owner: Address) -> Result<U256> {91 self.consume_store_reads(1)?;92 let owner = T::CrossAccountId::from_eth(owner);93 let balance = <Balance<T>>::get((self.id, owner));94 Ok(balance.into())95 }96 #[weight(<SelfWeightOf<T>>::transfer())]97 fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {98 let caller = T::CrossAccountId::from_eth(caller);99 let to = T::CrossAccountId::from_eth(to);100 let amount = amount.try_into().map_err(|_| "amount overflow")?;101 let budget = self102 .recorder103 .weight_calls_budget(<StructureWeight<T>>::find_parent());104105 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;106 Ok(true)107 }108109 #[weight(<SelfWeightOf<T>>::transfer_from())]110 fn transfer_from(111 &mut self,112 caller: Caller,113 from: Address,114 to: Address,115 amount: U256,116 ) -> Result<bool> {117 let caller = T::CrossAccountId::from_eth(caller);118 let from = T::CrossAccountId::from_eth(from);119 let to = T::CrossAccountId::from_eth(to);120 let amount = amount.try_into().map_err(|_| "amount overflow")?;121 let budget = self122 .recorder123 .weight_calls_budget(<StructureWeight<T>>::find_parent());124125 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)126 .map_err(dispatch_to_evm::<T>)?;127 Ok(true)128 }129 #[weight(<SelfWeightOf<T>>::approve())]130 fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result<bool> {131 let caller = T::CrossAccountId::from_eth(caller);132 let spender = T::CrossAccountId::from_eth(spender);133 let amount = amount.try_into().map_err(|_| "amount overflow")?;134135 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)136 .map_err(dispatch_to_evm::<T>)?;137 Ok(true)138 }139 fn allowance(&self, owner: Address, spender: Address) -> Result<U256> {140 self.consume_store_reads(1)?;141 let owner = T::CrossAccountId::from_eth(owner);142 let spender = T::CrossAccountId::from_eth(spender);143144 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())145 }146}147148#[solidity_interface(name = ERC20Mintable)]149impl<T: Config> FungibleHandle<T> {150 /// Mint tokens for `to` account.151 /// @param to account that will receive minted tokens152 /// @param amount amount of tokens to mint153 #[weight(<SelfWeightOf<T>>::create_item())]154 fn mint(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {155 let caller = T::CrossAccountId::from_eth(caller);156 let to = T::CrossAccountId::from_eth(to);157 let amount = amount.try_into().map_err(|_| "amount overflow")?;158 let budget = self159 .recorder160 .weight_calls_budget(<StructureWeight<T>>::find_parent());161 <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)162 .map_err(dispatch_to_evm::<T>)?;163 Ok(true)164 }165}166167#[solidity_interface(name = ERC20UniqueExtensions)]168impl<T: Config> FungibleHandle<T>169where170 T::AccountId: From<[u8; 32]>,171{172 /// @dev Function to check the amount of tokens that an owner allowed to a spender.173 /// @param owner crossAddress The address which owns the funds.174 /// @param spender crossAddress The address which will spend the funds.175 /// @return A uint256 specifying the amount of tokens still available for the spender.176 fn allowance_cross(&self, owner: CrossAddress, spender: CrossAddress) -> Result<U256> {177 let owner = owner.into_sub_cross_account::<T>()?;178 let spender = spender.into_sub_cross_account::<T>()?;179180 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())181 }182183 /// @notice A description for the collection.184 fn description(&self) -> Result<String> {185 Ok(decode_utf16(self.description.iter().copied())186 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))187 .collect::<String>())188 }189190 #[weight(<SelfWeightOf<T>>::create_item())]191 fn mint_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {192 let caller = T::CrossAccountId::from_eth(caller);193 let to = to.into_sub_cross_account::<T>()?;194 let amount = amount.try_into().map_err(|_| "amount overflow")?;195 let budget = self196 .recorder197 .weight_calls_budget(<StructureWeight<T>>::find_parent());198 <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)199 .map_err(dispatch_to_evm::<T>)?;200 Ok(true)201 }202203 #[weight(<SelfWeightOf<T>>::approve())]204 fn approve_cross(205 &mut self,206 caller: Caller,207 spender: CrossAddress,208 amount: U256,209 ) -> Result<bool> {210 let caller = T::CrossAccountId::from_eth(caller);211 let spender = spender.into_sub_cross_account::<T>()?;212 let amount = amount.try_into().map_err(|_| "amount overflow")?;213214 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)215 .map_err(dispatch_to_evm::<T>)?;216 Ok(true)217 }218219 /// Burn tokens from account220 /// @dev Function that burns an `amount` of the tokens of a given account,221 /// deducting from the sender's allowance for said account.222 /// @param from The account whose tokens will be burnt.223 /// @param amount The amount that will be burnt.224 #[solidity(hide)]225 #[weight(<SelfWeightOf<T>>::burn_from())]226 fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result<bool> {227 let caller = T::CrossAccountId::from_eth(caller);228 let from = T::CrossAccountId::from_eth(from);229 let amount = amount.try_into().map_err(|_| "amount overflow")?;230 let budget = self231 .recorder232 .weight_calls_budget(<StructureWeight<T>>::find_parent());233234 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)235 .map_err(dispatch_to_evm::<T>)?;236 Ok(true)237 }238239 /// Burn tokens from account240 /// @dev Function that burns an `amount` of the tokens of a given account,241 /// deducting from the sender's allowance for said account.242 /// @param from The account whose tokens will be burnt.243 /// @param amount The amount that will be burnt.244 #[weight(<SelfWeightOf<T>>::burn_from())]245 fn burn_from_cross(246 &mut self,247 caller: Caller,248 from: CrossAddress,249 amount: U256,250 ) -> Result<bool> {251 let caller = T::CrossAccountId::from_eth(caller);252 let from = from.into_sub_cross_account::<T>()?;253 let amount = amount.try_into().map_err(|_| "amount overflow")?;254 let budget = self255 .recorder256 .weight_calls_budget(<StructureWeight<T>>::find_parent());257258 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)259 .map_err(dispatch_to_evm::<T>)?;260 Ok(true)261 }262263 /// Mint tokens for multiple accounts.264 /// @param amounts array of pairs of account address and amount265 #[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]266 fn mint_bulk(&mut self, caller: Caller, amounts: Vec<AmountForAddress>) -> Result<bool> {267 let caller = T::CrossAccountId::from_eth(caller);268 let budget = self269 .recorder270 .weight_calls_budget(<StructureWeight<T>>::find_parent());271 let amounts = amounts272 .into_iter()273 .map(|AmountForAddress { to, amount }| {274 Ok((275 T::CrossAccountId::from_eth(to),276 amount.try_into().map_err(|_| "amount overflow")?,277 ))278 })279 .collect::<Result<_>>()?;280281 <Pallet<T>>::create_multiple_items(&self, &caller, amounts, &budget)282 .map_err(dispatch_to_evm::<T>)?;283 Ok(true)284 }285286 #[weight(<SelfWeightOf<T>>::transfer())]287 fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {288 let caller = T::CrossAccountId::from_eth(caller);289 let to = to.into_sub_cross_account::<T>()?;290 let amount = amount.try_into().map_err(|_| "amount overflow")?;291 let budget = self292 .recorder293 .weight_calls_budget(<StructureWeight<T>>::find_parent());294295 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;296 Ok(true)297 }298299 #[weight(<SelfWeightOf<T>>::transfer_from())]300 fn transfer_from_cross(301 &mut self,302 caller: Caller,303 from: CrossAddress,304 to: CrossAddress,305 amount: U256,306 ) -> Result<bool> {307 let caller = T::CrossAccountId::from_eth(caller);308 let from = from.into_sub_cross_account::<T>()?;309 let to = to.into_sub_cross_account::<T>()?;310 let amount = amount.try_into().map_err(|_| "amount overflow")?;311 let budget = self312 .recorder313 .weight_calls_budget(<StructureWeight<T>>::find_parent());314315 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)316 .map_err(dispatch_to_evm::<T>)?;317 Ok(true)318 }319320 /// @notice Returns collection helper contract address321 fn collection_helper_address(&self) -> Result<Address> {322 Ok(T::ContractAddress::get())323 }324}325326#[solidity_interface(327 name = UniqueFungible,328 is(329 ERC20,330 ERC20Mintable,331 ERC20UniqueExtensions,332 Collection(via(common_mut returns CollectionHandle<T>)),333 )334)]335impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}336337generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);338generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);339340impl<T: Config> CommonEvmHandler for FungibleHandle<T>341where342 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,343{344 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");345346 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {347 call::<T, UniqueFungibleCall<T>, _, _>(handle, self)348 }349}pallets/fungible/src/lib.rsdiffbeforeafterboth--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -165,8 +165,8 @@
pub type Allowance<T: Config> = StorageNMap<
Key = (
Key<Twox64Concat, CollectionId>,
- Key<Blake2_128, T::CrossAccountId>,
- Key<Blake2_128Concat, T::CrossAccountId>,
+ Key<Blake2_128, T::CrossAccountId>, // Owner
+ Key<Blake2_128Concat, T::CrossAccountId>, // Spender
),
Value = u128,
QueryKind = ValueQuery,
pallets/refungible/src/erc_token.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -31,7 +31,7 @@
use pallet_common::{
CommonWeightInfo,
erc::{CommonEvmHandler, PrecompileResult},
- eth::collection_id_to_address,
+ eth::{collection_id_to_address, CrossAddress},
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};
@@ -207,11 +207,7 @@
/// @param owner crossAddress The address which owns the funds.
/// @param spender crossAddress The address which will spend the funds.
/// @return A uint256 specifying the amount of tokens still available for the spender.
- fn allowance_cross(
- &self,
- owner: pallet_common::eth::CrossAddress,
- spender: pallet_common::eth::CrossAddress,
- ) -> Result<U256> {
+ fn allowance_cross(&self, owner: CrossAddress, spender: CrossAddress) -> Result<U256> {
let owner = owner.into_sub_cross_account::<T>()?;
let spender = spender.into_sub_cross_account::<T>()?;
@@ -245,7 +241,7 @@
fn burn_from_cross(
&mut self,
caller: Caller,
- from: pallet_common::eth::CrossAddress,
+ from: CrossAddress,
amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -271,7 +267,7 @@
fn approve_cross(
&mut self,
caller: Caller,
- spender: pallet_common::eth::CrossAddress,
+ spender: CrossAddress,
amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -298,12 +294,7 @@
/// @param to The crossaccount to transfer to.
/// @param amount The amount to be transferred.
#[weight(<CommonWeights<T>>::transfer())]
- fn transfer_cross(
- &mut self,
- caller: Caller,
- to: pallet_common::eth::CrossAddress,
- amount: U256,
- ) -> Result<bool> {
+ fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = to.into_sub_cross_account::<T>()?;
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -324,8 +315,8 @@
fn transfer_from_cross(
&mut self,
caller: Caller,
- from: pallet_common::eth::CrossAddress,
- to: pallet_common::eth::CrossAddress,
+ from: CrossAddress,
+ to: CrossAddress,
amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -240,13 +240,13 @@
QueryKind = ValueQuery,
>;
- /// Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet.
+ /// Spender set by a wallet owner that could perform certain transactions on all tokens in the wallet.
#[pallet::storage]
pub type CollectionAllowance<T: Config> = StorageNMap<
Key = (
Key<Twox64Concat, CollectionId>,
Key<Blake2_128Concat, T::CrossAccountId>, // Owner
- Key<Blake2_128Concat, T::CrossAccountId>, // Operator
+ Key<Blake2_128Concat, T::CrossAccountId>, // Spender
),
Value = bool,
QueryKind = ValueQuery,
@@ -1403,18 +1403,18 @@
pub fn set_allowance_for_all(
collection: &RefungibleHandle<T>,
owner: &T::CrossAccountId,
- operator: &T::CrossAccountId,
+ spender: &T::CrossAccountId,
approve: bool,
) -> DispatchResult {
<PalletCommon<T>>::set_allowance_for_all(
collection,
owner,
- operator,
+ spender,
approve,
- || <CollectionAllowance<T>>::insert((collection.id, owner, operator), approve),
+ || <CollectionAllowance<T>>::insert((collection.id, owner, spender), approve),
ERC721Events::ApprovalForAll {
owner: *owner.as_eth(),
- operator: *operator.as_eth(),
+ operator: *spender.as_eth(),
approved: approve,
}
.to_log(collection_id_to_address(collection.id)),
@@ -1425,9 +1425,9 @@
pub fn allowance_for_all(
collection: &RefungibleHandle<T>,
owner: &T::CrossAccountId,
- operator: &T::CrossAccountId,
+ spender: &T::CrossAccountId,
) -> bool {
- <CollectionAllowance<T>>::get((collection.id, owner, operator))
+ <CollectionAllowance<T>>::get((collection.id, owner, spender))
}
pub fn repair_item(collection: &RefungibleHandle<T>, token: TokenId) -> DispatchResult {