Skip to content

Commit

Permalink
feat: add more functions to the fuzzing
Browse files Browse the repository at this point in the history
  • Loading branch information
shekohex committed Dec 20, 2024
1 parent 8fdcd5d commit 2ffe570
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 17 deletions.
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
pkgs.harper
pkgs.cargo-nextest
pkgs.cargo-tarpaulin
pkgs.lldb
];
# Environment variables
RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library";
Expand Down
196 changes: 179 additions & 17 deletions pallets/multi-asset-delegation/fuzzer/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@
use frame_support::traits::{Currency, GetCallName, Hooks, UnfilteredDispatchable};
use honggfuzz::fuzz;
use pallet_multi_asset_delegation::{mock::*, pallet as mad};
use rand::Rng;
use pallet_multi_asset_delegation::{mock::*, pallet as mad, types::*};
use rand::{seq::SliceRandom, Rng};

const MAX_ED_MULTIPLE: Balance = 10_000;
const MIN_ED_MULTIPLE: Balance = 10;

fn random_account_id<R: Rng>(rng: &mut R) -> AccountId {
rng.gen::<[u8; 32]>().into()
}

/// Grab random accounts.
fn random_signed_origin<R: Rng>(rng: &mut R) -> (RuntimeOrigin, AccountId) {
let acc: AccountId = rng.gen::<[u8; 32]>().into();
let acc = random_account_id(rng);
(RuntimeOrigin::signed(acc.clone()), acc)
}

Expand All @@ -41,6 +45,17 @@ fn random_ed_multiple<R: Rng>(rng: &mut R) -> Balance {
ExistentialDeposit::get() * multiple
}

fn random_asset<R: Rng>(rng: &mut R) -> Asset<AssetId> {
let asset_id = rng.gen_range(1..u128::MAX);
let is_evm = rng.gen_bool(0.5);
if is_evm {
let evm_address = rng.gen::<[u8; 20]>().into();
Asset::Erc20(evm_address)
} else {
Asset::Custom(asset_id)
}
}

fn fund_account<R: Rng>(rng: &mut R, account: &AccountId) {
let target_amount = random_ed_multiple(rng);
if let Some(top_up) = target_amount.checked_sub(Balances::free_balance(account)) {
Expand All @@ -50,26 +65,173 @@ fn fund_account<R: Rng>(rng: &mut R, account: &AccountId) {
}

fn random_call<R: Rng>(mut rng: &mut R) -> (mad::Call<Runtime>, RuntimeOrigin) {
let op = rng.gen::<usize>();
let op_count = <mad::Call<Runtime> as GetCallName>::get_call_names().len();
let op = <mad::Call<Runtime> as GetCallName>::get_call_names()
.choose(rng)
.cloned()
.unwrap();

match op % op_count {
0 => {
match op {
"join_operators" => {
// join_operators
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let bond_amount = random_ed_multiple(&mut rng);
(mad::Call::join_operators { bond_amount }, origin)
},
1 => {
"schedule_leave_operators" => {
// Schedule leave operators
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::schedule_leave_operators {}, origin)
},
"cancel_leave_operators" => {
// Cancel leave operators
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::cancel_leave_operators {}, origin)
},
"execute_leave_operators" => {
// Execute leave operators
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::execute_leave_operators {}, origin)
},
"operator_bond_more" => {
// Operator bond more
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let additional_bond = random_ed_multiple(&mut rng);
(mad::Call::operator_bond_more { additional_bond }, origin)
},
"schedule_operator_unstake" => {
// Schedule operator unstake
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let unstake_amount = random_ed_multiple(&mut rng);
(mad::Call::schedule_operator_unstake { unstake_amount }, origin)
},
"execute_operator_unstake" => {
// Execute operator unstake
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::execute_operator_unstake {}, origin)
},
"cancel_operator_unstake" => {
// Cancel operator unstake
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::cancel_operator_unstake {}, origin)
},
"go_offline" => {
// Go offline
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::go_offline {}, origin)
},
"go_online" => {
// Go online
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::go_online {}, origin)
},
"deposit" => {
// Deposit
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let asset_id = random_asset(&mut rng);
let amount = random_ed_multiple(&mut rng);
let evm_address =
if rng.gen_bool(0.5) { Some(rng.gen::<[u8; 20]>().into()) } else { None };
(mad::Call::deposit { asset_id, amount, evm_address }, origin)
},
"schedule_withdraw" => {
// Schedule withdraw
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let asset_id = random_asset(&mut rng);
let amount = random_ed_multiple(&mut rng);
(mad::Call::schedule_withdraw { asset_id, amount }, origin)
},
"execute_withdraw" => {
// Execute withdraw
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let evm_address =
if rng.gen_bool(0.5) { Some(rng.gen::<[u8; 20]>().into()) } else { None };
(mad::Call::execute_withdraw { evm_address }, origin)
},
"cancel_withdraw" => {
// Cancel withdraw
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let asset_id = random_asset(&mut rng);
let amount = random_ed_multiple(&mut rng);
(mad::Call::cancel_withdraw { asset_id, amount }, origin)
},
"delegate" => {
// Delegate
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let operator = random_account_id(&mut rng);
let asset_id = random_asset(&mut rng);
let amount = random_ed_multiple(&mut rng);
let blueprint_selection = {
let all = rng.gen_bool(0.5);
if all {
DelegatorBlueprintSelection::All
} else {
let count = rng.gen_range(1..MaxDelegatorBlueprints::get());
DelegatorBlueprintSelection::Fixed(
(0..count)
.map(|_| rng.gen::<u64>())
.collect::<Vec<_>>()
.try_into()
.unwrap(),
)
}
};
(mad::Call::delegate { operator, asset_id, amount, blueprint_selection }, origin)
},
"schedule_delegator_unstakes" => {
// Schedule delegator unstakes
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let operator = random_account_id(&mut rng);
let asset_id = random_asset(&mut rng);
let amount = random_ed_multiple(&mut rng);
(mad::Call::schedule_delegator_unstakes { operator, asset_id, amount }, origin)
},
"execute_delegator_unstake" => {
// Execute delegator unstake
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
(mad::Call::execute_delegator_unstake {}, origin)
},
"cancel_delegator_unstake" => {
// Cancel delegator unstake
let (origin, who) = random_signed_origin(&mut rng);
fund_account(&mut rng, &who);
let operator = random_account_id(&mut rng);
let asset_id = random_asset(&mut rng);
let amount = random_ed_multiple(&mut rng);
(mad::Call::cancel_delegator_unstake { operator, asset_id, amount }, origin)
},
"set_incentive_apy_and_cap" => {
// Set incentive APY and cap
let is_root = rng.gen_bool(0.5);
let (origin, who) = if is_root {
(RuntimeOrigin::root(), [0u8; 32].into())
} else {
random_signed_origin(&mut rng)
};
fund_account(&mut rng, &who);
let vault_id = rng.gen();
let apy = rng.gen::<u8>().into();
let cap = rng.gen_range(0..Balance::MAX);
(mad::Call::set_incentive_apy_and_cap { vault_id, apy, cap }, origin)
},
_ => {
// Do nothing for now.
(mad::Call::schedule_leave_operators {}, RuntimeOrigin::none())
unimplemented!("unknown call name: {}", op)
},
}
}
Expand Down Expand Up @@ -103,13 +265,13 @@ fn main() {
};

sp_tracing::trace!(
"iteration {}, call {:?}, origin {:?}, outcome: {:?}, so far {} ok {} err",
iteration,
call,
origin,
outcome,
ok,
err,
%iteration,
?call,
?origin,
?outcome,
%ok,
%err,
"fuzzed call"
);

// execute sanity checks at a fixed interval, possibly on every block.
Expand Down
2 changes: 2 additions & 0 deletions pallets/multi-asset-delegation/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub type Nonce = u32;
pub type AssetId = u128;
pub type BlockNumber = BlockNumberFor<Runtime>;

pub use tangle_primitives::services::Asset;

#[frame_support::derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for Runtime {
type BaseCallFilter = frame_support::traits::Everything;
Expand Down

0 comments on commit 2ffe570

Please sign in to comment.