integration_tests.rs 40.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.

//! Mocking utilities for testing with real pallets.

Shawn Tabrizi's avatar
Shawn Tabrizi committed
19
20
21
22
23
use crate::{
	auctions, crowdloan, paras_registrar,
	slot_range::SlotRange,
	slots,
	traits::{AuctionStatus, Auctioneer, Registrar as RegistrarT},
24
25
};
use frame_support::{
Shawn Tabrizi's avatar
Shawn Tabrizi committed
26
27
28
	assert_noop, assert_ok, parameter_types,
	traits::{Currency, GenesisBuild, KeyOwnerProofSystem, OnFinalize, OnInitialize},
	PalletId,
29
30
};
use frame_support_test::TestRandomness;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
31
32
33
use frame_system::EnsureRoot;
use primitives::v1::{
	BlockNumber, HeadData, Header, Id as ParaId, ValidationCode, LOWEST_PUBLIC_ID,
34
};
Shawn Tabrizi's avatar
Shawn Tabrizi committed
35
36
37
38
39
40
use runtime_parachains::{configuration, paras, shared, Origin as ParaOrigin, ParaLifecycle};
use sp_core::{crypto::KeyTypeId, H256};
use sp_io::TestExternalities;
use sp_keystore::{testing::KeyStore, KeystoreExt};
use sp_runtime::traits::{BlakeTwo256, IdentityLookup, One};
use sp_std::sync::Arc;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;

type AccountId = u32;
type Balance = u32;
type Moment = u32;

frame_support::construct_runtime!(
	pub enum Test where
		Block = Block,
		NodeBlock = Block,
		UncheckedExtrinsic = UncheckedExtrinsic,
	{
		// System Stuff
56
57
58
		System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
		Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned},
59
60

		// Parachains Runtime
61
		Configuration: configuration::{Pallet, Call, Storage, Config<T>},
ferrell-code's avatar
ferrell-code committed
62
		Paras: paras::{Pallet, Origin, Call, Storage, Event, Config},
63
		ParasShared: shared::{Pallet, Call, Storage},
64
65

		// Para Onboarding Pallets
66
67
68
69
		Registrar: paras_registrar::{Pallet, Call, Storage, Event<T>},
		Auctions: auctions::{Pallet, Call, Storage, Event<T>},
		Crowdloan: crowdloan::{Pallet, Call, Storage, Event<T>},
		Slots: slots::{Pallet, Call, Storage, Event<T>},
70
71
72
	}
);

Shawn Tabrizi's avatar
Shawn Tabrizi committed
73
use crate::{auctions::Error as AuctionsError, crowdloan::Error as CrowdloanError};
74
75
76
77
78
79
80
81

parameter_types! {
	pub const BlockHashCount: u32 = 250;
	pub BlockWeights: frame_system::limits::BlockWeights =
		frame_system::limits::BlockWeights::simple_max(4 * 1024 * 1024);
}

impl frame_system::Config for Test {
82
	type BaseCallFilter = frame_support::traits::Everything;
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	type BlockWeights = BlockWeights;
	type BlockLength = ();
	type DbWeight = ();
	type Origin = Origin;
	type Call = Call;
	type Index = u64;
	type BlockNumber = BlockNumber;
	type Hash = H256;
	type Hashing = BlakeTwo256;
	type AccountId = AccountId;
	type Lookup = IdentityLookup<AccountId>;
	type Header = Header;
	type Event = Event;
	type BlockHashCount = BlockHashCount;
	type Version = ();
	type PalletInfo = PalletInfo;
	type AccountData = pallet_balances::AccountData<Balance>;
	type OnNewAccount = ();
	type OnKilledAccount = ();
	type SystemWeightInfo = ();
	type SS58Prefix = ();
104
	type OnSetCode = ();
105
106
107
108
109
110
}

parameter_types! {
	pub const EpochDuration: u64 = 10;
	pub const ExpectedBlockTime: Moment = 6_000;
	pub const ReportLongevity: u64 = 10;
111
	pub const MaxAuthorities: u32 = 100_000;
112
113
114
115
116
117
}

impl pallet_babe::Config for Test {
	type EpochDuration = EpochDuration;
	type ExpectedBlockTime = ExpectedBlockTime;
	type EpochChangeTrigger = pallet_babe::ExternalTrigger;
118
	type DisabledValidators = ();
119
	type KeyOwnerProofSystem = ();
Shawn Tabrizi's avatar
Shawn Tabrizi committed
120
121
122
123
	type KeyOwnerProof = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
		KeyTypeId,
		pallet_babe::AuthorityId,
	)>>::Proof;
124
125
126
127
128
129
	type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
		KeyTypeId,
		pallet_babe::AuthorityId,
	)>>::IdentificationTuple;
	type HandleEquivocation = ();
	type WeightInfo = ();
130
	type MaxAuthorities = MaxAuthorities;
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
}

parameter_types! {
	pub const MinimumPeriod: Moment = 6_000 / 2;
}

impl pallet_timestamp::Config for Test {
	type Moment = Moment;
	type OnTimestampSet = ();
	type MinimumPeriod = MinimumPeriod;
	type WeightInfo = ();
}

parameter_types! {
	pub static ExistentialDeposit: Balance = 1;
Gavin Wood's avatar
Gavin Wood committed
146
	pub const MaxReserves: u32 = 50;
147
148
149
150
151
152
153
154
155
156
}

impl pallet_balances::Config for Test {
	type MaxLocks = ();
	type Balance = Balance;
	type Event = Event;
	type DustRemoval = ();
	type ExistentialDeposit = ExistentialDeposit;
	type AccountStore = System;
	type WeightInfo = ();
Gavin Wood's avatar
Gavin Wood committed
157
158
	type MaxReserves = MaxReserves;
	type ReserveIdentifier = [u8; 8];
159
160
}

161
impl configuration::Config for Test {
162
	type WeightInfo = configuration::TestWeightInfo;
163
}
164

Shawn Tabrizi's avatar
Shawn Tabrizi committed
165
impl shared::Config for Test {}
166
167
168

impl paras::Config for Test {
	type Origin = Origin;
169
	type Event = Event;
170
	type WeightInfo = paras::TestWeightInfo;
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
}

parameter_types! {
	pub const ParaDeposit: Balance = 500;
	pub const DataDepositPerByte: Balance = 1;
}

impl paras_registrar::Config for Test {
	type Event = Event;
	type OnSwap = (Crowdloan, Slots);
	type ParaDeposit = ParaDeposit;
	type DataDepositPerByte = DataDepositPerByte;
	type Currency = Balances;
	type Origin = Origin;
	type WeightInfo = crate::paras_registrar::TestWeightInfo;
}

parameter_types! {
	pub const EndingPeriod: BlockNumber = 10;
190
	pub const SampleLength: BlockNumber = 1;
191
192
193
194
195
}

impl auctions::Config for Test {
	type Event = Event;
	type Leaser = Slots;
196
	type Registrar = Registrar;
197
	type EndingPeriod = EndingPeriod;
198
	type SampleLength = SampleLength;
199
200
201
202
203
204
205
	type Randomness = TestRandomness<Self>;
	type InitiateOrigin = EnsureRoot<AccountId>;
	type WeightInfo = crate::auctions::TestWeightInfo;
}

parameter_types! {
	pub const LeasePeriod: BlockNumber = 100;
206
	pub static LeaseOffset: BlockNumber = 0;
207
208
209
210
211
212
213
}

impl slots::Config for Test {
	type Event = Event;
	type Currency = Balances;
	type Registrar = Registrar;
	type LeasePeriod = LeasePeriod;
214
	type LeaseOffset = LeaseOffset;
215
216
217
218
	type WeightInfo = crate::slots::TestWeightInfo;
}

parameter_types! {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
219
	pub const CrowdloanId: PalletId = PalletId(*b"py/cfund");
220
221
222
	pub const SubmissionDeposit: Balance = 100;
	pub const MinContribution: Balance = 1;
	pub const RemoveKeysLimit: u32 = 100;
223
	pub const MaxMemoLength: u8 = 32;
224
225
226
227
}

impl crowdloan::Config for Test {
	type Event = Event;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
228
	type PalletId = CrowdloanId;
229
230
231
232
233
	type SubmissionDeposit = SubmissionDeposit;
	type MinContribution = MinContribution;
	type RemoveKeysLimit = RemoveKeysLimit;
	type Registrar = Registrar;
	type Auctioneer = Auctions;
234
	type MaxMemoLength = MaxMemoLength;
235
236
237
238
239
	type WeightInfo = crate::crowdloan::TestWeightInfo;
}

/// Create a new set of test externalities.
pub fn new_test_ext() -> TestExternalities {
240
	let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
241
242
	GenesisBuild::<Test>::assimilate_storage(
		&configuration::GenesisConfig {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
243
244
245
246
			config: configuration::HostConfiguration {
				max_code_size: 2 * 1024 * 1024,      // 2 MB
				max_head_data_size: 1 * 1024 * 1024, // 1 MB
				..Default::default()
247
			},
Shawn Tabrizi's avatar
Shawn Tabrizi committed
248
249
250
251
		},
		&mut t,
	)
	.unwrap();
252
253
254
255
256
257
258
	let keystore = KeyStore::new();
	let mut ext: sp_io::TestExternalities = t.into();
	ext.register_extension(KeystoreExt(Arc::new(keystore)));
	ext.execute_with(|| System::set_block_number(1));
	ext
}

259
260
261
262
263
pub fn new_test_ext_with_offset(n: BlockNumber) -> TestExternalities {
	LeaseOffset::set(n);
	new_test_ext()
}

264
265
266
267
const BLOCKS_PER_SESSION: u32 = 10;

fn maybe_new_session(n: u32) {
	if n % BLOCKS_PER_SESSION == 0 {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
268
		shared::Pallet::<Test>::set_session_index(shared::Pallet::<Test>::session_index() + 1);
269
270
271
272
273
274
275
276
277
		Paras::test_on_new_session();
	}
}

fn test_genesis_head(size: usize) -> HeadData {
	HeadData(vec![0u8; size])
}

fn test_validation_code(size: usize) -> ValidationCode {
asynchronous rob's avatar
asynchronous rob committed
278
	let validation_code = vec![0u8; size as usize];
279
280
281
282
283
284
285
286
287
288
289
	ValidationCode(validation_code)
}

fn para_origin(id: u32) -> ParaOrigin {
	ParaOrigin::Parachain(id.into())
}

fn run_to_block(n: u32) {
	assert!(System::block_number() < n);
	while System::block_number() < n {
		let block_number = System::block_number();
290
		AllPallets::on_finalize(block_number);
291
292
293
294
		System::on_finalize(block_number);
		System::set_block_number(block_number + 1);
		System::on_initialize(block_number + 1);
		maybe_new_session(block_number + 1);
295
		AllPallets::on_initialize(block_number + 1);
296
297
298
299
300
301
302
303
304
305
306
307
	}
}

fn run_to_session(n: u32) {
	let block_number = BLOCKS_PER_SESSION * n;
	run_to_block(block_number);
}

fn last_event() -> Event {
	System::events().pop().expect("Event expected").event
}

308
309
// Runs an end to end test of the auction, crowdloan, slots, and onboarding process over varying
// lease period offsets.
310
311
#[test]
fn basic_end_to_end_works() {
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
	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());
			// User 1 and 2 will own parachains
			Balances::make_free_balance_be(&1, 1_000_000_000);
			Balances::make_free_balance_be(&2, 1_000_000_000);
			// First register 2 parathreads
			let genesis_head = Registrar::worst_head_data();
			let validation_code = Registrar::worst_validation_code();
			assert_ok!(Registrar::reserve(Origin::signed(1)));
			assert_ok!(Registrar::register(
				Origin::signed(1),
				ParaId::from(para_1),
				genesis_head.clone(),
				validation_code.clone(),
			));
			assert_ok!(Registrar::reserve(Origin::signed(2)));
			assert_ok!(Registrar::register(
				Origin::signed(2),
				ParaId::from(2001),
				genesis_head,
				validation_code,
			));

			// Paras should be onboarding
			assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Onboarding));
			assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Onboarding));

			// Start a new auction in the future
			let duration = 99u32 + offset;
			let lease_period_index_start = 4u32;
			assert_ok!(Auctions::new_auction(Origin::root(), duration, lease_period_index_start));

			// 2 sessions later they are parathreads
			run_to_session(2);
			assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
			assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));

			// Para 1 will bid directly for slot 1, 2
			// Open a crowdloan for Para 2 for slot 3, 4
			assert_ok!(Crowdloan::create(
				Origin::signed(2),
				ParaId::from(para_2),
				1_000,                        // Cap
				lease_period_index_start + 2, // First Slot
				lease_period_index_start + 3, // Last Slot
				200 + offset,                 // Block End
Shawn Tabrizi's avatar
Shawn Tabrizi committed
362
				None,
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
			));
			let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(para_2));

			// Auction ending begins on block 100 + offset, so we make a bid before then.
			run_to_block(90 + offset);

			Balances::make_free_balance_be(&10, 1_000_000_000);
			Balances::make_free_balance_be(&20, 1_000_000_000);

			// User 10 will bid directly for parachain 1
			assert_ok!(Auctions::bid(
				Origin::signed(10),
				ParaId::from(para_1),
				1,                            // Auction Index
				lease_period_index_start + 0, // First Slot
				lease_period_index_start + 1, // Last slot
				910,                          // Amount
			));

			// User 2 will be a contribute to crowdloan for parachain 2
			Balances::make_free_balance_be(&2, 1_000_000_000);
			assert_ok!(Crowdloan::contribute(Origin::signed(2), ParaId::from(para_2), 920, None));

			// Auction ends at block 110 + offset
			run_to_block(109 + offset);
			assert_eq!(
				last_event(),
				crowdloan::Event::<Test>::HandleBidResult(ParaId::from(para_2), Ok(())).into(),
			);
			run_to_block(110 + offset);
			assert_eq!(last_event(), auctions::Event::<Test>::AuctionClosed(1).into());

			// Paras should have won slots
			assert_eq!(
				slots::Leases::<Test>::get(ParaId::from(para_1)),
				// -- 1 --- 2 --- 3 --------- 4 ------------ 5 --------
				vec![None, None, None, Some((10, 910)), Some((10, 910))],
			);
			assert_eq!(
				slots::Leases::<Test>::get(ParaId::from(para_2)),
				// -- 1 --- 2 --- 3 --- 4 --- 5 ---------------- 6 --------------------------- 7 ----------------
				vec![
					None,
					None,
					None,
					None,
					None,
					Some((crowdloan_account, 920)),
					Some((crowdloan_account, 920))
				],
			);

			// Should not be able to contribute to a winning crowdloan
			Balances::make_free_balance_be(&3, 1_000_000_000);
			assert_noop!(
				Crowdloan::contribute(Origin::signed(3), ParaId::from(2001), 10, None),
				CrowdloanError::<Test>::BidOrLeaseActive
			);

			// New leases will start on block 400
			let lease_start_block = 400 + offset;
			run_to_block(lease_start_block);

			// First slot, Para 1 should be transitioning to Parachain
			assert_eq!(
				Paras::lifecycle(ParaId::from(para_1)),
				Some(ParaLifecycle::UpgradingParathread)
			);
			assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));

			// Two sessions later, it has upgraded
			run_to_block(lease_start_block + 20);
			assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parachain));
			assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));

			// Second slot nothing happens :)
			run_to_block(lease_start_block + 100);
			assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parachain));
			assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));

			// Third slot, Para 2 should be upgrading, and Para 1 is downgrading
			run_to_block(lease_start_block + 200);
			assert_eq!(
				Paras::lifecycle(ParaId::from(para_1)),
				Some(ParaLifecycle::DowngradingParachain)
			);
			assert_eq!(
				Paras::lifecycle(ParaId::from(para_2)),
				Some(ParaLifecycle::UpgradingParathread)
			);

			// Two sessions later, they have transitioned
			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::Parachain));

			// Fourth slot nothing happens :)
			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::Parachain));

			// Fifth slot, Para 2 is downgrading
			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::DowngradingParachain)
			);

			// Two sessions later, Para 2 is downgraded
			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));
		});
	}
478
479
480
481
482
483
}

#[test]
fn basic_errors_fail() {
	new_test_ext().execute_with(|| {
		assert!(System::block_number().is_one());
484
		let para_id = LOWEST_PUBLIC_ID;
485
		// Can't double register
486
487
		Balances::make_free_balance_be(&1, 1_000_000_000);
		Balances::make_free_balance_be(&2, 1_000_000_000);
488
489
490

		let genesis_head = Registrar::worst_head_data();
		let validation_code = Registrar::worst_validation_code();
491
		assert_ok!(Registrar::reserve(Origin::signed(1)));
492
493
		assert_ok!(Registrar::register(
			Origin::signed(1),
494
			para_id,
495
496
497
			genesis_head.clone(),
			validation_code.clone(),
		));
498
		assert_ok!(Registrar::reserve(Origin::signed(2)));
Shawn Tabrizi's avatar
Shawn Tabrizi committed
499
500
501
502
		assert_noop!(
			Registrar::register(Origin::signed(2), para_id, genesis_head, validation_code,),
			paras_registrar::Error::<Test>::NotOwner
		);
503
504
505
506
507
508
509

		// Start an auction
		let duration = 99u32;
		let lease_period_index_start = 4u32;
		assert_ok!(Auctions::new_auction(Origin::root(), duration, lease_period_index_start));

		// Cannot create a crowdloan if you do not own the para
Shawn Tabrizi's avatar
Shawn Tabrizi committed
510
511
512
513
514
515
516
517
518
519
520
521
		assert_noop!(
			Crowdloan::create(
				Origin::signed(2),
				para_id,
				1_000,                        // Cap
				lease_period_index_start + 2, // First Slot
				lease_period_index_start + 3, // Last Slot
				200,                          // Block End
				None,
			),
			crowdloan::Error::<Test>::InvalidOrigin
		);
522
523
524
525
526
527
528
529
530
	});
}

#[test]
fn competing_slots() {
	// This test will verify that competing slots, from different sources will resolve appropriately.
	new_test_ext().execute_with(|| {
		assert!(System::block_number().is_one());
		let max_bids = 10u32;
531
		let para_id = LOWEST_PUBLIC_ID;
532
533

		// Create n paras and owners
Shawn Tabrizi's avatar
Shawn Tabrizi committed
534
		for n in 1..=max_bids {
535
			Balances::make_free_balance_be(&n, 1_000_000_000);
536
537
			let genesis_head = Registrar::worst_head_data();
			let validation_code = Registrar::worst_validation_code();
538
			assert_ok!(Registrar::reserve(Origin::signed(n)));
539
540
			assert_ok!(Registrar::register(
				Origin::signed(n),
541
				para_id + n - 1,
542
543
544
545
546
547
				genesis_head,
				validation_code,
			));
		}

		// Start a new auction in the future
548
		let duration = 149u32;
549
550
551
		let lease_period_index_start = 4u32;
		assert_ok!(Auctions::new_auction(Origin::root(), duration, lease_period_index_start));

552
553
554
		// Paras should be onboarded
		run_to_block(20); // session 2

Shawn Tabrizi's avatar
Shawn Tabrizi committed
555
		for n in 1..=max_bids {
556
			// Increment block number
557
			run_to_block(System::block_number() + 10);
558
559
560
561

			Balances::make_free_balance_be(&(n * 10), n * 1_000);

			let (start, end) = match n {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
562
563
564
565
566
567
568
569
570
				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),
571
572
573
574
				10 => (3, 3),
				_ => panic!("test not meant for this"),
			};

575
			// Users will bid directly for parachain
576
577
			assert_ok!(Auctions::bid(
				Origin::signed(n * 10),
578
				para_id + n - 1,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
579
				1,                                // Auction Index
580
				lease_period_index_start + start, // First Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
581
582
				lease_period_index_start + end,   // Last slot
				n * 900,                          // Amount
583
584
585
			));
		}

586
587
		// Auction should be done after ending period
		run_to_block(160);
588
589
590
591
592

		// Appropriate Paras should have won slots
		// 900 + 4500 + 2x 8100 = 21,600
		// 900 + 4500 + 7200 + 9000 = 21,600
		assert_eq!(
593
			slots::Leases::<Test>::get(para_id),
594
595
596
597
			// -- 1 --- 2 --- 3 ---------- 4 ------
			vec![None, None, None, Some((10, 900))],
		);
		assert_eq!(
598
			slots::Leases::<Test>::get(para_id + 4),
599
600
601
602
603
			// -- 1 --- 2 --- 3 --- 4 ---------- 5 -------
			vec![None, None, None, None, Some((50, 4500))],
		);
		// TODO: Is this right?
		assert_eq!(
604
			slots::Leases::<Test>::get(para_id + 8),
605
606
607
608
609
610
611
612
613
614
615
616
			// -- 1 --- 2 --- 3 --- 4 --- 5 ---------- 6 --------------- 7 -------
			vec![None, None, None, None, None, Some((90, 8100)), Some((90, 8100))],
		);
	});
}

#[test]
fn competing_bids() {
	// This test will verify that competing bids, from different sources will resolve appropriately.
	new_test_ext().execute_with(|| {
		assert!(System::block_number().is_one());

617
		let start_para = LOWEST_PUBLIC_ID - 1;
618
		// Create 3 paras and owners
Shawn Tabrizi's avatar
Shawn Tabrizi committed
619
		for n in 1..=3 {
620
			Balances::make_free_balance_be(&n, 1_000_000_000);
621
622
			let genesis_head = Registrar::worst_head_data();
			let validation_code = Registrar::worst_validation_code();
623
			assert_ok!(Registrar::reserve(Origin::signed(n)));
624
625
			assert_ok!(Registrar::register(
				Origin::signed(n),
626
				ParaId::from(start_para + n),
627
628
629
				genesis_head,
				validation_code,
			));
630
631
632
633
		}

		// Finish registration of paras.
		run_to_session(2);
634

635
636
637
638
639
640
		// Start a new auction in the future
		let starting_block = System::block_number();
		let duration = 99u32;
		let lease_period_index_start = 4u32;
		assert_ok!(Auctions::new_auction(Origin::root(), duration, lease_period_index_start));

Shawn Tabrizi's avatar
Shawn Tabrizi committed
641
		for n in 1..=3 {
642
643
644
			// Create a crowdloan for each para
			assert_ok!(Crowdloan::create(
				Origin::signed(n),
645
				ParaId::from(start_para + n),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
646
				100_000,                      // Cap
647
648
				lease_period_index_start + 2, // First Slot
				lease_period_index_start + 3, // Last Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
649
				200,                          // Block End,
650
651
652
653
				None,
			));
		}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
654
		for n in 1..=9 {
655
			// Increment block number
656
			run_to_block(starting_block + n * 10);
657
658
659

			Balances::make_free_balance_be(&(n * 10), n * 1_000);

660
			let para = start_para + n % 3 + 1;
661
662
663
664
665
666

			if n % 2 == 0 {
				// User 10 will bid directly for parachain 1
				assert_ok!(Auctions::bid(
					Origin::signed(n * 10),
					ParaId::from(para),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
667
					1,                            // Auction Index
668
669
					lease_period_index_start + 0, // First Slot
					lease_period_index_start + 1, // Last slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
670
					n * 900,                      // Amount
671
672
				));
			} else {
673
				// User 20 will be a contribute to crowdloan for parachain 2
674
675
676
677
678
679
680
681
682
683
				assert_ok!(Crowdloan::contribute(
					Origin::signed(n * 10),
					ParaId::from(para),
					n + 900,
					None,
				));
			}
		}

		// Auction should be done
684
		run_to_block(starting_block + 110);
685
686

		// Appropriate Paras should have won slots
687
		let crowdloan_2 = Crowdloan::fund_account_id(ParaId::from(2001));
688
		assert_eq!(
689
			slots::Leases::<Test>::get(ParaId::from(2000)),
690
			// -- 1 --- 2 --- 3 --- 4 --- 5 ------------- 6 ------------------------ 7 -------------
Shawn Tabrizi's avatar
Shawn Tabrizi committed
691
692
693
694
695
696
697
698
699
			vec![
				None,
				None,
				None,
				None,
				None,
				Some((crowdloan_2, 1812)),
				Some((crowdloan_2, 1812))
			],
700
701
		);
		assert_eq!(
702
			slots::Leases::<Test>::get(ParaId::from(2002)),
703
704
705
706
707
708
709
710
711
712
713
			// -- 1 --- 2 --- 3 ---------- 4 --------------- 5 -------
			vec![None, None, None, Some((80, 7200)), Some((80, 7200))],
		);
	});
}

#[test]
fn basic_swap_works() {
	// This test will test a swap between a parachain and parathread works successfully.
	new_test_ext().execute_with(|| {
		assert!(System::block_number().is_one()); // So events are emitted
Shawn Tabrizi's avatar
Shawn Tabrizi committed
714
										  // User 1 and 2 will own paras
715
716
		Balances::make_free_balance_be(&1, 1_000_000_000);
		Balances::make_free_balance_be(&2, 1_000_000_000);
717
		// First register 2 parathreads with different data
718
		assert_ok!(Registrar::reserve(Origin::signed(1)));
719
720
		assert_ok!(Registrar::register(
			Origin::signed(1),
721
			ParaId::from(2000),
722
723
724
			test_genesis_head(10),
			test_validation_code(10),
		));
725
		assert_ok!(Registrar::reserve(Origin::signed(2)));
726
727
		assert_ok!(Registrar::register(
			Origin::signed(2),
728
			ParaId::from(2001),
729
730
731
732
733
			test_genesis_head(20),
			test_validation_code(20),
		));

		// Paras should be onboarding
734
735
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
736
737
738
739
740
741
742
743

		// Start a new auction in the future
		let duration = 99u32;
		let lease_period_index_start = 4u32;
		assert_ok!(Auctions::new_auction(Origin::root(), duration, lease_period_index_start));

		// 2 sessions later they are parathreads
		run_to_session(2);
744
745
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
746
747
748
749

		// Open a crowdloan for Para 1 for slots 0-3
		assert_ok!(Crowdloan::create(
			Origin::signed(1),
750
			ParaId::from(2000),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
751
			1_000_000,                    // Cap
752
753
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 3, // Last Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
754
			200,                          // Block End
755
756
			None,
		));
757
		let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(2000));
758
759
760

		// Bunch of contributions
		let mut total = 0;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
761
		for i in 10..20 {
762
			Balances::make_free_balance_be(&i, 1_000_000_000);
763
			assert_ok!(Crowdloan::contribute(Origin::signed(i), ParaId::from(2000), 900 - i, None));
764
765
766
767
768
769
770
771
772
773
774
775
776
777
			total += 900 - i;
		}
		assert!(total > 0);
		assert_eq!(Balances::free_balance(&crowdloan_account), total);

		// Go to end of auction where everyone won their slots
		run_to_block(200);

		// Deposit is appropriately taken
		// ----------------------------------------- para deposit --- crowdloan
		assert_eq!(Balances::reserved_balance(&1), (500 + 10 * 2 * 1) + 100);
		assert_eq!(Balances::reserved_balance(&2), 500 + 20 * 2 * 1);
		assert_eq!(Balances::reserved_balance(&crowdloan_account), total);
		// Crowdloan is appropriately set
778
779
		assert!(Crowdloan::funds(ParaId::from(2000)).is_some());
		assert!(Crowdloan::funds(ParaId::from(2001)).is_none());
780
781
782
783
784
785

		// New leases will start on block 400
		let lease_start_block = 400;
		run_to_block(lease_start_block);

		// Slots are won by Para 1
786
787
		assert!(!Slots::lease(ParaId::from(2000)).is_empty());
		assert!(Slots::lease(ParaId::from(2001)).is_empty());
788
789
790

		// 2 sessions later it is a parachain
		run_to_block(lease_start_block + 20);
791
792
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parachain));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
793
794

		// Initiate a swap
Shawn Tabrizi's avatar
Shawn Tabrizi committed
795
796
797
798
799
800
801
802
803
804
		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)
		));
805

806
807
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::DowngradingParachain));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::UpgradingParathread));
808
809
810

		// 2 session later they have swapped
		run_to_block(lease_start_block + 40);
811
812
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parachain));
813
814

		// Deregister parathread
815
		assert_ok!(Registrar::deregister(para_origin(2000).into(), ParaId::from(2000)));
816
817
818
819
		// Correct deposit is unreserved
		assert_eq!(Balances::reserved_balance(&1), 100); // crowdloan deposit left over
		assert_eq!(Balances::reserved_balance(&2), 500 + 20 * 2 * 1);
		// Crowdloan ownership is swapped
820
821
		assert!(Crowdloan::funds(ParaId::from(2000)).is_none());
		assert!(Crowdloan::funds(ParaId::from(2001)).is_some());
822
		// Slot is swapped
823
824
		assert!(Slots::lease(ParaId::from(2000)).is_empty());
		assert!(!Slots::lease(ParaId::from(2001)).is_empty());
825
826

		// Cant dissolve
Shawn Tabrizi's avatar
Shawn Tabrizi committed
827
828
829
830
831
832
833
834
		assert_noop!(
			Crowdloan::dissolve(Origin::signed(1), ParaId::from(2000)),
			CrowdloanError::<Test>::InvalidParaId
		);
		assert_noop!(
			Crowdloan::dissolve(Origin::signed(2), ParaId::from(2001)),
			CrowdloanError::<Test>::NotReadyToDissolve
		);
835
836
837
838
839
840

		// Go way in the future when the para is offboarded
		run_to_block(lease_start_block + 1000);

		// Withdraw of contributions works
		assert_eq!(Balances::free_balance(&crowdloan_account), total);
Shawn Tabrizi's avatar
Shawn Tabrizi committed
841
		for i in 10..20 {
842
			assert_ok!(Crowdloan::withdraw(Origin::signed(i), i, ParaId::from(2001)));
843
844
845
846
		}
		assert_eq!(Balances::free_balance(&crowdloan_account), 0);

		// Dissolve returns the balance of the person who put a deposit for crowdloan
847
		assert_ok!(Crowdloan::dissolve(Origin::signed(1), ParaId::from(2001)));
848
849
850
851
		assert_eq!(Balances::reserved_balance(&1), 0);
		assert_eq!(Balances::reserved_balance(&2), 500 + 20 * 2 * 1);

		// Final deregister sets everything back to the start
852
		assert_ok!(Registrar::deregister(para_origin(2001).into(), ParaId::from(2001)));
853
854
855
856
857
858
859
860
		assert_eq!(Balances::reserved_balance(&2), 0);
	})
}

#[test]
fn crowdloan_ending_period_bid() {
	new_test_ext().execute_with(|| {
		assert!(System::block_number().is_one()); // So events are emitted
Shawn Tabrizi's avatar
Shawn Tabrizi committed
861
										  // User 1 and 2 will own paras
862
863
		Balances::make_free_balance_be(&1, 1_000_000_000);
		Balances::make_free_balance_be(&2, 1_000_000_000);
864
		// First register 2 parathreads
865
		assert_ok!(Registrar::reserve(Origin::signed(1)));
866
867
		assert_ok!(Registrar::register(
			Origin::signed(1),
868
			ParaId::from(2000),
869
870
871
			test_genesis_head(10),
			test_validation_code(10),
		));
872
		assert_ok!(Registrar::reserve(Origin::signed(2)));
873
874
		assert_ok!(Registrar::register(
			Origin::signed(2),
875
			ParaId::from(2001),
876
877
878
879
880
			test_genesis_head(20),
			test_validation_code(20),
		));

		// Paras should be onboarding
881
882
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
883
884
885
886
887
888
889
890

		// Start a new auction in the future
		let duration = 99u32;
		let lease_period_index_start = 4u32;
		assert_ok!(Auctions::new_auction(Origin::root(), duration, lease_period_index_start));

		// 2 sessions later they are parathreads
		run_to_session(2);
891
892
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
893
894
895
896

		// Open a crowdloan for Para 1 for slots 0-3
		assert_ok!(Crowdloan::create(
			Origin::signed(1),
897
			ParaId::from(2000),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
898
			1_000_000,                    // Cap
899
900
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 3, // Last Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
901
			200,                          // Block End
902
903
			None,
		));
904
		let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(2000));
905
906
907

		// Bunch of contributions
		let mut total = 0;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
908
		for i in 10..20 {
909
			Balances::make_free_balance_be(&i, 1_000_000_000);
910
			assert_ok!(Crowdloan::contribute(Origin::signed(i), ParaId::from(2000), 900 - i, None));
911
912
913
914
915
916
			total += 900 - i;
		}
		assert!(total > 0);
		assert_eq!(Balances::free_balance(&crowdloan_account), total);

		// Bid for para 2 directly
917
		Balances::make_free_balance_be(&2, 1_000_000_000);
918
919
		assert_ok!(Auctions::bid(
			Origin::signed(2),
920
			ParaId::from(2001),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
921
			1,                            // Auction Index
922
923
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 1, // Last slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
924
			900,                          // Amount
925
926
927
928
929
		));

		// Go to beginning of ending period
		run_to_block(100);

930
		assert_eq!(Auctions::auction_status(100), AuctionStatus::<u32>::EndingPeriod(0, 0));
931
		let mut winning = [None; SlotRange::SLOT_RANGE_COUNT];
932
		winning[SlotRange::ZeroOne as u8 as usize] = Some((2, ParaId::from(2001), 900));
Shawn Tabrizi's avatar
Shawn Tabrizi committed
933
934
		winning[SlotRange::ZeroThree as u8 as usize] =
			Some((crowdloan_account, ParaId::from(2000), total));
935

936
		assert_eq!(Auctions::winning(0), Some(winning));
937
938
939

		run_to_block(101);

940
		Balances::make_free_balance_be(&1234, 1_000_000_000);
941
		assert_ok!(Crowdloan::contribute(Origin::signed(1234), ParaId::from(2000), 900, None));
942
943
944

		// Data propagates correctly
		run_to_block(102);
945
		let mut winning = [None; SlotRange::SLOT_RANGE_COUNT];
946
		winning[SlotRange::ZeroOne as u8 as usize] = Some((2, ParaId::from(2001), 900));
Shawn Tabrizi's avatar
Shawn Tabrizi committed
947
948
		winning[SlotRange::ZeroThree as u8 as usize] =
			Some((crowdloan_account, ParaId::from(2000), total + 900));
949
		assert_eq!(Auctions::winning(2), Some(winning));
950
951
	})
}
952
953
954
955
956
957
958
959
960
961
962
963

#[test]
fn auction_bid_requires_registered_para() {
	new_test_ext().execute_with(|| {
		assert!(System::block_number().is_one()); // So events are emitted

		// Start a new auction in the future
		let duration = 99u32;
		let lease_period_index_start = 4u32;
		assert_ok!(Auctions::new_auction(Origin::root(), duration, lease_period_index_start));

		// Can't bid with non-registered paras
964
		Balances::make_free_balance_be(&1, 1_000_000_000);
Shawn Tabrizi's avatar
Shawn Tabrizi committed
965
966
967
968
969
970
971
972
973
974
975
		assert_noop!(
			Auctions::bid(
				Origin::signed(1),
				ParaId::from(2000),
				1,                            // Auction Index
				lease_period_index_start + 0, // First Slot
				lease_period_index_start + 1, // Last slot
				900,                          // Amount
			),
			AuctionsError::<Test>::ParaNotRegistered
		);
976
977

		// Now we register the para
978
		assert_ok!(Registrar::reserve(Origin::signed(1)));
979
980
		assert_ok!(Registrar::register(
			Origin::signed(1),
981
			ParaId::from(2000),
982
983
984
985
986
			test_genesis_head(10),
			test_validation_code(10),
		));

		// Still can't bid until it is fully onboarded
Shawn Tabrizi's avatar
Shawn Tabrizi committed
987
988
989
990
991
992
993
994
995
996
997
		assert_noop!(
			Auctions::bid(
				Origin::signed(1),
				ParaId::from(2000),
				1,                            // Auction Index
				lease_period_index_start + 0, // First Slot
				lease_period_index_start + 1, // Last slot
				900,                          // Amount
			),
			AuctionsError::<Test>::ParaNotRegistered
		);
998
999
1000

		// Onboarded on Session 2
		run_to_session(2);
For faster browsing, not all history is shown. View entire blame