integration_tests.rs 39.9 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
111
112
113
114
115
116
}

parameter_types! {
	pub const EpochDuration: u64 = 10;
	pub const ExpectedBlockTime: Moment = 6_000;
	pub const ReportLongevity: u64 = 10;
}

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

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
144
	pub const MaxReserves: u32 = 50;
145
146
147
148
149
150
151
152
153
154
}

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
155
156
	type MaxReserves = MaxReserves;
	type ReserveIdentifier = [u8; 8];
157
158
}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
159
impl configuration::Config for Test {}
160

Shawn Tabrizi's avatar
Shawn Tabrizi committed
161
impl shared::Config for Test {}
162
163
164

impl paras::Config for Test {
	type Origin = Origin;
165
	type Event = Event;
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
}

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;
185
	pub const SampleLength: BlockNumber = 1;
186
187
188
189
190
}

impl auctions::Config for Test {
	type Event = Event;
	type Leaser = Slots;
191
	type Registrar = Registrar;
192
	type EndingPeriod = EndingPeriod;
193
	type SampleLength = SampleLength;
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
	type Randomness = TestRandomness<Self>;
	type InitiateOrigin = EnsureRoot<AccountId>;
	type WeightInfo = crate::auctions::TestWeightInfo;
}

parameter_types! {
	pub const LeasePeriod: BlockNumber = 100;
}

impl slots::Config for Test {
	type Event = Event;
	type Currency = Balances;
	type Registrar = Registrar;
	type LeasePeriod = LeasePeriod;
	type WeightInfo = crate::slots::TestWeightInfo;
}

parameter_types! {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
212
	pub const CrowdloanId: PalletId = PalletId(*b"py/cfund");
213
214
215
	pub const SubmissionDeposit: Balance = 100;
	pub const MinContribution: Balance = 1;
	pub const RemoveKeysLimit: u32 = 100;
216
	pub const MaxMemoLength: u8 = 32;
217
218
219
220
}

impl crowdloan::Config for Test {
	type Event = Event;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
221
	type PalletId = CrowdloanId;
222
223
224
225
226
	type SubmissionDeposit = SubmissionDeposit;
	type MinContribution = MinContribution;
	type RemoveKeysLimit = RemoveKeysLimit;
	type Registrar = Registrar;
	type Auctioneer = Auctions;
227
	type MaxMemoLength = MaxMemoLength;
228
229
230
231
232
	type WeightInfo = crate::crowdloan::TestWeightInfo;
}

/// Create a new set of test externalities.
pub fn new_test_ext() -> TestExternalities {
233
	let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
234
235
	GenesisBuild::<Test>::assimilate_storage(
		&configuration::GenesisConfig {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
236
237
238
239
			config: configuration::HostConfiguration {
				max_code_size: 2 * 1024 * 1024,      // 2 MB
				max_head_data_size: 1 * 1024 * 1024, // 1 MB
				..Default::default()
240
			},
Shawn Tabrizi's avatar
Shawn Tabrizi committed
241
242
243
244
		},
		&mut t,
	)
	.unwrap();
245
246
247
248
249
250
251
252
253
254
255
	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
}

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
256
		shared::Pallet::<Test>::set_session_index(shared::Pallet::<Test>::session_index() + 1);
257
258
259
260
261
262
263
264
265
		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
266
	let validation_code = vec![0u8; size as usize];
267
268
269
270
271
272
273
274
275
276
277
	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();
278
		AllPallets::on_finalize(block_number);
279
280
281
282
		System::on_finalize(block_number);
		System::set_block_number(block_number + 1);
		System::on_initialize(block_number + 1);
		maybe_new_session(block_number + 1);
283
		AllPallets::on_initialize(block_number + 1);
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
	}
}

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
}

#[test]
fn basic_end_to_end_works() {
	new_test_ext().execute_with(|| {
299
300
		let para_1 = LOWEST_PUBLIC_ID;
		let para_2 = LOWEST_PUBLIC_ID + 1;
301
302
		assert!(System::block_number().is_one());
		// User 1 and 2 will own parachains
303
304
		Balances::make_free_balance_be(&1, 1_000_000_000);
		Balances::make_free_balance_be(&2, 1_000_000_000);
305
306
307
		// First register 2 parathreads
		let genesis_head = Registrar::worst_head_data();
		let validation_code = Registrar::worst_validation_code();
308
		assert_ok!(Registrar::reserve(Origin::signed(1)));
309
310
		assert_ok!(Registrar::register(
			Origin::signed(1),
311
			ParaId::from(para_1),
312
313
314
			genesis_head.clone(),
			validation_code.clone(),
		));
315
		assert_ok!(Registrar::reserve(Origin::signed(2)));
316
317
		assert_ok!(Registrar::register(
			Origin::signed(2),
318
			ParaId::from(2001),
319
320
321
322
323
			genesis_head,
			validation_code,
		));

		// Paras should be onboarding
324
325
		assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Onboarding));
		assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Onboarding));
326
327
328
329
330
331
332
333

		// 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);
334
335
		assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
336
337
338
339
340

		// 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),
341
			ParaId::from(para_2),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
342
			1_000,                        // Cap
343
344
			lease_period_index_start + 2, // First Slot
			lease_period_index_start + 3, // Last Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
345
			200,                          // Block End
346
347
			None,
		));
348
		let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(para_2));
349
350
351
352

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

353
354
		Balances::make_free_balance_be(&10, 1_000_000_000);
		Balances::make_free_balance_be(&20, 1_000_000_000);
355
356
357
358

		// User 10 will bid directly for parachain 1
		assert_ok!(Auctions::bid(
			Origin::signed(10),
359
			ParaId::from(para_1),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
360
			1,                            // Auction Index
361
362
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 1, // Last slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
363
			910,                          // Amount
364
365
		));

366
		// User 2 will be a contribute to crowdloan for parachain 2
367
		Balances::make_free_balance_be(&2, 1_000_000_000);
368
		assert_ok!(Crowdloan::contribute(Origin::signed(2), ParaId::from(para_2), 920, None));
369
370
371
372
373

		// Auction ends at block 110
		run_to_block(109);
		assert_eq!(
			last_event(),
374
			crowdloan::Event::<Test>::HandleBidResult(ParaId::from(para_2), Ok(())).into(),
375
376
		);
		run_to_block(110);
377
		assert_eq!(last_event(), auctions::Event::<Test>::AuctionClosed(1).into());
378
379
380

		// Paras should have won slots
		assert_eq!(
381
			slots::Leases::<Test>::get(ParaId::from(para_1)),
382
383
384
385
			// -- 1 --- 2 --- 3 --------- 4 ------------ 5 --------
			vec![None, None, None, Some((10, 910)), Some((10, 910))],
		);
		assert_eq!(
386
			slots::Leases::<Test>::get(ParaId::from(para_2)),
387
			// -- 1 --- 2 --- 3 --- 4 --- 5 ---------------- 6 --------------------------- 7 ----------------
Shawn Tabrizi's avatar
Shawn Tabrizi committed
388
389
390
391
392
393
394
395
396
			vec![
				None,
				None,
				None,
				None,
				None,
				Some((crowdloan_account, 920)),
				Some((crowdloan_account, 920))
			],
397
398
		);

399
		// Should not be able to contribute to a winning crowdloan
400
		Balances::make_free_balance_be(&3, 1_000_000_000);
Shawn Tabrizi's avatar
Shawn Tabrizi committed
401
402
403
404
		assert_noop!(
			Crowdloan::contribute(Origin::signed(3), ParaId::from(2001), 10, None),
			CrowdloanError::<Test>::BidOrLeaseActive
		);
405

406
407
408
409
410
		// New leases will start on block 400
		let lease_start_block = 400;
		run_to_block(lease_start_block);

		// First slot, Para 1 should be transitioning to Parachain
Shawn Tabrizi's avatar
Shawn Tabrizi committed
411
412
413
414
		assert_eq!(
			Paras::lifecycle(ParaId::from(para_1)),
			Some(ParaLifecycle::UpgradingParathread)
		);
415
		assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
416
417
418

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

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

		// Third slot, Para 2 should be upgrading, and Para 1 is downgrading
		run_to_block(lease_start_block + 200);
Shawn Tabrizi's avatar
Shawn Tabrizi committed
429
430
431
432
433
434
435
436
		assert_eq!(
			Paras::lifecycle(ParaId::from(para_1)),
			Some(ParaLifecycle::DowngradingParachain)
		);
		assert_eq!(
			Paras::lifecycle(ParaId::from(para_2)),
			Some(ParaLifecycle::UpgradingParathread)
		);
437
438
439

		// Two sessions later, they have transitioned
		run_to_block(lease_start_block + 220);
440
441
		assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parachain));
442
443
444

		// Fourth slot nothing happens :)
		run_to_block(lease_start_block + 300);
445
446
		assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parachain));
447
448
449

		// Fifth slot, Para 2 is downgrading
		run_to_block(lease_start_block + 400);
450
		assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
Shawn Tabrizi's avatar
Shawn Tabrizi committed
451
452
453
454
		assert_eq!(
			Paras::lifecycle(ParaId::from(para_2)),
			Some(ParaLifecycle::DowngradingParachain)
		);
455
456
457

		// Two sessions later, Para 2 is downgraded
		run_to_block(lease_start_block + 420);
458
459
		assert_eq!(Paras::lifecycle(ParaId::from(para_1)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(para_2)), Some(ParaLifecycle::Parathread));
460
461
462
463
464
465
466
	});
}

#[test]
fn basic_errors_fail() {
	new_test_ext().execute_with(|| {
		assert!(System::block_number().is_one());
467
		let para_id = LOWEST_PUBLIC_ID;
468
		// Can't double register
469
470
		Balances::make_free_balance_be(&1, 1_000_000_000);
		Balances::make_free_balance_be(&2, 1_000_000_000);
471
472
473

		let genesis_head = Registrar::worst_head_data();
		let validation_code = Registrar::worst_validation_code();
474
		assert_ok!(Registrar::reserve(Origin::signed(1)));
475
476
		assert_ok!(Registrar::register(
			Origin::signed(1),
477
			para_id,
478
479
480
			genesis_head.clone(),
			validation_code.clone(),
		));
481
		assert_ok!(Registrar::reserve(Origin::signed(2)));
Shawn Tabrizi's avatar
Shawn Tabrizi committed
482
483
484
485
		assert_noop!(
			Registrar::register(Origin::signed(2), para_id, genesis_head, validation_code,),
			paras_registrar::Error::<Test>::NotOwner
		);
486
487
488
489
490
491
492

		// 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
493
494
495
496
497
498
499
500
501
502
503
504
		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
		);
505
506
507
508
509
510
511
512
513
	});
}

#[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;
514
		let para_id = LOWEST_PUBLIC_ID;
515
516

		// Create n paras and owners
Shawn Tabrizi's avatar
Shawn Tabrizi committed
517
		for n in 1..=max_bids {
518
			Balances::make_free_balance_be(&n, 1_000_000_000);
519
520
			let genesis_head = Registrar::worst_head_data();
			let validation_code = Registrar::worst_validation_code();
521
			assert_ok!(Registrar::reserve(Origin::signed(n)));
522
523
			assert_ok!(Registrar::register(
				Origin::signed(n),
524
				para_id + n - 1,
525
526
527
528
529
530
				genesis_head,
				validation_code,
			));
		}

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

535
536
537
		// Paras should be onboarded
		run_to_block(20); // session 2

Shawn Tabrizi's avatar
Shawn Tabrizi committed
538
		for n in 1..=max_bids {
539
			// Increment block number
540
			run_to_block(System::block_number() + 10);
541
542
543
544

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

			let (start, end) = match n {
Shawn Tabrizi's avatar
Shawn Tabrizi committed
545
546
547
548
549
550
551
552
553
				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),
554
555
556
557
				10 => (3, 3),
				_ => panic!("test not meant for this"),
			};

558
			// Users will bid directly for parachain
559
560
			assert_ok!(Auctions::bid(
				Origin::signed(n * 10),
561
				para_id + n - 1,
Shawn Tabrizi's avatar
Shawn Tabrizi committed
562
				1,                                // Auction Index
563
				lease_period_index_start + start, // First Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
564
565
				lease_period_index_start + end,   // Last slot
				n * 900,                          // Amount
566
567
568
			));
		}

569
570
		// Auction should be done after ending period
		run_to_block(160);
571
572
573
574
575

		// Appropriate Paras should have won slots
		// 900 + 4500 + 2x 8100 = 21,600
		// 900 + 4500 + 7200 + 9000 = 21,600
		assert_eq!(
576
			slots::Leases::<Test>::get(para_id),
577
578
579
580
			// -- 1 --- 2 --- 3 ---------- 4 ------
			vec![None, None, None, Some((10, 900))],
		);
		assert_eq!(
581
			slots::Leases::<Test>::get(para_id + 4),
582
583
584
585
586
			// -- 1 --- 2 --- 3 --- 4 ---------- 5 -------
			vec![None, None, None, None, Some((50, 4500))],
		);
		// TODO: Is this right?
		assert_eq!(
587
			slots::Leases::<Test>::get(para_id + 8),
588
589
590
591
592
593
594
595
596
597
598
599
			// -- 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());

600
		let start_para = LOWEST_PUBLIC_ID - 1;
601
		// Create 3 paras and owners
Shawn Tabrizi's avatar
Shawn Tabrizi committed
602
		for n in 1..=3 {
603
			Balances::make_free_balance_be(&n, 1_000_000_000);
604
605
			let genesis_head = Registrar::worst_head_data();
			let validation_code = Registrar::worst_validation_code();
606
			assert_ok!(Registrar::reserve(Origin::signed(n)));
607
608
			assert_ok!(Registrar::register(
				Origin::signed(n),
609
				ParaId::from(start_para + n),
610
611
612
				genesis_head,
				validation_code,
			));
613
614
615
616
		}

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

618
619
620
621
622
623
		// 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
624
		for n in 1..=3 {
625
626
627
			// Create a crowdloan for each para
			assert_ok!(Crowdloan::create(
				Origin::signed(n),
628
				ParaId::from(start_para + n),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
629
				100_000,                      // Cap
630
631
				lease_period_index_start + 2, // First Slot
				lease_period_index_start + 3, // Last Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
632
				200,                          // Block End,
633
634
635
636
				None,
			));
		}

Shawn Tabrizi's avatar
Shawn Tabrizi committed
637
		for n in 1..=9 {
638
			// Increment block number
639
			run_to_block(starting_block + n * 10);
640
641
642

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

643
			let para = start_para + n % 3 + 1;
644
645
646
647
648
649

			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
650
					1,                            // Auction Index
651
652
					lease_period_index_start + 0, // First Slot
					lease_period_index_start + 1, // Last slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
653
					n * 900,                      // Amount
654
655
				));
			} else {
656
				// User 20 will be a contribute to crowdloan for parachain 2
657
658
659
660
661
662
663
664
665
666
				assert_ok!(Crowdloan::contribute(
					Origin::signed(n * 10),
					ParaId::from(para),
					n + 900,
					None,
				));
			}
		}

		// Auction should be done
667
		run_to_block(starting_block + 110);
668
669

		// Appropriate Paras should have won slots
670
		let crowdloan_2 = Crowdloan::fund_account_id(ParaId::from(2001));
671
		assert_eq!(
672
			slots::Leases::<Test>::get(ParaId::from(2000)),
673
			// -- 1 --- 2 --- 3 --- 4 --- 5 ------------- 6 ------------------------ 7 -------------
Shawn Tabrizi's avatar
Shawn Tabrizi committed
674
675
676
677
678
679
680
681
682
			vec![
				None,
				None,
				None,
				None,
				None,
				Some((crowdloan_2, 1812)),
				Some((crowdloan_2, 1812))
			],
683
684
		);
		assert_eq!(
685
			slots::Leases::<Test>::get(ParaId::from(2002)),
686
687
688
689
690
691
692
693
694
695
696
			// -- 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
697
										  // User 1 and 2 will own paras
698
699
		Balances::make_free_balance_be(&1, 1_000_000_000);
		Balances::make_free_balance_be(&2, 1_000_000_000);
700
		// First register 2 parathreads with different data
701
		assert_ok!(Registrar::reserve(Origin::signed(1)));
702
703
		assert_ok!(Registrar::register(
			Origin::signed(1),
704
			ParaId::from(2000),
705
706
707
			test_genesis_head(10),
			test_validation_code(10),
		));
708
		assert_ok!(Registrar::reserve(Origin::signed(2)));
709
710
		assert_ok!(Registrar::register(
			Origin::signed(2),
711
			ParaId::from(2001),
712
713
714
715
716
			test_genesis_head(20),
			test_validation_code(20),
		));

		// Paras should be onboarding
717
718
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
719
720
721
722
723
724
725
726

		// 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);
727
728
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
729
730
731
732

		// Open a crowdloan for Para 1 for slots 0-3
		assert_ok!(Crowdloan::create(
			Origin::signed(1),
733
			ParaId::from(2000),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
734
			1_000_000,                    // Cap
735
736
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 3, // Last Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
737
			200,                          // Block End
738
739
			None,
		));
740
		let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(2000));
741
742
743

		// Bunch of contributions
		let mut total = 0;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
744
		for i in 10..20 {
745
			Balances::make_free_balance_be(&i, 1_000_000_000);
746
			assert_ok!(Crowdloan::contribute(Origin::signed(i), ParaId::from(2000), 900 - i, None));
747
748
749
750
751
752
753
754
755
756
757
758
759
760
			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
761
762
		assert!(Crowdloan::funds(ParaId::from(2000)).is_some());
		assert!(Crowdloan::funds(ParaId::from(2001)).is_none());
763
764
765
766
767
768

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

		// Slots are won by Para 1
769
770
		assert!(!Slots::lease(ParaId::from(2000)).is_empty());
		assert!(Slots::lease(ParaId::from(2001)).is_empty());
771
772
773

		// 2 sessions later it is a parachain
		run_to_block(lease_start_block + 20);
774
775
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parachain));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
776
777

		// Initiate a swap
Shawn Tabrizi's avatar
Shawn Tabrizi committed
778
779
780
781
782
783
784
785
786
787
		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)
		));
788

789
790
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::DowngradingParachain));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::UpgradingParathread));
791
792
793

		// 2 session later they have swapped
		run_to_block(lease_start_block + 40);
794
795
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parachain));
796
797

		// Deregister parathread
798
		assert_ok!(Registrar::deregister(para_origin(2000).into(), ParaId::from(2000)));
799
800
801
802
		// 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
803
804
		assert!(Crowdloan::funds(ParaId::from(2000)).is_none());
		assert!(Crowdloan::funds(ParaId::from(2001)).is_some());
805
		// Slot is swapped
806
807
		assert!(Slots::lease(ParaId::from(2000)).is_empty());
		assert!(!Slots::lease(ParaId::from(2001)).is_empty());
808
809

		// Cant dissolve
Shawn Tabrizi's avatar
Shawn Tabrizi committed
810
811
812
813
814
815
816
817
		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
		);
818
819
820
821
822
823

		// 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
824
		for i in 10..20 {
825
			assert_ok!(Crowdloan::withdraw(Origin::signed(i), i, ParaId::from(2001)));
826
827
828
829
		}
		assert_eq!(Balances::free_balance(&crowdloan_account), 0);

		// Dissolve returns the balance of the person who put a deposit for crowdloan
830
		assert_ok!(Crowdloan::dissolve(Origin::signed(1), ParaId::from(2001)));
831
832
833
834
		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
835
		assert_ok!(Registrar::deregister(para_origin(2001).into(), ParaId::from(2001)));
836
837
838
839
840
841
842
843
		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
844
										  // User 1 and 2 will own paras
845
846
		Balances::make_free_balance_be(&1, 1_000_000_000);
		Balances::make_free_balance_be(&2, 1_000_000_000);
847
		// First register 2 parathreads
848
		assert_ok!(Registrar::reserve(Origin::signed(1)));
849
850
		assert_ok!(Registrar::register(
			Origin::signed(1),
851
			ParaId::from(2000),
852
853
854
			test_genesis_head(10),
			test_validation_code(10),
		));
855
		assert_ok!(Registrar::reserve(Origin::signed(2)));
856
857
		assert_ok!(Registrar::register(
			Origin::signed(2),
858
			ParaId::from(2001),
859
860
861
862
863
			test_genesis_head(20),
			test_validation_code(20),
		));

		// Paras should be onboarding
864
865
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
866
867
868
869
870
871
872
873

		// 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);
874
875
		assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
		assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
876
877
878
879

		// Open a crowdloan for Para 1 for slots 0-3
		assert_ok!(Crowdloan::create(
			Origin::signed(1),
880
			ParaId::from(2000),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
881
			1_000_000,                    // Cap
882
883
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 3, // Last Slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
884
			200,                          // Block End
885
886
			None,
		));
887
		let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(2000));
888
889
890

		// Bunch of contributions
		let mut total = 0;
Shawn Tabrizi's avatar
Shawn Tabrizi committed
891
		for i in 10..20 {
892
			Balances::make_free_balance_be(&i, 1_000_000_000);
893
			assert_ok!(Crowdloan::contribute(Origin::signed(i), ParaId::from(2000), 900 - i, None));
894
895
896
897
898
899
			total += 900 - i;
		}
		assert!(total > 0);
		assert_eq!(Balances::free_balance(&crowdloan_account), total);

		// Bid for para 2 directly
900
		Balances::make_free_balance_be(&2, 1_000_000_000);
901
902
		assert_ok!(Auctions::bid(
			Origin::signed(2),
903
			ParaId::from(2001),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
904
			1,                            // Auction Index
905
906
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 1, // Last slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
907
			900,                          // Amount
908
909
910
911
912
		));

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

913
		assert_eq!(Auctions::auction_status(100), AuctionStatus::<u32>::EndingPeriod(0, 0));
914
		let mut winning = [None; SlotRange::SLOT_RANGE_COUNT];
915
		winning[SlotRange::ZeroOne as u8 as usize] = Some((2, ParaId::from(2001), 900));
Shawn Tabrizi's avatar
Shawn Tabrizi committed
916
917
		winning[SlotRange::ZeroThree as u8 as usize] =
			Some((crowdloan_account, ParaId::from(2000), total));
918

919
		assert_eq!(Auctions::winning(0), Some(winning));
920
921
922

		run_to_block(101);

923
		Balances::make_free_balance_be(&1234, 1_000_000_000);
924
		assert_ok!(Crowdloan::contribute(Origin::signed(1234), ParaId::from(2000), 900, None));
925
926
927

		// Data propagates correctly
		run_to_block(102);
928
		let mut winning = [None; SlotRange::SLOT_RANGE_COUNT];
929
		winning[SlotRange::ZeroOne as u8 as usize] = Some((2, ParaId::from(2001), 900));
Shawn Tabrizi's avatar
Shawn Tabrizi committed
930
931
		winning[SlotRange::ZeroThree as u8 as usize] =
			Some((crowdloan_account, ParaId::from(2000), total + 900));
932
		assert_eq!(Auctions::winning(2), Some(winning));
933
934
	})
}
935
936
937
938
939
940
941
942
943
944
945
946

#[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
947
		Balances::make_free_balance_be(&1, 1_000_000_000);
Shawn Tabrizi's avatar
Shawn Tabrizi committed
948
949
950
951
952
953
954
955
956
957
958
		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
		);
959
960

		// Now we register the para
961
		assert_ok!(Registrar::reserve(Origin::signed(1)));
962
963
		assert_ok!(Registrar::register(
			Origin::signed(1),
964
			ParaId::from(2000),
965
966
967
968
969
			test_genesis_head(10),
			test_validation_code(10),
		));

		// Still can't bid until it is fully onboarded
Shawn Tabrizi's avatar
Shawn Tabrizi committed
970
971
972
973
974
975
976
977
978
979
980
		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
		);
981
982
983
984
985

		// Onboarded on Session 2
		run_to_session(2);

		// Success
986
		Balances::make_free_balance_be(&1, 1_000_000_000);
987
988
		assert_ok!(Auctions::bid(
			Origin::signed(1),
989
			ParaId::from(2000),
Shawn Tabrizi's avatar
Shawn Tabrizi committed
990
			1,                            // Auction Index
991
992
			lease_period_index_start + 0, // First Slot
			lease_period_index_start + 1, // Last slot
Shawn Tabrizi's avatar
Shawn Tabrizi committed
993
			900,                          // Amount
994
995
996
		));
	});
}
997
998
999
1000

#[test]
fn gap_bids_work() {
	new_test_ext().execute_with(|| {
For faster browsing, not all history is shown. View entire blame