Skip to content

Commit

Permalink
spike foreign fungibles v2
Browse files Browse the repository at this point in the history
  • Loading branch information
Daanvdplas committed Feb 18, 2025
1 parent 76128fc commit 253d80e
Show file tree
Hide file tree
Showing 5 changed files with 453 additions and 41 deletions.
8 changes: 6 additions & 2 deletions pallets/api/src/fungibles/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,14 @@ mod benchmarks {

#[benchmark]
// Storage: `Assets`
fn total_supply() {
fn total_supply(a: Linear<0, 1>) {
#[block]
{
Pallet::<T>::read(Read::TotalSupply(TokenIdOf::<T>::zero()));
match a {
0 => Pallet::<T>::read(Read::TotalSupply(TokenIdOf::<T>::TrustBacked(0))),

Check failure on line 115 in pallets/api/src/fungibles/benchmarking.rs

View workflow job for this annotation

GitHub Actions / clippy

mismatched types

error[E0308]: mismatched types --> pallets/api/src/fungibles/benchmarking.rs:115:74 | 115 | 0 => Pallet::<T>::read(Read::TotalSupply(TokenIdOf::<T>::TrustBacked(0))), | --------------------------- ^ expected associated type, found integer | | | arguments to this enum variant are incorrect | = note: expected associated type `<T as pallet_assets::Config<<T as fungibles::pallet::Config>::TrustBackedAssetsInstance>>::AssetId` found type `{integer}` = help: consider constraining the associated type `<T as pallet_assets::Config<<T as fungibles::pallet::Config>::TrustBackedAssetsInstance>>::AssetId` to `{integer}` or calling a method that returns `<T as pallet_assets::Config<<T as fungibles::pallet::Config>::TrustBackedAssetsInstance>>::AssetId` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html note: tuple variant defined here --> pallets/api/src/fungibles/mod.rs:44:2 | 44 | TrustBacked(TrustId), | ^^^^^^^^^^^
1 =>
Pallet::<T>::read(Read::TotalSupply(TokenIdOf::<T>::Foreign(Location::Parent))),

Check failure on line 117 in pallets/api/src/fungibles/benchmarking.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared type `Location`

error[E0433]: failed to resolve: use of undeclared type `Location` --> pallets/api/src/fungibles/benchmarking.rs:117:66 | 117 | Pallet::<T>::read(Read::TotalSupply(TokenIdOf::<T>::Foreign(Location::Parent))), | ^^^^^^^^ use of undeclared type `Location` | help: consider importing this struct | 36 + use std::panic::Location; |
}

Check failure on line 118 in pallets/api/src/fungibles/benchmarking.rs

View workflow job for this annotation

GitHub Actions / clippy

mismatched types

error[E0308]: mismatched types --> pallets/api/src/fungibles/benchmarking.rs:114:4 | 114 | / match a { 115 | | 0 => Pallet::<T>::read(Read::TotalSupply(TokenIdOf::<T>::TrustBacked(0))), 116 | | 1 => 117 | | Pallet::<T>::read(Read::TotalSupply(TokenIdOf::<T>::Foreign(Location::Parent))), 118 | | } | | ^- help: consider using a semicolon here: `;` | |_____________| | expected `()`, found `ReadResult<T>` | = note: expected unit type `()` found enum `fungibles::pallet::ReadResult<T>`
}
}
#[benchmark]
Expand Down
254 changes: 218 additions & 36 deletions pallets/api/src/fungibles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -13,16 +18,49 @@ mod benchmarking;
mod tests;
pub mod weights;

type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
type TokenIdOf<T> = <AssetsOf<T> as Inspect<<T as frame_system::Config>::AccountId>>::AssetId;
type TokenIdParameterOf<T> = <T as pallet_assets::Config<AssetsInstanceOf<T>>>::AssetIdParameter;
type AssetsOf<T> = pallet_assets::Pallet<T, AssetsInstanceOf<T>>;
type AssetsErrorOf<T> = pallet_assets::Error<T, AssetsInstanceOf<T>>;
type AssetsInstanceOf<T> = <T as Config>::AssetsInstance;
type AssetsWeightInfoOf<T> = <T as pallet_assets::Config<AssetsInstanceOf<T>>>::WeightInfo;
type BalanceOf<T> = <AssetsOf<T> as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
type TrustBackedTokenIdParameterOf<T> =
<T as pallet_assets::Config<TrustBackedAssetsInstanceOf<T>>>::AssetIdParameter;
type ForeignTokenIdParameterOf<T> =
<T as pallet_assets::Config<ForeignAssetsInstanceOf<T>>>::AssetIdParameter;

type TrustBackedAssetsOf<T> = pallet_assets::Pallet<T, TrustBackedAssetsInstanceOf<T>>;
type ForeignAssetsOf<T> = pallet_assets::Pallet<T, ForeignAssetsInstanceOf<T>>;

type TrustBackedAssetsErrorOf<T> = pallet_assets::Error<T, TrustBackedAssetsInstanceOf<T>>;
type ForeignAssetsErrorOf<T> = pallet_assets::Error<T, ForeignAssetsInstanceOf<T>>;

type TrustBackedAssetsInstanceOf<T> = <T as Config>::TrustBackedAssetsInstance;
type ForeignAssetsInstanceOf<T> = <T as Config>::ForeignAssetsInstance;

type TrustBackedAssetsWeightInfoOf<T> =
<T as pallet_assets::Config<TrustBackedAssetsInstanceOf<T>>>::WeightInfo;
type ForeignAssetsWeightInfoOf<T> =
<T as pallet_assets::Config<ForeignAssetsInstanceOf<T>>>::WeightInfo;
type WeightOf<T> = <T as Config>::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<TrustId, ForeignId> {
TrustBacked(TrustId),
Foreign(ForeignId),
}

/// Renamed to TokenIdOf for minimal changes.
/// It wraps the asset ID from:
/// - the trust‑backed instance (using `TrustBackedAssetsInstanceOf<T>`), and
/// - the foreign instance (using `ForeignAssetsInstanceOf<T>`).
type TokenIdOf<T> = MultiAssetId<
<pallet_assets::Pallet<T, TrustBackedAssetsInstanceOf<T>> as Inspect<
<T as frame_system::Config>::AccountId,
>>::AssetId,
<pallet_assets::Pallet<T, ForeignAssetsInstanceOf<T>> as Inspect<
<T as frame_system::Config>::AccountId,
>>::AssetId,
>;

type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
type BalanceOf<T> = <T as Config>::Balance;

#[frame_support::pallet]
pub mod pallet {
use core::cmp::Ordering::*;
Expand All @@ -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<Self::AssetsInstance> {
pub trait Config:
frame_system::Config
+ pallet_assets::Config<Self::TrustBackedAssetsInstance>
+ pallet_assets::Config<Self::ForeignAssetsInstance>
{
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::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<
<pallet_assets::Pallet<Self, Self::TrustBackedAssetsInstance> as Inspect<
<Self as frame_system::Config>::AccountId,
>>::Balance,
> + From<
<pallet_assets::Pallet<Self, Self::TrustBackedAssetsInstance> as Inspect<
<Self as frame_system::Config>::AccountId,
>>::Balance,
> + Into<
<pallet_assets::Pallet<Self, Self::ForeignAssetsInstance> as Inspect<
<Self as frame_system::Config>::AccountId,
>>::Balance,
> + From<
<pallet_assets::Pallet<Self, Self::ForeignAssetsInstance> as Inspect<
<Self as frame_system::Config>::AccountId,
>>::Balance,
>;
/// Weight information for dispatchable functions in this pallet.
type WeightInfo: WeightInfo;
}

Expand Down Expand Up @@ -94,6 +163,14 @@ pub mod pallet {
},
}

// A helper function to compute the weight parameter based on the token variant.
fn weight_param<T: Config>(token: &TokenIdOf<T>) -> u32 {
match token {
MultiAssetId::TrustBacked(_) => 0,
MultiAssetId::Foreign(_) => 1,
}
}

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Transfers `value` amount of tokens from the caller's account to account `to`.
Expand All @@ -103,20 +180,38 @@ pub mod pallet {
/// - `to` - The recipient account.
/// - `value` - The number of tokens to transfer.
#[pallet::call_index(3)]
#[pallet::weight(AssetsWeightInfoOf::<T>::transfer_keep_alive())]
#[pallet::weight(
if weight_param::<T> (& token) == 0 {
TrustBackedAssetsWeightInfoOf::<T>::transfer_keep_alive()
} else {
ForeignAssetsWeightInfoOf::<T>::transfer_keep_alive()
}
)]
pub fn transfer(
origin: OriginFor<T>,
token: TokenIdOf<T>,
to: AccountIdOf<T>,
value: BalanceOf<T>,
) -> DispatchResult {
let from = ensure_signed(origin.clone())?;
AssetsOf::<T>::transfer_keep_alive(
origin,
token.clone().into(),
T::Lookup::unlookup(to.clone()),
value,
)?;
match token.clone() {
MultiAssetId::TrustBacked(id) => {
TrustBackedAssetsOf::<T>::transfer_keep_alive(
origin,
id.into(),
T::Lookup::unlookup(to.clone()),
value.into(),
)?;
},
MultiAssetId::Foreign(id) => {
ForeignAssetsOf::<T>::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(())
}
Expand Down Expand Up @@ -499,7 +594,7 @@ pub mod pallet {
fn weight(request: &Self::Read) -> Weight {
use Read::*;
match request {
TotalSupply(_) => <T as Config>::WeightInfo::total_supply(),
TotalSupply(id) => <T as Config>::WeightInfo::total_supply(weight_param(id)),

Check failure on line 597 in pallets/api/src/fungibles/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

this function takes 0 arguments but 1 argument was supplied

error[E0061]: this function takes 0 arguments but 1 argument was supplied --> pallets/api/src/fungibles/mod.rs:597:24 | 597 | TotalSupply(id) => <T as Config>::WeightInfo::total_supply(weight_param(id)), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- unexpected argument of type `u32` | note: associated function defined here --> pallets/api/src/fungibles/weights.rs:36:5 | 36 | fn total_supply() -> Weight; | ^^^^^^^^^^^^ help: remove the extra argument | 597 - TotalSupply(id) => <T as Config>::WeightInfo::total_supply(weight_param(id)), 597 + TotalSupply(id) => <T as Config>::WeightInfo::total_supply(), |
BalanceOf { .. } => <T as Config>::WeightInfo::balance_of(),
Allowance { .. } => <T as Config>::WeightInfo::allowance(),
TokenName(_) => <T as Config>::WeightInfo::token_name(),
Expand All @@ -516,23 +611,110 @@ pub mod pallet {
fn read(request: Self::Read) -> Self::Result {
use Read::*;
match request {
TotalSupply(token) => ReadResult::TotalSupply(AssetsOf::<T>::total_supply(token)),
BalanceOf { token, owner } =>
ReadResult::BalanceOf(AssetsOf::<T>::balance(token, owner)),
Allowance { token, owner, spender } =>
ReadResult::Allowance(AssetsOf::<T>::allowance(token, &owner, &spender)),
TokenName(token) => ReadResult::TokenName(
Some(<AssetsOf<T> as MetadataInspect<AccountIdOf<T>>>::name(token))
TotalSupply(token) => {
let total = match token {
MultiAssetId::TrustBacked(id) =>
TrustBackedAssetsOf::<T>::total_supply(id).into(),
MultiAssetId::Foreign(id) => ForeignAssetsOf::<T>::total_supply(id).into(),
};
ReadResult::TotalSupply(total)
},
BalanceOf { token, owner } => {
let bal = match token {
MultiAssetId::TrustBacked(id) => pallet_assets::Pallet::<
T,
TrustBackedAssetsInstanceOf<T>,
>::balance(id, &owner)
.into(),
MultiAssetId::Foreign(id) => pallet_assets::Pallet::<
T,
ForeignAssetsInstanceOf<T>,
>::balance(id, &owner)
.into(),
};
ReadResult::BalanceOf(bal)
},
Allowance { token, owner, spender } => {
let allow = match token {
MultiAssetId::TrustBacked(id) => pallet_assets::Pallet::<
T,
TrustBackedAssetsInstanceOf<T>,
>::allowance(id, &owner, &spender)
.into(),
MultiAssetId::Foreign(id) => pallet_assets::Pallet::<
T,
ForeignAssetsInstanceOf<T>,
>::allowance(id, &owner, &spender)
.into(),
};
ReadResult::Allowance(allow)
},
TokenName(token) => {
let name = match token {
MultiAssetId::TrustBacked(id) => Some(<pallet_assets::Pallet<
T,
TrustBackedAssetsInstanceOf<T>,
> as MetadataInspect<AccountIdOf<T>>>::name(
id
))
.filter(|v| !v.is_empty()),
MultiAssetId::Foreign(id) => Some(<pallet_assets::Pallet<
T,
ForeignAssetsInstanceOf<T>,
> as MetadataInspect<AccountIdOf<T>>>::name(
id
))
.filter(|v| !v.is_empty()),
};
ReadResult::TokenName(name)
},
TokenSymbol(token) => {
let symbol = match token {
MultiAssetId::TrustBacked(id) => Some(<pallet_assets::Pallet<
T,
TrustBackedAssetsInstanceOf<T>,
> as MetadataInspect<AccountIdOf<T>>>::symbol(
id
))
.filter(|v| !v.is_empty()),
),
TokenSymbol(token) => ReadResult::TokenSymbol(
Some(<AssetsOf<T> as MetadataInspect<AccountIdOf<T>>>::symbol(token))
MultiAssetId::Foreign(id) => Some(<pallet_assets::Pallet<
T,
ForeignAssetsInstanceOf<T>,
> as MetadataInspect<AccountIdOf<T>>>::symbol(
id
))
.filter(|v| !v.is_empty()),
),
TokenDecimals(token) => ReadResult::TokenDecimals(
<AssetsOf<T> as MetadataInspect<AccountIdOf<T>>>::decimals(token),
),
TokenExists(token) => ReadResult::TokenExists(AssetsOf::<T>::asset_exists(token)),
};
ReadResult::TokenSymbol(symbol)
},
TokenDecimals(token) => {
let decimals = match token {
MultiAssetId::TrustBacked(id) => <pallet_assets::Pallet<
T,
TrustBackedAssetsInstanceOf<T>,
> as MetadataInspect<AccountIdOf<T>>>::decimals(
id
),
MultiAssetId::Foreign(id) => <pallet_assets::Pallet<
T,
ForeignAssetsInstanceOf<T>,
> as MetadataInspect<AccountIdOf<T>>>::decimals(
id
),
};
ReadResult::TokenDecimals(decimals)
},
TokenExists(token) => {
let exists = match token {
MultiAssetId::TrustBacked(id) => pallet_assets::Pallet::<
T,
TrustBackedAssetsInstanceOf<T>,
>::asset_exists(id),
MultiAssetId::Foreign(id) =>
pallet_assets::Pallet::<T, ForeignAssetsInstanceOf<T>>::asset_exists(id),
};
ReadResult::TokenExists(exists)
},
}
}
}
Expand Down
Loading

0 comments on commit 253d80e

Please sign in to comment.