diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index 3f462a55..4ad921dc 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -33,6 +33,8 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] std = [ diff --git a/pallets/api/src/fungibles/benchmarking.rs b/pallets/api/src/fungibles/benchmarking.rs new file mode 100644 index 00000000..7c0ad6ce --- /dev/null +++ b/pallets/api/src/fungibles/benchmarking.rs @@ -0,0 +1,60 @@ +//! Benchmarking setup for pallet-cards + +use super::{AccountIdOf, AssetIdOf, Assets, AssetsInstanceOf, BalanceOf, Call, Config, Pallet}; +use frame_benchmarking::{account, v2::*}; +use frame_support::{ + assert_ok, + traits::{ + fungibles::{ + approvals::{Inspect as ApprovalInspect, Mutate}, + Create, Inspect, + }, + Currency, + }, +}; +use frame_system::RawOrigin; +use sp_runtime::traits::Zero; + +const SEED: u32 = 1; + +#[benchmarks( + where + > as Inspect<::AccountId>>::AssetId: Zero, +)] +mod benchmarks { + use super::*; + + // The worst case scenario is when the allowance is set to a value which is lower than the + // current allowance. + #[benchmark] + fn approve() -> Result<(), BenchmarkError> { + let asset = AssetIdOf::::zero(); + let decreased_value = >::from(50u32); + let min_balance = >::from(1u32); + let owner: AccountIdOf = account("Alice", 0, SEED); + let spender: AccountIdOf = account("Bob", 0, SEED); + let value = >::from(100u32); + T::Currency::make_free_balance_be(&owner, 100u32.into()); + assert_ok!( as Create>>::create( + asset.clone().into(), + owner.clone(), + true, + min_balance + )); + assert_ok!( as Mutate>>::approve( + asset.clone(), + &owner, + &spender, + value + )); + + #[extrinsic_call] + _(RawOrigin::Signed(owner.clone()), asset.clone(), spender.clone(), decreased_value); + + assert_eq!(Assets::::allowance(asset, &owner, &spender), decreased_value); + + Ok(()) + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/pallets/api/src/fungibles/mod.rs b/pallets/api/src/fungibles/mod.rs index e0213230..3c298475 100644 --- a/pallets/api/src/fungibles/mod.rs +++ b/pallets/api/src/fungibles/mod.rs @@ -3,6 +3,8 @@ /// consistent API that adheres to standards in the smart contract space. pub use pallet::*; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; #[cfg(test)] mod tests; @@ -125,7 +127,7 @@ pub mod pallet { /// # Returns /// Returns `Ok(())` if successful, or an error if the approval fails. #[pallet::call_index(2)] - #[pallet::weight(T::DbWeight::get().reads(2) + AssetsWeightInfo::::cancel_approval() + AssetsWeightInfo::::approve_transfer())] + #[pallet::weight(T::DbWeight::get().reads(1) + AssetsWeightInfo::::cancel_approval() + AssetsWeightInfo::::approve_transfer())] pub fn approve( origin: OriginFor, id: AssetIdOf, @@ -133,6 +135,7 @@ pub mod pallet { mut value: BalanceOf, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone()) + // To have the caller pay some fees. .map_err(|e| e.with_weight(T::DbWeight::get().reads(1)))?; let current_allowance = Assets::::allowance(id.clone(), &who, &spender); let spender = T::Lookup::unlookup(spender); @@ -146,7 +149,7 @@ pub mod pallet { value.saturating_reduce(current_allowance); Assets::::approve_transfer(origin, id, spender, value).map_err(|e| { e.with_weight( - T::DbWeight::get().reads(2) + AssetsWeightInfo::::approve_transfer(), + T::DbWeight::get().reads(1) + AssetsWeightInfo::::approve_transfer(), ) })?; } else {