From 142072c27e604113e252aecc819936a12661e1be Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Mon, 17 Feb 2025 15:38:49 +0100 Subject: [PATCH 1/3] spike foreign fungibles v2 --- pallets/api/src/fungibles/benchmarking.rs | 8 +- pallets/api/src/fungibles/mod.rs | 254 +++++++++++++++++++--- pop-api/src/v0/fungibles/mod.rs | 197 ++++++++++++++++- runtime/devnet/src/config/api/mod.rs | 7 +- runtime/devnet/src/config/assets.rs | 28 +++ runtime/devnet/src/lib.rs | 2 + 6 files changed, 455 insertions(+), 41 deletions(-) diff --git a/pallets/api/src/fungibles/benchmarking.rs b/pallets/api/src/fungibles/benchmarking.rs index 7ded38c0f..1a06ab5d4 100644 --- a/pallets/api/src/fungibles/benchmarking.rs +++ b/pallets/api/src/fungibles/benchmarking.rs @@ -108,10 +108,14 @@ mod benchmarks { #[benchmark] // Storage: `Assets` - fn total_supply() { + fn total_supply(a: Linear<0, 1>) { #[block] { - Pallet::::read(Read::TotalSupply(TokenIdOf::::zero())); + match a { + 0 => Pallet::::read(Read::TotalSupply(TokenIdOf::::TrustBacked(0))), + 1 => + Pallet::::read(Read::TotalSupply(TokenIdOf::::Foreign(Location::Parent))), + } } } #[benchmark] diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index 1b10f03ec..9e0f1e359 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -2,7 +2,12 @@ //! goal is to provide a simplified, consistent API that adheres to standards in the smart contract //! space. -use frame_support::traits::fungibles::{metadata::Inspect as MetadataInspect, Inspect}; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{ + __private::RuntimeDebug, + pallet_prelude::TypeInfo, + traits::fungibles::{metadata::Inspect as MetadataInspect, Inspect}, +}; pub use pallet::*; use pallet_assets::WeightInfo as AssetsWeightInfoTrait; use weights::WeightInfo; @@ -13,16 +18,49 @@ mod benchmarking; mod tests; pub mod weights; -type AccountIdOf = ::AccountId; -type TokenIdOf = as Inspect<::AccountId>>::AssetId; -type TokenIdParameterOf = >>::AssetIdParameter; -type AssetsOf = pallet_assets::Pallet>; -type AssetsErrorOf = pallet_assets::Error>; -type AssetsInstanceOf = ::AssetsInstance; -type AssetsWeightInfoOf = >>::WeightInfo; -type BalanceOf = as Inspect<::AccountId>>::Balance; +type TrustBackedTokenIdParameterOf = + >>::AssetIdParameter; +type ForeignTokenIdParameterOf = + >>::AssetIdParameter; + +type TrustBackedAssetsOf = pallet_assets::Pallet>; +type ForeignAssetsOf = pallet_assets::Pallet>; + +type TrustBackedAssetsErrorOf = pallet_assets::Error>; +type ForeignAssetsErrorOf = pallet_assets::Error>; + +type TrustBackedAssetsInstanceOf = ::TrustBackedAssetsInstance; +type ForeignAssetsInstanceOf = ::ForeignAssetsInstance; + +type TrustBackedAssetsWeightInfoOf = + >>::WeightInfo; +type ForeignAssetsWeightInfoOf = + >>::WeightInfo; type WeightOf = ::WeightInfo; +// Our unified asset identifier type. The variant determines which asset instance to call. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum MultiAssetId { + TrustBacked(TrustId), + Foreign(ForeignId), +} + +/// Renamed to TokenIdOf for minimal changes. +/// It wraps the asset ID from: +/// - the trust‑backed instance (using `TrustBackedAssetsInstanceOf`), and +/// - the foreign instance (using `ForeignAssetsInstanceOf`). +type TokenIdOf = MultiAssetId< + > as Inspect< + ::AccountId, + >>::AssetId, + > as Inspect< + ::AccountId, + >>::AssetId, +>; + +type AccountIdOf = ::AccountId; +type BalanceOf = ::Balance; + #[frame_support::pallet] pub mod pallet { use core::cmp::Ordering::*; @@ -42,13 +80,44 @@ pub mod pallet { use super::*; /// Configure the pallet by specifying the parameters and types on which it depends. + /// + /// It now requires two asset instances: + /// - `TrustBackedAssetsInstance`: used for trust‑backed assets (formerly the sole instance), + /// - `ForeignAssetsInstance`: used for foreign assets. #[pallet::config] - pub trait Config: frame_system::Config + pallet_assets::Config { + pub trait Config: + frame_system::Config + + pallet_assets::Config + + pallet_assets::Config + { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// The instance of pallet-assets. - type AssetsInstance; - /// Weight information for dispatchables in this pallet. + /// The asset instance for trust‑backed assets (renamed from the old AssetsInstance). + type TrustBackedAssetsInstance; + /// The asset instance for foreign assets. + type ForeignAssetsInstance; + type Balance: Parameter + + MaybeSerializeDeserialize + + Default + + Copy + + Into< + as Inspect< + ::AccountId, + >>::Balance, + > + From< + as Inspect< + ::AccountId, + >>::Balance, + > + Into< + as Inspect< + ::AccountId, + >>::Balance, + > + From< + as Inspect< + ::AccountId, + >>::Balance, + >; + /// Weight information for dispatchable functions in this pallet. type WeightInfo: WeightInfo; } @@ -94,6 +163,14 @@ pub mod pallet { }, } + // A helper function to compute the weight parameter based on the token variant. + fn weight_param(token: &TokenIdOf) -> u32 { + match token { + MultiAssetId::TrustBacked(_) => 0, + MultiAssetId::Foreign(_) => 1, + } + } + #[pallet::call] impl Pallet { /// Transfers `value` amount of tokens from the caller's account to account `to`. @@ -103,7 +180,13 @@ pub mod pallet { /// - `to` - The recipient account. /// - `value` - The number of tokens to transfer. #[pallet::call_index(3)] - #[pallet::weight(AssetsWeightInfoOf::::transfer_keep_alive())] + #[pallet::weight( + if weight_param:: (& token) == 0 { + TrustBackedAssetsWeightInfoOf::::transfer_keep_alive() + } else { + ForeignAssetsWeightInfoOf::::transfer_keep_alive() + } + )] pub fn transfer( origin: OriginFor, token: TokenIdOf, @@ -111,12 +194,24 @@ pub mod pallet { value: BalanceOf, ) -> DispatchResult { let from = ensure_signed(origin.clone())?; - AssetsOf::::transfer_keep_alive( - origin, - token.clone().into(), - T::Lookup::unlookup(to.clone()), - value, - )?; + match token.clone() { + MultiAssetId::TrustBacked(id) => { + TrustBackedAssetsOf::::transfer_keep_alive( + origin, + id.into(), + T::Lookup::unlookup(to.clone()), + value.into(), + )?; + }, + MultiAssetId::Foreign(id) => { + ForeignAssetsOf::::transfer_keep_alive( + origin, + id.into(), + T::Lookup::unlookup(to.clone()), + value.into(), + )?; + }, + } Self::deposit_event(Event::Transfer { token, from: Some(from), to: Some(to), value }); Ok(()) } @@ -499,7 +594,7 @@ pub mod pallet { fn weight(request: &Self::Read) -> Weight { use Read::*; match request { - TotalSupply(_) => ::WeightInfo::total_supply(), + TotalSupply(id) => ::WeightInfo::total_supply(weight_param(id)), BalanceOf { .. } => ::WeightInfo::balance_of(), Allowance { .. } => ::WeightInfo::allowance(), TokenName(_) => ::WeightInfo::token_name(), @@ -516,23 +611,110 @@ pub mod pallet { fn read(request: Self::Read) -> Self::Result { use Read::*; match request { - TotalSupply(token) => ReadResult::TotalSupply(AssetsOf::::total_supply(token)), - BalanceOf { token, owner } => - ReadResult::BalanceOf(AssetsOf::::balance(token, owner)), - Allowance { token, owner, spender } => - ReadResult::Allowance(AssetsOf::::allowance(token, &owner, &spender)), - TokenName(token) => ReadResult::TokenName( - Some( as MetadataInspect>>::name(token)) + TotalSupply(token) => { + let total = match token { + MultiAssetId::TrustBacked(id) => + TrustBackedAssetsOf::::total_supply(id).into(), + MultiAssetId::Foreign(id) => ForeignAssetsOf::::total_supply(id).into(), + }; + ReadResult::TotalSupply(total) + }, + BalanceOf { token, owner } => { + let bal = match token { + MultiAssetId::TrustBacked(id) => pallet_assets::Pallet::< + T, + TrustBackedAssetsInstanceOf, + >::balance(id, &owner) + .into(), + MultiAssetId::Foreign(id) => pallet_assets::Pallet::< + T, + ForeignAssetsInstanceOf, + >::balance(id, &owner) + .into(), + }; + ReadResult::BalanceOf(bal) + }, + Allowance { token, owner, spender } => { + let allow = match token { + MultiAssetId::TrustBacked(id) => pallet_assets::Pallet::< + T, + TrustBackedAssetsInstanceOf, + >::allowance(id, &owner, &spender) + .into(), + MultiAssetId::Foreign(id) => pallet_assets::Pallet::< + T, + ForeignAssetsInstanceOf, + >::allowance(id, &owner, &spender) + .into(), + }; + ReadResult::Allowance(allow) + }, + TokenName(token) => { + let name = match token { + MultiAssetId::TrustBacked(id) => Some(, + > as MetadataInspect>>::name( + id + )) + .filter(|v| !v.is_empty()), + MultiAssetId::Foreign(id) => Some(, + > as MetadataInspect>>::name( + id + )) + .filter(|v| !v.is_empty()), + }; + ReadResult::TokenName(name) + }, + TokenSymbol(token) => { + let symbol = match token { + MultiAssetId::TrustBacked(id) => Some(, + > as MetadataInspect>>::symbol( + id + )) .filter(|v| !v.is_empty()), - ), - TokenSymbol(token) => ReadResult::TokenSymbol( - Some( as MetadataInspect>>::symbol(token)) + MultiAssetId::Foreign(id) => Some(, + > as MetadataInspect>>::symbol( + id + )) .filter(|v| !v.is_empty()), - ), - TokenDecimals(token) => ReadResult::TokenDecimals( - as MetadataInspect>>::decimals(token), - ), - TokenExists(token) => ReadResult::TokenExists(AssetsOf::::asset_exists(token)), + }; + ReadResult::TokenSymbol(symbol) + }, + TokenDecimals(token) => { + let decimals = match token { + MultiAssetId::TrustBacked(id) => , + > as MetadataInspect>>::decimals( + id + ), + MultiAssetId::Foreign(id) => , + > as MetadataInspect>>::decimals( + id + ), + }; + ReadResult::TokenDecimals(decimals) + }, + TokenExists(token) => { + let exists = match token { + MultiAssetId::TrustBacked(id) => pallet_assets::Pallet::< + T, + TrustBackedAssetsInstanceOf, + >::asset_exists(id), + MultiAssetId::Foreign(id) => + pallet_assets::Pallet::>::asset_exists(id), + }; + ReadResult::TokenExists(exists) + }, } } } diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index 1e1479820..529e8a5a1 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -16,7 +16,7 @@ pub use traits::*; use crate::{ constants::{ASSETS, BALANCES, FUNGIBLES, MODULE_ERROR}, - primitives::{AccountId, Balance, TokenId}, + primitives::{AccountId, Balance}, ChainExtensionMethodApi, Result, StatusCode, }; @@ -24,6 +24,13 @@ pub mod errors; pub mod events; pub mod traits; +#[derive(Debug, PartialEq, Eq, Clone)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum TokenId { + TrustBacked(u32), + Foreign(xcm::Location), +} + /// Returns the total token supply for a specified token. /// /// # Parameters @@ -341,3 +348,191 @@ fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { crate::v0::build_read_state(FUNGIBLES, state_query) } + +mod xcm { + extern crate alloc; + + use alloc::sync::Arc; + + use codec::{Decode, Encode}; + + #[derive(Debug, PartialEq, Clone, Eq)] + #[ink::scale_derive(Encode, Decode, TypeInfo)] + pub struct Location { + /// The number of parent junctions at the beginning of this `Location`. + pub parents: u8, + /// The interior (i.e. non-parent) junctions that this `Location` contains. + pub interior: Junctions, + } + + #[derive(Debug, PartialEq, Eq, Clone)] + #[ink::scale_derive(Encode, Decode, TypeInfo)] + pub enum Junctions { + /// The interpreting consensus system. + Here, + /// A relative path comprising 1 junction. + X1(Arc<[Junction; 1]>), + /// A relative path comprising 2 junctions. + X2(Arc<[Junction; 2]>), + /// A relative path comprising 3 junctions. + X3(Arc<[Junction; 3]>), + /// A relative path comprising 4 junctions. + X4(Arc<[Junction; 4]>), + /// A relative path comprising 5 junctions. + X5(Arc<[Junction; 5]>), + /// A relative path comprising 6 junctions. + X6(Arc<[Junction; 6]>), + /// A relative path comprising 7 junctions. + X7(Arc<[Junction; 7]>), + /// A relative path comprising 8 junctions. + X8(Arc<[Junction; 8]>), + } + + #[derive(Debug, PartialEq, Eq, Clone)] + #[ink::scale_derive(Encode, Decode, TypeInfo)] + pub enum Junction { + /// An indexed parachain belonging to and operated by the context. + /// + /// Generally used when the context is a Polkadot Relay-chain. + Parachain(#[codec(compact)] u32), + /// A 32-byte identifier for an account of a specific network that is respected as a + /// sovereign endpoint within the context. + /// + /// Generally used when the context is a Substrate-based chain. + AccountId32 { network: Option, id: [u8; 32] }, + /// An 8-byte index for an account of a specific network that is respected as a sovereign + /// endpoint within the context. + /// + /// May be used when the context is a Frame-based chain and includes e.g. an indices + /// pallet. + AccountIndex64 { + network: Option, + #[codec(compact)] + index: u64, + }, + /// A 20-byte identifier for an account of a specific network that is respected as a + /// sovereign endpoint within the context. + /// + /// May be used when the context is an Ethereum or Bitcoin chain or smart-contract. + AccountKey20 { network: Option, key: [u8; 20] }, + /// An instanced, indexed pallet that forms a constituent part of the context. + /// + /// Generally used when the context is a Frame-based chain. + PalletInstance(u8), + /// A non-descript index within the context location. + /// + /// Usage will vary widely owing to its generality. + /// + /// NOTE: Try to avoid using this and instead use a more specific item. + GeneralIndex(#[codec(compact)] u128), + /// A nondescript array datum, 32 bytes, acting as a key within the context + /// location. + /// + /// Usage will vary widely owing to its generality. + /// + /// NOTE: Try to avoid using this and instead use a more specific item. + // Note this is implemented as an array with a length rather than using `BoundedVec` owing + // to the bound for ` + GeneralKey { length: u8, data: [u8; 32] }, + /// The unambiguous child. + /// + /// Not currently used except as a fallback when deriving context. + OnlyChild, + /// A pluralistic body existing within consensus. + /// + /// Typical to be used to represent a governance origin of a chain, but could in principle + /// be used to represent things such as multisigs also. + Plurality { id: BodyId, part: BodyPart }, + /// A global network capable of externalizing its own consensus. This is not generally + /// meaningful outside of the universal level. + GlobalConsensus(NetworkId), + } + + #[derive(Debug, PartialEq, Clone, Eq)] + #[ink::scale_derive(Encode, Decode, TypeInfo)] + pub enum NetworkId { + /// Network specified by the first 32 bytes of its genesis block. + ByGenesis([u8; 32]), + /// Network defined by the first 32-bytes of the hash and number of some block it contains. + ByFork { block_number: u64, block_hash: [u8; 32] }, + /// The Polkadot mainnet Relay-chain. + Polkadot, + /// The Kusama canary-net Relay-chain. + Kusama, + /// An Ethereum network specified by its chain ID. + Ethereum { + /// The EIP-155 chain ID. + #[codec(compact)] + chain_id: u64, + }, + /// The Bitcoin network, including hard-forks supported by Bitcoin Core development team. + BitcoinCore, + /// The Bitcoin network, including hard-forks supported by Bitcoin Cash developers. + BitcoinCash, + /// The Polkadot Bulletin chain. + PolkadotBulletin, + } + + #[derive(Debug, PartialEq, Clone, Eq)] + #[ink::scale_derive(Encode, Decode, TypeInfo)] + pub enum BodyId { + /// The only body in its context. + Unit, + /// A named body. + Moniker([u8; 4]), + /// An indexed body. + Index(#[codec(compact)] u32), + /// The unambiguous executive body (for Polkadot, this would be the Polkadot council). + Executive, + /// The unambiguous technical body (for Polkadot, this would be the Technical Committee). + Technical, + /// The unambiguous legislative body (for Polkadot, this could be considered the opinion of + /// a majority of lock-voters). + Legislative, + /// The unambiguous judicial body (this doesn't exist on Polkadot, but if it were to get a + /// "grand oracle", it may be considered as that). + Judicial, + /// The unambiguous defense body (for Polkadot, an opinion on the topic given via a public + /// referendum on the `staking_admin` track). + Defense, + /// The unambiguous administration body (for Polkadot, an opinion on the topic given via a + /// public referendum on the `general_admin` track). + Administration, + /// The unambiguous treasury body (for Polkadot, an opinion on the topic given via a public + /// referendum on the `treasurer` track). + Treasury, + } + + #[derive(Debug, PartialEq, Clone, Eq)] + #[ink::scale_derive(Encode, Decode, TypeInfo)] + pub enum BodyPart { + /// The body's declaration, under whatever means it decides. + Voice, + /// A given number of members of the body. + Members { + #[codec(compact)] + count: u32, + }, + /// A given number of members of the body, out of some larger caucus. + Fraction { + #[codec(compact)] + nom: u32, + #[codec(compact)] + denom: u32, + }, + /// No less than the given proportion of members of the body. + AtLeastProportion { + #[codec(compact)] + nom: u32, + #[codec(compact)] + denom: u32, + }, + /// More than the given proportion of members of the body. + MoreThanProportion { + #[codec(compact)] + nom: u32, + #[codec(compact)] + denom: u32, + }, + } +} diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index e49a4c7d9..6f700b931 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -6,12 +6,13 @@ use cumulus_primitives_core::Weight; use frame_support::traits::Contains; pub(crate) use pallet_api::Extension; use pallet_api::{extension::*, Read}; +use parachains_common::Balance; use sp_core::ConstU8; use sp_runtime::DispatchError; use versioning::*; use crate::{ - config::assets::{TrustBackedAssetsInstance, TrustBackedNftsInstance}, + config::assets::{ForeignAssetsInstance, TrustBackedAssetsInstance, TrustBackedNftsInstance}, fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; @@ -82,8 +83,10 @@ impl RuntimeResult { } impl fungibles::Config for Runtime { - type AssetsInstance = TrustBackedAssetsInstance; + type Balance = Balance; + type ForeignAssetsInstance = ForeignAssetsInstance; type RuntimeEvent = RuntimeEvent; + type TrustBackedAssetsInstance = TrustBackedAssetsInstance; type WeightInfo = fungibles::weights::SubstrateWeight; } diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 704cf4c37..83cfd6609 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -8,6 +8,7 @@ use frame_system::{EnsureRoot, EnsureSigned}; use pallet_nfts::PalletFeatures; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId, Signature}; use sp_runtime::traits::Verify; +use xcm::v5::Location; use crate::{ deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, @@ -123,6 +124,7 @@ impl pallet_nft_fractionalization::Config for Runtime { pub(crate) type TrustBackedAssetsInstance = pallet_assets::Instance1; pub type TrustBackedAssetsCall = pallet_assets::Call; + impl pallet_assets::Config for Runtime { type ApprovalDeposit = ApprovalDeposit; type AssetAccountDeposit = AssetAccountDeposit; @@ -146,6 +148,32 @@ impl pallet_assets::Config for Runtime { type WeightInfo = pallet_assets::weights::SubstrateWeight; } +pub(crate) type ForeignAssetsInstance = pallet_assets::Instance2; +pub type ForeignAssetsCall = pallet_assets::Call; + +impl pallet_assets::Config for Runtime { + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; + type AssetId = Location; + type AssetIdParameter = Location; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); + type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); + type ForceOrigin = AssetsForceOrigin; + type Freezer = (); + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type RemoveItemsLimit = ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; + type StringLimit = AssetsStringLimit; + type WeightInfo = pallet_assets::weights::SubstrateWeight; +} + #[cfg(test)] mod tests { use frame_support::traits::StorageInfoTrait; diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index aca3c865a..46e87ab68 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -648,6 +648,8 @@ mod runtime { pub type NftFractionalization = pallet_nft_fractionalization::Pallet; #[runtime::pallet_index(52)] pub type Assets = pallet_assets::Pallet; + #[runtime::pallet_index(53)] + pub type ForeignAssets = pallet_assets::Pallet; // Pop API #[runtime::pallet_index(150)] From c8d96850fbef18ceb51595c411e68c5541037004 Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Tue, 18 Feb 2025 14:08:24 +0100 Subject: [PATCH 2/3] show contract --- .../contracts/fungibles/lib.rs | 122 +++++++++--------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/pop-api/integration-tests/contracts/fungibles/lib.rs b/pop-api/integration-tests/contracts/fungibles/lib.rs index b029413e3..f05e920cd 100755 --- a/pop-api/integration-tests/contracts/fungibles/lib.rs +++ b/pop-api/integration-tests/contracts/fungibles/lib.rs @@ -6,12 +6,12 @@ /// 4. PSP-22 Mintable & Burnable use ink::prelude::vec::Vec; use pop_api::{ - fungibles::{ - self as api, - events::{Approval, Created, DestroyStarted, MetadataCleared, MetadataSet, Transfer}, - }, - primitives::TokenId, - StatusCode, + fungibles::{ + self as api, + events::{Approval, Created, DestroyStarted, MetadataCleared, MetadataSet, Transfer}, + TokenId, + }, + StatusCode, }; pub type Result = core::result::Result; @@ -61,16 +61,16 @@ mod fungibles { api::allowance(token, owner, spender) } - #[ink(message)] - pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> Result<()> { - api::transfer(token, to, value)?; - self.env().emit_event(Transfer { - from: Some(self.env().account_id()), - to: Some(to), - value, - }); - Ok(()) - } + #[ink(message)] + pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> Result<()> { + api::transfer(token.clone(), to, value)?; + self.env().emit_event(Transfer { + from: Some(self.env().account_id()), + to: Some(to), + value, + }); + Ok(()) + } #[ink(message)] pub fn transfer_from( @@ -140,51 +140,51 @@ mod fungibles { api::token_decimals(token) } - /// 3. Asset Management: - /// - create - /// - start_destroy - /// - set_metadata - /// - clear_metadata - /// - token_exists - - #[ink(message)] - pub fn create( - &mut self, - id: TokenId, - admin: AccountId, - min_balance: Balance, - ) -> Result<()> { - api::create(id, admin, min_balance)?; - self.env().emit_event(Created { id, creator: admin, admin }); - Ok(()) - } - - #[ink(message)] - pub fn start_destroy(&mut self, token: TokenId) -> Result<()> { - api::start_destroy(token)?; - self.env().emit_event(DestroyStarted { token }); - Ok(()) - } - - #[ink(message)] - pub fn set_metadata( - &mut self, - token: TokenId, - name: Vec, - symbol: Vec, - decimals: u8, - ) -> Result<()> { - api::set_metadata(token, name.clone(), symbol.clone(), decimals)?; - self.env().emit_event(MetadataSet { token, name, symbol, decimals }); - Ok(()) - } - - #[ink(message)] - pub fn clear_metadata(&mut self, token: TokenId) -> Result<()> { - api::clear_metadata(token)?; - self.env().emit_event(MetadataCleared { token }); - Ok(()) - } + /// 3. Asset Management: + /// - create + /// - start_destroy + /// - set_metadata + /// - clear_metadata + /// - token_exists + + #[ink(message)] + pub fn create( + &mut self, + id: TokenId, + admin: AccountId, + min_balance: Balance, + ) -> Result<()> { + api::create(id.clone(), admin, min_balance)?; + self.env().emit_event(Created { id, creator: admin, admin }); + Ok(()) + } + + #[ink(message)] + pub fn start_destroy(&mut self, token: TokenId) -> Result<()> { + api::start_destroy(token.clone())?; + self.env().emit_event(DestroyStarted { token }); + Ok(()) + } + + #[ink(message)] + pub fn set_metadata( + &mut self, + token: TokenId, + name: Vec, + symbol: Vec, + decimals: u8, + ) -> Result<()> { + api::set_metadata(token.clone(), name.clone(), symbol.clone(), decimals)?; + self.env().emit_event(MetadataSet { token, name, symbol, decimals }); + Ok(()) + } + + #[ink(message)] + pub fn clear_metadata(&mut self, token: TokenId) -> Result<()> { + api::clear_metadata(token.clone())?; + self.env().emit_event(MetadataCleared { token }); + Ok(()) + } #[ink(message)] pub fn token_exists(&self, token: TokenId) -> Result { From 1f787eebbe6e0f4a4dc6fa8fdb67812f41cd745e Mon Sep 17 00:00:00 2001 From: Daanvdplas Date: Wed, 19 Feb 2025 08:43:09 +0100 Subject: [PATCH 3/3] feature gate foreign fungibles --- pop-api/Cargo.toml | 1 + pop-api/integration-tests/contracts/fungibles/Cargo.toml | 2 +- pop-api/src/v0/fungibles/mod.rs | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index e3597236a..475e8c298 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -33,6 +33,7 @@ path = "src/lib.rs" [features] default = [ "std" ] +foreign_fungibles = [ ] fungibles = [ ] nonfungibles = [ ] std = [ diff --git a/pop-api/integration-tests/contracts/fungibles/Cargo.toml b/pop-api/integration-tests/contracts/fungibles/Cargo.toml index 80b71a4b0..b4c89ab72 100755 --- a/pop-api/integration-tests/contracts/fungibles/Cargo.toml +++ b/pop-api/integration-tests/contracts/fungibles/Cargo.toml @@ -8,7 +8,7 @@ version = "0.1.0" [dependencies] ink = { version = "5.1.0", default-features = false } -pop-api = { path = "../../../../pop-api", default-features = false, features = [ "fungibles" ] } +pop-api = { path = "../../../../pop-api", default-features = false, features = [ "foreign_fungibles", "fungibles" ] } [lib] path = "lib.rs" diff --git a/pop-api/src/v0/fungibles/mod.rs b/pop-api/src/v0/fungibles/mod.rs index 529e8a5a1..a9ae84520 100644 --- a/pop-api/src/v0/fungibles/mod.rs +++ b/pop-api/src/v0/fungibles/mod.rs @@ -27,7 +27,10 @@ pub mod traits; #[derive(Debug, PartialEq, Eq, Clone)] #[ink::scale_derive(Encode, Decode, TypeInfo)] pub enum TokenId { + #[codec(index = 0)] TrustBacked(u32), + #[cfg(feature = "foreign_fungibles")] + #[codec(index = 1)] Foreign(xcm::Location), }