Skip to content

Commit

Permalink
256 audit pdm 006 add weight charging to chain extension calls (#280)
Browse files Browse the repository at this point in the history
* add placeholder weights to chain extensions

* update weights

* fix issues and generate weights

* fix tests

* remove trace, shorten allowance weight info
  • Loading branch information
ashneverdawn authored Jul 19, 2023
1 parent 0f6cbb5 commit 5b922a2
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 56 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"node",
"pallets/parachain-staking",
"pallets/vesting-manager",
"pallets/orml-currencies-allowance-extension",
"runtime/common",
"runtime/amplitude",
"runtime/foucoco",
Expand Down
70 changes: 64 additions & 6 deletions pallets/orml-currencies-allowance-extension/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,82 @@ use sp_std::prelude::*;

benchmarks! {
add_allowed_currencies {
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
let added_currencies: Vec<CurrencyOf<T>> = vec![native_currency_id];
}: _(RawOrigin::Root, added_currencies)
}: add_allowed_currencies(RawOrigin::Root, added_currencies)
verify {
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
assert_eq!(AllowedCurrencies::<T>::get(native_currency_id), Some(()));
}

remove_allowed_currencies {
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
AllowedCurrencies::<T>::insert(native_currency_id, ());

let removed_currencies: Vec<CurrencyOf<T>> = vec![native_currency_id];
}: _(RawOrigin::Root, removed_currencies)
}: remove_allowed_currencies(RawOrigin::Root, removed_currencies)
verify {
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
assert_eq!(AllowedCurrencies::<T>::get(native_currency_id), None);
}

approve {
//allow currency
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
AllowedCurrencies::<T>::insert(native_currency_id, ());

//initialize accounts
let owner: T::AccountId = account("Alice", 0, 0);
let delegate: T::AccountId = account("Bob", 0, 0);

//fund account
let amount = BalanceOf::<T>::from(1_000_000_000u32);
<orml_currencies::Pallet<T> as MultiCurrency<T::AccountId>>::deposit(native_currency_id, &owner, amount);

}: approve(RawOrigin::Signed(owner), native_currency_id, delegate, amount)
verify {
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
let owner: T::AccountId = account("Alice", 0, 0);
let delegate: T::AccountId = account("Bob", 0, 0);
let amount = BalanceOf::<T>::from(1_000_000_000u32);

//check that the allowance was updated
assert_eq!(TokenAllowance::<T>::allowance(native_currency_id, &owner, &delegate), amount);
}

transfer_from {
//allow currency
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
AllowedCurrencies::<T>::insert(native_currency_id, ());

//initialize accounts
let owner: T::AccountId = account("Alice", 0, 0);
let delegate: T::AccountId = account("Bob", 0, 0);
let destination: T::AccountId = account("Charlie", 0, 0);

//fund accounts
let amount = BalanceOf::<T>::from(1_000_000_000u32);
<orml_currencies::Pallet<T> as MultiCurrency<T::AccountId>>::deposit(native_currency_id, &owner, amount);
<orml_currencies::Pallet<T> as MultiCurrency<T::AccountId>>::deposit(native_currency_id, &delegate, amount);

//approve
TokenAllowance::<T>::do_approve_transfer(native_currency_id, &owner, &delegate, amount);

}: transfer_from(RawOrigin::Signed(delegate), native_currency_id, owner, destination, amount)
verify {
let native_currency_id = <T as orml_currencies::Config>::GetNativeCurrencyId::get();
let owner: T::AccountId = account("Alice", 0, 0);
let delegate: T::AccountId = account("Bob", 0, 0);
let destination: T::AccountId = account("Charlie", 0, 0);
let amount = BalanceOf::<T>::from(1_000_000_000u32);

//check that the allowance was updated
assert_eq!(TokenAllowance::<T>::allowance(native_currency_id, &owner, &delegate), BalanceOf::<T>::from(0u32));

//check that the balance was updated
let destination_balance = <orml_currencies::Pallet<T> as MultiCurrency<T::AccountId>>::free_balance(native_currency_id, &destination);
assert_eq!(destination_balance, amount);
}
}

impl_benchmark_test_suite!(TokenAllowance, crate::mock::ExtBuilder::build(), crate::mock::Test);
99 changes: 58 additions & 41 deletions pallets/orml-currencies-allowance-extension/src/default_weights.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,84 @@

//! Autogenerated weights for orml_currencies_allowance_extension
//! Autogenerated weights for `orml_currencies_allowance_extension`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-03-20, STEPS: `100`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! HOSTNAME: `MacBook-Pro`, CPU: `<UNKNOWN>`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
//! DATE: 2023-07-18, STEPS: `100`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `Hugos-MacBook-Pro.local`, CPU: `<UNKNOWN>`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("foucoco"), DB CACHE: 1024

// Executed Command:
// ./target/release/spacewalk-standalone
// ./target/release/pendulum-node
// benchmark
// pallet
// --chain=dev
// --chain=foucoco
// --pallet=orml-currencies-allowance-extension
// --extrinsic=*
// --steps=100
// --repeat=10
// --wasm-execution=compiled
// --output=pallets/default_weights.rs
// --template=./.maintain/frame-weight-template.hbs
// --output=pallets/orml-currencies-allowance-extension/src/default_weights.rs

#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(clippy::unnecessary_cast)]

use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use frame_support::{traits::Get, weights::Weight};
use sp_std::marker::PhantomData;

/// Weight functions needed for orml_currencies_allowance_extension.
pub trait WeightInfo {
fn add_allowed_currencies() -> Weight;
fn remove_allowed_currencies() -> Weight;
}

/// Weights for orml_currencies_allowance_extension using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// Storage: TokenAllowance AllowedCurrencies (r:0 w:1)
/// Weight functions for `orml_currencies_allowance_extension`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> crate::WeightInfo for WeightInfo<T> {
/// Storage: TokenAllowance AllowedCurrencies (r:0 w:1)
/// Proof Skipped: TokenAllowance AllowedCurrencies (max_values: None, max_size: None, mode: Measured)
fn add_allowed_currencies() -> Weight {
// Minimum execution time: 12_000 nanoseconds.
Weight::from_parts(14_000_000 as u64, 0)
.saturating_add(T::DbWeight::get().writes(1 as u64))
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 5_000_000 picoseconds.
Weight::from_parts(6_000_000, 0)
.saturating_add(Weight::from_parts(0, 0))
.saturating_add(T::DbWeight::get().writes(1))
}
// Storage: TokenAllowance AllowedCurrencies (r:0 w:1)
/// Storage: TokenAllowance AllowedCurrencies (r:0 w:1)
/// Proof Skipped: TokenAllowance AllowedCurrencies (max_values: None, max_size: None, mode: Measured)
fn remove_allowed_currencies() -> Weight {
// Minimum execution time: 31_000 nanoseconds.
Weight::from_parts(32_000_000 as u64, 0)
.saturating_add(T::DbWeight::get().writes(1 as u64))
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 5_000_000 picoseconds.
Weight::from_parts(6_000_000, 0)
.saturating_add(Weight::from_parts(0, 0))
.saturating_add(T::DbWeight::get().writes(1))
}
}

// For backwards compatibility and tests
impl WeightInfo for () {
// Storage: TokenAllowance AllowedCurrencies (r:0 w:1)
fn add_allowed_currencies() -> Weight {
// Minimum execution time: 12_000 nanoseconds.
Weight::from_parts(14_000_000 as u64, 0)
.saturating_add(RocksDbWeight::get().writes(1 as u64))
/// Storage: TokenAllowance AllowedCurrencies (r:1 w:0)
/// Proof Skipped: TokenAllowance AllowedCurrencies (max_values: None, max_size: None, mode: Measured)
/// Storage: TokenAllowance Approvals (r:1 w:1)
/// Proof Skipped: TokenAllowance Approvals (max_values: None, max_size: None, mode: Measured)
fn approve() -> Weight {
// Proof Size summary in bytes:
// Measured: `184`
// Estimated: `7298`
// Minimum execution time: 11_000_000 picoseconds.
Weight::from_parts(12_000_000, 0)
.saturating_add(Weight::from_parts(0, 7298))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
// Storage: TokenAllowance AllowedCurrencies (r:0 w:1)
fn remove_allowed_currencies() -> Weight {
// Minimum execution time: 31_000 nanoseconds.
Weight::from_parts(32_000_000 as u64, 0)
.saturating_add(RocksDbWeight::get().writes(1 as u64))
/// Storage: TokenAllowance AllowedCurrencies (r:1 w:0)
/// Proof Skipped: TokenAllowance AllowedCurrencies (max_values: None, max_size: None, mode: Measured)
/// Storage: TokenAllowance Approvals (r:1 w:1)
/// Proof Skipped: TokenAllowance Approvals (max_values: None, max_size: None, mode: Measured)
/// Storage: System Account (r:2 w:2)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn transfer_from() -> Weight {
// Proof Size summary in bytes:
// Measured: `561`
// Estimated: `14248`
// Minimum execution time: 29_000_000 picoseconds.
Weight::from_parts(30_000_000, 0)
.saturating_add(Weight::from_parts(0, 14248))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(3))
}
}
56 changes: 52 additions & 4 deletions pallets/orml-currencies-allowance-extension/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#[cfg(test)]
extern crate mocktopus;

pub use default_weights::{SubstrateWeight, WeightInfo};
use frame_support::{dispatch::DispatchResult, ensure};
use frame_support::{dispatch::DispatchResult, ensure, weights::Weight};

#[cfg(test)]
use mocktopus::macros::mockable;
use orml_traits::MultiCurrency;
Expand All @@ -16,7 +16,7 @@ use sp_std::{convert::TryInto, prelude::*, vec};
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;

mod default_weights;
pub mod default_weights;

#[cfg(test)]
mod mock;
Expand All @@ -36,10 +36,18 @@ pub(crate) type CurrencyOf<T> =
<T as frame_system::Config>::AccountId,
>>::CurrencyId;

/// Weight functions needed for orml_currencies_allowance_extension.
pub trait WeightInfo {
fn add_allowed_currencies() -> Weight;
fn remove_allowed_currencies() -> Weight;
fn approve() -> Weight;
fn transfer_from() -> Weight;
}

#[frame_support::pallet]
pub mod pallet {
use frame_support::{pallet_prelude::*, transactional};
use frame_system::{ensure_root, pallet_prelude::OriginFor};
use frame_system::{ensure_root, ensure_signed, pallet_prelude::OriginFor};

use super::*;

Expand Down Expand Up @@ -166,6 +174,46 @@ pub mod pallet {
Self::deposit_event(Event::AllowedCurrenciesDeleted { currencies });
Ok(())
}

/// Approve an amount for another account to spend on owner's behalf.
///
/// # Arguments
/// * `id` - the currency_id of the asset to approve
/// * `delegate` - the spender account to approve the asset for
/// * `amount` - the amount of the asset to approve
#[pallet::call_index(2)]
#[pallet::weight(<T as Config>::WeightInfo::approve())]
#[transactional]
pub fn approve(
origin: OriginFor<T>,
id: CurrencyOf<T>,
delegate: T::AccountId,
amount: BalanceOf<T>,
) -> DispatchResult {
let owner = ensure_signed(origin)?;
Self::do_approve_transfer(id, &owner, &delegate, amount)
}

/// Execute a pre-approved transfer from another account
///
/// # Arguments
/// * `id` - the currency_id of the asset to transfer
/// * `owner` - the owner account of the asset to transfer
/// * `destination` - the destination account to transfer to
/// * `amount` - the amount of the asset to transfer
#[pallet::call_index(3)]
#[pallet::weight(<T as Config>::WeightInfo::transfer_from())]
#[transactional]
pub fn transfer_from(
origin: OriginFor<T>,
id: CurrencyOf<T>,
owner: T::AccountId,
destination: T::AccountId,
amount: BalanceOf<T>,
) -> DispatchResult {
let delegate = ensure_signed(origin)?;
Self::do_transfer_approved(id, &owner, &delegate, &destination, amount)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion pallets/orml-currencies-allowance-extension/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl orml_currencies::Config for Test {

impl Config for Test {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type WeightInfo = token_allowance::default_weights::WeightInfo<Test>;
}

pub struct ExtBuilder;
Expand Down
2 changes: 2 additions & 0 deletions runtime/foucoco/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ runtime-benchmarks = [
"replace/runtime-benchmarks",
"stellar-relay/runtime-benchmarks",
"vault-registry/runtime-benchmarks",

"orml-currencies-allowance-extension/runtime-benchmarks",
]

try-runtime = [
Expand Down
Loading

0 comments on commit 5b922a2

Please sign in to comment.