mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-26 01:51:07 +00:00
1a1bfd2af9
* cargo fmt * Create benchmarks for XCM instructions introduced in v3 (#4564) * Create benchmarks for BurnAsset and ExpectAsset * Add benchmarks for ExpectOrigin and ExpectError * Add benchmarks for QueryPallet and ExpectPallet * Add benchmarks for ReportTransactStatus and ClearTransactStatus * cargo fmt * Use AllPalletsWithSystem in mocks * Update XCM generic benchmarks for westend * Remove default impls for some XCM weight functions * Fix compilation error * Add weight_args helper attribute * Remove manually written XcmWeightInfo * Parse trailing comma * Revert "Add weight_args helper attribute" This reverts commit 3b7c47a6182e1b9227036c38b406d494c3fcf6fd. * Fixes * Fixes * XCM v3: Introduce querier field into `QueryReponse` (#4732) * Introduce querier field into QueryReponse * Convert &Option<MultiLocation> to Option<&MultiLocation> &Option<T> is almost always never quite useful, most of the time it still gets converted to an Option<&T> via `as_ref`, so we should simply make functions that accept Option<&T> instead. * Fix tests * cargo fmt * Fix benchmarks * Appease spellchecker * Fix test * Fix tests * Fix test * Fix mock * Fixes * Fix tests * Add test for response queriers * Update xcm/pallet-xcm/src/lib.rs * Test for non-existence of querier Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Fixes * Fixes * Add `starts_with` function to `MultiLocation` and `Junctions` (#4835) * add matches_prefix function to MultiLocation and Junctions * rename matches_prefix to starts_with * remove unnecessary main in doc comment Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Make use of starts_with in match_and_split Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * XCM v3: Bridge infrastructure (#4681) * XCM bridge infrastructure * Missing bit of cherry-pick * Revamped XCM proc macros; new NetworkIds * Fixes * Formatting * ExportMessage instruction and config type * Add MessageExporter definitions * Formatting * Missing files * Fixes * Initial bridging config API * Allow for two-stage XCM execution * Update xcm/src/v3/mod.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * XCM crate building again * Initial bridging primitive * Docs * Docs * More work * More work * Merge branch 'gav-xcm-v3' into gav-xcm-v3-bridging * Make build * WithComputedOrigin and SovereignPaidRemoteExporter * Remove TODOs * Slim bridge API and tests. * Fixes * More work * First bridge test passing * Formatting * Another test * Next round of bridging tests * Repot tests * Cleanups * Paid bridging * Formatting * Tests * Spelling * Formatting * Fees and refactoring * Fixes * Formatting * Refactor SendXcm to become two-phase * Fix tests * Refactoring of SendXcm and ExportXcm complete * Formatting * Rename CannotReachDestination -> NotApplicable * Remove XCM v0 * Minor grumbles * Formatting * Formatting * Fixes * Fixes * Cleanup XCM config * Fee handling * Fixes * Formatting * Fixes * Bump Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Bump Substrate * XCM v3: `ExchangeAsset` and Remote-locking (#4945) * Asset Exchange and Locks * Make sure XCM typers impl MaxEncodedLen * Basic implementation for locks * Bump Substrate * Missing files * Use new API * Introduce instruction * Big refactor * Docs * Remove deprecated struct * Remove deprecated struct * Repot XCM builder tests * ExchangeAsset test * Exchange tests * Locking tests * Locking tests * Fixes and tests * Fixes * Formatting * Spelling * Add simulator test for remote locking * Fix tests * Bump * XCM v3: Support for non-fungibles (#4950) * NFT support and a test * New files. * Integration tests for sending NFTs * Formatting * Broken Cargo features * Use 2021 edition * Fixes * Formatting * Formatting * Update xcm/xcm-builder/src/asset_conversion.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update xcm/xcm-builder/src/nonfungibles_adapter.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update xcm/xcm-executor/src/lib.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Fixes * Fixes * Fixes * Formatting * Fixes Co-authored-by: Bastian Köcher <info@kchr.de> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * XCM v3: Context & ID hash (#4756) * send_xcm returns message hash * cargo fmt * Create topic register and instructions * Fix weights * Use tabs * Sketch out XcmContext * Fix doc test * Add the XCM context as a parameter to executor trait fns * Fixes * Add XcmContext parameter * Revert adding context as an arg to SendXcm trait methods * Revert adding context argument to ConvertOrigin trait methods * cargo fmt * Do not change the API of XcmExecutor::execute * Fixes * Fixes * Fixes * Fixes * Remove convenience method * Fixes * Fixes * cargo fmt * Fixes * Add benchmarks for XCM topic instructions * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark --chain=westend-dev --steps=50 --repeat=20 --pallet=pallet_xcm_benchmarks::generic --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./runtime/westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs * Remove context argument on FilterAssetLocation * Fixes * Remove unused import * Fixes * Fixes * Fixes * Accept XCM hash parameter in ExecuteXcm trait methods * cargo fmt * Properly enable sp-io/std * Fixes * default-features = false * Fixes * Fixes * Fixes * Make XcmContext optional in withdraw_asset * Fixes * Fixes * Fixes * Modify tests to check for the correct XCM hash * Small refactor * cargo fmt * Check for expected hash in xcm-builder unit tests * Add doc comment for the optionality of the XCM context in withdraw_asset * Update xcm/src/v3/traits.rs * Update xcm/src/v3/traits.rs * Store XcmContext and avoid rebuilding * Use ref for XcmContext * Formatting * Fix incorrect hash CC @KiChjang * Refactor and make clear fake hashes * Fixes * Fixes * Fixes * Fix broken hashing * Docs * Fixes * Fixes * Fixes * Formatting * Fixes * Fixes * Fixes * Remove unknowable hash * Formatting * Use message hash for greater identifiability * Formatting * Fixes * Formatting Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Parity Bot <admin@parity.io> * Fixes * Fixes * Fixes * Fixes * Formatting * Fixes * Formatting * Fixes * Fixes * Formatting * Formatting * Remove horrible names * Bump * Remove InvertLocation trait (#5092) * Remove InvertLocation trait * Remove unneeded functions * Formatting * Fixes * Remove XCMv1 (#5094) * Remove XCMv1 * Remove XCMv1 * Formatting * Fixes * Fixes * Formatting * derive serialize/deserialize for xcm primitives (#5036) * derive serialize/deserialize for xcm primitives * derive serialize/deserialize for xcm primitives * update v3 * update v2 Co-authored-by: Gav Wood <gavin@parity.io> * Update lock * Fixes * Add benchmarks for the ExchangeAsset instruction * `AliasOrigin` instruction stub (#5122) * AliasOrigin instruction stub * Fixes * Fixes * Update substrate * Fixes * Ensure same array length before using copy_from_slice * Fixes * Add benchmarks for the UniversalOrigin instruction * Remove unused import * Remove unused import * Add benchmarks for SetFeesMode instruction * Add benchmarks for asset (un)locking instructions * Leave AliasOrigin unbenchmarked * Fixes after merge * cargo fmt * Fixes * Fixes * Set TrustedReserves to None on both Kusama and Westend * Remove extraneous reserve_asset_deposited benchmark * Fix universal_origin benchmark * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark pallet --chain=westend-dev --steps=50 --repeat=20 --pallet=pallet_xcm_benchmarks::generic --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./runtime/westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs * Don't rely on skipped benchmark functions * Fixes * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark pallet --chain=kusama-dev --steps=50 --repeat=20 --pallet=pallet_xcm_benchmarks::generic --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./runtime/kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs * Fix unused variables * Fixes * Spelling * Fixes * Fix codec index of VersionedXcm * Allows to customize how calls are dispatched from XCM (#5657) * CallDispatcher trait * fmt * unused import * fix test-runtime * remove JustDispatch type * fix typo in test-runtime * missing CallDispatcher * more missing CallDispatcher * Update comment `NoteAssetLocked` -> `NoteUnlockable` * Fixes * Fixes * Adjust MultiAssets weights based on new wild card variants * Fixes * Fixes * Fixes * Fixes * Fixes * Some late fixes for XCMv3 (#5237) * Maximise chances that trapped assets can be reclaimed * Do origin check as part of ExportMessage for security * Formatting * Fixes * Cleanup export XCM APIs * Formatting * Update xcm/src/v3/junctions.rs * UnpaidExecution instruction and associated barrier. * Tighten barriers (ClearOrigin/QueryResponse) * Allow only 1 ClearOrigin instruction in AllowTopLevelPaidExecutionFrom * Bi-directional teleport accounting * Revert other fix * Build fixes] * Tests build * Benchmark fixes Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update Substrate * Re-export `pub` stuff from universal_exports.rs + removed unecessary clone (#6145) * Re-export `pub` stuff from universal_exports.rs * Removed unnecessary clone * Use 2D weights in XCM v3 (#6134) * Depend upon sp-core instead of sp-runtime * Make sp-io a dev-dependency * Use 2D weights in XCM v3 * cargo fmt * Add XCM pallet migration to runtimes * Use from_parts * cargo fmt * Fixes * cargo fmt * Remove XCMWeight import * Fixes * Fixes * Fixes * Fixes * Use translate in migration * Increase max upward message size in tests * Fix doc test * Remove most uses of from_ref_time * cargo fmt * Fixes * Fixes * Add extrinsic benchmarking to XCM pallet * cargo fmt * Fixes * Use old syntax * cargo fmt * Fixes * Remove hardcoded weights * Add XCM pallet to benchmarks * Use successful origin * Fix weird type parameter compilation issue * Fixes * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime rococo-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime kusama-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * Use benchmarked XCM pallet weights * Fixes * Fixes * Use override instead of skip * Fixes * Fixes * Fixes * Fixes * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * Fixes * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm Co-authored-by: command-bot <> * Replace Weight::MAX with 100b weight units * Add test to ensure all_gte in barriers is correct * Update xcm/src/v3/junction.rs Co-authored-by: asynchronous rob <rphmeier@gmail.com> * Add more weight tests * cargo fmt * Create thread_local in XCM executor to limit recursion depth (#6304) * Create thread_local in XCM executor to limit recursion depth * Add unit test for recursion limit * Fix statefulness in tests * Remove panic * Use defer and environmental macro * Fix the implementation * Use nicer interface * Change ThisNetwork to AnyNetwork * Move recursion check up to top level * cargo fmt * Update comment Co-authored-by: Bastian Köcher <info@kchr.de> * Add upper limit on the number of overweight messages in the queue (#6298) * Add upper limit on the number of ovwerweight messages in the queue * Add newline * Introduce whitelist for Transact and limit UMP processing to 10 messages per block (#6280) * Add SafeCallFilter to XcmConfig * Limit UMP to receive 10 messages every block * Place 10 message limit on processing instead of receiving * Always increment the message_processed count whenever a message is processed * Add as_derivative to the Transact whitelist * cargo fmt * Fixes * Update xcm/xcm-builder/src/universal_exports.rs Co-authored-by: Branislav Kontur <bkontur@gmail.com> * Fixes * Fixes * Remove topic register and instead use the topic field in XcmContext * Derive some common traits for DispatchBlobError * Fixes * cargo fmt * Fixes * Fixes * Fix comments * Fixes * Introduce WithOriginFilter and apply it as the CallDispatcher for runtimes * Fixes * Appease clippy and fixes * Fixes * Fix more clippy issues * Fixes * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * Add benchmark function for ExportMessage * Fix comment * Add upper limit to DownwardMessageQueues size * Add max size check for queue in can_queue_downward_message * Fixes * Make Transact runtime call configurable * Return Weight::MAX when there is no successful send XCM origin * Update substrate * Fixes * Fixes * Remove ExportMessage benchmark * Remove assertion on Transact instruction benchmark * Make reachable destination configurable in XCM pallet benchmarks * Fixes * Fixes * Remove cfg attribute in fuzzer * Fixes * Remove cfg attribute for XCM pallet in test runtime * Fixes * Use ReachableDest where possible * Fixes * Add benchmark for UnpaidExecution * Update substrate * Ensure benchmark functions pass filters * Add runtime-benchmarks feature to fuzzer * Ensure FixedRateOfFungible accounts for proof size weights * cargo fmt * Whitelist remark_with_event when runtime-benchmarks feature is enabled * Use remark_with_event for Transact benchmarks * Fix Cargo.lock * Allow up to 3 DescendOrigin instructions before UnpaidExecution * cargo fmt * Edit code comment * Check check_origin for unpaid execution privilege * Fixes * Small nits for xcm-v3 (#6408) * Add possibility to skip benchmark for export_message * ".git/.scripts/bench-bot.sh" xcm westend-dev pallet_xcm_benchmarks::generic * Revert * ".git/.scripts/bench-bot.sh" xcm westend-dev pallet_xcm_benchmarks::generic * Add HaulBlobError to `fn haul_blob` * ".git/.scripts/bench-bot.sh" xcm westend-dev pallet_xcm_benchmarks::generic Co-authored-by: command-bot <> * Revert changes to UnpaidExecution * Change AllowUnpaidExecutionFrom to be explicit * Fix log text * cargo fmt * Add benchmarks for XCM pallet version migration (#6448) * Add benchmarks for XCM pallet version migration * cargo fmt * Fixes * Fixes * Fixes * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime kusama-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime rococo-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * Fix benchmarks * Fix benchmarks * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime kusama-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime rococo-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm Co-authored-by: command-bot <> * Merge remote-tracking branch 'origin/master' into gav-xcm-v3 * Fixes * Fix comments (#6470) * Specify Ethereum networks by their chain id (#6286) Co-authored-by: Squirrel <gilescope@gmail.com> * Use for Kusama * Use WithComputedOrigin for Polkadot, Rococo and Westend * Update lock * Fix warning * Update xcm/pallet-xcm/src/tests.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update runtime/parachains/src/ump/migration.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update xcm/pallet-xcm/src/migration.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixes * cargo fmt * Typo * Update xcm/src/v3/mod.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Docs * Docs * Docs * Docs * Update xcm/src/v3/multiasset.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add tests for MultiAssets::from_sorted_and_deduplicated * Fail gracefully when same instance NFTs are detected during push * Update Substrate to fix benchmarks * Apply suggestions from code review * Update runtime/kusama/src/xcm_config.rs * Rename arguments * Attempt to fix benchmark * ".git/.scripts/commands/bench/bench.sh" runtime polkadot-dev runtime_parachains::ump * Use actual weights for UMP pallet in Polkadot * ".git/.scripts/commands/bench/bench.sh" runtime kusama-dev runtime_parachains::ump * ".git/.scripts/commands/bench/bench.sh" runtime westend-dev runtime_parachains::ump * ".git/.scripts/commands/bench/bench.sh" runtime rococo-dev runtime_parachains::ump Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Bastian Köcher <info@kchr.de> Co-authored-by: Parity Bot <admin@parity.io> Co-authored-by: stanly-johnson <stanlyjohnson@outlook.com> Co-authored-by: nanocryk <6422796+nanocryk@users.noreply.github.com> Co-authored-by: Branislav Kontur <bkontur@gmail.com> Co-authored-by: asynchronous rob <rphmeier@gmail.com> Co-authored-by: command-bot <> Co-authored-by: Vincent Geddes <vincent.geddes@hey.com> Co-authored-by: Squirrel <gilescope@gmail.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
1620 lines
48 KiB
Rust
1620 lines
48 KiB
Rust
// 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.
|
|
|
|
use crate::{
|
|
auctions, crowdloan, paras_registrar,
|
|
slot_range::SlotRange,
|
|
slots,
|
|
traits::{AuctionStatus, Auctioneer, Leaser, Registrar as RegistrarT},
|
|
};
|
|
use frame_support::{
|
|
assert_noop, assert_ok, parameter_types,
|
|
traits::{Currency, GenesisBuild, KeyOwnerProofSystem, OnFinalize, OnInitialize},
|
|
weights::Weight,
|
|
PalletId,
|
|
};
|
|
use frame_support_test::TestRandomness;
|
|
use frame_system::EnsureRoot;
|
|
use parity_scale_codec::Encode;
|
|
use primitives::{BlockNumber, HeadData, Header, Id as ParaId, ValidationCode, LOWEST_PUBLIC_ID};
|
|
use runtime_parachains::{
|
|
configuration, origin, 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},
|
|
transaction_validity::TransactionPriority,
|
|
AccountId32,
|
|
};
|
|
use sp_std::sync::Arc;
|
|
|
|
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
|
type Block = frame_system::mocking::MockBlock<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)
|
|
}
|
|
|
|
frame_support::construct_runtime!(
|
|
pub enum Test where
|
|
Block = Block,
|
|
NodeBlock = Block,
|
|
UncheckedExtrinsic = UncheckedExtrinsic,
|
|
{
|
|
// System Stuff
|
|
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},
|
|
|
|
// Parachains Runtime
|
|
Configuration: configuration::{Pallet, Call, Storage, Config<T>},
|
|
Paras: paras::{Pallet, Call, Storage, Event, Config},
|
|
ParasShared: shared::{Pallet, Call, Storage},
|
|
ParachainsOrigin: origin::{Pallet, Origin},
|
|
|
|
// Para Onboarding Pallets
|
|
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>},
|
|
}
|
|
);
|
|
|
|
impl<C> frame_system::offchain::SendTransactionTypes<C> for Test
|
|
where
|
|
RuntimeCall: From<C>,
|
|
{
|
|
type Extrinsic = UncheckedExtrinsic;
|
|
type OverarchingCall = RuntimeCall;
|
|
}
|
|
|
|
use crate::{auctions::Error as AuctionsError, crowdloan::Error as CrowdloanError};
|
|
|
|
parameter_types! {
|
|
pub const BlockHashCount: u32 = 250;
|
|
pub BlockWeights: frame_system::limits::BlockWeights =
|
|
frame_system::limits::BlockWeights::simple_max(
|
|
Weight::from_parts(4 * 1024 * 1024, u64::MAX),
|
|
);
|
|
}
|
|
|
|
impl frame_system::Config for Test {
|
|
type BaseCallFilter = frame_support::traits::Everything;
|
|
type BlockWeights = BlockWeights;
|
|
type BlockLength = ();
|
|
type DbWeight = ();
|
|
type RuntimeOrigin = RuntimeOrigin;
|
|
type RuntimeCall = RuntimeCall;
|
|
type Index = u64;
|
|
type BlockNumber = BlockNumber;
|
|
type Hash = H256;
|
|
type Hashing = BlakeTwo256;
|
|
type AccountId = AccountId;
|
|
type Lookup = IdentityLookup<AccountId>;
|
|
type Header = Header;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type BlockHashCount = BlockHashCount;
|
|
type Version = ();
|
|
type PalletInfo = PalletInfo;
|
|
type AccountData = pallet_balances::AccountData<Balance>;
|
|
type OnNewAccount = ();
|
|
type OnKilledAccount = ();
|
|
type SystemWeightInfo = ();
|
|
type SS58Prefix = ();
|
|
type OnSetCode = ();
|
|
type MaxConsumers = frame_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 pallet_babe::Config for Test {
|
|
type EpochDuration = EpochDuration;
|
|
type ExpectedBlockTime = ExpectedBlockTime;
|
|
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
|
|
type DisabledValidators = ();
|
|
type KeyOwnerProofSystem = ();
|
|
type KeyOwnerProof = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
|
|
KeyTypeId,
|
|
pallet_babe::AuthorityId,
|
|
)>>::Proof;
|
|
type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(
|
|
KeyTypeId,
|
|
pallet_babe::AuthorityId,
|
|
)>>::IdentificationTuple;
|
|
type HandleEquivocation = ();
|
|
type WeightInfo = ();
|
|
type MaxAuthorities = MaxAuthorities;
|
|
}
|
|
|
|
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;
|
|
pub const MaxReserves: u32 = 50;
|
|
}
|
|
|
|
impl pallet_balances::Config for Test {
|
|
type MaxLocks = ();
|
|
type Balance = Balance;
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type DustRemoval = ();
|
|
type ExistentialDeposit = ExistentialDeposit;
|
|
type AccountStore = System;
|
|
type WeightInfo = ();
|
|
type MaxReserves = MaxReserves;
|
|
type ReserveIdentifier = [u8; 8];
|
|
}
|
|
|
|
impl configuration::Config for Test {
|
|
type WeightInfo = configuration::TestWeightInfo;
|
|
}
|
|
|
|
impl shared::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 NextSessionRotation = crate::mock::TestNextSessionRotation;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/// Create a new set of test externalities.
|
|
pub fn new_test_ext() -> TestExternalities {
|
|
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
|
GenesisBuild::<Test>::assimilate_storage(
|
|
&configuration::GenesisConfig {
|
|
config: configuration::HostConfiguration {
|
|
max_code_size: 2 * 1024 * 1024, // 2 MB
|
|
max_head_data_size: 1 * 1024 * 1024, // 1 MB
|
|
..Default::default()
|
|
},
|
|
},
|
|
&mut t,
|
|
)
|
|
.unwrap();
|
|
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
|
|
}
|
|
|
|
#[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;
|
|
|
|
fn maybe_new_session(n: u32) {
|
|
if n % BLOCKS_PER_SESSION == 0 {
|
|
shared::Pallet::<Test>::set_session_index(shared::Pallet::<Test>::session_index() + 1);
|
|
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::Parachain(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) {
|
|
assert!(System::block_number() < n);
|
|
while System::block_number() < n {
|
|
let block_number = System::block_number();
|
|
AllPalletsWithSystem::on_finalize(block_number);
|
|
System::set_block_number(block_number + 1);
|
|
maybe_new_session(block_number + 1);
|
|
AllPalletsWithSystem::on_initialize(block_number + 1);
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
// Runs an end to end test of the auction, crowdloan, slots, and onboarding process over varying
|
|
// lease period offsets.
|
|
#[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());
|
|
// User 1 and 2 will own parachains
|
|
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
|
|
Balances::make_free_balance_be(&account_id(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(signed(1)));
|
|
assert_ok!(Registrar::register(
|
|
signed(1),
|
|
ParaId::from(para_1),
|
|
genesis_head.clone(),
|
|
validation_code.clone(),
|
|
));
|
|
assert_ok!(Registrar::reserve(signed(2)));
|
|
assert_ok!(Registrar::register(
|
|
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(
|
|
RuntimeOrigin::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(
|
|
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
|
|
None,
|
|
));
|
|
let fund_2 = Crowdloan::funds(ParaId::from(para_2)).unwrap();
|
|
let crowdloan_account = Crowdloan::fund_account_id(fund_2.fund_index);
|
|
|
|
// Auction ending begins on block 100 + offset, so we make a bid before then.
|
|
run_to_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);
|
|
|
|
// User 10 will bid directly for parachain 1
|
|
assert_ok!(Auctions::bid(
|
|
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(&account_id(2), 1_000_000_000);
|
|
assert_ok!(Crowdloan::contribute(signed(2), ParaId::from(para_2), 920, None));
|
|
|
|
// Auction ends at block 110 + offset
|
|
run_to_block(109 + offset);
|
|
assert!(contains_event(
|
|
crowdloan::Event::<Test>::HandleBidResult {
|
|
para_id: ParaId::from(para_2),
|
|
result: Ok(())
|
|
}
|
|
.into()
|
|
));
|
|
run_to_block(110 + offset);
|
|
assert_eq!(
|
|
last_event(),
|
|
auctions::Event::<Test>::AuctionClosed { auction_index: 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((account_id(10), 910)), Some((account_id(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.clone(), 920)),
|
|
Some((crowdloan_account.clone(), 920))
|
|
],
|
|
);
|
|
|
|
// Should not be able to contribute to a winning crowdloan
|
|
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
|
|
);
|
|
|
|
// 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));
|
|
});
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn basic_errors_fail() {
|
|
new_test_ext().execute_with(|| {
|
|
assert!(System::block_number().is_one());
|
|
let para_id = LOWEST_PUBLIC_ID;
|
|
// Can't double register
|
|
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
|
|
);
|
|
|
|
// Start an auction
|
|
let duration = 99u32;
|
|
let lease_period_index_start = 4u32;
|
|
assert_ok!(Auctions::new_auction(
|
|
RuntimeOrigin::root(),
|
|
duration,
|
|
lease_period_index_start
|
|
));
|
|
|
|
// Cannot create a crowdloan if you do not own the para
|
|
assert_noop!(
|
|
Crowdloan::create(
|
|
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
|
|
);
|
|
});
|
|
}
|
|
|
|
#[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;
|
|
let para_id = LOWEST_PUBLIC_ID;
|
|
|
|
// Create n paras and owners
|
|
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();
|
|
let validation_code = Registrar::worst_validation_code();
|
|
assert_ok!(Registrar::reserve(signed(n)));
|
|
assert_ok!(Registrar::register(
|
|
signed(n),
|
|
para_id + n - 1,
|
|
genesis_head,
|
|
validation_code,
|
|
));
|
|
}
|
|
|
|
// Start a new auction in the future
|
|
let duration = 149u32;
|
|
let lease_period_index_start = 4u32;
|
|
assert_ok!(Auctions::new_auction(
|
|
RuntimeOrigin::root(),
|
|
duration,
|
|
lease_period_index_start
|
|
));
|
|
|
|
// Paras should be onboarded
|
|
run_to_block(20); // session 2
|
|
|
|
for n in 1..=max_bids {
|
|
// Increment block number
|
|
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"),
|
|
};
|
|
|
|
// Users will bid directly for parachain
|
|
assert_ok!(Auctions::bid(
|
|
signed(n * 10),
|
|
para_id + n - 1,
|
|
1, // Auction Index
|
|
lease_period_index_start + start, // First Slot
|
|
lease_period_index_start + end, // Last slot
|
|
n * 900, // Amount
|
|
));
|
|
}
|
|
|
|
// Auction should be done after ending period
|
|
run_to_block(160);
|
|
|
|
// Appropriate Paras should have won slots
|
|
// 900 + 4500 + 2x 8100 = 21,600
|
|
// 900 + 4500 + 7200 + 9000 = 21,600
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(para_id),
|
|
// -- 1 --- 2 --- 3 ---------- 4 ------
|
|
vec![None, None, None, Some((account_id(10), 900))],
|
|
);
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(para_id + 4),
|
|
// -- 1 --- 2 --- 3 --- 4 ---------- 5 -------
|
|
vec![None, None, None, None, Some((account_id(50), 4500))],
|
|
);
|
|
// TODO: Is this right?
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(para_id + 8),
|
|
// -- 1 --- 2 --- 3 --- 4 --- 5 ---------- 6 --------------- 7 -------
|
|
vec![
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
Some((account_id(90), 8100)),
|
|
Some((account_id(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());
|
|
|
|
let start_para = LOWEST_PUBLIC_ID - 1;
|
|
// Create 3 paras and owners
|
|
for n in 1..=3 {
|
|
Balances::make_free_balance_be(&account_id(n), 1_000_000_000);
|
|
let genesis_head = Registrar::worst_head_data();
|
|
let validation_code = Registrar::worst_validation_code();
|
|
assert_ok!(Registrar::reserve(signed(n)));
|
|
assert_ok!(Registrar::register(
|
|
signed(n),
|
|
ParaId::from(start_para + n),
|
|
genesis_head,
|
|
validation_code,
|
|
));
|
|
}
|
|
|
|
// Finish registration of paras.
|
|
run_to_session(2);
|
|
|
|
// 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(
|
|
RuntimeOrigin::root(),
|
|
duration,
|
|
lease_period_index_start
|
|
));
|
|
|
|
for n in 1..=3 {
|
|
// Create a crowdloan for each para
|
|
assert_ok!(Crowdloan::create(
|
|
signed(n),
|
|
ParaId::from(start_para + n),
|
|
100_000, // Cap
|
|
lease_period_index_start + 2, // First Slot
|
|
lease_period_index_start + 3, // Last Slot
|
|
200, // Block End,
|
|
None,
|
|
));
|
|
}
|
|
|
|
for n in 1..=9 {
|
|
// Increment block number
|
|
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 {
|
|
// User 10 will bid directly for parachain 1
|
|
assert_ok!(Auctions::bid(
|
|
signed(n * 10),
|
|
ParaId::from(para),
|
|
1, // Auction Index
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 1, // Last slot
|
|
n * 900, // Amount
|
|
));
|
|
} else {
|
|
// User 20 will be a contribute to crowdloan for parachain 2
|
|
assert_ok!(Crowdloan::contribute(
|
|
signed(n * 10),
|
|
ParaId::from(para),
|
|
n + 900,
|
|
None,
|
|
));
|
|
}
|
|
}
|
|
|
|
// Auction should be done
|
|
run_to_block(starting_block + 110);
|
|
|
|
// Appropriate Paras should have won slots
|
|
let fund_1 = Crowdloan::funds(ParaId::from(2000)).unwrap();
|
|
let crowdloan_1 = Crowdloan::fund_account_id(fund_1.fund_index);
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(ParaId::from(2000)),
|
|
// -- 1 --- 2 --- 3 --- 4 --- 5 ------------- 6 ------------------------ 7 -------------
|
|
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)),
|
|
// -- 1 --- 2 --- 3 ---------- 4 --------------- 5 -------
|
|
vec![None, None, None, Some((account_id(80), 7200)), Some((account_id(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 */
|
|
// User 1 and 2 will own paras
|
|
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
|
|
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
|
|
// First register 2 parathreads with different data
|
|
assert_ok!(Registrar::reserve(signed(1)));
|
|
assert_ok!(Registrar::register(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
test_genesis_head(10),
|
|
test_validation_code(10),
|
|
));
|
|
assert_ok!(Registrar::reserve(signed(2)));
|
|
assert_ok!(Registrar::register(
|
|
signed(2),
|
|
ParaId::from(2001),
|
|
test_genesis_head(20),
|
|
test_validation_code(20),
|
|
));
|
|
|
|
// Paras should be onboarding
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
|
|
|
|
// Start a new auction in the future
|
|
let duration = 99u32;
|
|
let lease_period_index_start = 4u32;
|
|
assert_ok!(Auctions::new_auction(
|
|
RuntimeOrigin::root(),
|
|
duration,
|
|
lease_period_index_start
|
|
));
|
|
|
|
// 2 sessions later they are parathreads
|
|
run_to_session(2);
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
|
|
|
|
// Open a crowdloan for Para 1 for slots 0-3
|
|
assert_ok!(Crowdloan::create(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
1_000_000, // Cap
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 3, // Last Slot
|
|
200, // Block End
|
|
None,
|
|
));
|
|
let fund = Crowdloan::funds(ParaId::from(2000)).unwrap();
|
|
let crowdloan_account = Crowdloan::fund_account_id(fund.fund_index);
|
|
|
|
// Bunch of contributions
|
|
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);
|
|
|
|
// 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(&account_id(1)), (500 + 10 * 2 * 1) + 100);
|
|
assert_eq!(Balances::reserved_balance(&account_id(2)), 500 + 20 * 2 * 1);
|
|
assert_eq!(Balances::reserved_balance(&crowdloan_account), total);
|
|
// Crowdloan is appropriately set
|
|
assert!(Crowdloan::funds(ParaId::from(2000)).is_some());
|
|
assert!(Crowdloan::funds(ParaId::from(2001)).is_none());
|
|
|
|
// New leases will start on block 400
|
|
let lease_start_block = 400;
|
|
run_to_block(lease_start_block);
|
|
|
|
// Slots are won by Para 1
|
|
assert!(!Slots::lease(ParaId::from(2000)).is_empty());
|
|
assert!(Slots::lease(ParaId::from(2001)).is_empty());
|
|
|
|
// 2 sessions later it is a parachain
|
|
run_to_block(lease_start_block + 20);
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parachain));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
|
|
|
|
// Initiate a swap
|
|
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::DowngradingParachain));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::UpgradingParathread));
|
|
|
|
// 2 session later they have swapped
|
|
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::Parachain));
|
|
|
|
// Deregister parathread
|
|
assert_ok!(Registrar::deregister(para_origin(2000).into(), ParaId::from(2000)));
|
|
// Correct deposit is unreserved
|
|
assert_eq!(Balances::reserved_balance(&account_id(1)), 100); // crowdloan deposit left over
|
|
assert_eq!(Balances::reserved_balance(&account_id(2)), 500 + 20 * 2 * 1);
|
|
// Crowdloan ownership is swapped
|
|
assert!(Crowdloan::funds(ParaId::from(2000)).is_none());
|
|
assert!(Crowdloan::funds(ParaId::from(2001)).is_some());
|
|
// Slot is swapped
|
|
assert!(Slots::lease(ParaId::from(2000)).is_empty());
|
|
assert!(!Slots::lease(ParaId::from(2001)).is_empty());
|
|
|
|
// Cant dissolve
|
|
assert_noop!(
|
|
Crowdloan::dissolve(signed(1), ParaId::from(2000)),
|
|
CrowdloanError::<Test>::InvalidParaId
|
|
);
|
|
assert_noop!(
|
|
Crowdloan::dissolve(signed(2), ParaId::from(2001)),
|
|
CrowdloanError::<Test>::NotReadyToDissolve
|
|
);
|
|
|
|
// 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);
|
|
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);
|
|
|
|
// Dissolve returns the balance of the person who put a deposit for crowdloan
|
|
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)), 500 + 20 * 2 * 1);
|
|
|
|
// Final deregister sets everything back to the start
|
|
assert_ok!(Registrar::deregister(para_origin(2001).into(), ParaId::from(2001)));
|
|
assert_eq!(Balances::reserved_balance(&account_id(2)), 0);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn parachain_swap_works() {
|
|
// This test will test a swap between two parachains works successfully.
|
|
new_test_ext().execute_with(|| {
|
|
assert!(System::block_number().is_one()); /* So events are emitted */
|
|
// User 1 and 2 will own paras
|
|
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
|
|
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
|
|
// First register 2 parathreads with different data
|
|
assert_ok!(Registrar::reserve(signed(1)));
|
|
assert_ok!(Registrar::register(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
test_genesis_head(10),
|
|
test_validation_code(10),
|
|
));
|
|
assert_ok!(Registrar::reserve(signed(2)));
|
|
assert_ok!(Registrar::register(
|
|
signed(2),
|
|
ParaId::from(2001),
|
|
test_genesis_head(20),
|
|
test_validation_code(20),
|
|
));
|
|
|
|
// Paras should be onboarding
|
|
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::next_fund_index())),
|
|
0
|
|
);
|
|
|
|
// Start a new auction in the future
|
|
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
|
|
));
|
|
|
|
// 2 sessions later they are parathreads
|
|
run_to_block(starting_block + 20);
|
|
assert_eq!(Paras::lifecycle(ParaId::from(winner)), Some(ParaLifecycle::Parathread));
|
|
|
|
// Open a crowdloan for Para 1 for slots 0-3
|
|
assert_ok!(Crowdloan::create(
|
|
signed(unique_id),
|
|
ParaId::from(winner),
|
|
1_000_000, // Cap
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 7, // Last Slot
|
|
end, // Block End
|
|
None,
|
|
));
|
|
let winner_fund = Crowdloan::funds(ParaId::from(winner)).unwrap();
|
|
let crowdloan_account = Crowdloan::fund_account_id(winner_fund.fund_index);
|
|
|
|
// Bunch of contributions
|
|
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);
|
|
|
|
// Go to end of auction where everyone won their slots
|
|
run_to_block(end);
|
|
|
|
// Crowdloan is appropriately set
|
|
assert!(Crowdloan::funds(ParaId::from(winner)).is_some());
|
|
|
|
// New leases will start on block lease period index * 100
|
|
let lease_start_block = lease_period_index_start * 100;
|
|
run_to_block(lease_start_block);
|
|
};
|
|
|
|
start_auction(4u32, 2000, 200);
|
|
// Slots are won by Para 1
|
|
assert!(!Slots::lease(ParaId::from(2000)).is_empty());
|
|
assert!(Slots::lease(ParaId::from(2001)).is_empty());
|
|
|
|
// 2 sessions later it is a parachain
|
|
run_to_block(4 * 100 + 20);
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parachain));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
|
|
|
|
// Let's repeat the process now for another parachain.
|
|
start_auction(6u32, 2001, 500);
|
|
// Slots are won by Para 1
|
|
assert!(!Slots::lease(ParaId::from(2000)).is_empty());
|
|
assert!(!Slots::lease(ParaId::from(2001)).is_empty());
|
|
|
|
// 2 sessions later it is a parachain
|
|
run_to_block(6 * 100 + 20);
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parachain));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parachain));
|
|
|
|
// Currently we are on lease 6
|
|
assert_eq!(
|
|
<Slots as Leaser<_>>::lease_period_index(System::block_number()),
|
|
Some((6u32, false))
|
|
);
|
|
|
|
// This means that parachain 1 should only have 6 slots left, and parachain 2 has all 8.
|
|
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(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(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::lease(ParaId::from(2000)).len(), 6);
|
|
assert_eq!(Slots::lease(ParaId::from(2001)).len(), 8);
|
|
|
|
// Now we swap them.
|
|
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)
|
|
));
|
|
|
|
// Crowdloan Swapped
|
|
let fund_2000 = Crowdloan::funds(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(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
|
|
);
|
|
|
|
// Slots Swapped
|
|
assert_eq!(Slots::lease(ParaId::from(2000)).len(), 8);
|
|
assert_eq!(Slots::lease(ParaId::from(2001)).len(), 6);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn crowdloan_ending_period_bid() {
|
|
new_test_ext().execute_with(|| {
|
|
assert!(System::block_number().is_one()); /* So events are emitted */
|
|
// User 1 and 2 will own paras
|
|
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
|
|
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
|
|
// First register 2 parathreads
|
|
assert_ok!(Registrar::reserve(signed(1)));
|
|
assert_ok!(Registrar::register(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
test_genesis_head(10),
|
|
test_validation_code(10),
|
|
));
|
|
assert_ok!(Registrar::reserve(signed(2)));
|
|
assert_ok!(Registrar::register(
|
|
signed(2),
|
|
ParaId::from(2001),
|
|
test_genesis_head(20),
|
|
test_validation_code(20),
|
|
));
|
|
|
|
// Paras should be onboarding
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Onboarding));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Onboarding));
|
|
|
|
// Start a new auction in the future
|
|
let duration = 99u32;
|
|
let lease_period_index_start = 4u32;
|
|
assert_ok!(Auctions::new_auction(
|
|
RuntimeOrigin::root(),
|
|
duration,
|
|
lease_period_index_start
|
|
));
|
|
|
|
// 2 sessions later they are parathreads
|
|
run_to_session(2);
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2000)), Some(ParaLifecycle::Parathread));
|
|
assert_eq!(Paras::lifecycle(ParaId::from(2001)), Some(ParaLifecycle::Parathread));
|
|
|
|
// Open a crowdloan for Para 1 for slots 0-3
|
|
assert_ok!(Crowdloan::create(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
1_000_000, // Cap
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 3, // Last Slot
|
|
200, // Block End
|
|
None,
|
|
));
|
|
let fund = Crowdloan::funds(ParaId::from(2000)).unwrap();
|
|
let crowdloan_account = Crowdloan::fund_account_id(fund.fund_index);
|
|
|
|
// Bunch of contributions
|
|
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);
|
|
|
|
// Bid for para 2 directly
|
|
Balances::make_free_balance_be(&account_id(2), 1_000_000_000);
|
|
assert_ok!(Auctions::bid(
|
|
signed(2),
|
|
ParaId::from(2001),
|
|
1, // Auction Index
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 1, // Last slot
|
|
900, // Amount
|
|
));
|
|
|
|
// Go to beginning of ending period
|
|
run_to_block(100);
|
|
|
|
assert_eq!(Auctions::auction_status(100), 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(0), Some(winning));
|
|
|
|
run_to_block(101);
|
|
|
|
Balances::make_free_balance_be(&account_id(1234), 1_000_000_000);
|
|
assert_ok!(Crowdloan::contribute(signed(1234), ParaId::from(2000), 900, None));
|
|
|
|
// Data propagates correctly
|
|
run_to_block(102);
|
|
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(2), Some(winning));
|
|
})
|
|
}
|
|
|
|
#[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(
|
|
RuntimeOrigin::root(),
|
|
duration,
|
|
lease_period_index_start
|
|
));
|
|
|
|
// Can't bid with non-registered paras
|
|
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
|
|
assert_noop!(
|
|
Auctions::bid(
|
|
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
|
|
);
|
|
|
|
// Now we register the para
|
|
assert_ok!(Registrar::reserve(signed(1)));
|
|
assert_ok!(Registrar::register(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
test_genesis_head(10),
|
|
test_validation_code(10),
|
|
));
|
|
|
|
// Still can't bid until it is fully onboarded
|
|
assert_noop!(
|
|
Auctions::bid(
|
|
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
|
|
);
|
|
|
|
// Onboarded on Session 2
|
|
run_to_session(2);
|
|
|
|
// Success
|
|
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
|
|
assert_ok!(Auctions::bid(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
1, // Auction Index
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 1, // Last slot
|
|
900, // Amount
|
|
));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn gap_bids_work() {
|
|
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(
|
|
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);
|
|
|
|
// Now register 2 paras
|
|
assert_ok!(Registrar::reserve(signed(1)));
|
|
assert_ok!(Registrar::register(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
test_genesis_head(10),
|
|
test_validation_code(10),
|
|
));
|
|
assert_ok!(Registrar::reserve(signed(2)));
|
|
assert_ok!(Registrar::register(
|
|
signed(2),
|
|
ParaId::from(2001),
|
|
test_genesis_head(10),
|
|
test_validation_code(10),
|
|
));
|
|
|
|
// Onboarded on Session 2
|
|
run_to_session(2);
|
|
|
|
// Make bids
|
|
Balances::make_free_balance_be(&account_id(10), 1_000_000_000);
|
|
Balances::make_free_balance_be(&account_id(20), 1_000_000_000);
|
|
// Slot 1 for 100 from 10
|
|
assert_ok!(Auctions::bid(
|
|
signed(10),
|
|
ParaId::from(2000),
|
|
1, // Auction Index
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 0, // Last slot
|
|
100, // Amount
|
|
));
|
|
// Slot 4 for 400 from 10
|
|
assert_ok!(Auctions::bid(
|
|
signed(10),
|
|
ParaId::from(2000),
|
|
1, // Auction Index
|
|
lease_period_index_start + 3, // First Slot
|
|
lease_period_index_start + 3, // Last slot
|
|
400, // Amount
|
|
));
|
|
|
|
// A bid for another para is counted separately.
|
|
assert_ok!(Auctions::bid(
|
|
signed(10),
|
|
ParaId::from(2001),
|
|
1, // Auction Index
|
|
lease_period_index_start + 1, // First Slot
|
|
lease_period_index_start + 1, // Last slot
|
|
555, // Amount
|
|
));
|
|
assert_eq!(Balances::reserved_balance(&account_id(10)), 400 + 555);
|
|
|
|
// Slot 2 for 800 from 20, overtaking 10's bid
|
|
assert_ok!(Auctions::bid(
|
|
signed(20),
|
|
ParaId::from(2000),
|
|
1, // Auction Index
|
|
lease_period_index_start + 1, // First Slot
|
|
lease_period_index_start + 1, // Last slot
|
|
800, // Amount
|
|
));
|
|
// Slot 3 for 200 from 20
|
|
assert_ok!(Auctions::bid(
|
|
signed(20),
|
|
ParaId::from(2000),
|
|
1, // Auction Index
|
|
lease_period_index_start + 2, // First Slot
|
|
lease_period_index_start + 2, // Last slot
|
|
200, // Amount
|
|
));
|
|
|
|
// Finish the auction
|
|
run_to_block(110 + LeaseOffset::get());
|
|
|
|
// Should have won the lease periods
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(ParaId::from(2000)),
|
|
vec![
|
|
// LP 1
|
|
None,
|
|
// LP 2
|
|
None,
|
|
// LP 3
|
|
None,
|
|
// LP 4
|
|
Some((account_id(10), 100)),
|
|
// LP 5
|
|
Some((account_id(20), 800)),
|
|
// LP 6
|
|
Some((account_id(20), 200)),
|
|
// LP 7
|
|
Some((account_id(10), 400))
|
|
],
|
|
);
|
|
// Appropriate amount is reserved (largest of the values)
|
|
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
|
|
// Appropriate amount is reserved (largest of the values)
|
|
assert_eq!(Balances::reserved_balance(&account_id(20)), 800);
|
|
|
|
// Progress through the leases and note the correct amount of balance is reserved.
|
|
|
|
add_blocks(300 + LeaseOffset::get());
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(ParaId::from(2000)),
|
|
vec![
|
|
// LP 4
|
|
Some((account_id(10), 100)),
|
|
// LP 5
|
|
Some((account_id(20), 800)),
|
|
// LP 6
|
|
Some((account_id(20), 200)),
|
|
// LP 7
|
|
Some((account_id(10), 400))
|
|
],
|
|
);
|
|
// Nothing changed.
|
|
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
|
|
assert_eq!(Balances::reserved_balance(&account_id(20)), 800);
|
|
|
|
// Lease period 4 is done, but nothing is unreserved since user 1 has a debt on lease 7
|
|
add_blocks(100);
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(ParaId::from(2000)),
|
|
vec![
|
|
// LP 5
|
|
Some((account_id(20), 800)),
|
|
// LP 6
|
|
Some((account_id(20), 200)),
|
|
// LP 7
|
|
Some((account_id(10), 400))
|
|
],
|
|
);
|
|
// Nothing changed.
|
|
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
|
|
assert_eq!(Balances::reserved_balance(&account_id(20)), 800);
|
|
|
|
// Lease period 5 is done, and 20 will unreserve down to 200.
|
|
add_blocks(100);
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(ParaId::from(2000)),
|
|
// --------- 6 -------------- 7 -------
|
|
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);
|
|
|
|
// Lease period 6 is done, and 20 will unreserve everything.
|
|
add_blocks(100);
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(ParaId::from(2000)),
|
|
// --------- 7 -------
|
|
vec![Some((account_id(10), 400))],
|
|
);
|
|
assert_eq!(Balances::reserved_balance(&account_id(10)), 400);
|
|
assert_eq!(Balances::reserved_balance(&account_id(20)), 0);
|
|
|
|
// All leases are done. Everything is unreserved.
|
|
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);
|
|
});
|
|
}
|
|
|
|
// This test verifies that if a parachain already has won some lease periods, that it cannot bid for
|
|
// any of those same lease periods again.
|
|
#[test]
|
|
fn cant_bid_on_existing_lease_periods() {
|
|
new_test_ext().execute_with(|| {
|
|
assert!(System::block_number().is_one()); /* So events are emitted */
|
|
Balances::make_free_balance_be(&account_id(1), 1_000_000_000);
|
|
// First register a parathread
|
|
assert_ok!(Registrar::reserve(signed(1)));
|
|
assert_ok!(Registrar::register(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
test_genesis_head(10),
|
|
test_validation_code(10),
|
|
));
|
|
|
|
// 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(
|
|
RuntimeOrigin::root(),
|
|
duration,
|
|
lease_period_index_start
|
|
));
|
|
|
|
// 2 sessions later they are parathreads
|
|
run_to_session(2);
|
|
|
|
// Open a crowdloan for Para 1 for slots 0-3
|
|
assert_ok!(Crowdloan::create(
|
|
signed(1),
|
|
ParaId::from(2000),
|
|
1_000_000, // Cap
|
|
lease_period_index_start + 0, // First Slot
|
|
lease_period_index_start + 1, // Last Slot
|
|
400, // Long block end
|
|
None,
|
|
));
|
|
let fund = Crowdloan::funds(ParaId::from(2000)).unwrap();
|
|
let crowdloan_account = Crowdloan::fund_account_id(fund.fund_index);
|
|
|
|
// Bunch of contributions
|
|
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);
|
|
|
|
// Finish the auction.
|
|
run_to_block(starting_block + 110);
|
|
|
|
// Appropriate Paras should have won slots
|
|
assert_eq!(
|
|
slots::Leases::<Test>::get(ParaId::from(2000)),
|
|
// -- 1 --- 2 --- 3 ------------- 4 ------------------------ 5 -------------
|
|
vec![
|
|
None,
|
|
None,
|
|
None,
|
|
Some((crowdloan_account.clone(), 8855)),
|
|
Some((crowdloan_account.clone(), 8855))
|
|
],
|
|
);
|
|
|
|
// Let's start another auction for the same range
|
|
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
|
|
));
|
|
|
|
// Poke the crowdloan into `NewRaise`
|
|
assert_ok!(Crowdloan::poke(signed(1), ParaId::from(2000)));
|
|
assert_eq!(Crowdloan::new_raise(), vec![ParaId::from(2000)]);
|
|
|
|
// Beginning of ending block.
|
|
run_to_block(starting_block + 100);
|
|
|
|
// Bids cannot be made which intersect
|
|
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,
|
|
);
|
|
|
|
// Will work when not overlapping
|
|
assert_ok!(Auctions::bid(
|
|
RuntimeOrigin::signed(crowdloan_account.clone()),
|
|
ParaId::from(2000),
|
|
2,
|
|
lease_period_index_start + 2,
|
|
lease_period_index_start + 3,
|
|
100,
|
|
));
|
|
});
|
|
}
|