pallet_chain_extension_assets/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
20
21#[cfg(test)]
22mod mock;
23#[cfg(test)]
24mod tests;
25
26pub use assets_chain_extension_types::Command::{self, *};
27use assets_chain_extension_types::{handle_result, Outcome, LOG_TARGET};
28use frame_support::traits::fungibles::{
29 approvals::Inspect as AllowanceInspect, metadata::Inspect as MetadataInspect, Inspect,
30};
31use frame_support::DefaultNoBound;
32use frame_system::RawOrigin;
33use pallet_assets::WeightInfo;
34use pallet_contracts::chain_extension::{
35 ChainExtension, Environment, Ext, InitState, RetVal, SysConfig,
36};
37use parity_scale_codec::Encode;
38use sp_runtime::traits::{Get, StaticLookup};
39use sp_runtime::DispatchError;
40use sp_std::marker::PhantomData;
41type Weight<T> = <T as pallet_assets::Config>::WeightInfo;
42
43#[derive(DefaultNoBound)]
45pub struct AssetsExtension<T>(PhantomData<T>);
46
47impl<T> ChainExtension<T> for AssetsExtension<T>
48where
49 T: pallet_assets::Config + pallet_contracts::Config,
50 <T as pallet_assets::Config>::AssetId: Copy,
51 <<T as SysConfig>::Lookup as StaticLookup>::Source: From<<T as SysConfig>::AccountId>,
52{
53 fn call<E: Ext>(&mut self, env: Environment<E, InitState>) -> Result<RetVal, DispatchError>
54 where
55 E: Ext<T = T>,
56 {
57 let mut env = env.buf_in_buf_out();
58 match env.func_id().try_into().map_err(|_| {
59 DispatchError::Other("Unsupported func id in Pallet Assets Chain Extension")
60 })? {
61 Transfer => {
62 env.charge_weight(Weight::<T>::transfer())?;
63
64 let (id, target, amount): (
65 <T as pallet_assets::Config>::AssetId,
66 T::AccountId,
67 T::Balance,
68 ) = env.read_as()?;
69
70 log::trace!(
71 target: LOG_TARGET,
72 "transfer: raw arguments: id: {:?}, to: {:?}, amount: {:?}",
73 id,
74 target,
75 amount
76 );
77
78 let call_result = pallet_assets::Pallet::<T>::transfer(
79 RawOrigin::Signed(env.ext().address().clone()).into(),
80 id.into(),
81 target.into(),
82 amount,
83 );
84 handle_result!(call_result);
85 }
86 TransferApproved => {
87 env.charge_weight(Weight::<T>::transfer_approved())?;
88
89 let (id, owner, destination, amount): (
90 <T as pallet_assets::Config>::AssetId,
91 T::AccountId,
92 T::AccountId,
93 T::Balance,
94 ) = env.read_as()?;
95
96 log::trace!(target: LOG_TARGET,
97 "transfer_approved: raw arguments: id: {:?}, owner: {:?}, destination: {:?}, amount: {:?}",
98 id, owner, destination, amount);
99
100 let call_result = pallet_assets::Pallet::<T>::transfer_approved(
101 RawOrigin::Signed(env.ext().address().clone()).into(),
102 id.into(),
103 owner.into(),
104 destination.into(),
105 amount,
106 );
107 handle_result!(call_result);
108 }
109 Mint => {
110 env.charge_weight(Weight::<T>::mint())?;
111
112 let (id, beneficiary, amount): (
113 <T as pallet_assets::Config>::AssetId,
114 T::AccountId,
115 T::Balance,
116 ) = env.read_as()?;
117
118 log::trace!(
119 target: LOG_TARGET,
120 "mint: raw arguments: id: {:?}, beneficiary: {:?}, amount: {:?}",
121 id,
122 beneficiary,
123 amount
124 );
125
126 let call_result = pallet_assets::Pallet::<T>::mint(
127 RawOrigin::Signed(env.ext().address().clone()).into(),
128 id.into(),
129 beneficiary.into(),
130 amount,
131 );
132 handle_result!(call_result);
133 }
134 Burn => {
135 env.charge_weight(Weight::<T>::burn())?;
136
137 let (id, who, amount): (
138 <T as pallet_assets::Config>::AssetId,
139 T::AccountId,
140 T::Balance,
141 ) = env.read_as()?;
142
143 log::trace!(
144 target: LOG_TARGET,
145 "burn: raw arguments: id: {:?}, who: {:?}, amount: {:?}",
146 id,
147 who,
148 amount
149 );
150
151 let call_result = pallet_assets::Pallet::<T>::burn(
152 RawOrigin::Signed(env.ext().address().clone()).into(),
153 id.into(),
154 who.into(),
155 amount,
156 );
157 handle_result!(call_result);
158 }
159 ApproveTransfer => {
160 env.charge_weight(Weight::<T>::approve_transfer())?;
161
162 let (id, delegate, amount): (
163 <T as pallet_assets::Config>::AssetId,
164 T::AccountId,
165 T::Balance,
166 ) = env.read_as()?;
167
168 log::trace!(
169 target: LOG_TARGET,
170 "approve_transfer: raw arguments: id: {id:?}, delegate: {delegate:?}, amount: {amount:?}",
171 );
172
173 let call_result = pallet_assets::Pallet::<T>::approve_transfer(
174 RawOrigin::Signed(env.ext().address().clone()).into(),
175 id.into(),
176 delegate.into(),
177 amount,
178 );
179 handle_result!(call_result);
180 }
181 BalanceOf => {
182 env.charge_weight(T::DbWeight::get().reads(1_u64))?;
183
184 let (id, who): (<T as pallet_assets::Config>::AssetId, T::AccountId) =
185 env.read_as()?;
186
187 pallet_assets::Pallet::<T>::balance(id, who)
188 .using_encoded(|r| env.write(r, false, None))?;
189 }
190 TotalSupply => {
191 env.charge_weight(T::DbWeight::get().reads(1_u64))?;
192
193 let id: <T as pallet_assets::Config>::AssetId = env.read_as()?;
194
195 pallet_assets::Pallet::<T>::total_supply(id)
196 .using_encoded(|r| env.write(r, false, None))?;
197 }
198 Allowance => {
199 env.charge_weight(T::DbWeight::get().reads(1_u64))?;
200
201 let (id, owner, delegate): (
202 <T as pallet_assets::Config>::AssetId,
203 T::AccountId,
204 T::AccountId,
205 ) = env.read_as()?;
206
207 <pallet_assets::Pallet<T> as AllowanceInspect<T::AccountId>>::allowance(
208 id, &owner, &delegate,
209 )
210 .using_encoded(|r| env.write(r, false, None))?;
211 }
212 MetadataName => {
213 env.charge_weight(T::DbWeight::get().reads(1_u64))?;
214
215 let id: <T as pallet_assets::Config>::AssetId = env.read_as()?;
216
217 <pallet_assets::Pallet<T> as MetadataInspect<T::AccountId>>::name(id)
218 .using_encoded(|r| env.write(r, false, None))?;
219 }
220 MetadataSymbol => {
221 env.charge_weight(T::DbWeight::get().reads(1_u64))?;
222
223 let id: <T as pallet_assets::Config>::AssetId = env.read_as()?;
224
225 <pallet_assets::Pallet<T> as MetadataInspect<T::AccountId>>::symbol(id)
226 .using_encoded(|r| env.write(r, false, None))?;
227 }
228 MetadataDecimals => {
229 env.charge_weight(T::DbWeight::get().reads(1_u64))?;
230
231 let id: <T as pallet_assets::Config>::AssetId = env.read_as()?;
232
233 <pallet_assets::Pallet<T> as MetadataInspect<T::AccountId>>::decimals(id)
234 .using_encoded(|r| env.write(r, false, None))?;
235 }
236 MinimumBalance => {
237 env.charge_weight(T::DbWeight::get().reads(1_u64))?;
238
239 let id: <T as pallet_assets::Config>::AssetId = env.read_as()?;
240
241 <pallet_assets::Pallet<T> as Inspect<T::AccountId>>::minimum_balance(id)
242 .using_encoded(|r| env.write(r, false, None))?;
243 }
244 }
245
246 Ok(RetVal::Converging(Outcome::Success as u32))
247 }
248}