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> AssetsCallback<T::AssetId, T::AccountId> for ForeignAssetId<T, I>
27where
28 T: Config<ForeignAssetId = T::AssetId> + pallet_assets::Config<I>,
29 I: 'static,
30{
31 fn created(id: &T::AssetId, _: &T::AccountId) -> Result<(), ()> {
32 Pallet::<T>::insert_asset_mapping(id).map(|_| ())
33 }
34
35 fn destroyed(id: &T::AssetId) -> Result<(), ()> {
36 Pallet::<T>::remove_asset_mapping(id);
37 Ok(())
38 }
39}
40
41#[frame_support::pallet]
42pub mod pallet {
43 use super::*;
44 use frame_support::{pallet_prelude::*, Blake2_128Concat};
45
46 #[pallet::config]
47 pub trait Config: frame_system::Config {
48 type ForeignAssetId: Member + Parameter + Clone + MaybeSerializeDeserialize + MaxEncodedLen;
51
52 #[cfg(feature = "runtime-benchmarks")]
55 type AssetsInstance: 'static;
56 }
57
58 const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
59
60 #[pallet::pallet]
61 #[pallet::storage_version(STORAGE_VERSION)]
62 pub struct Pallet<T>(_);
63
64 #[pallet::storage]
67 pub type NextAssetIndex<T: Config> = StorageValue<_, u32, ValueQuery>;
68
69 #[pallet::storage]
71 pub type AssetIndexToForeignAssetId<T: Config> =
72 StorageMap<_, Identity, u32, T::ForeignAssetId, OptionQuery>;
73
74 #[pallet::storage]
76 pub type ForeignAssetIdToAssetIndex<T: Config> =
77 StorageMap<_, Blake2_128Concat, T::ForeignAssetId, u32, OptionQuery>;
78
79 impl<T: Config> Pallet<T> {
80 pub fn asset_id_of(asset_index: u32) -> Option<T::ForeignAssetId> {
82 AssetIndexToForeignAssetId::<T>::get(asset_index)
83 }
84
85 pub fn asset_index_of(asset_id: &T::ForeignAssetId) -> Option<u32> {
87 ForeignAssetIdToAssetIndex::<T>::get(asset_id)
88 }
89
90 pub fn next_asset_index() -> u32 {
92 NextAssetIndex::<T>::get()
93 }
94
95 pub fn insert_asset_mapping(asset_id: &T::ForeignAssetId) -> Result<u32, ()> {
98 if ForeignAssetIdToAssetIndex::<T>::contains_key(asset_id) {
99 log::error!(target: LOG_TARGET, "Asset id {:?} already mapped", asset_id);
100 return Err(());
101 }
102
103 let asset_index = NextAssetIndex::<T>::get();
104 let next_index = asset_index.checked_add(1).ok_or_else(|| {
105 log::error!(target: LOG_TARGET, "Asset index overflow");
106 })?;
107
108 AssetIndexToForeignAssetId::<T>::insert(asset_index, asset_id.clone());
109 ForeignAssetIdToAssetIndex::<T>::insert(asset_id, asset_index);
110 NextAssetIndex::<T>::put(next_index);
111
112 log::debug!(target: LOG_TARGET, "Mapped asset {:?} to index {:?}", asset_id, asset_index);
113 Ok(asset_index)
114 }
115
116 pub fn remove_asset_mapping(asset_id: &T::ForeignAssetId) {
118 if let Some(asset_index) = ForeignAssetIdToAssetIndex::<T>::take(asset_id) {
119 AssetIndexToForeignAssetId::<T>::remove(asset_index);
120 }
121 }
122 }
123}