Newer
Older
// Now try to create a crowdloan campaign
let para = new_para();
let e = Error::<Test>::InvalidParaId;
assert_noop!(Crowdloan::create(Origin::signed(1), 1.into(), 1000, 1, 4, 9, None), e);
// Cannot create a crowdloan with bad lease periods
let e = Error::<Test>::LastPeriodBeforeFirstPeriod;
assert_noop!(Crowdloan::create(Origin::signed(1), para, 1000, 4, 1, 9, None), e);
let e = Error::<Test>::LastPeriodTooFarInFuture;
assert_noop!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 5, 9, None), e);
// Cannot create a crowdloan without some deposit funds
assert_ok!(TestRegistrar::<Test>::register(1337, ParaId::from(1234), Default::default(), Default::default()));
let e = BalancesError::<Test, _>::InsufficientBalance;
assert_noop!(Crowdloan::create(Origin::signed(1337), ParaId::from(1234), 1000, 1, 3, 9, None), e);
// Cannot create a crowdloan with nonsense end date
// This crowdloan would end in lease period 2, but is bidding for some slot that starts in lease period 1.
assert_noop!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 4, 41, None), Error::<Test>::EndTooFarInFuture);
});
}
#[test]
fn contribute_works() {
new_test_ext().execute_with(|| {
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 4, 9, None));
assert_eq!(Crowdloan::contribution_get(u32::from(para), &1).0, 0);
assert_ok!(Crowdloan::contribute(Origin::signed(1), para, 49, None));
// User 1 has spent some funds to do this, transfer fees **are** taken
// Contributions are stored in the trie
assert_eq!(Crowdloan::contribution_get(u32::from(para), &1).0, 49);
// Contributions appear in free balance of crowdloan
assert_eq!(Balances::free_balance(Crowdloan::fund_account_id(para)), 49);
assert_eq!(Crowdloan::new_raise(), vec![para]);
let fund = Crowdloan::funds(para).unwrap();
// Last contribution time recorded
assert_eq!(fund.last_contribution, LastContribution::PreEnding(0));
assert_eq!(fund.raised, 49);
});
}
#[test]
fn contribute_with_verifier_works() {
new_test_ext().execute_with(|| {
let pubkey = crypto::create_ed25519_pubkey(b"//verifier".to_vec());
// Set up a crowdloan
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 4, 9, Some(pubkey.clone())));
// No contributions yet
assert_eq!(Crowdloan::contribution_get(u32::from(para), &1).0, 0);
assert_noop!(Crowdloan::contribute(Origin::signed(1), para, 49, None), Error::<Test>::InvalidSignature);
let payload = (0u32, 1u64, 0u64, 49u64);
let valid_signature = crypto::create_ed25519_signature(&payload.encode(), pubkey.clone());
let invalid_signature = MultiSignature::default();
// Invalid signature
assert_noop!(Crowdloan::contribute(Origin::signed(1), para, 49, Some(invalid_signature)), Error::<Test>::InvalidSignature);
// Valid signature wrong parameter
assert_noop!(Crowdloan::contribute(Origin::signed(1), para, 50, Some(valid_signature.clone())), Error::<Test>::InvalidSignature);
assert_noop!(Crowdloan::contribute(Origin::signed(2), para, 49, Some(valid_signature.clone())), Error::<Test>::InvalidSignature);
assert_ok!(Crowdloan::contribute(Origin::signed(1), para, 49, Some(valid_signature.clone())));
// Reuse valid signature
assert_noop!(Crowdloan::contribute(Origin::signed(1), para, 49, Some(valid_signature)), Error::<Test>::InvalidSignature);
let payload_2 = (0u32, 1u64, 49u64, 10u64);
let valid_signature_2 = crypto::create_ed25519_signature(&payload_2.encode(), pubkey);
// New valid signature
assert_ok!(Crowdloan::contribute(Origin::signed(1), para, 10, Some(valid_signature_2)));
// Contributions appear in free balance of crowdloan
assert_eq!(Balances::free_balance(Crowdloan::fund_account_id(para)), 59);
// Contribution amount is correct
let fund = Crowdloan::funds(para).unwrap();
assert_eq!(fund.raised, 59);
});
}
#[test]
fn contribute_handles_basic_errors() {
new_test_ext().execute_with(|| {
// Cannot contribute to non-existing fund
assert_noop!(Crowdloan::contribute(Origin::signed(1), para, 49, None), Error::<Test>::InvalidParaId);
// Cannot contribute below minimum contribution
assert_noop!(Crowdloan::contribute(Origin::signed(1), para, 9, None), Error::<Test>::ContributionTooSmall);
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 4, 9, None));
assert_ok!(Crowdloan::contribute(Origin::signed(1), para, 101, None));
// Cannot contribute past the limit
assert_noop!(Crowdloan::contribute(Origin::signed(2), para, 900, None), Error::<Test>::CapExceeded);
// Move past end date
run_to_block(10);
// Cannot contribute to ended fund
assert_noop!(Crowdloan::contribute(Origin::signed(1), para, 49, None), Error::<Test>::ContributionPeriodOver);
// If a crowdloan has already won, it should not allow contributions.
let para_2 = new_para();
assert_ok!(Crowdloan::create(Origin::signed(1), para_2, 1000, 1, 4, 40, None));
// Emulate a win by leasing out and putting a deposit. Slots pallet would normally do this.
let crowdloan_account = Crowdloan::fund_account_id(para_2);
make_winner(para_2, crowdloan_account);
assert_noop!(Crowdloan::contribute(Origin::signed(1), para_2, 49, None), Error::<Test>::BidOrLeaseActive);
// Move past lease period 1, should not be allowed to have further contributions with a crowdloan
// that has starting period 1.
let para_3 = new_para();
assert_ok!(Crowdloan::create(Origin::signed(1), para_3, 1000, 1, 4, 40, None));
run_to_block(40);
assert_eq!(TestAuctioneer::lease_period_index(), 2);
assert_noop!(Crowdloan::contribute(Origin::signed(1), para_3, 49, None), Error::<Test>::ContributionPeriodOver);
new_test_ext().execute_with(|| {
let first_period = 1;
let last_period = 4;
assert_ok!(TestAuctioneer::new_auction(5, 0));
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, first_period, last_period, 9, None));
let bidder = Crowdloan::fund_account_id(para);
run_to_block(1);
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
run_to_block(3);
assert_ok!(Crowdloan::contribute(Origin::signed(3), para, 150, None));
run_to_block(5);
assert_ok!(Crowdloan::contribute(Origin::signed(4), para, 200, None));
run_to_block(8);
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 250, None));
BidPlaced { height: 5, amount: 250, bidder, para, first_period, last_period },
BidPlaced { height: 6, amount: 450, bidder, para, first_period, last_period },
BidPlaced { height: 9, amount: 700, bidder, para, first_period, last_period },
new_test_ext().execute_with(|| {
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
assert_ok!(Crowdloan::contribute(Origin::signed(3), para, 50, None));
let account_id = Crowdloan::fund_account_id(para);
// para has no reserved funds, indicating it did not win the auction.
assert_eq!(Balances::reserved_balance(&account_id), 0);
// but there's still the funds in its balance.
assert_eq!(Balances::free_balance(&account_id), 150);
assert_eq!(Balances::free_balance(2), 1900);
assert_eq!(Balances::free_balance(3), 2950);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 2, para));
assert_eq!(Balances::free_balance(&account_id), 50);
assert_eq!(Balances::free_balance(2), 2000);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 3, para));
assert_eq!(Balances::free_balance(&account_id), 0);
assert_eq!(Balances::free_balance(3), 3000);
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
#[test]
fn withdraw_cannot_be_griefed() {
new_test_ext().execute_with(|| {
let para = new_para();
// Set up a crowdloan
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
run_to_block(10);
let account_id = Crowdloan::fund_account_id(para);
// user sends the crowdloan funds trying to make an accounting error
assert_ok!(Balances::transfer(Origin::signed(1), account_id, 10));
// overfunded now
assert_eq!(Balances::free_balance(&account_id), 110);
assert_eq!(Balances::free_balance(2), 1900);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 2, para));
assert_eq!(Balances::free_balance(2), 2000);
// Some funds are left over
assert_eq!(Balances::free_balance(&account_id), 10);
// They wil be orphaned at the end
assert_ok!(Crowdloan::dissolve(Origin::signed(1), para));
assert_eq!(Balances::free_balance(&account_id), 0);
});
}
fn dissolving_failed_without_contributions_works() {
new_test_ext().execute_with(|| {
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
assert_noop!(Crowdloan::dissolve(Origin::signed(2), para), Error::<Test>::NotReadyToDissolve);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 2, para));
assert_ok!(Crowdloan::dissolve(Origin::signed(1), para));
assert_eq!(Balances::free_balance(1), 1000);
fn dissolving_failed_with_contributions_works() {
new_test_ext().execute_with(|| {
let para = new_para();
let issuance = Balances::total_issuance();
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
assert_ok!(Crowdloan::contribute(Origin::signed(3), para, 50, None));
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 2, para));
run_to_block(14);
assert_noop!(Crowdloan::dissolve(Origin::signed(1), para), Error::<Test>::NotReadyToDissolve);
run_to_block(15);
assert_ok!(Crowdloan::dissolve(Origin::signed(1), para));
assert_eq!(Balances::free_balance(1), 1000);
assert_eq!(Balances::total_issuance(), issuance - 50);
fn withdraw_from_finished_works() {
new_test_ext().execute_with(|| {
let para = new_para();
let account_id = Crowdloan::fund_account_id(para);
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None));
// Fund crowdloans.
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
assert_ok!(Crowdloan::contribute(Origin::signed(3), para, 50, None));
// simulate the reserving of para's funds. this actually happens in the Slots pallet.
assert_ok!(Balances::reserve(&account_id, 150));
run_to_block(19);
assert_noop!(Crowdloan::withdraw(Origin::signed(2), 2, para), Error::<Test>::BidOrLeaseActive);
run_to_block(20);
// simulate the unreserving of para's funds, now that the lease expired. this actually
// happens in the Slots pallet.
Balances::unreserve(&account_id, 150);
// para has no reserved funds, indicating it did ot win the auction.
assert_eq!(Balances::reserved_balance(&account_id), 0);
// but there's still the funds in its balance.
assert_eq!(Balances::free_balance(&account_id), 150);
assert_eq!(Balances::free_balance(2), 1900);
assert_eq!(Balances::free_balance(3), 2950);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 2, para));
assert_eq!(Balances::free_balance(&account_id), 50);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 3, para));
assert_eq!(Balances::free_balance(&account_id), 0);
fn dissolving_finished_without_contributions_works() {
new_test_ext().execute_with(|| {
// Set up a crowdloan
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None));
// Fund crowdloans.
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
// during this time the funds get reserved and unreserved.
run_to_block(20);
assert_noop!(Crowdloan::dissolve(Origin::signed(2), para), Error::<Test>::NotReadyToDissolve);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 2, para));
// Only crowdloan creator can dissolve when raised is zero.
assert_noop!(Crowdloan::dissolve(Origin::signed(2), para), Error::<Test>::NotReadyToDissolve);
assert_ok!(Crowdloan::dissolve(Origin::signed(1), para));
assert_eq!(Balances::free_balance(1), 1000);
fn dissolving_finished_with_contributions_works() {
new_test_ext().execute_with(|| {
let para = new_para();
let issuance = Balances::total_issuance();
assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None));
assert_ok!(Crowdloan::contribute(Origin::signed(3), para, 50, None));
run_to_block(20);
assert_ok!(Crowdloan::withdraw(Origin::signed(2), 2, para));
run_to_block(24);
assert_noop!(Crowdloan::dissolve(Origin::signed(1), para), Error::<Test>::NotReadyToDissolve);
run_to_block(25);
assert_ok!(Crowdloan::dissolve(Origin::signed(1), para));
assert_eq!(Balances::free_balance(1), 1000);
assert_eq!(Balances::total_issuance(), issuance - 50);
new_test_ext().execute_with(|| {
let para_1 = new_para();
let para_2 = new_para();
// Set up crowdloans
assert_ok!(Crowdloan::create(Origin::signed(1), para_1, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::create(Origin::signed(1), para_2, 1000, 1, 1, 9, None));
// Different contributions
assert_ok!(Crowdloan::contribute(Origin::signed(2), para_1, 100, None));
assert_ok!(Crowdloan::contribute(Origin::signed(3), para_2, 50, None));
// Original state
assert_eq!(Funds::<Test>::get(para_1).unwrap().raised, 100);
assert_eq!(Funds::<Test>::get(para_2).unwrap().raised, 50);
// Swap
Crowdloan::on_swap(para_1, para_2);
// Final state
assert_eq!(Funds::<Test>::get(para_2).unwrap().raised, 100);
assert_eq!(Funds::<Test>::get(para_1).unwrap().raised, 50);
fn cannot_create_fund_when_already_active() {
new_test_ext().execute_with(|| {
assert_ok!(Crowdloan::create(Origin::signed(1), para_1, 1000, 1, 1, 9, None));
// Cannot create a fund again
assert_noop!(
Crowdloan::create(Origin::signed(1), para_1, 1000, 1, 1, 9, None),
Error::<Test>::FundNotEnded,
);
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
#[test]
fn edit_works() {
new_test_ext().execute_with(|| {
let para_1 = new_para();
assert_ok!(Crowdloan::create(Origin::signed(1), para_1, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::contribute(Origin::signed(2), para_1, 100, None));
let old_crowdloan = Crowdloan::funds(para_1).unwrap();
assert_ok!(Crowdloan::edit(Origin::root(), para_1, 1234, 2, 3, 4, None));
let new_crowdloan = Crowdloan::funds(para_1).unwrap();
// Some things stay the same
assert_eq!(old_crowdloan.retiring, new_crowdloan.retiring);
assert_eq!(old_crowdloan.depositor, new_crowdloan.depositor);
assert_eq!(old_crowdloan.deposit, new_crowdloan.deposit);
assert_eq!(old_crowdloan.raised, new_crowdloan.raised);
// Some things change
assert!(old_crowdloan.cap != new_crowdloan.cap);
assert!(old_crowdloan.first_period != new_crowdloan.first_period);
assert!(old_crowdloan.last_period != new_crowdloan.last_period);
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
#[test]
fn add_memo_works() {
new_test_ext().execute_with(|| {
let para_1 = new_para();
assert_ok!(Crowdloan::create(Origin::signed(1), para_1, 1000, 1, 1, 9, None));
// Cant add a memo before you have contributed.
assert_noop!(
Crowdloan::add_memo(Origin::signed(1), para_1, b"hello, world".to_vec()),
Error::<Test>::NoContributions,
);
// Make a contribution. Initially no memo.
assert_ok!(Crowdloan::contribute(Origin::signed(1), para_1, 100, None));
assert_eq!(Crowdloan::contribution_get(0u32, &1), (100, vec![]));
// Can't place a memo that is too large.
assert_noop!(
Crowdloan::add_memo(Origin::signed(1), para_1, vec![123; 123]),
Error::<Test>::MemoTooLarge,
);
// Adding a memo to an existing contribution works
assert_ok!(Crowdloan::add_memo(Origin::signed(1), para_1, b"hello, world".to_vec()));
assert_eq!(Crowdloan::contribution_get(0u32, &1), (100, b"hello, world".to_vec()));
// Can contribute again and data persists
assert_ok!(Crowdloan::contribute(Origin::signed(1), para_1, 100, None));
assert_eq!(Crowdloan::contribution_get(0u32, &1), (200, b"hello, world".to_vec()));
});
}
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking {
use super::{*, Module as Crowdloan};
use frame_system::RawOrigin;
use frame_support::{
assert_ok,
traits::OnInitialize,
};
use sp_runtime::traits::{Bounded, CheckedSub};
use frame_benchmarking::{benchmarks, whitelisted_caller, account, impl_benchmark_test_suite};
fn assert_last_event<T: Config>(generic_event: <T as Config>::Event) {
Shaun Wang
committed
let events = frame_system::Pallet::<T>::events();
let system_event: <T as frame_system::Config>::Event = generic_event.into();
// compare to the last event record
let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
assert_eq!(event, &system_event);
}
fn create_fund<T: Config>(id: u32, end: T::BlockNumber) -> ParaId {
let lease_period_index = T::Auctioneer::lease_period_index();
let first_period = lease_period_index;
let last_period = lease_period_index + 3u32.into();
let caller = account("fund_creator", id, 0);
CurrencyOf::<T>::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
// Assume ed25519 is most complex signature format
let pubkey = crypto::create_ed25519_pubkey(b"//verifier".to_vec());
let head_data = T::Registrar::worst_head_data();
let validation_code = T::Registrar::worst_validation_code();
assert_ok!(T::Registrar::register(caller.clone(), para_id, head_data, validation_code));
T::Registrar::execute_pending_transitions();
assert_ok!(Crowdloan::<T>::create(
RawOrigin::Signed(caller).into(),
para_id,
cap,
first_period,
last_period,
end,
Some(pubkey)
));
para_id
fn contribute_fund<T: Config>(who: &T::AccountId, index: ParaId) {
CurrencyOf::<T>::make_free_balance_be(&who, BalanceOf::<T>::max_value());
let pubkey = crypto::create_ed25519_pubkey(b"//verifier".to_vec());
let payload = (index, &who, BalanceOf::<T>::default(), value);
let sig = crypto::create_ed25519_signature(&payload.encode(), pubkey);
assert_ok!(Crowdloan::<T>::contribute(RawOrigin::Signed(who.clone()).into(), index, value, Some(sig)));
let first_period = 0u32.into();
let last_period = 3u32.into();
let end = T::Auctioneer::lease_period();
let caller: T::AccountId = whitelisted_caller();
let head_data = T::Registrar::worst_head_data();
let validation_code = T::Registrar::worst_validation_code();
let verifier = account("verifier", 0, 0);
CurrencyOf::<T>::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
T::Registrar::register(caller.clone(), para_id, head_data, validation_code)?;
}: _(RawOrigin::Signed(caller), para_id, cap, first_period, last_period, end, Some(verifier))
assert_last_event::<T>(RawEvent::Created(para_id).into())
}
// Contribute has two arms: PreEnding and Ending, but both are equal complexity.
contribute {
let fund_index = create_fund::<T>(1, 100u32.into());
let caller: T::AccountId = whitelisted_caller();
let contribution = T::MinContribution::get();
CurrencyOf::<T>::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
assert!(NewRaise::get().is_empty());
let pubkey = crypto::create_ed25519_pubkey(b"//verifier".to_vec());
let payload = (fund_index, &caller, BalanceOf::<T>::default(), contribution);
let sig = crypto::create_ed25519_signature(&payload.encode(), pubkey);
}: _(RawOrigin::Signed(caller.clone()), fund_index, contribution, Some(sig))
verify {
// NewRaise is appended to, so we don't need to fill it up for worst case scenario.
assert!(!NewRaise::get().is_empty());
assert_last_event::<T>(RawEvent::Contributed(caller, fund_index, contribution).into());
}
withdraw {
let fund_index = create_fund::<T>(1, 100u32.into());
let caller: T::AccountId = whitelisted_caller();
let contributor = account("contributor", 0, 0);
contribute_fund::<T>(&contributor, fund_index);
Shaun Wang
committed
frame_system::Pallet::<T>::set_block_number(200u32.into());
}: _(RawOrigin::Signed(caller), contributor.clone(), fund_index)
verify {
assert_last_event::<T>(RawEvent::Withdrew(contributor, fund_index, T::MinContribution::get()).into());
}
// Worst case: Dissolve removes `RemoveKeysLimit` keys, and then finishes up the dissolution of the fund.
dissolve {
let k in 0 .. T::RemoveKeysLimit::get();
let fund_index = create_fund::<T>(1, 100u32.into());
// Dissolve will remove at most `RemoveKeysLimit` at once.
contribute_fund::<T>(&account("contributor", i, 0), fund_index);
}
// One extra contributor so we can trigger withdraw
contribute_fund::<T>(&account("last_contributor", 0, 0), fund_index);
let caller: T::AccountId = whitelisted_caller();
Shaun Wang
committed
frame_system::Pallet::<T>::set_block_number(T::BlockNumber::max_value());
Crowdloan::<T>::withdraw(
RawOrigin::Signed(caller.clone()).into(),
account("last_contributor", 0, 0),
fund_index,
)?;
}: _(RawOrigin::Signed(caller.clone()), fund_index)
verify {
assert_last_event::<T>(RawEvent::Dissolved(fund_index).into());
}
edit {
let para_id = ParaId::from(1);
let cap = BalanceOf::<T>::max_value();
let first_period = 0u32.into();
let last_period = 3u32.into();
let end = T::Auctioneer::lease_period();
let caller: T::AccountId = whitelisted_caller();
let head_data = T::Registrar::worst_head_data();
let validation_code = T::Registrar::worst_validation_code();
let verifier: MultiSigner = account("verifier", 0, 0);
CurrencyOf::<T>::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
T::Registrar::register(caller.clone(), para_id, head_data, validation_code)?;
Crowdloan::<T>::create(
RawOrigin::Signed(caller).into(),
para_id, cap, first_period, last_period, end, Some(verifier.clone()),
)?;
// Doesn't matter what we edit to, so use the same values.
}: _(RawOrigin::Root, para_id, cap, first_period, last_period, end, Some(verifier))
verify {
assert_last_event::<T>(RawEvent::Edited(para_id).into())
}
add_memo {
let fund_index = create_fund::<T>(1, 100u32.into());
let caller: T::AccountId = whitelisted_caller();
contribute_fund::<T>(&caller, fund_index);
let worst_memo = vec![42; T::MaxMemoLength::get().into()];
}: _(RawOrigin::Signed(caller.clone()), fund_index, worst_memo.clone())
verify {
let fund = Funds::<T>::get(fund_index).expect("fund was created...");
assert_eq!(
Crowdloan::<T>::contribution_get(fund.trie_index, &caller),
(T::MinContribution::get(), worst_memo),
);
}
// Worst case scenario: N funds are all in the `NewRaise` list, we are
// in the beginning of the ending period, and each fund outbids the next
on_initialize {
// We test the complexity over different number of new raise
let n in 2 .. 100;
let end_block: T::BlockNumber = 100u32.into();
let pubkey = crypto::create_ed25519_pubkey(b"//verifier".to_vec());
let fund_index = create_fund::<T>(i, end_block);
let contributor: T::AccountId = account("contributor", i, 0);
let contribution = T::MinContribution::get() * (i + 1).into();
let payload = (fund_index, &contributor, BalanceOf::<T>::default(), contribution);
let sig = crypto::create_ed25519_signature(&payload.encode(), pubkey.clone());
CurrencyOf::<T>::make_free_balance_be(&contributor, BalanceOf::<T>::max_value());
Crowdloan::<T>::contribute(RawOrigin::Signed(contributor).into(), fund_index, contribution, Some(sig))?;
let lease_period_index = T::Auctioneer::lease_period_index();
let duration = end_block
Shaun Wang
committed
.checked_sub(&frame_system::Pallet::<T>::block_number())
.ok_or("duration of auction less than zero")?;
T::Auctioneer::new_auction(duration, lease_period_index)?;
assert_eq!(T::Auctioneer::is_ending(end_block), Some(0u32.into()));
assert_eq!(NewRaise::get().len(), n as usize);
let old_endings_count = EndingsCount::get();
}: {
Crowdloan::<T>::on_initialize(end_block);
} verify {
assert_eq!(EndingsCount::get(), old_endings_count + 1);
assert_last_event::<T>(RawEvent::HandleBidResult((n - 1).into(), Ok(())).into());
}
}
impl_benchmark_test_suite!(
Crowdloan,
crate::integration_tests::new_test_ext(),
crate::integration_tests::Test,
);