use crate::{
auctions, crowdloan, identity_migrator,
mock::{conclude_pvf_checking, validators_public_keys},
paras_registrar,
slot_range::SlotRange,
slots,
traits::{AuctionStatus, Auctioneer, Leaser, Registrar as RegistrarT},
};
use alloc::sync::Arc;
use codec::Encode;
use pezframe_support::{
assert_noop, assert_ok, derive_impl, parameter_types,
traits::{ConstU32, Currency},
weights::Weight,
PalletId,
};
use pezframe_support_test::TestRandomness;
use pezframe_system::EnsureRoot;
use pezkuwi_primitives::{
BlockNumber, HeadData, Id as ParaId, SessionIndex, ValidationCode, LOWEST_PUBLIC_ID,
MAX_CODE_SIZE,
};
use pezkuwi_runtime_teyrchains::{
configuration, dmp, origin, paras, shared, Origin as ParaOrigin, ParaLifecycle,
};
use pezpallet_identity::{self, legacy::IdentityInfo};
use pezsp_core::{ConstUint, H256};
use pezsp_io::TestExternalities;
use pezsp_keyring::Sr25519Keyring;
use pezsp_keystore::{testing::MemoryKeystore, KeystoreExt};
use pezsp_runtime::{
traits::{BlakeTwo256, IdentityLookup, One, Verify},
transaction_validity::TransactionPriority,
AccountId32, BuildStorage, MultiSignature,
};
type UncheckedExtrinsic = pezframe_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = pezframe_system::mocking::MockBlockU32<Test>;
type AccountId = AccountId32;
type Balance = u32;
type Moment = u32;
fn account_id(i: u32) -> AccountId32 {
let b4 = i.encode();
let b32 = [&b4[..], &b4[..], &b4[..], &b4[..], &b4[..], &b4[..], &b4[..], &b4[..]].concat();
let array: [u8; 32] = b32.try_into().unwrap();
array.into()
}
fn signed(i: u32) -> RuntimeOrigin {
let account_id = account_id(i);
RuntimeOrigin::signed(account_id)
}
pezframe_support::construct_runtime!(
pub enum Test
{
System: pezframe_system,
Balances: pezpallet_balances,
Babe: pezpallet_babe,
Configuration: configuration,
Paras: paras,
ParasShared: shared,
TeyrchainsOrigin: origin,
Dmp: dmp,
Registrar: paras_registrar,
Auctions: auctions,
Crowdloan: crowdloan,
Slots: slots,
Identity: pezpallet_identity,
IdentityMigrator: identity_migrator,
}
);
impl<C> pezframe_system::offchain::CreateTransactionBase<C> for Test
where
RuntimeCall: From<C>,
{
type Extrinsic = UncheckedExtrinsic;
type RuntimeCall = RuntimeCall;
}
impl<C> pezframe_system::offchain::CreateBare<C> for Test
where
RuntimeCall: From<C>,
{
fn create_bare(call: Self::RuntimeCall) -> Self::Extrinsic {
UncheckedExtrinsic::new_bare(call)
}
}
use crate::{auctions::Error as AuctionsError, crowdloan::Error as CrowdloanError};
parameter_types! {
pub BlockWeights: pezframe_system::limits::BlockWeights =
pezframe_system::limits::BlockWeights::simple_max(
Weight::from_parts(4 * 1024 * 1024, u64::MAX),
);
}
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
impl pezframe_system::Config for Test {
type BaseCallFilter = pezframe_support::traits::Everything;
type BlockWeights = BlockWeights;
type BlockLength = ();
type DbWeight = ();
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pezpallet_balances::AccountData<Balance>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = pezframe_support::traits::ConstU32<16>;
}
parameter_types! {
pub const EpochDuration: u64 = 10;
pub const ExpectedBlockTime: Moment = 6_000;
pub const ReportLongevity: u64 = 10;
pub const MaxAuthorities: u32 = 100_000;
}
impl pezpallet_babe::Config for Test {
type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
type EpochChangeTrigger = pezpallet_babe::ExternalTrigger;
type DisabledValidators = ();
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
type MaxNominators = ConstU32<0>;
type KeyOwnerProof = pezsp_core::Void;
type EquivocationReportSystem = ();
}
parameter_types! {
pub const MinimumPeriod: Moment = 6_000 / 2;
}
impl pezpallet_timestamp::Config for Test {
type Moment = Moment;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}
parameter_types! {
pub static ExistentialDeposit: Balance = 1;
}
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
impl pezpallet_balances::Config for Test {
type Balance = Balance;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
}
impl configuration::Config for Test {
type WeightInfo = configuration::TestWeightInfo;
}
impl shared::Config for Test {
type DisabledValidators = ();
}
impl dmp::Config for Test {}
impl origin::Config for Test {}
parameter_types! {
pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
}
impl paras::Config for Test {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = paras::TestWeightInfo;
type UnsignedPriority = ParasUnsignedPriority;
type QueueFootprinter = ();
type NextSessionRotation = crate::mock::TestNextSessionRotation;
type OnNewHead = ();
type AssignCoretime = ();
type Fungible = Balances;
type CooldownRemovalMultiplier = ConstUint<1>;
type AuthorizeCurrentCodeOrigin = EnsureRoot<Self::AccountId>;
}
parameter_types! {
pub const ParaDeposit: Balance = 500;
pub const DataDepositPerByte: Balance = 1;
}
impl paras_registrar::Config for Test {
type RuntimeEvent = RuntimeEvent;
type OnSwap = (Crowdloan, Slots);
type ParaDeposit = ParaDeposit;
type DataDepositPerByte = DataDepositPerByte;
type Currency = Balances;
type RuntimeOrigin = RuntimeOrigin;
type WeightInfo = crate::paras_registrar::TestWeightInfo;
}
parameter_types! {
pub const EndingPeriod: BlockNumber = 10;
pub const SampleLength: BlockNumber = 1;
}
impl auctions::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Leaser = Slots;
type Registrar = Registrar;
type EndingPeriod = EndingPeriod;
type SampleLength = SampleLength;
type Randomness = TestRandomness<Self>;
type InitiateOrigin = EnsureRoot<AccountId>;
type WeightInfo = crate::auctions::TestWeightInfo;
}
parameter_types! {
pub const LeasePeriod: BlockNumber = 100;
pub static LeaseOffset: BlockNumber = 5;
}
impl slots::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type Registrar = Registrar;
type LeasePeriod = LeasePeriod;
type LeaseOffset = LeaseOffset;
type ForceOrigin = EnsureRoot<AccountId>;
type WeightInfo = crate::slots::TestWeightInfo;
}
parameter_types! {
pub const CrowdloanId: PalletId = PalletId(*b"py/cfund");
pub const SubmissionDeposit: Balance = 100;
pub const MinContribution: Balance = 1;
pub const RemoveKeysLimit: u32 = 100;
pub const MaxMemoLength: u8 = 32;
}
impl crowdloan::Config for Test {
type RuntimeEvent = RuntimeEvent;
type PalletId = CrowdloanId;
type SubmissionDeposit = SubmissionDeposit;
type MinContribution = MinContribution;
type RemoveKeysLimit = RemoveKeysLimit;
type Registrar = Registrar;
type Auctioneer = Auctions;
type MaxMemoLength = MaxMemoLength;
type WeightInfo = crate::crowdloan::TestWeightInfo;
}
impl pezpallet_identity::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type Slashed = ();
type BasicDeposit = ConstU32<100>;
type ByteDeposit = ConstU32<10>;
type UsernameDeposit = ConstU32<10>;
type SubAccountDeposit = ConstU32<100>;
type MaxSubAccounts = ConstU32<2>;
type IdentityInformation = IdentityInfo<ConstU32<2>>;
type MaxRegistrars = ConstU32<20>;
type RegistrarOrigin = EnsureRoot<AccountId>;
type ForceOrigin = EnsureRoot<AccountId>;
type OffchainSignature = MultiSignature;
type SigningPublicKey = <MultiSignature as Verify>::Signer;
type UsernameAuthorityOrigin = EnsureRoot<AccountId>;
type PendingUsernameExpiration = ConstU32<100>;
type UsernameGracePeriod = ConstU32<10>;
type MaxSuffixLength = ConstU32<7>;
type MaxUsernameLength = ConstU32<32>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
type WeightInfo = ();
}
impl identity_migrator::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Reaper = EnsureRoot<AccountId>;
type ReapIdentityHandler = ();
type WeightInfo = crate::identity_migrator::TestWeightInfo;
}
pub fn new_test_ext() -> TestExternalities {
let mut t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
configuration::GenesisConfig::<Test> {
config: configuration::HostConfiguration {
max_code_size: MAX_CODE_SIZE,
max_head_data_size: 1 * 1024 * 1024, ..Default::default()
},
}
.assimilate_storage(&mut t)
.unwrap();
let keystore = MemoryKeystore::new();
let mut ext: pezsp_io::TestExternalities = t.into();
ext.register_extension(KeystoreExt(Arc::new(keystore)));
ext.execute_with(|| System::set_block_number(1));
ext
}
#[cfg(feature = "runtime-benchmarks")]
pub fn new_test_ext_with_offset(n: BlockNumber) -> TestExternalities {
LeaseOffset::set(n);
new_test_ext()
}
const BLOCKS_PER_SESSION: u32 = 10;
const VALIDATORS: &[Sr25519Keyring] = &[
Sr25519Keyring::Alice,
Sr25519Keyring::Bob,
Sr25519Keyring::Charlie,
Sr25519Keyring::Dave,
Sr25519Keyring::Ferdie,
];
fn maybe_new_session(n: u32) {
if n.is_multiple_of(BLOCKS_PER_SESSION) {
let session_index = shared::CurrentSessionIndex::<Test>::get() + 1;
let validators_pub_keys = validators_public_keys(VALIDATORS);
shared::Pezpallet::<Test>::set_session_index(session_index);
shared::Pezpallet::<Test>::set_active_validators_ascending(validators_pub_keys);
Paras::test_on_new_session();
}
}
fn test_genesis_head(size: usize) -> HeadData {
HeadData(vec![0u8; size])
}
fn test_validation_code(size: usize) -> ValidationCode {
let validation_code = vec![0u8; size as usize];
ValidationCode(validation_code)
}
fn para_origin(id: u32) -> ParaOrigin {
ParaOrigin::Teyrchain(id.into())
}
fn add_blocks(n: u32) {
let block_number = System::block_number();
run_to_block(block_number + n);
}
fn run_to_block(n: u32) {
System::run_to_block_with::<AllPalletsWithSystem>(
n,
pezframe_system::RunToBlockHooks::default().before_initialize(|bn| {
maybe_new_session(bn);
}),
);
}
fn run_to_session(n: u32) {
let block_number = BLOCKS_PER_SESSION * n;
run_to_block(block_number);
}
fn last_event() -> RuntimeEvent {
System::events().pop().expect("RuntimeEvent expected").event
}
fn contains_event(event: RuntimeEvent) -> bool {
System::events().iter().any(|x| x.event == event)
}
#[test]
fn basic_end_to_end_works() {
for offset in [0u32, 50, 100, 200].iter() {
LeaseOffset::set(*offset);
new_test_ext().execute_with(|| {
let para_1 = LOWEST_PUBLIC_ID;
let para_2 = LOWEST_PUBLIC_ID + 1;
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let start_block = System::block_number();
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
let genesis_head = Registrar::worst_head_data();
let validation_code = Registrar::worst_validation_code();
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
ParaId::from(para_1),
genesis_head.clone(),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
assert_ok!(Registrar::reserve(signed(2)));
assert_ok!(Registrar::register(
signed(2),
ParaId::from(2001),
genesis_head,
validation_code,
));
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Onboarding));
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Onboarding));
let duration = 99u32 + offset;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
run_to_session(START_SESSION_INDEX + 2);
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
assert_ok!(Crowdloan::create(
signed(2),
ParaId::from(para_2),
1_000, lease_period_index_start + 2, lease_period_index_start + 3, 200 + offset, None,
));
let fund_2 = crowdloan::Funds::<Test>::get(ParaId::from(para_2)).unwrap();
let crowdloan_account = Crowdloan::fund_account_id(fund_2.fund_index);
run_to_block(start_block + 90 + offset);
Balances::make_free_balance_be(&account_id(10), 1_000_000_000);
Balances::make_free_balance_be(&account_id(20), 1_000_000_000);
assert_ok!(Auctions::bid(
signed(10),
ParaId::from(para_1),
1, lease_period_index_start + 0, lease_period_index_start + 1, 910, ));
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
assert_ok!(Crowdloan::contribute(signed(2), ParaId::from(para_2), 920, None));
run_to_block(start_block + 109 + offset);
assert!(contains_event(
crowdloan::Event::<Test>::HandleBidResult {
para_id: ParaId::from(para_2),
result: Ok(())
}
.into()
));
run_to_block(start_block + 110 + offset);
assert_eq!(
last_event(),
auctions::Event::<Test>::AuctionClosed { auction_index: 1 }.into()
);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(para_1)),
vec![None, None, None, Some((account_id(10), 910)), Some((account_id(10), 910))],
);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(para_2)),
vec![
None,
None,
None,
None,
None,
Some((crowdloan_account.clone(), 920)),
Some((crowdloan_account.clone(), 920))
],
);
Balances::make_free_balance_be(&account_id(3), 1_000_000_000);
assert_noop!(
Crowdloan::contribute(signed(3), ParaId::from(2001), 10, None),
CrowdloanError::<Test>::BidOrLeaseActive
);
let lease_start_block = start_block + 400 + offset;
run_to_block(lease_start_block);
assert_eq!(
Paras::lifecycle(ParaId::from(para_1)),
Some(ParaLifecycle::UpgradingParathread)
);
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
run_to_block(lease_start_block + 20);
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Teyrchain));
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
run_to_block(lease_start_block + 100);
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Teyrchain));
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
run_to_block(lease_start_block + 200);
assert_eq!(
Paras::lifecycle(ParaId::from(para_1)),
Some(ParaLifecycle::DowngradingTeyrchain)
);
assert_eq!(
Paras::lifecycle(ParaId::from(para_2)),
Some(ParaLifecycle::UpgradingParathread)
);
run_to_block(lease_start_block + 220);
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Teyrchain));
run_to_block(lease_start_block + 300);
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Teyrchain));
run_to_block(lease_start_block + 400);
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
assert_eq!(
Paras::lifecycle(ParaId::from(para_2)),
Some(ParaLifecycle::DowngradingTeyrchain)
);
run_to_block(lease_start_block + 420);
assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
});
}
}
#[test]
fn basic_errors_fail() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
let para_id = LOWEST_PUBLIC_ID;
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
let genesis_head = Registrar::worst_head_data();
let validation_code = Registrar::worst_validation_code();
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
para_id,
genesis_head.clone(),
validation_code.clone(),
));
assert_ok!(Registrar::reserve(signed(2)));
assert_noop!(
Registrar::register(signed(2), para_id, genesis_head, validation_code,),
paras_registrar::Error::<Test>::NotOwner
);
let duration = 99u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
assert_noop!(
Crowdloan::create(
signed(2),
para_id,
1_000, lease_period_index_start + 2, lease_period_index_start + 3, 200, None,
),
crowdloan::Error::<Test>::InvalidOrigin
);
});
}
#[test]
fn competing_slots() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
let max_bids = 10u32;
let para_id = LOWEST_PUBLIC_ID;
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let validation_code = Registrar::worst_validation_code();
for n in 1..=max_bids {
Balances::make_free_balance_be(&account_id(n), 1_000_000_000);
let genesis_head = Registrar::worst_head_data();
assert_ok!(Registrar::reserve(signed(n)));
assert_ok!(Registrar::register(
signed(n),
para_id + n - 1,
genesis_head,
validation_code.clone(),
));
}
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
let duration = 149u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
run_to_session(START_SESSION_INDEX + 2);
for n in 1..=max_bids {
run_to_block(System::block_number() + 10);
Balances::make_free_balance_be(&account_id(n * 10), n * 1_000);
let (start, end) = match n {
1 => (0, 0),
2 => (0, 1),
3 => (0, 2),
4 => (0, 3),
5 => (1, 1),
6 => (1, 2),
7 => (1, 3),
8 => (2, 2),
9 => (2, 3),
10 => (3, 3),
_ => panic!("test not meant for this"),
};
assert_ok!(Auctions::bid(
signed(n * 10),
para_id + n - 1,
1, lease_period_index_start + start, lease_period_index_start + end, n * 900, ));
}
run_to_block(180);
assert_eq!(
slots::Leases::<Test>::get(para_id),
vec![None, None, None, Some((account_id(10), 900))],
);
assert_eq!(
slots::Leases::<Test>::get(para_id + 4),
vec![None, None, None, None, Some((account_id(50), 4500))],
);
assert_eq!(
slots::Leases::<Test>::get(para_id + 8),
vec![
None,
None,
None,
None,
None,
Some((account_id(90), 8100)),
Some((account_id(90), 8100))
],
);
});
}
#[test]
fn competing_bids() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let start_para = LOWEST_PUBLIC_ID - 1;
let validation_code = Registrar::worst_validation_code();
for n in 1..=3 {
Balances::make_free_balance_be(&account_id(n), 1_000_000_000);
let genesis_head = Registrar::worst_head_data();
assert_ok!(Registrar::reserve(signed(n)));
assert_ok!(Registrar::register(
signed(n),
ParaId::from(start_para + n),
genesis_head,
validation_code.clone(),
));
}
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
let starting_block = System::block_number();
let duration = 99u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
for n in 1..=3 {
assert_ok!(Crowdloan::create(
signed(n),
ParaId::from(start_para + n),
100_000, lease_period_index_start + 2, lease_period_index_start + 3, 200, None,
));
}
for n in 1..=9 {
run_to_block(starting_block + n * 10);
Balances::make_free_balance_be(&account_id(n * 10), n * 1_000);
let para = start_para + n % 3 + 1;
if n % 2 == 0 {
assert_ok!(Auctions::bid(
signed(n * 10),
ParaId::from(para),
1, lease_period_index_start + 0, lease_period_index_start + 1, n * 900, ));
} else {
assert_ok!(Crowdloan::contribute(
signed(n * 10),
ParaId::from(para),
n + 900,
None,
));
}
}
run_to_block(starting_block + 110);
let fund_1 = crowdloan::Funds::<Test>::get(ParaId::from(2000)).unwrap();
let crowdloan_1 = Crowdloan::fund_account_id(fund_1.fund_index);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2000)),
vec![
None,
None,
None,
None,
None,
Some((crowdloan_1.clone(), 1812)),
Some((crowdloan_1.clone(), 1812))
],
);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2002)),
vec![None, None, None, Some((account_id(80), 7200)), Some((account_id(80), 7200))],
);
});
}
#[test]
fn basic_swap_works() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
let validation_code = test_validation_code(10);
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
ParaId::from(2000),
test_genesis_head(10),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
let validation_code = test_validation_code(20);
assert_ok!(Registrar::reserve(signed(2)));
assert_ok!(Registrar::register(
signed(2),
ParaId::from(2001),
test_genesis_head(20),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
let duration = 99u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
run_to_session(START_SESSION_INDEX + 2);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
assert_ok!(Crowdloan::create(
signed(1),
ParaId::from(2000),
1_000_000, lease_period_index_start + 0, lease_period_index_start + 3, 200, None,
));
let fund = crowdloan::Funds::<Test>::get(ParaId::from(2000)).unwrap();
let crowdloan_account = Crowdloan::fund_account_id(fund.fund_index);
let mut total = 0;
for i in 10..20 {
Balances::make_free_balance_be(&account_id(i), 1_000_000_000);
assert_ok!(Crowdloan::contribute(signed(i), ParaId::from(2000), 900 - i, None));
total += 900 - i;
}
assert!(total > 0);
assert_eq!(Balances::free_balance(&crowdloan_account), total);
run_to_block(200);
let crowdloan_deposit = 100;
let para_id_deposit = <Test as paras_registrar::Config>::ParaDeposit::get();
let code_deposit = configuration::ActiveConfig::<Test>::get().max_code_size
* <Test as paras_registrar::Config>::DataDepositPerByte::get();
assert_eq!(
Balances::reserved_balance(&account_id(1)),
crowdloan_deposit + para_id_deposit + code_deposit + 10
);
assert_eq!(Balances::reserved_balance(&account_id(2)), para_id_deposit + code_deposit + 20);
assert_eq!(Balances::reserved_balance(&crowdloan_account), total);
assert!(crowdloan::Funds::<Test>::get(ParaId::from(2000)).is_some());
assert!(crowdloan::Funds::<Test>::get(ParaId::from(2001)).is_none());
let lease_start_block = 400;
run_to_block(lease_start_block);
assert!(!slots::Leases::<Test>::get(ParaId::from(2000)).is_empty());
assert!(slots::Leases::<Test>::get(ParaId::from(2001)).is_empty());
run_to_block(lease_start_block + 20);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Teyrchain));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
assert_ok!(Registrar::swap(
para_origin(2000).into(),
ParaId::from(2000),
ParaId::from(2001)
));
assert_ok!(Registrar::swap(
para_origin(2001).into(),
ParaId::from(2001),
ParaId::from(2000)
));
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::DowngradingTeyrchain));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::UpgradingParathread));
run_to_block(lease_start_block + 40);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Teyrchain));
assert_ok!(Registrar::deregister(para_origin(2000).into(), ParaId::from(2000)));
assert_eq!(Balances::reserved_balance(&account_id(1)), crowdloan_deposit);
assert_eq!(Balances::reserved_balance(&account_id(2)), para_id_deposit + code_deposit + 20);
assert!(crowdloan::Funds::<Test>::get(ParaId::from(2000)).is_none());
assert!(crowdloan::Funds::<Test>::get(ParaId::from(2001)).is_some());
assert!(slots::Leases::<Test>::get(ParaId::from(2000)).is_empty());
assert!(!slots::Leases::<Test>::get(ParaId::from(2001)).is_empty());
assert_noop!(
Crowdloan::dissolve(signed(1), ParaId::from(2000)),
CrowdloanError::<Test>::InvalidParaId
);
assert_noop!(
Crowdloan::dissolve(signed(2), ParaId::from(2001)),
CrowdloanError::<Test>::NotReadyToDissolve
);
run_to_block(lease_start_block + 1000);
assert_eq!(Balances::free_balance(&crowdloan_account), total);
for i in 10..20 {
assert_ok!(Crowdloan::withdraw(signed(i), account_id(i), ParaId::from(2001)));
}
assert_eq!(Balances::free_balance(&crowdloan_account), 0);
assert_ok!(Crowdloan::dissolve(signed(1), ParaId::from(2001)));
assert_eq!(Balances::reserved_balance(&account_id(1)), 0);
assert_eq!(Balances::reserved_balance(&account_id(2)), para_id_deposit + code_deposit + 20);
assert_ok!(Registrar::deregister(para_origin(2001).into(), ParaId::from(2001)));
assert_eq!(Balances::reserved_balance(&account_id(2)), 0);
})
}
#[test]
fn teyrchain_swap_works() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
let validation_code = test_validation_code(10);
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
ParaId::from(2000),
test_genesis_head(10),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
let validation_code = test_validation_code(20);
assert_ok!(Registrar::reserve(signed(2)));
assert_ok!(Registrar::register(
signed(2),
ParaId::from(2001),
test_genesis_head(20),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
assert_eq!(
Balances::total_balance(&Crowdloan::fund_account_id(
crowdloan::NextFundIndex::<Test>::get()
)),
0
);
let start_auction = |lease_period_index_start, winner, end| {
let unique_id = winner - 1999u32;
let starting_block = System::block_number();
let duration = 99u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
run_to_block(starting_block + 20);
assert_eq!(Paras::lifecycle(ParaId::from(winner)), Some(ParaLifecycle::Parathread));
assert_ok!(Crowdloan::create(
signed(unique_id),
ParaId::from(winner),
1_000_000, lease_period_index_start + 0, lease_period_index_start + 7, end, None,
));
let winner_fund = crowdloan::Funds::<Test>::get(ParaId::from(winner)).unwrap();
let crowdloan_account = Crowdloan::fund_account_id(winner_fund.fund_index);
let mut total = 0;
for i in (unique_id * 10)..(unique_id + 1) * 10 {
Balances::make_free_balance_be(&account_id(i), 1_000_000_000);
assert_ok!(Crowdloan::contribute(signed(i), ParaId::from(winner), 900 - i, None));
total += 900 - i;
}
assert!(total > 0);
assert_eq!(Balances::free_balance(&crowdloan_account), total);
run_to_block(end);
assert!(crowdloan::Funds::<Test>::get(ParaId::from(winner)).is_some());
let lease_start_block = lease_period_index_start * 100;
run_to_block(lease_start_block);
};
start_auction(4u32, 2000, 200);
assert!(!slots::Leases::<Test>::get(ParaId::from(2000)).is_empty());
assert!(slots::Leases::<Test>::get(ParaId::from(2001)).is_empty());
run_to_block(4 * 100 + 20);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Teyrchain));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
start_auction(6u32, 2001, 500);
assert!(!slots::Leases::<Test>::get(ParaId::from(2000)).is_empty());
assert!(!slots::Leases::<Test>::get(ParaId::from(2001)).is_empty());
run_to_block(6 * 100 + 20);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Teyrchain));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Teyrchain));
assert_eq!(
<Slots as Leaser<_>>::lease_period_index(System::block_number()),
Some((6u32, false))
);
assert_eq!(slots::Leases::<Test>::get(ParaId::from(2000)).len(), 6);
assert_eq!(slots::Leases::<Test>::get(ParaId::from(2001)).len(), 8);
let fund_2000 = crowdloan::Funds::<Test>::get(ParaId::from(2000)).unwrap();
assert_eq!(fund_2000.fund_index, 0);
assert_eq!(
Balances::reserved_balance(&Crowdloan::fund_account_id(fund_2000.fund_index)),
fund_2000.raised
);
let fund_2001 = crowdloan::Funds::<Test>::get(ParaId::from(2001)).unwrap();
assert_eq!(fund_2001.fund_index, 1);
assert_eq!(
Balances::reserved_balance(&Crowdloan::fund_account_id(fund_2001.fund_index)),
fund_2001.raised
);
assert_eq!(slots::Leases::<Test>::get(ParaId::from(2000)).len(), 6);
assert_eq!(slots::Leases::<Test>::get(ParaId::from(2001)).len(), 8);
assert_ok!(Registrar::swap(
para_origin(2000).into(),
ParaId::from(2000),
ParaId::from(2001)
));
assert_ok!(Registrar::swap(
para_origin(2001).into(),
ParaId::from(2001),
ParaId::from(2000)
));
assert!(contains_event(
paras_registrar::Event::<Test>::Swapped {
para_id: ParaId::from(2001),
other_id: ParaId::from(2000)
}
.into()
));
let fund_2000 = crowdloan::Funds::<Test>::get(ParaId::from(2000)).unwrap();
assert_eq!(fund_2000.fund_index, 1);
assert_eq!(
Balances::reserved_balance(&Crowdloan::fund_account_id(fund_2000.fund_index)),
fund_2000.raised
);
let fund_2001 = crowdloan::Funds::<Test>::get(ParaId::from(2001)).unwrap();
assert_eq!(fund_2001.fund_index, 0);
assert_eq!(
Balances::reserved_balance(&Crowdloan::fund_account_id(fund_2001.fund_index)),
fund_2001.raised
);
assert_eq!(slots::Leases::<Test>::get(ParaId::from(2000)).len(), 8);
assert_eq!(slots::Leases::<Test>::get(ParaId::from(2001)).len(), 6);
})
}
#[test]
fn crowdloan_ending_period_bid() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
let validation_code = test_validation_code(10);
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
ParaId::from(2000),
test_genesis_head(10),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
let validation_code = test_validation_code(20);
assert_ok!(Registrar::reserve(signed(2)));
assert_ok!(Registrar::register(
signed(2),
ParaId::from(2001),
test_genesis_head(20),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
let duration = 99u32;
let ends_at = System::block_number() + duration;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
run_to_session(START_SESSION_INDEX + 2);
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
assert_ok!(Crowdloan::create(
signed(1),
ParaId::from(2000),
1_000_000, lease_period_index_start + 0, lease_period_index_start + 3, 200, None,
));
let fund = crowdloan::Funds::<Test>::get(ParaId::from(2000)).unwrap();
let crowdloan_account = Crowdloan::fund_account_id(fund.fund_index);
let mut total = 0;
for i in 10..20 {
Balances::make_free_balance_be(&account_id(i), 1_000_000_000);
assert_ok!(Crowdloan::contribute(signed(i), ParaId::from(2000), 900 - i, None));
total += 900 - i;
}
assert!(total > 0);
assert_eq!(Balances::free_balance(&crowdloan_account), total);
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
assert_ok!(Auctions::bid(
signed(2),
ParaId::from(2001),
1, lease_period_index_start + 0, lease_period_index_start + 1, 900, ));
run_to_block(ends_at);
assert_eq!(Auctions::auction_status(ends_at), AuctionStatus::<u32>::EndingPeriod(0, 0));
let mut winning = [(); SlotRange::SLOT_RANGE_COUNT].map(|_| None);
winning[SlotRange::ZeroOne as u8 as usize] = Some((account_id(2), ParaId::from(2001), 900));
winning[SlotRange::ZeroThree as u8 as usize] =
Some((crowdloan_account.clone(), ParaId::from(2000), total));
assert_eq!(auctions::Winning::<Test>::get(0), Some(winning));
run_to_block(ends_at + 1);
Balances::make_free_balance_be(&account_id(1234), 1_000_000_000);
assert_ok!(Crowdloan::contribute(signed(1234), ParaId::from(2000), 900, None));
run_to_block(ends_at + 2);
let mut winning = [(); SlotRange::SLOT_RANGE_COUNT].map(|_| None);
winning[SlotRange::ZeroOne as u8 as usize] = Some((account_id(2), ParaId::from(2001), 900));
winning[SlotRange::ZeroThree as u8 as usize] =
Some((crowdloan_account.clone(), ParaId::from(2000), total + 900));
assert_eq!(auctions::Winning::<Test>::get(2), Some(winning));
})
}
#[test]
fn auction_bid_requires_registered_para() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let duration = 99u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
assert_noop!(
Auctions::bid(
signed(1),
ParaId::from(2000),
1, lease_period_index_start + 0, lease_period_index_start + 1, 900, ),
AuctionsError::<Test>::ParaNotRegistered
);
let validation_code = test_validation_code(10);
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
ParaId::from(2000),
test_genesis_head(10),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
assert_noop!(
Auctions::bid(
signed(1),
ParaId::from(2000),
1, lease_period_index_start + 0, lease_period_index_start + 1, 900, ),
AuctionsError::<Test>::ParaNotRegistered
);
run_to_session(START_SESSION_INDEX + 2);
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
assert_ok!(Auctions::bid(
signed(1),
ParaId::from(2000),
1, lease_period_index_start + 0, lease_period_index_start + 1, 900, ));
});
}
#[test]
fn gap_bids_work() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let duration = 99u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
let validation_code = test_validation_code(10);
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
ParaId::from(2000),
test_genesis_head(10),
validation_code.clone(),
));
assert_ok!(Registrar::reserve(signed(2)));
assert_ok!(Registrar::register(
signed(2),
ParaId::from(2001),
test_genesis_head(10),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
Balances::make_free_balance_be(&account_id(10), 1_000_000_000);
Balances::make_free_balance_be(&account_id(20), 1_000_000_000);
assert_ok!(Auctions::bid(
signed(10),
ParaId::from(2000),
1, lease_period_index_start + 0, lease_period_index_start + 0, 100, ));
assert_ok!(Auctions::bid(
signed(10),
ParaId::from(2000),
1, lease_period_index_start + 3, lease_period_index_start + 3, 400, ));
assert_ok!(Auctions::bid(
signed(10),
ParaId::from(2001),
1, lease_period_index_start + 1, lease_period_index_start + 1, 555, ));
assert_eq!(Balances::reserved_balance(&account_id(10)), 400 + 555);
assert_ok!(Auctions::bid(
signed(20),
ParaId::from(2000),
1, lease_period_index_start + 1, lease_period_index_start + 1, 800, ));
assert_ok!(Auctions::bid(
signed(20),
ParaId::from(2000),
1, lease_period_index_start + 2, lease_period_index_start + 2, 200, ));
run_to_block(130 + LeaseOffset::get());
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2000)),
vec![
None,
None,
None,
Some((account_id(10), 100)),
Some((account_id(20), 800)),
Some((account_id(20), 200)),
Some((account_id(10), 400))
],
);
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
assert_eq!(Balances::reserved_balance(&account_id(20)), 800);
add_blocks(300 + LeaseOffset::get());
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2000)),
vec![
Some((account_id(10), 100)),
Some((account_id(20), 800)),
Some((account_id(20), 200)),
Some((account_id(10), 400))
],
);
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
assert_eq!(Balances::reserved_balance(&account_id(20)), 800);
add_blocks(100);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2000)),
vec![
Some((account_id(20), 800)),
Some((account_id(20), 200)),
Some((account_id(10), 400))
],
);
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
assert_eq!(Balances::reserved_balance(&account_id(20)), 800);
add_blocks(100);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2000)),
vec![Some((account_id(20), 200)), Some((account_id(10), 400))],
);
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
assert_eq!(Balances::reserved_balance(&account_id(20)), 200);
add_blocks(100);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2000)),
vec![Some((account_id(10), 400))],
);
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
assert_eq!(Balances::reserved_balance(&account_id(20)), 0);
add_blocks(100);
assert_eq!(slots::Leases::<Test>::get(ParaId::from(2000)), vec![]);
assert_eq!(Balances::reserved_balance(&account_id(10)), 0);
assert_eq!(Balances::reserved_balance(&account_id(20)), 0);
});
}
#[test]
fn cant_bid_on_existing_lease_periods() {
new_test_ext().execute_with(|| {
assert!(System::block_number().is_one());
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
let validation_code = test_validation_code(10);
assert_ok!(Registrar::reserve(signed(1)));
assert_ok!(Registrar::register(
signed(1),
ParaId::from(2000),
test_genesis_head(10),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
let starting_block = System::block_number();
let duration = 99u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
run_to_session(START_SESSION_INDEX + 2);
assert_ok!(Crowdloan::create(
signed(1),
ParaId::from(2000),
1_000_000, lease_period_index_start + 0, lease_period_index_start + 1, 400, None,
));
let fund = crowdloan::Funds::<Test>::get(ParaId::from(2000)).unwrap();
let crowdloan_account = Crowdloan::fund_account_id(fund.fund_index);
let mut total = 0;
for i in 10..20 {
Balances::make_free_balance_be(&account_id(i), 1_000_000_000);
assert_ok!(Crowdloan::contribute(signed(i), ParaId::from(2000), 900 - i, None));
total += 900 - i;
}
assert!(total > 0);
assert_eq!(Balances::free_balance(&crowdloan_account), total);
run_to_block(starting_block + 110);
assert_eq!(
slots::Leases::<Test>::get(ParaId::from(2000)),
vec![
None,
None,
None,
Some((crowdloan_account.clone(), 8855)),
Some((crowdloan_account.clone(), 8855))
],
);
let starting_block = System::block_number();
let duration = 99u32;
let lease_period_index_start = 4u32;
assert_ok!(Auctions::new_auction(
RuntimeOrigin::root(),
duration,
lease_period_index_start
));
assert_ok!(Crowdloan::poke(signed(1), ParaId::from(2000)));
assert_eq!(crowdloan::NewRaise::<Test>::get(), vec![ParaId::from(2000)]);
run_to_block(starting_block + 100);
assert_noop!(
Auctions::bid(
RuntimeOrigin::signed(crowdloan_account.clone()),
ParaId::from(2000),
2,
lease_period_index_start + 0,
lease_period_index_start + 1,
100,
),
AuctionsError::<Test>::AlreadyLeasedOut,
);
assert_noop!(
Auctions::bid(
RuntimeOrigin::signed(crowdloan_account.clone()),
ParaId::from(2000),
2,
lease_period_index_start + 1,
lease_period_index_start + 2,
100,
),
AuctionsError::<Test>::AlreadyLeasedOut,
);
assert_noop!(
Auctions::bid(
RuntimeOrigin::signed(crowdloan_account.clone()),
ParaId::from(2000),
2,
lease_period_index_start - 1,
lease_period_index_start + 0,
100,
),
AuctionsError::<Test>::AlreadyLeasedOut,
);
assert_noop!(
Auctions::bid(
RuntimeOrigin::signed(crowdloan_account.clone()),
ParaId::from(2000),
2,
lease_period_index_start + 0,
lease_period_index_start + 0,
100,
),
AuctionsError::<Test>::AlreadyLeasedOut,
);
assert_noop!(
Auctions::bid(
RuntimeOrigin::signed(crowdloan_account.clone()),
ParaId::from(2000),
2,
lease_period_index_start + 1,
lease_period_index_start + 1,
100,
),
AuctionsError::<Test>::AlreadyLeasedOut,
);
assert_noop!(
Auctions::bid(
RuntimeOrigin::signed(crowdloan_account.clone()),
ParaId::from(2000),
2,
lease_period_index_start - 1,
lease_period_index_start + 5,
100,
),
AuctionsError::<Test>::AlreadyLeasedOut,
);
assert_ok!(Auctions::bid(
RuntimeOrigin::signed(crowdloan_account.clone()),
ParaId::from(2000),
2,
lease_period_index_start + 2,
lease_period_index_start + 3,
100,
));
});
}