diff --git a/frame/bonded-finance/src/benchmarks.rs b/frame/bonded-finance/src/benchmarks.rs index 75ed776baf3..09b991481ad 100644 --- a/frame/bonded-finance/src/benchmarks.rs +++ b/frame/bonded-finance/src/benchmarks.rs @@ -6,7 +6,7 @@ use crate::{AssetIdOf, BalanceOf, BlockNumberOf, BondOfferOf, Call, Config, Pall use codec::Decode; use composable_support::validation::Validated; use composable_traits::bonded_finance::{BondDuration, BondOffer, BondOfferReward}; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_support::{ dispatch::UnfilteredDispatchable, traits::{fungible::Mutate as _, fungibles::Mutate as _}, @@ -83,9 +83,10 @@ benchmarks! { where_clause { where BalanceOf: From } + offer { let [bond_asset, reward_asset] = assets::(); - let caller: T::AccountId = whitelisted_caller(); + let caller: T::AccountId = account("caller", 0, 0xCAFEBABE); initial_mint::(bond_asset, &caller, reward_asset); let bond_offer = bond_offer::(bond_asset, reward_asset); let validated_bond_offer = Validated::new(bond_offer).unwrap(); @@ -93,7 +94,7 @@ benchmarks! { bond { let [bond_asset, reward_asset] = assets::(); - let caller: T::AccountId = whitelisted_caller(); + let caller: T::AccountId = account("caller", 0, 0xCAFEBABE); initial_mint::(bond_asset, &caller, reward_asset); let bond_offer = bond_offer::(bond_asset, reward_asset); let nb_of_bonds = bond_offer.nb_of_bonds; @@ -103,7 +104,7 @@ benchmarks! { cancel { let [bond_asset, reward_asset] = assets::(); - let caller: T::AccountId = whitelisted_caller(); + let caller: T::AccountId = account("caller", 0, 0xCAFEBABE); initial_mint::(bond_asset, &caller, reward_asset); let bond_offer = bond_offer::(bond_asset, reward_asset); let nb_of_bonds = bond_offer.nb_of_bonds; diff --git a/frame/bonded-finance/src/tests.rs b/frame/bonded-finance/src/tests.rs index e94c28edb7c..060cbc067eb 100644 --- a/frame/bonded-finance/src/tests.rs +++ b/frame/bonded-finance/src/tests.rs @@ -15,8 +15,6 @@ use frame_support::{ use mock::{Event, *}; use proptest::prelude::*; -#[test] - prop_compose! { // NOTE(hussein-aitlahcen): we use u32 before casting to avoid overflows /// Pseudo random valid simple offer diff --git a/frame/mosaic/src/benchmarking.rs b/frame/mosaic/src/benchmarking.rs index 2de5886e695..f44aff65a3f 100644 --- a/frame/mosaic/src/benchmarking.rs +++ b/frame/mosaic/src/benchmarking.rs @@ -8,6 +8,7 @@ use frame_support::{ traits::{fungibles::Mutate, Get}, }; use frame_system::RawOrigin; +const MIN_TRANSFER_SIZE: u128 = 1_000_000_000_000; const MAX_TRANSFER_SIZE: u128 = 100_000_000_000_000_000; const BUDGET_AMOUNT: u128 = 100_000_000_000_000_000_000; const TRANSFER_AMOUNT: u128 = 100_000_000_000_000; @@ -36,6 +37,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; @@ -55,6 +57,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer).into(), network_id.clone(), network_info)); @@ -82,6 +85,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); @@ -110,6 +114,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); @@ -139,6 +144,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); @@ -174,6 +180,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); @@ -209,6 +216,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); @@ -244,6 +252,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; diff --git a/frame/mosaic/src/lib.rs b/frame/mosaic/src/lib.rs index de73e6bc555..2c4b5a8dcba 100644 --- a/frame/mosaic/src/lib.rs +++ b/frame/mosaic/src/lib.rs @@ -129,6 +129,7 @@ pub mod pallet { #[derive(Clone, Debug, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq)] pub struct NetworkInfo { pub enabled: bool, + pub min_transfer_size: Balance, pub max_transfer_size: Balance, } @@ -341,6 +342,7 @@ pub mod pallet { NoStaleTransactions, InsufficientBudget, ExceedsMaxTransferSize, + BelowMinTransferSize, NoClaimableTx, TxStillLocked, NoOutgoingTx, @@ -462,6 +464,7 @@ pub mod pallet { NetworkInfos::::get(network_id.clone()).ok_or(Error::::UnsupportedNetwork)?; ensure!(network_info.enabled, Error::::NetworkDisabled); ensure!(network_info.max_transfer_size >= amount, Error::::ExceedsMaxTransferSize); + ensure!(network_info.min_transfer_size <= amount, Error::::BelowMinTransferSize); T::Assets::transfer( asset_id, diff --git a/frame/mosaic/src/tests.rs b/frame/mosaic/src/tests.rs index d02be73ab00..43aabf96ee6 100644 --- a/frame/mosaic/src/tests.rs +++ b/frame/mosaic/src/tests.rs @@ -1,4 +1,3 @@ -use crate::validation::{ValidTTL, ValidTimeLockPeriod}; /// TODO /// /// 1. Test each extrinsic @@ -223,7 +222,8 @@ mod set_network { #[test] fn relayer_can_set_network() { let network_id = 3; - let network_info = NetworkInfo { enabled: false, max_transfer_size: 100000 }; + let network_info = + NetworkInfo { enabled: false, min_transfer_size: 1, max_transfer_size: 100000 }; new_test_ext().execute_with(|| { assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -235,7 +235,8 @@ mod set_network { #[test] fn root_cannot_set_network() { let network_id = 3; - let network_info = NetworkInfo { enabled: false, max_transfer_size: 100000 }; + let network_info = + NetworkInfo { enabled: false, min_transfer_size: 1, max_transfer_size: 100000 }; new_test_ext().execute_with(|| { assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -249,7 +250,8 @@ mod set_network { #[test] fn none_cannot_set_network() { let network_id = 3; - let network_info = NetworkInfo { enabled: false, max_transfer_size: 100000 }; + let network_info = + NetworkInfo { enabled: false, min_transfer_size: 1, max_transfer_size: 100000 }; new_test_ext().execute_with(|| { assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -391,7 +393,7 @@ fn initialize() { assert_ok!(Mosaic::set_network( Origin::relayer(), 1, - NetworkInfo { enabled: true, max_transfer_size: 100000 }, + NetworkInfo { enabled: true, min_transfer_size: 1, max_transfer_size: 100000 }, )); assert_ok!(Mosaic::set_budget(Origin::root(), 1, BUDGET, BudgetPenaltyDecayer::linear(10))); assert_ok!(Mosaic::update_asset_mapping( @@ -617,10 +619,11 @@ mod timelocked_mint { fn can_mint_up_to_the_penalised_budget( account_a in account_id(), decay in 1..100u128, // todo, - max_transfer_size in 1..10_000_000u128, + min_transfer_size in 1..10_000_000u128, + max_transfer_size in 10_000_000u128..100_000_000u128, asset_id in 1..100u128, network_id in 1..100u32, - remote_asset_id in any::(), + remote_asset_id in any::(), start_block in 1..10_000u64, (budget, first_part, second_part) in budget_with_split(), ) { @@ -632,7 +635,7 @@ mod timelocked_mint { prop_assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, ), "relayer may set network info"); prop_assert_ok!(Mosaic::set_budget(Origin::root(), asset_id, budget, BudgetPenaltyDecayer::linear(decay)), "root may set budget"); prop_assert_ok!(Mosaic::update_asset_mapping(Origin::root(), asset_id, network_id, Some(remote_asset_id))); @@ -654,10 +657,11 @@ mod timelocked_mint { fn cannot_mint_more_than_the_penalised_budget( account_a in account_id(), decay in 1..100u128, // todo, - max_transfer_size in 1..10_000_000u128, + min_transfer_size in 1..10_000_000u128, + max_transfer_size in 10_000_000u128..100_000_000u128, asset_id in 1..100u128, network_id in 1..100u32, - remote_asset_id in any::(), + remote_asset_id in any::(), start_block in 1..10_000u64, (budget, first_part, second_part) in budget_with_split(), ) { @@ -669,7 +673,7 @@ mod timelocked_mint { prop_assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, ), "relayer may set network info"); prop_assert_ok!(Mosaic::set_budget(Origin::root(), asset_id, budget, BudgetPenaltyDecayer::linear(decay)), "root may set budget"); prop_assert_ok!(Mosaic::update_asset_mapping(Origin::root(), asset_id, network_id, Some(remote_asset_id))); @@ -692,10 +696,11 @@ mod timelocked_mint { fn should_be_able_to_mint_again_after_waiting_for_penalty_to_decay( account_a in account_id(), decay_factor in 1..100u128, // todo, - max_transfer_size in 1..10_000_000u128, + min_transfer_size in 1..10_000_000u128, + max_transfer_size in 10_000_000u128..100_000_000u128, asset_id in 1..100u128, network_id in 1..100u32, - remote_asset_id in any::(), + remote_asset_id in any::(), start_block in 1..10_000u64, (budget, first_part, second_part) in budget_with_split(), iteration_count in 2..10u64, @@ -713,7 +718,7 @@ mod timelocked_mint { prop_assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, ), "relayer may set network info"); prop_assert_ok!(Mosaic::set_budget(Origin::root(), asset_id, budget, budget_penalty_decayer.clone()), "root may set budget"); prop_assert_ok!(Mosaic::update_asset_mapping(Origin::root(), asset_id, network_id, Some(remote_asset_id))); @@ -1031,9 +1036,57 @@ mod transfer_to { }) } + #[test] + fn transfer_to_below_min_transfer_size() { + ExtBuilder { balances: Default::default() }.build().execute_with(|| { + let min_transfer_size = 1000; + let max_transfer_size = 100000; + + assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); + + let network_id = 1; + assert_ok!(Mosaic::set_network( + Origin::relayer(), + network_id, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, + )); + + let asset_id: u128 = 1; + assert_ok!(Mosaic::set_budget( + Origin::root(), + asset_id, + 10000, + BudgetPenaltyDecayer::linear(10) + )); + + let remote_asset_id = [0xFFu8; 20]; + assert_ok!(Mosaic::update_asset_mapping( + Origin::root(), + asset_id, + network_id, + Some(remote_asset_id) + )); + + let amount = min_transfer_size - 1; + assert_ok!(Tokens::mint_into(asset_id, &ALICE, amount)); + assert_noop!( + Mosaic::transfer_to( + Origin::signed(ALICE), + network_id, + asset_id, + [0; 20], + amount, + true + ), + Error::::BelowMinTransferSize + ); + }) + } + #[test] fn transfer_to_exceeds_max_transfer_size() { ExtBuilder { balances: Default::default() }.build().execute_with(|| { + let min_transfer_size = 1; let max_transfer_size = 100000; assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -1042,7 +1095,7 @@ mod transfer_to { assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, )); let asset_id: u128 = 1; @@ -1114,7 +1167,7 @@ mod transfer_to { assert_ok!(Mosaic::set_network( Origin::relayer(), 1, - NetworkInfo { enabled: true, max_transfer_size: 100000 }, + NetworkInfo { enabled: true, min_transfer_size: 1, max_transfer_size: 100000 }, )); // We don't register the asset @@ -1268,7 +1321,6 @@ mod test_validation { use super::*; use composable_support::validation::Validate; use frame_support::assert_ok; - use mock::Test; use validation::{ValidTTL, ValidTimeLockPeriod}; #[test] diff --git a/frame/vesting/src/benchmarks.rs b/frame/vesting/src/benchmarks.rs index e5dc54270ea..6ec384f03b0 100644 --- a/frame/vesting/src/benchmarks.rs +++ b/frame/vesting/src/benchmarks.rs @@ -90,7 +90,7 @@ benchmarks! { vested_transfer { let asset_id = asset::(); - let from: T::AccountId = zero_account::(); + let from: T::AccountId = create_account::("from", 0xCAFEBABE); fund_account::(&from, asset_id.clone(), FUNDING.into()); let dest = T::Lookup::unlookup(create_account::("dest", 1)); let per_period = T::MinVestedTransfer::get(); diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 6ca8cb20ad6..471f736ab55 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -143,6 +143,8 @@ pub mod module { AmountLow, /// Failed because the maximum vesting schedules was exceeded MaxVestingSchedulesExceeded, + /// Trying to vest to ourselves + TryingToSelfVest, } #[pallet::event] @@ -307,6 +309,8 @@ impl VestedTransfer for Pallet { to: &Self::AccountId, schedule: VestingSchedule, ) -> frame_support::dispatch::DispatchResult { + ensure!(from != to, Error::::TryingToSelfVest); + let schedule_amount = ensure_valid_vesting_schedule::(&schedule)?; let total_amount = Self::locked_balance(to, asset) diff --git a/frame/vesting/src/tests.rs b/frame/vesting/src/tests.rs index fd29986ba81..fef688539cb 100644 --- a/frame/vesting/src/tests.rs +++ b/frame/vesting/src/tests.rs @@ -105,6 +105,29 @@ fn vesting_from_chain_spec_works() { }); } +#[test] +fn vested_transfer_self_vest_ko() { + ExtBuilder::build().execute_with(|| { + System::set_block_number(1); + + let schedule = VestingSchedule { + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, + period_count: 1_u32, + per_period: 100_u64, + }; + assert_noop!( + Vesting::vested_transfer( + Origin::root(), + ALICE, + ALICE, + MockCurrencyId::BTC, + schedule.clone(), + ), + Error::::TryingToSelfVest + ); + }); +} + #[test] fn vested_transfer_works() { ExtBuilder::build().execute_with(|| {