difftreelog
refactor return CrossAccountId in backing storages
in: master
14 files changed
client/rpc/src/lib.rsdiffbeforeafterboth75 ) -> Result<String>;75 ) -> Result<String>;767677 #[rpc(name = "nft_adminlist")]77 #[rpc(name = "nft_adminlist")]78 fn adminlist(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<Vec<AccountId>>;78 fn adminlist(79 &self,80 collection: CollectionId,81 at: Option<BlockHash>,82 ) -> Result<Vec<CrossAccountId>>;79 #[rpc(name = "nft_allowlist")]83 #[rpc(name = "nft_allowlist")]80 fn allowlist(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<Vec<AccountId>>;84 fn allowlist(85 &self,86 collection: CollectionId,87 at: Option<BlockHash>,88 ) -> Result<Vec<CrossAccountId>>;81 #[rpc(name = "nft_lastTokenId")]89 #[rpc(name = "nft_lastTokenId")]82 fn last_token_id(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<TokenId>;90 fn last_token_id(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<TokenId>;83}91}150 pass_method!(balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> String => |v| v.to_string());158 pass_method!(balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> String => |v| v.to_string());151 pass_method!(allowance(collection: CollectionId, sender: CrossAccountId, spender: CrossAccountId, token: TokenId) -> String => |v| v.to_string());159 pass_method!(allowance(collection: CollectionId, sender: CrossAccountId, spender: CrossAccountId, token: TokenId) -> String => |v| v.to_string());152160153 pass_method!(adminlist(collection: CollectionId) -> Vec<AccountId>);161 pass_method!(adminlist(collection: CollectionId) -> Vec<CrossAccountId>);154 pass_method!(allowlist(collection: CollectionId) -> Vec<AccountId>);162 pass_method!(allowlist(collection: CollectionId) -> Vec<CrossAccountId>);155 pass_method!(last_token_id(collection: CollectionId) -> TokenId);163 pass_method!(last_token_id(collection: CollectionId) -> TokenId);156}164}157165pallets/common/src/account.rsdiffbeforeafterboth20 fn from_sub(account: AccountId) -> Self;20 fn from_sub(account: AccountId) -> Self;21 fn from_eth(account: H160) -> Self;21 fn from_eth(account: H160) -> Self;2223 fn conv_eq(&self, other: &Self) -> bool;22}24}232524#[derive(Encode, Decode, Serialize, Deserialize, TypeInfo)]26#[derive(Encode, Decode, Serialize, Deserialize, TypeInfo)]28 Ethereum(H160),30 Ethereum(H160),29}31}303231#[derive(Eq)]33#[derive(PartialEq, Eq)]32pub struct BasicCrossAccountId<T: Config> {34pub struct BasicCrossAccountId<T: Config> {33 /// If true - then ethereum is canonical encoding35 /// If true - then ethereum is canonical encoding34 from_ethereum: bool,36 from_ethereum: bool,77 }79 }78}80}798180impl<T: Config> PartialEq for BasicCrossAccountId<T> {81 fn eq(&self, other: &Self) -> bool {82 if self.from_ethereum == other.from_ethereum {83 self.substrate == other.substrate && self.ethereum == other.ethereum84 } else if self.from_ethereum {85 // ethereum is canonical encoding, but we need to compare derived address86 self.substrate == other.substrate87 } else {88 self.ethereum == other.ethereum89 }90 }91}92impl<T: Config> Clone for BasicCrossAccountId<T> {82impl<T: Config> Clone for BasicCrossAccountId<T> {93 fn clone(&self) -> Self {83 fn clone(&self) -> Self {94 Self {84 Self {158 from_ethereum: true,148 from_ethereum: true,159 }149 }160 }150 }151 fn conv_eq(&self, other: &Self) -> bool {152 if self.from_ethereum == other.from_ethereum {153 self.substrate == other.substrate && self.ethereum == other.ethereum154 } else if self.from_ethereum {155 // ethereum is canonical encoding, but we need to compare derived address156 self.substrate == other.substrate157 } else {158 self.ethereum == other.ethereum159 }160 }161}161}162impl<T: Config> From<BasicCrossAccountIdRepr<T::AccountId>> for BasicCrossAccountId<T> {162impl<T: Config> From<BasicCrossAccountIdRepr<T::AccountId>> for BasicCrossAccountId<T> {163 fn from(repr: BasicCrossAccountIdRepr<T::AccountId>) -> Self {163 fn from(repr: BasicCrossAccountIdRepr<T::AccountId>) -> Self {pallets/common/src/lib.rsdiffbeforeafterboth98 pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> Result<bool, DispatchError> {98 pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> Result<bool, DispatchError> {99 self.consume_sload()?;99 self.consume_sload()?;100100101 Ok(*subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject.as_sub())))101 Ok(*subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject)))102 }102 }103 pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {103 pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {104 ensure!(self.is_owner_or_admin(subject)?, <Error<T>>::NoPermission);104 ensure!(self.is_owner_or_admin(subject)?, <Error<T>>::NoPermission);114 self.consume_sload()?;114 self.consume_sload()?;115115116 ensure!(116 ensure!(117 <Allowlist<T>>::get((self.id, user.as_sub())),117 <Allowlist<T>>::get((self.id, user)),118 <Error<T>>::AddressNotInAllowlist118 <Error<T>>::AddressNotInAllowlist119 );119 );120 Ok(())120 Ok(())139#[frame_support::pallet]139#[frame_support::pallet]140pub mod pallet {140pub mod pallet {141 use super::*;141 use super::*;142 use frame_support::{pallet_prelude::*};143 use frame_support::{Blake2_128Concat, storage::Key};142 use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key};144 use account::{EvmBackwardsAddressMapping, CrossAccountId};143 use account::{EvmBackwardsAddressMapping, CrossAccountId};145 use frame_support::traits::Currency;144 use frame_support::traits::Currency;146 use nft_data_structs::TokenId;145 use nft_data_structs::TokenId;311 pub type IsAdmin<T: Config> = StorageNMap<310 pub type IsAdmin<T: Config> = StorageNMap<312 Key = (311 Key = (313 Key<Blake2_128Concat, CollectionId>,312 Key<Blake2_128Concat, CollectionId>,314 Key<Blake2_128Concat, T::AccountId>,313 Key<Blake2_128Concat, T::CrossAccountId>,315 ),314 ),316 Value = bool,315 Value = bool,317 QueryKind = ValueQuery,316 QueryKind = ValueQuery,322 pub type Allowlist<T: Config> = StorageNMap<321 pub type Allowlist<T: Config> = StorageNMap<323 Key = (322 Key = (324 Key<Blake2_128Concat, CollectionId>,323 Key<Blake2_128Concat, CollectionId>,325 Key<Blake2_128Concat, T::AccountId>,324 Key<Blake2_128Concat, T::CrossAccountId>,326 ),325 ),327 Value = bool,326 Value = bool,328 QueryKind = ValueQuery,327 QueryKind = ValueQuery,pallets/fungible/src/common.rsdiffbeforeafterboth3use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};3use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};4use nft_data_structs::TokenId;4use nft_data_structs::TokenId;5use pallet_common::{5use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};6 CommonCollectionOperations, CommonWeightInfo, account::CrossAccountId, with_weight,7};8use sp_runtime::ArithmeticError;6use sp_runtime::ArithmeticError;9use sp_std::{vec::Vec, vec};7use sp_std::{vec::Vec, vec};188 }186 }189187190 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {188 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {191 if <Balance<T>>::get((self.id, account.as_sub())) != 0 {189 if <Balance<T>>::get((self.id, account)) != 0 {192 vec![TokenId::default()]190 vec![TokenId::default()]193 } else {191 } else {194 vec![]192 vec![]218 }216 }219217220 fn account_balance(&self, account: T::CrossAccountId) -> u32 {218 fn account_balance(&self, account: T::CrossAccountId) -> u32 {221 if <Balance<T>>::get((self.id, account.as_sub())) != 0 {219 if <Balance<T>>::get((self.id, account)) != 0 {222 1220 1223 } else {221 } else {224 0222 0229 if token != TokenId::default() {227 if token != TokenId::default() {230 return 0;228 return 0;231 }229 }232 <Balance<T>>::get((self.id, account.as_sub()))230 <Balance<T>>::get((self.id, account))233 }231 }234232235 fn allowance(233 fn allowance(241 if token != TokenId::default() {239 if token != TokenId::default() {242 return 0;240 return 0;243 }241 }244 <Allowance<T>>::get((self.id, sender.as_sub(), spender.as_sub()))242 <Allowance<T>>::get((self.id, sender, spender))245 }243 }246}244}247245pallets/fungible/src/erc.rsdiffbeforeafterboth52 }52 }53 fn balance_of(&self, owner: address) -> Result<uint256> {53 fn balance_of(&self, owner: address) -> Result<uint256> {54 let owner = T::CrossAccountId::from_eth(owner);54 let owner = T::CrossAccountId::from_eth(owner);55 let balance = <Balance<T>>::get((self.id, owner.as_sub()));55 let balance = <Balance<T>>::get((self.id, owner));56 Ok(balance.into())56 Ok(balance.into())57 }57 }58 fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {58 fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {92 let owner = T::CrossAccountId::from_eth(owner);92 let owner = T::CrossAccountId::from_eth(owner);93 let spender = T::CrossAccountId::from_eth(spender);93 let spender = T::CrossAccountId::from_eth(spender);949495 Ok(<Allowance<T>>::get((self.id, owner.as_sub(), spender.as_sub())).into())95 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())96 }96 }97}97}9898pallets/fungible/src/lib.rsdiffbeforeafterboth55 pub(super) type Balance<T: Config> = StorageNMap<55 pub(super) type Balance<T: Config> = StorageNMap<56 Key = (56 Key = (57 Key<Twox64Concat, CollectionId>,57 Key<Twox64Concat, CollectionId>,58 Key<Blake2_128Concat, T::AccountId>,58 Key<Blake2_128Concat, T::CrossAccountId>,59 ),59 ),60 Value = u128,60 Value = u128,61 QueryKind = ValueQuery,61 QueryKind = ValueQuery,65 pub(super) type Allowance<T: Config> = StorageNMap<65 pub(super) type Allowance<T: Config> = StorageNMap<66 Key = (66 Key = (67 Key<Twox64Concat, CollectionId>,67 Key<Twox64Concat, CollectionId>,68 Key<Blake2_128, T::AccountId>,68 Key<Blake2_128, T::CrossAccountId>,69 Key<Blake2_128Concat, T::AccountId>,69 Key<Blake2_128Concat, T::CrossAccountId>,70 ),70 ),71 Value = u128,71 Value = u128,72 QueryKind = ValueQuery,72 QueryKind = ValueQuery,119 .checked_sub(amount)119 .checked_sub(amount)120 .ok_or(<CommonError<T>>::TokenValueTooLow)?;120 .ok_or(<CommonError<T>>::TokenValueTooLow)?;121121122 let balance = <Balance<T>>::get((collection.id, owner.as_sub()))122 let balance = <Balance<T>>::get((collection.id, owner))123 .checked_sub(amount)123 .checked_sub(amount)124 .ok_or(<CommonError<T>>::TokenValueTooLow)?;124 .ok_or(<CommonError<T>>::TokenValueTooLow)?;125125130 // =========130 // =========131131132 if balance == 0 {132 if balance == 0 {133 <Balance<T>>::remove((collection.id, owner.as_sub()));133 <Balance<T>>::remove((collection.id, owner));134 } else {134 } else {135 <Balance<T>>::insert((collection.id, owner.as_sub()), balance);135 <Balance<T>>::insert((collection.id, owner), balance);136 }136 }137 <TotalSupply<T>>::insert(collection.id, total_supply);137 <TotalSupply<T>>::insert(collection.id, total_supply);138138167 }167 }168 <PalletCommon<T>>::ensure_correct_receiver(to)?;168 <PalletCommon<T>>::ensure_correct_receiver(to)?;169169170 let balance_from = <Balance<T>>::get((collection.id, from.as_sub()))170 let balance_from = <Balance<T>>::get((collection.id, from))171 .checked_sub(amount)171 .checked_sub(amount)172 .ok_or(<CommonError<T>>::TokenValueTooLow)?;172 .ok_or(<CommonError<T>>::TokenValueTooLow)?;173 let balance_to = if from != to {173 let balance_to = if from != to {174 Some(174 Some(175 <Balance<T>>::get((collection.id, to.as_sub()))175 <Balance<T>>::get((collection.id, to))176 .checked_add(amount)176 .checked_add(amount)177 .ok_or(ArithmeticError::Overflow)?,177 .ok_or(ArithmeticError::Overflow)?,178 )178 )190 if let Some(balance_to) = balance_to {190 if let Some(balance_to) = balance_to {191 // from != to191 // from != to192 if balance_from == 0 {192 if balance_from == 0 {193 <Balance<T>>::remove((collection.id, from.as_sub()));193 <Balance<T>>::remove((collection.id, from));194 } else {194 } else {195 <Balance<T>>::insert((collection.id, from.as_sub()), balance_from);195 <Balance<T>>::insert((collection.id, from), balance_from);196 }196 }197 <Balance<T>>::insert((collection.id, to.as_sub()), balance_to);197 <Balance<T>>::insert((collection.id, to), balance_to);198 }198 }199199200 collection.log_infallible(ERC20Events::Transfer {200 collection.log_infallible(ERC20Events::Transfer {242 collection.consume_sload()?;242 collection.consume_sload()?;243 let balance = balances243 let balance = balances244 .entry(user.clone())244 .entry(user.clone())245 .or_insert_with(|| <Balance<T>>::get((collection.id, user.as_sub())));245 .or_insert_with(|| <Balance<T>>::get((collection.id, user)));246 *balance = (*balance)246 *balance = (*balance)247 .checked_add(amount)247 .checked_add(amount)248 .ok_or(ArithmeticError::Overflow)?;248 .ok_or(ArithmeticError::Overflow)?;259259260 <TotalSupply<T>>::insert(collection.id, total_supply);260 <TotalSupply<T>>::insert(collection.id, total_supply);261 for (user, amount) in balances {261 for (user, amount) in balances {262 <Balance<T>>::insert((collection.id, user.as_sub()), amount);262 <Balance<T>>::insert((collection.id, &user), amount);263263264 collection.log_infallible(ERC20Events::Transfer {264 collection.log_infallible(ERC20Events::Transfer {265 from: H160::default(),265 from: H160::default(),283 spender: &T::CrossAccountId,283 spender: &T::CrossAccountId,284 amount: u128,284 amount: u128,285 ) {285 ) {286 <Allowance<T>>::insert((collection.id, owner.as_sub(), spender.as_sub()), amount);286 <Allowance<T>>::insert((collection.id, owner, spender), amount);287287288 collection.log_infallible(ERC20Events::Approval {288 collection.log_infallible(ERC20Events::Approval {289 owner: *owner.as_eth(),289 owner: *owner.as_eth(),310 collection.check_allowlist(&spender)?;310 collection.check_allowlist(&spender)?;311 }311 }312312313 if <Balance<T>>::get((collection.id, owner.as_sub())) < amount {313 if <Balance<T>>::get((collection.id, owner)) < amount {314 ensure!(314 ensure!(315 collection.ignores_owned_amount(owner)?,315 collection.ignores_owned_amount(owner)?,316 <CommonError<T>>::CantApproveMoreThanOwned316 <CommonError<T>>::CantApproveMoreThanOwned330 to: &T::CrossAccountId,330 to: &T::CrossAccountId,331 amount: u128,331 amount: u128,332 ) -> DispatchResult {332 ) -> DispatchResult {333 if spender == from {333 if spender.conv_eq(from) {334 return Self::transfer(collection, from, to, amount);334 return Self::transfer(collection, from, to, amount);335 }335 }336 if collection.access == AccessMode::WhiteList {336 if collection.access == AccessMode::WhiteList {337 // `from`, `to` checked in [`transfer`]337 // `from`, `to` checked in [`transfer`]338 collection.check_allowlist(spender)?;338 collection.check_allowlist(spender)?;339 }339 }340340341 let allowance = <Allowance<T>>::get((collection.id, from.as_sub(), spender.as_sub()))341 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);342 .checked_sub(amount);343 if allowance.is_none() {342 if allowance.is_none() {344 ensure!(343 ensure!(362 from: &T::CrossAccountId,361 from: &T::CrossAccountId,363 amount: u128,362 amount: u128,364 ) -> DispatchResult {363 ) -> DispatchResult {365 if spender == from {364 if spender.conv_eq(from) {366 return Self::burn(collection, from, amount);365 return Self::burn(collection, from, amount);367 }366 }368 if collection.access == AccessMode::WhiteList {367 if collection.access == AccessMode::WhiteList {369 // `from` checked in [`burn`]368 // `from` checked in [`burn`]370 collection.check_allowlist(spender)?;369 collection.check_allowlist(spender)?;371 }370 }372371373 let allowance = <Allowance<T>>::get((collection.id, from.as_sub(), spender.as_sub()))372 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);374 .checked_sub(amount);375 if allowance.is_none() {373 if allowance.is_none() {376 ensure!(374 ensure!(pallets/nft/src/lib.rsdiffbeforeafterboth948948949// TODO: limit returned entries?949// TODO: limit returned entries?950impl<T: Config> Pallet<T> {950impl<T: Config> Pallet<T> {951 pub fn adminlist(collection: CollectionId) -> Vec<T::AccountId> {951 pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {952 <IsAdmin<T>>::iter_prefix((collection,))952 <IsAdmin<T>>::iter_prefix((collection,))953 .map(|(a, _)| a)953 .map(|(a, _)| a)954 .collect()954 .collect()955 }955 }956 pub fn allowlist(collection: CollectionId) -> Vec<T::AccountId> {956 pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {957 <Allowlist<T>>::iter_prefix((collection,))957 <Allowlist<T>>::iter_prefix((collection,))958 .map(|(a, _)| a)958 .map(|(a, _)| a)959 .collect()959 .collect()pallets/nonfungible/src/common.rsdiffbeforeafterboth3use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};3use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};4use nft_data_structs::TokenId;4use nft_data_structs::TokenId;5use pallet_common::{5use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};6 CommonCollectionOperations, CommonWeightInfo, account::CrossAccountId, with_weight,7};8use sp_runtime::DispatchError;6use sp_runtime::DispatchError;9use sp_std::vec::Vec;7use sp_std::vec::Vec;200 }198 }201199202 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {200 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {203 <Owned<T>>::iter_prefix((self.id, account.as_sub()))201 <Owned<T>>::iter_prefix((self.id, account))204 .map(|(id, _)| id)202 .map(|(id, _)| id)205 .collect()203 .collect()206 }204 }234 }232 }235233236 fn account_balance(&self, account: T::CrossAccountId) -> u32 {234 fn account_balance(&self, account: T::CrossAccountId) -> u32 {237 <AccountBalance<T>>::get((self.id, account.as_sub()))235 <AccountBalance<T>>::get((self.id, account))238 }236 }239237240 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {238 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {pallets/nonfungible/src/erc.rsdiffbeforeafterboth93impl<T: Config> NonfungibleHandle<T> {93impl<T: Config> NonfungibleHandle<T> {94 fn balance_of(&self, owner: address) -> Result<uint256> {94 fn balance_of(&self, owner: address) -> Result<uint256> {95 let owner = T::CrossAccountId::from_eth(owner);95 let owner = T::CrossAccountId::from_eth(owner);96 let balance = <AccountBalance<T>>::get((self.id, owner.as_sub()));96 let balance = <AccountBalance<T>>::get((self.id, owner));97 Ok(balance.into())97 Ok(balance.into())98 }98 }99 fn owner_of(&self, token_id: uint256) -> Result<address> {99 fn owner_of(&self, token_id: uint256) -> Result<address> {pallets/nonfungible/src/lib.rsdiffbeforeafterboth80 pub(super) type Owned<T: Config> = StorageNMap<80 pub(super) type Owned<T: Config> = StorageNMap<81 Key = (81 Key = (82 Key<Twox64Concat, CollectionId>,82 Key<Twox64Concat, CollectionId>,83 Key<Blake2_128Concat, T::AccountId>,83 Key<Blake2_128Concat, T::CrossAccountId>,84 Key<Twox64Concat, TokenId>,84 Key<Twox64Concat, TokenId>,85 ),85 ),86 Value = bool,86 Value = bool,91 pub(super) type AccountBalance<T: Config> = StorageNMap<91 pub(super) type AccountBalance<T: Config> = StorageNMap<92 Key = (92 Key = (93 Key<Twox64Concat, CollectionId>,93 Key<Twox64Concat, CollectionId>,94 Key<Blake2_128Concat, T::AccountId>,94 Key<Blake2_128Concat, T::CrossAccountId>,95 ),95 ),96 Value = u32,96 Value = u32,97 QueryKind = ValueQuery,97 QueryKind = ValueQuery,179179180 // =========180 // =========181181182 <Owned<T>>::remove((collection.id, token_data.owner.as_sub(), token));182 <Owned<T>>::remove((collection.id, &token_data.owner, token));183 <TokensBurnt<T>>::insert(collection.id, burnt);183 <TokensBurnt<T>>::insert(collection.id, burnt);184 <TokenData<T>>::remove((collection.id, token));184 <TokenData<T>>::remove((collection.id, token));185 let old_spender = <Allowance<T>>::take((collection.id, token));185 let old_spender = <Allowance<T>>::take((collection.id, token));234 }234 }235 <PalletCommon<T>>::ensure_correct_receiver(to)?;235 <PalletCommon<T>>::ensure_correct_receiver(to)?;236236237 let balance_from = <AccountBalance<T>>::get((collection.id, from.as_sub()))237 let balance_from = <AccountBalance<T>>::get((collection.id, from))238 .checked_sub(1)238 .checked_sub(1)239 .ok_or(<CommonError<T>>::TokenValueTooLow)?;239 .ok_or(<CommonError<T>>::TokenValueTooLow)?;240 let balance_to = if from != to {240 let balance_to = if from != to {241 let balance_to = <AccountBalance<T>>::get((collection.id, to.as_sub()))241 let balance_to = <AccountBalance<T>>::get((collection.id, to))242 .checked_add(1)242 .checked_add(1)243 .ok_or(ArithmeticError::Overflow)?;243 .ok_or(ArithmeticError::Overflow)?;244244268 if let Some(balance_to) = balance_to {268 if let Some(balance_to) = balance_to {269 // from != to269 // from != to270 if balance_from == 0 {270 if balance_from == 0 {271 <AccountBalance<T>>::remove((collection.id, from.as_sub()));271 <AccountBalance<T>>::remove((collection.id, from));272 } else {272 } else {273 <AccountBalance<T>>::insert((collection.id, from.as_sub()), balance_from);273 <AccountBalance<T>>::insert((collection.id, from), balance_from);274 }274 }275 <AccountBalance<T>>::insert((collection.id, to.as_sub()), balance_to);275 <AccountBalance<T>>::insert((collection.id, to), balance_to);276 <Owned<T>>::remove((collection.id, from.as_sub(), token));276 <Owned<T>>::remove((collection.id, from, token));277 <Owned<T>>::insert((collection.id, to.as_sub(), token), true);277 <Owned<T>>::insert((collection.id, to, token), true);278 }278 }279 Self::set_allowance_unchecked(collection, from, token, None, true);279 Self::set_allowance_unchecked(collection, from, token, None, true);280280336 let mut balances = BTreeMap::new();336 let mut balances = BTreeMap::new();337 for data in &data {337 for data in &data {338 let balance = balances338 let balance = balances339 .entry(data.owner.as_sub())339 .entry(&data.owner)340 .or_insert_with(|| <AccountBalance<T>>::get((collection.id, data.owner.as_sub())));340 .or_insert_with(|| <AccountBalance<T>>::get((collection.id, &data.owner)));341 *balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;341 *balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;342342343 ensure!(343 ensure!(364 owner: data.owner.clone(),364 owner: data.owner.clone(),365 },365 },366 );366 );367 <Owned<T>>::insert((collection.id, data.owner.as_sub(), token), true);367 <Owned<T>>::insert((collection.id, &data.owner, token), true);368368369 collection.log_infallible(ERC721Events::Transfer {369 collection.log_infallible(ERC721Events::Transfer {370 from: H160::default(),370 from: H160::default(),481 to: &T::CrossAccountId,481 to: &T::CrossAccountId,482 token: TokenId,482 token: TokenId,483 ) -> DispatchResult {483 ) -> DispatchResult {484 if spender == from {484 if spender.conv_eq(from) {485 return Self::transfer(collection, from, to, token);485 return Self::transfer(collection, from, to, token);486 }486 }487 if collection.access == AccessMode::WhiteList {487 if collection.access == AccessMode::WhiteList {509 from: &T::CrossAccountId,509 from: &T::CrossAccountId,510 token: TokenId,510 token: TokenId,511 ) -> DispatchResult {511 ) -> DispatchResult {512 if spender == from {512 if spender.conv_eq(from) {513 return Self::burn(collection, from, token);513 return Self::burn(collection, from, token);514 }514 }515 if collection.access == AccessMode::WhiteList {515 if collection.access == AccessMode::WhiteList {pallets/refungible/src/common.rsdiffbeforeafterboth4use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};4use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};5use nft_data_structs::TokenId;5use nft_data_structs::TokenId;6use pallet_common::{6use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};7 CommonCollectionOperations, CommonWeightInfo, account::CrossAccountId, with_weight,8};9use sp_runtime::DispatchError;7use sp_runtime::DispatchError;10use sp_std::vec::Vec;8use sp_std::vec::Vec;196 }194 }197195198 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {196 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {199 <Owned<T>>::iter_prefix((self.id, account.as_sub()))197 <Owned<T>>::iter_prefix((self.id, account))200 .map(|(id, _)| id)198 .map(|(id, _)| id)201 .collect()199 .collect()202 }200 }224 }222 }225223226 fn account_balance(&self, account: T::CrossAccountId) -> u32 {224 fn account_balance(&self, account: T::CrossAccountId) -> u32 {227 <AccountBalance<T>>::get((self.id, account.as_sub()))225 <AccountBalance<T>>::get((self.id, account))228 }226 }229227230 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {228 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {231 <Balance<T>>::get((self.id, token, account.as_sub()))229 <Balance<T>>::get((self.id, token, account))232 }230 }233231234 fn allowance(232 fn allowance(237 spender: T::CrossAccountId,235 spender: T::CrossAccountId,238 token: TokenId,236 token: TokenId,239 ) -> u128 {237 ) -> u128 {240 <Allowance<T>>::get((self.id, token, sender.as_sub(), spender))238 <Allowance<T>>::get((self.id, token, sender, spender))241 }239 }242}240}243241pallets/refungible/src/lib.rsdiffbeforeafterboth83 pub(super) type Owned<T: Config> = StorageNMap<83 pub(super) type Owned<T: Config> = StorageNMap<84 Key = (84 Key = (85 Key<Twox64Concat, CollectionId>,85 Key<Twox64Concat, CollectionId>,86 Key<Blake2_128Concat, T::AccountId>,86 Key<Blake2_128Concat, T::CrossAccountId>,87 Key<Twox64Concat, TokenId>,87 Key<Twox64Concat, TokenId>,88 ),88 ),89 Value = bool,89 Value = bool,95 Key = (95 Key = (96 Key<Twox64Concat, CollectionId>,96 Key<Twox64Concat, CollectionId>,97 // Owner97 // Owner98 Key<Blake2_128Concat, T::AccountId>,98 Key<Blake2_128Concat, T::CrossAccountId>,99 ),99 ),100 Value = u32,100 Value = u32,101 QueryKind = ValueQuery,101 QueryKind = ValueQuery,107 Key<Twox64Concat, CollectionId>,107 Key<Twox64Concat, CollectionId>,108 Key<Twox64Concat, TokenId>,108 Key<Twox64Concat, TokenId>,109 // Owner109 // Owner110 Key<Blake2_128Concat, T::AccountId>,110 Key<Blake2_128Concat, T::CrossAccountId>,111 ),111 ),112 Value = u128,112 Value = u128,113 QueryKind = ValueQuery,113 QueryKind = ValueQuery,119 Key<Twox64Concat, CollectionId>,119 Key<Twox64Concat, CollectionId>,120 Key<Twox64Concat, TokenId>,120 Key<Twox64Concat, TokenId>,121 // Owner121 // Owner122 Key<Blake2_128, T::AccountId>,122 Key<Blake2_128, T::CrossAccountId>,123 // Spender123 // Spender124 Key<Blake2_128Concat, T::CrossAccountId>,124 Key<Blake2_128Concat, T::CrossAccountId>,125 ),125 ),206 if total_supply == 0 {206 if total_supply == 0 {207 // Ensure user actually owns this amount207 // Ensure user actually owns this amount208 ensure!(208 ensure!(209 <Balance<T>>::get((collection.id, token, owner.as_sub())) == amount,209 <Balance<T>>::get((collection.id, token, owner)) == amount,210 <CommonError<T>>::TokenValueTooLow210 <CommonError<T>>::TokenValueTooLow211 );211 );212 let account_balance = <AccountBalance<T>>::get((collection.id, owner.as_sub()))212 let account_balance = <AccountBalance<T>>::get((collection.id, owner))213 .checked_sub(1)213 .checked_sub(1)214 // Should not occur214 // Should not occur215 .ok_or(ArithmeticError::Underflow)?;215 .ok_or(ArithmeticError::Underflow)?;216216217 // =========217 // =========218218219 <Owned<T>>::remove((collection.id, owner.as_sub(), token));219 <Owned<T>>::remove((collection.id, owner, token));220 <AccountBalance<T>>::insert((collection.id, owner.as_sub()), account_balance);220 <AccountBalance<T>>::insert((collection.id, owner), account_balance);221 Self::burn_token(collection, token)?;221 Self::burn_token(collection, token)?;222 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(222 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(223 collection.id,223 collection.id,228 return Ok(());228 return Ok(());229 }229 }230230231 let balance = <Balance<T>>::get((collection.id, token, owner.as_sub()))231 let balance = <Balance<T>>::get((collection.id, token, owner))232 .checked_sub(amount)232 .checked_sub(amount)233 .ok_or(<CommonError<T>>::TokenValueTooLow)?;233 .ok_or(<CommonError<T>>::TokenValueTooLow)?;234 let account_balance = if balance == 0 {234 let account_balance = if balance == 0 {235 <AccountBalance<T>>::get((collection.id, owner.as_sub()))235 <AccountBalance<T>>::get((collection.id, owner))236 .checked_sub(1)236 .checked_sub(1)237 // Should not occur237 // Should not occur238 .ok_or(ArithmeticError::Underflow)?238 .ok_or(ArithmeticError::Underflow)?243 // =========243 // =========244244245 if balance == 0 {245 if balance == 0 {246 <Owned<T>>::remove((collection.id, owner.as_sub(), token));246 <Owned<T>>::remove((collection.id, owner, token));247 <Balance<T>>::remove((collection.id, token, owner.as_sub()));247 <Balance<T>>::remove((collection.id, token, owner));248 <AccountBalance<T>>::insert((collection.id, owner.as_sub()), account_balance);248 <AccountBalance<T>>::insert((collection.id, owner), account_balance);249 } else {249 } else {250 <Balance<T>>::insert((collection.id, token, owner.as_sub()), balance);250 <Balance<T>>::insert((collection.id, token, owner), balance);251 }251 }252 <TotalSupply<T>>::insert((collection.id, token), total_supply);252 <TotalSupply<T>>::insert((collection.id, token), total_supply);253 // TODO: ERC20 transfer event253 // TODO: ERC20 transfer event278 }278 }279 <PalletCommon<T>>::ensure_correct_receiver(to)?;279 <PalletCommon<T>>::ensure_correct_receiver(to)?;280280281 let balance_from = <Balance<T>>::get((collection.id, token, from.as_sub()))281 let balance_from = <Balance<T>>::get((collection.id, token, from))282 .checked_sub(amount)282 .checked_sub(amount)283 .ok_or(<CommonError<T>>::TokenValueTooLow)?;283 .ok_or(<CommonError<T>>::TokenValueTooLow)?;284 let mut create_target = false;284 let mut create_target = false;285 let from_to_differ = from != to;285 let from_to_differ = from != to;286 let balance_to = if from != to {286 let balance_to = if from != to {287 let old_balance = <Balance<T>>::get((collection.id, token, to.as_sub()));287 let old_balance = <Balance<T>>::get((collection.id, token, to));288 if old_balance == 0 {288 if old_balance == 0 {289 create_target = true;289 create_target = true;290 }290 }299299300 let account_balance_from = if balance_from == 0 {300 let account_balance_from = if balance_from == 0 {301 Some(301 Some(302 <AccountBalance<T>>::get((collection.id, from.as_sub()))302 <AccountBalance<T>>::get((collection.id, from))303 .checked_sub(1)303 .checked_sub(1)304 // Should not occur304 // Should not occur305 .ok_or(ArithmeticError::Underflow)?,305 .ok_or(ArithmeticError::Underflow)?,310 // Account data is created in token, AccountBalance should be increased310 // Account data is created in token, AccountBalance should be increased311 // But only if from != to as we shouldn't check overflow in this case311 // But only if from != to as we shouldn't check overflow in this case312 let account_balance_to = if create_target && from_to_differ {312 let account_balance_to = if create_target && from_to_differ {313 let account_balance_to = <AccountBalance<T>>::get((collection.id, to.as_sub()))313 let account_balance_to = <AccountBalance<T>>::get((collection.id, to))314 .checked_add(1)314 .checked_add(1)315 .ok_or(ArithmeticError::Overflow)?;315 .ok_or(ArithmeticError::Overflow)?;316 ensure!(316 ensure!(328 if let Some(balance_to) = balance_to {328 if let Some(balance_to) = balance_to {329 // from != to329 // from != to330 if balance_from == 0 {330 if balance_from == 0 {331 <Balance<T>>::remove((collection.id, token, from.as_sub()));331 <Balance<T>>::remove((collection.id, token, from));332 } else {332 } else {333 <Balance<T>>::insert((collection.id, token, from.as_sub()), balance_from);333 <Balance<T>>::insert((collection.id, token, from), balance_from);334 }334 }335 <Balance<T>>::insert((collection.id, token, to.as_sub()), balance_to);335 <Balance<T>>::insert((collection.id, token, to), balance_to);336 if let Some(account_balance_from) = account_balance_from {336 if let Some(account_balance_from) = account_balance_from {337 <AccountBalance<T>>::insert((collection.id, from.as_sub()), account_balance_from);337 <AccountBalance<T>>::insert((collection.id, from), account_balance_from);338 <Owned<T>>::remove((collection.id, from.as_sub(), token));338 <Owned<T>>::remove((collection.id, from, token));339 }339 }340 if let Some(account_balance_to) = account_balance_to {340 if let Some(account_balance_to) = account_balance_to {341 <AccountBalance<T>>::insert((collection.id, to.as_sub()), account_balance_to);341 <AccountBalance<T>>::insert((collection.id, to), account_balance_to);342 <Owned<T>>::insert((collection.id, to.as_sub(), token), true);342 <Owned<T>>::insert((collection.id, to, token), true);343 }343 }344 }344 }345345412 for data in &data {412 for data in &data {413 for (owner, _) in &data.users {413 for (owner, _) in &data.users {414 let balance = balances414 let balance = balances415 .entry(owner.as_sub())415 .entry(owner)416 .or_insert_with(|| <AccountBalance<T>>::get((collection.id, owner.as_sub())));416 .or_insert_with(|| <AccountBalance<T>>::get((collection.id, owner)));417 *balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;417 *balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;418418419 ensure!(419 ensure!(444 if amount == 0 {444 if amount == 0 {445 continue;445 continue;446 }446 }447 <Balance<T>>::insert((collection.id, token_id, user.as_sub()), amount);447 <Balance<T>>::insert((collection.id, token_id, &user), amount);448 <Owned<T>>::insert((collection.id, user.as_sub(), TokenId(token_id)), true);448 <Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);449 // TODO: ERC20 transfer event449 // TODO: ERC20 transfer event450 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(450 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(451 collection.id,451 collection.id,465 token: TokenId,465 token: TokenId,466 amount: u128,466 amount: u128,467 ) {467 ) {468 <Allowance<T>>::insert((collection.id, token, sender.as_sub(), spender), amount);468 <Allowance<T>>::insert((collection.id, token, sender, spender), amount);469 // TODO: ERC20 approval event469 // TODO: ERC20 approval event470 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(470 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(471 collection.id,471 collection.id,490490491 <PalletCommon<T>>::ensure_correct_receiver(spender)?;491 <PalletCommon<T>>::ensure_correct_receiver(spender)?;492492493 if <Balance<T>>::get((collection.id, token, sender.as_sub())) < amount {493 if <Balance<T>>::get((collection.id, token, sender)) < amount {494 ensure!(494 ensure!(495 collection.ignores_owned_amount(sender)? && Self::token_exists(collection, token),495 collection.ignores_owned_amount(sender)? && Self::token_exists(collection, token),496 <CommonError<T>>::CantApproveMoreThanOwned496 <CommonError<T>>::CantApproveMoreThanOwned511 token: TokenId,511 token: TokenId,512 amount: u128,512 amount: u128,513 ) -> DispatchResult {513 ) -> DispatchResult {514 if spender == from {514 if spender.conv_eq(from) {515 return Self::transfer(collection, from, to, token, amount);515 return Self::transfer(collection, from, to, token, amount);516 }516 }517 if collection.access == AccessMode::WhiteList {517 if collection.access == AccessMode::WhiteList {518 // `from`, `to` checked in [`transfer`]518 // `from`, `to` checked in [`transfer`]519 collection.check_allowlist(spender)?;519 collection.check_allowlist(spender)?;520 }520 }521521522 let allowance = <Allowance<T>>::get((collection.id, token, from.as_sub(), &spender))522 let allowance =523 .checked_sub(amount);523 <Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);524 if allowance.is_none() {524 if allowance.is_none() {525 ensure!(525 ensure!(544 token: TokenId,544 token: TokenId,545 amount: u128,545 amount: u128,546 ) -> DispatchResult {546 ) -> DispatchResult {547 if spender == from {547 if spender.conv_eq(from) {548 return Self::burn(collection, from, token, amount);548 return Self::burn(collection, from, token, amount);549 }549 }550 if collection.access == AccessMode::WhiteList {550 if collection.access == AccessMode::WhiteList {551 // `from` checked in [`burn`]551 // `from` checked in [`burn`]552 collection.check_allowlist(spender)?;552 collection.check_allowlist(spender)?;553 }553 }554554555 let allowance = <Allowance<T>>::get((collection.id, token, from.as_sub(), &spender))555 let allowance =556 .checked_sub(amount);556 <Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);557 if allowance.is_none() {557 if allowance.is_none() {558 ensure!(558 ensure!(primitives/rpc/src/lib.rsdiffbeforeafterboth30 /// Used for ethereum integration30 /// Used for ethereum integration31 fn eth_contract_code(account: H160) -> Option<Vec<u8>>;31 fn eth_contract_code(account: H160) -> Option<Vec<u8>>;323233 fn adminlist(collection: CollectionId) -> Vec<AccountId>;33 fn adminlist(collection: CollectionId) -> Vec<CrossAccountId>;34 fn allowlist(collection: CollectionId) -> Vec<AccountId>;34 fn allowlist(collection: CollectionId) -> Vec<CrossAccountId>;35 fn last_token_id(collection: CollectionId) -> TokenId;35 fn last_token_id(collection: CollectionId) -> TokenId;36 }36 }37}37}runtime/src/lib.rsdiffbeforeafterboth1037 .or_else(|| <pallet_evm_migration::OnMethodCall<Runtime>>::get_code(&account))1038 .or_else(|| <pallet_evm_contract_helpers::HelpersOnMethodCall<Self>>::get_code(&account))1037 }1039 }1038 fn adminlist(collection: CollectionId) -> Vec<AccountId> {1040 fn adminlist(collection: CollectionId) -> Vec<CrossAccountId> {1039 <pallet_nft::Pallet<Runtime>>::adminlist(collection)1041 <pallet_nft::Pallet<Runtime>>::adminlist(collection)1040 }1042 }1041 fn allowlist(collection: CollectionId) -> Vec<AccountId> {1043 fn allowlist(collection: CollectionId) -> Vec<CrossAccountId> {1042 <pallet_nft::Pallet<Runtime>>::allowlist(collection)1044 <pallet_nft::Pallet<Runtime>>::allowlist(collection)1043 }1045 }1044 fn last_token_id(collection: CollectionId) -> TokenId {1046 fn last_token_id(collection: CollectionId) -> TokenId {