pallet_assets_precompiles/
foreign_assets.rs1use core::marker::PhantomData;
19use pallet_assets::AssetsCallback;
20
21pub use pallet::*;
22
23const LOG_TARGET: &str = "pallet_foreign_assets";
24
25pub struct ForeignAssetId<T, I = ()>(PhantomData<(T, I)>);
26impl<T: Config, I>
27 AssetsCallback<T::AssetId, T::AccountId, <T as pallet_assets::Config<I>>::Balance>
28 for ForeignAssetId<T, I>
29where
30 T: Config<ForeignAssetId = T::AssetId> + pallet_assets::Config<I>,
31 I: 'static,
32{
33 fn created(id: &T::AssetId, _: &T::AccountId) -> Result<(), ()> {
34 Pallet::<T>::insert_asset_mapping(id).map(|_| ())
35 }
36
37 fn destroyed(id: &T::AssetId) -> Result<(), ()> {
38 Pallet::<T>::remove_asset_mapping(id);
39 Ok(())
40 }
41}
42
43#[frame_support::pallet]
44pub mod pallet {
45 use super::*;
46 use frame_support::{pallet_prelude::*, Blake2_128Concat};
47
48 #[pallet::config]
49 pub trait Config: frame_system::Config {
50 type ForeignAssetId: Member + Parameter + Clone + MaybeSerializeDeserialize + MaxEncodedLen;
53
54 #[cfg(feature = "runtime-benchmarks")]
57 type AssetsInstance: 'static;
58 }
59
60 const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
61
62 #[pallet::pallet]
63 #[pallet::storage_version(STORAGE_VERSION)]
64 pub struct Pallet<T>(_);
65
66 #[pallet::storage]
69 pub type NextAssetIndex<T: Config> = StorageValue<_, u32, ValueQuery>;
70
71 #[pallet::storage]
73 pub type AssetIndexToForeignAssetId<T: Config> =
74 StorageMap<_, Identity, u32, T::ForeignAssetId, OptionQuery>;
75
76 #[pallet::storage]
78 pub type ForeignAssetIdToAssetIndex<T: Config> =
79 StorageMap<_, Blake2_128Concat, T::ForeignAssetId, u32, OptionQuery>;
80
81 impl<T: Config> Pallet<T> {
82 pub fn asset_id_of(asset_index: u32) -> Option<T::ForeignAssetId> {
84 AssetIndexToForeignAssetId::<T>::get(asset_index)
85 }
86
87 pub fn asset_index_of(asset_id: &T::ForeignAssetId) -> Option<u32> {
89 ForeignAssetIdToAssetIndex::<T>::get(asset_id)
90 }
91
92 pub fn next_asset_index() -> u32 {
94 NextAssetIndex::<T>::get()
95 }
96
97 pub fn insert_asset_mapping(asset_id: &T::ForeignAssetId) -> Result<u32, ()> {
100 if ForeignAssetIdToAssetIndex::<T>::contains_key(asset_id) {
101 log::error!(target: LOG_TARGET, "Asset id {:?} already mapped", asset_id);
102 return Err(());
103 }
104
105 let asset_index = NextAssetIndex::<T>::get();
106 let next_index = asset_index.checked_add(1).ok_or_else(|| {
107 log::error!(target: LOG_TARGET, "Asset index overflow");
108 })?;
109
110 AssetIndexToForeignAssetId::<T>::insert(asset_index, asset_id.clone());
111 ForeignAssetIdToAssetIndex::<T>::insert(asset_id, asset_index);
112 NextAssetIndex::<T>::put(next_index);
113
114 log::debug!(target: LOG_TARGET, "Mapped asset {:?} to index {:?}", asset_id, asset_index);
115 Ok(asset_index)
116 }
117
118 pub fn remove_asset_mapping(asset_id: &T::ForeignAssetId) {
120 if let Some(asset_index) = ForeignAssetIdToAssetIndex::<T>::take(asset_id) {
121 AssetIndexToForeignAssetId::<T>::remove(asset_index);
122 }
123 }
124 }
125}