diff --git a/runtime/common/src/crowdloan.rs b/runtime/common/src/crowdloan.rs index 86fc53f8d59b..a500a2583562 100644 --- a/runtime/common/src/crowdloan.rs +++ b/runtime/common/src/crowdloan.rs @@ -87,7 +87,7 @@ type BalanceOf = as Currency<::Acco type NegativeImbalanceOf = as Currency<::AccountId>>::NegativeImbalance; -type TrieIndex = u32; +type FundIndex = u32; pub trait WeightInfo { fn create() -> Weight; @@ -170,8 +170,8 @@ pub struct FundInfo { /// Last lease period in range to bid on; it's actually a `LeasePeriod`, but that's the same type /// as `BlockNumber`. pub last_period: LeasePeriod, - /// Index used for the child trie of this fund - pub trie_index: TrieIndex, + /// Unique index used to represent this fund. + pub fund_index: FundIndex, } #[frame_support::pallet] @@ -246,8 +246,8 @@ pub mod pallet { /// Tracker for the next available trie index #[pallet::storage] - #[pallet::getter(fn next_trie_index)] - pub(super) type NextTrieIndex = StorageValue<_, u32, ValueQuery>; + #[pallet::getter(fn next_fund_index)] + pub(super) type NextFundIndex = StorageValue<_, u32, ValueQuery>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -342,7 +342,7 @@ pub mod pallet { // Care needs to be taken by the crowdloan creator that this function will succeed given // the crowdloaning configuration. We do some checks ahead of time in crowdloan `create`. let result = T::Auctioneer::place_bid( - Self::fund_account_id(para_id), + Self::fund_account_id(fund.fund_index), para_id, fund.first_period, fund.last_period, @@ -408,8 +408,8 @@ pub mod pallet { ensure!(depositor == manager, Error::::InvalidOrigin); ensure!(T::Registrar::is_registered(index), Error::::InvalidParaId); - let trie_index = Self::next_trie_index(); - let new_trie_index = trie_index.checked_add(1).ok_or(Error::::Overflow)?; + let fund_index = Self::next_fund_index(); + let new_fund_index = fund_index.checked_add(1).ok_or(Error::::Overflow)?; let deposit = T::SubmissionDeposit::get(); @@ -427,11 +427,11 @@ pub mod pallet { last_contribution: LastContribution::Never, first_period, last_period, - trie_index, + fund_index, }, ); - NextTrieIndex::::put(new_trie_index); + NextFundIndex::::put(new_fund_index); // Add a lock to the para so that the configuration cannot be changed. T::Registrar::apply_lock(index); @@ -479,15 +479,15 @@ pub mod pallet { let mut fund = Self::funds(index).ok_or(Error::::InvalidParaId)?; let now = frame_system::Pallet::::block_number(); - let fund_account = Self::fund_account_id(index); + let fund_account = Self::fund_account_id(fund.fund_index); Self::ensure_crowdloan_ended(now, &fund_account, &fund)?; - let (balance, _) = Self::contribution_get(fund.trie_index, &who); + let (balance, _) = Self::contribution_get(fund.fund_index, &who); ensure!(balance > Zero::zero(), Error::::NoContributions); CurrencyOf::::transfer(&fund_account, &who, balance, AllowDeath)?; - Self::contribution_kill(fund.trie_index, &who); + Self::contribution_kill(fund.fund_index, &who); fund.raised = fund.raised.saturating_sub(balance); Funds::::insert(index, &fund); @@ -510,12 +510,12 @@ pub mod pallet { let mut fund = Self::funds(index).ok_or(Error::::InvalidParaId)?; let now = frame_system::Pallet::::block_number(); - let fund_account = Self::fund_account_id(index); + let fund_account = Self::fund_account_id(fund.fund_index); Self::ensure_crowdloan_ended(now, &fund_account, &fund)?; let mut refund_count = 0u32; // Try killing the crowdloan child trie - let contributions = Self::contribution_iterator(fund.trie_index); + let contributions = Self::contribution_iterator(fund.fund_index); // Assume everyone will be refunded. let mut all_refunded = true; for (who, (balance, _)) in contributions { @@ -525,7 +525,7 @@ pub mod pallet { break } CurrencyOf::::transfer(&fund_account, &who, balance, AllowDeath)?; - Self::contribution_kill(fund.trie_index, &who); + Self::contribution_kill(fund.fund_index, &who); fund.raised = fund.raised.saturating_sub(balance); refund_count += 1; } @@ -561,7 +561,7 @@ pub mod pallet { // Assuming state is not corrupted, the child trie should already be cleaned up // and all funds in the crowdloan account have been returned. If not, governance // can take care of that. - debug_assert!(Self::contribution_iterator(fund.trie_index).count().is_zero()); + debug_assert!(Self::contribution_iterator(fund.fund_index).count().is_zero()); CurrencyOf::::unreserve(&fund.depositor, fund.deposit); Funds::::remove(index); @@ -598,7 +598,7 @@ pub mod pallet { last_contribution: fund.last_contribution, first_period, last_period, - trie_index: fund.trie_index, + fund_index: fund.fund_index, }, ); @@ -616,10 +616,10 @@ pub mod pallet { ensure!(memo.len() <= T::MaxMemoLength::get().into(), Error::::MemoTooLarge); let fund = Self::funds(index).ok_or(Error::::InvalidParaId)?; - let (balance, _) = Self::contribution_get(fund.trie_index, &who); + let (balance, _) = Self::contribution_get(fund.fund_index, &who); ensure!(balance > Zero::zero(), Error::::NoContributions); - Self::contribution_put(fund.trie_index, &who, &balance, &memo); + Self::contribution_put(fund.fund_index, &who, &balance, &memo); Self::deposit_event(Event::::MemoUpdated(who, index, memo)); Ok(()) } @@ -658,11 +658,11 @@ impl Pallet { /// /// This actually does computation. If you need to keep using it, then make sure you cache the /// value and only call this once. - pub fn fund_account_id(index: ParaId) -> T::AccountId { + pub fn fund_account_id(index: FundIndex) -> T::AccountId { T::PalletId::get().into_sub_account(index) } - pub fn id_from_index(index: TrieIndex) -> child::ChildInfo { + pub fn id_from_index(index: FundIndex) -> child::ChildInfo { let mut buf = Vec::new(); buf.extend_from_slice(b"crowdloan"); buf.extend_from_slice(&index.encode()[..]); @@ -670,7 +670,7 @@ impl Pallet { } pub fn contribution_put( - index: TrieIndex, + index: FundIndex, who: &T::AccountId, balance: &BalanceOf, memo: &[u8], @@ -678,22 +678,22 @@ impl Pallet { who.using_encoded(|b| child::put(&Self::id_from_index(index), b, &(balance, memo))); } - pub fn contribution_get(index: TrieIndex, who: &T::AccountId) -> (BalanceOf, Vec) { + pub fn contribution_get(index: FundIndex, who: &T::AccountId) -> (BalanceOf, Vec) { who.using_encoded(|b| { child::get_or_default::<(BalanceOf, Vec)>(&Self::id_from_index(index), b) }) } - pub fn contribution_kill(index: TrieIndex, who: &T::AccountId) { + pub fn contribution_kill(index: FundIndex, who: &T::AccountId) { who.using_encoded(|b| child::kill(&Self::id_from_index(index), b)); } - pub fn crowdloan_kill(index: TrieIndex) -> child::KillStorageResult { + pub fn crowdloan_kill(index: FundIndex) -> child::KillStorageResult { child::kill_storage(&Self::id_from_index(index), Some(T::RemoveKeysLimit::get())) } pub fn contribution_iterator( - index: TrieIndex, + index: FundIndex, ) -> ChildTriePrefixIterator<(T::AccountId, (BalanceOf, Vec))> { ChildTriePrefixIterator::<_>::with_prefix_over_key::( &Self::id_from_index(index), @@ -752,7 +752,7 @@ impl Pallet { ensure!(current_lease_period <= fund.first_period, Error::::ContributionPeriodOver); // Make sure crowdloan has not already won. - let fund_account = Self::fund_account_id(index); + let fund_account = Self::fund_account_id(fund.fund_index); ensure!( !T::Auctioneer::has_won_an_auction(index, &fund_account), Error::::BidOrLeaseActive @@ -762,7 +762,7 @@ impl Pallet { // contributions into the auction when it would not impact the outcome. ensure!(!T::Auctioneer::auction_status(now).is_vrf(), Error::::VrfDelayInProgress); - let (old_balance, memo) = Self::contribution_get(fund.trie_index, &who); + let (old_balance, memo) = Self::contribution_get(fund.fund_index, &who); if let Some(ref verifier) = fund.verifier { let signature = signature.ok_or(Error::::InvalidSignature)?; @@ -776,7 +776,7 @@ impl Pallet { CurrencyOf::::transfer(&who, &fund_account, value, existence)?; let balance = old_balance.saturating_add(value); - Self::contribution_put(fund.trie_index, &who, &balance, &memo); + Self::contribution_put(fund.fund_index, &who, &balance, &memo); if T::Auctioneer::auction_status(now).is_ending().is_some() { match fund.last_contribution { @@ -966,7 +966,8 @@ mod tests { // Emulate what would happen if we won an auction: // balance is reserved and a deposit_held is recorded fn set_winner(para: ParaId, who: u64, winner: bool) { - let account_id = Crowdloan::fund_account_id(para); + let fund = Funds::::get(para).unwrap(); + let account_id = Crowdloan::fund_account_id(fund.fund_index); if winner { let free_balance = Balances::free_balance(&account_id); Balances::reserve(&account_id, free_balance) @@ -1177,7 +1178,7 @@ mod tests { last_contribution: LastContribution::Never, first_period: 1, last_period: 4, - trie_index: 0, + fund_index: 0, }; assert_eq!(Crowdloan::funds(para), Some(fund_info)); // User has deposit removed from their free balance @@ -1217,7 +1218,7 @@ mod tests { last_contribution: LastContribution::Never, first_period: 1, last_period: 4, - trie_index: 0, + fund_index: 0, }; assert_eq!(Crowdloan::funds(ParaId::from(0)), Some(fund_info)); // User has deposit removed from their free balance @@ -1270,6 +1271,7 @@ mod tests { fn contribute_works() { new_test_ext().execute_with(|| { let para = new_para(); + let index = NextFundIndex::::get(); // Set up a crowdloan assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 4, 9, None)); @@ -1284,7 +1286,7 @@ mod tests { // Contributions are stored in the trie assert_eq!(Crowdloan::contribution_get(u32::from(para), &1).0, 49); // Contributions appear in free balance of crowdloan - assert_eq!(Balances::free_balance(Crowdloan::fund_account_id(para)), 49); + assert_eq!(Balances::free_balance(Crowdloan::fund_account_id(index)), 49); // Crowdloan is added to NewRaise assert_eq!(Crowdloan::new_raise(), vec![para]); @@ -1300,6 +1302,7 @@ mod tests { fn contribute_with_verifier_works() { new_test_ext().execute_with(|| { let para = new_para(); + let index = NextFundIndex::::get(); let pubkey = crypto::create_ed25519_pubkey(b"//verifier".to_vec()); // Set up a crowdloan assert_ok!(Crowdloan::create( @@ -1364,7 +1367,7 @@ mod tests { assert_ok!(Crowdloan::contribute(Origin::signed(1), para, 10, Some(valid_signature_2))); // Contributions appear in free balance of crowdloan - assert_eq!(Balances::free_balance(Crowdloan::fund_account_id(para)), 59); + assert_eq!(Balances::free_balance(Crowdloan::fund_account_id(index)), 59); // Contribution amount is correct let fund = Crowdloan::funds(para).unwrap(); @@ -1409,9 +1412,10 @@ mod tests { // If a crowdloan has already won, it should not allow contributions. let para_2 = new_para(); + let index = NextFundIndex::::get(); assert_ok!(Crowdloan::create(Origin::signed(1), para_2, 1000, 1, 4, 40, None)); // Emulate a win by leasing out and putting a deposit. Slots pallet would normally do this. - let crowdloan_account = Crowdloan::fund_account_id(para_2); + let crowdloan_account = Crowdloan::fund_account_id(index); set_winner(para_2, crowdloan_account, true); assert_noop!( Crowdloan::contribute(Origin::signed(1), para_2, 49, None), @@ -1478,6 +1482,7 @@ mod tests { fn bidding_works() { new_test_ext().execute_with(|| { let para = new_para(); + let index = NextFundIndex::::get(); let first_period = 1; let last_period = 4; @@ -1493,7 +1498,7 @@ mod tests { 9, None )); - let bidder = Crowdloan::fund_account_id(para); + let bidder = Crowdloan::fund_account_id(index); // Fund crowdloan run_to_block(1); @@ -1524,6 +1529,7 @@ mod tests { fn withdraw_from_failed_works() { new_test_ext().execute_with(|| { let para = new_para(); + let index = NextFundIndex::::get(); // Set up a crowdloan assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None)); @@ -1531,7 +1537,7 @@ mod tests { assert_ok!(Crowdloan::contribute(Origin::signed(3), para, 50, None)); run_to_block(10); - let account_id = Crowdloan::fund_account_id(para); + let account_id = Crowdloan::fund_account_id(index); // para has no reserved funds, indicating it did not win the auction. assert_eq!(Balances::reserved_balance(&account_id), 0); // but there's still the funds in its balance. @@ -1553,13 +1559,14 @@ mod tests { fn withdraw_cannot_be_griefed() { new_test_ext().execute_with(|| { let para = new_para(); + let index = NextFundIndex::::get(); // Set up a crowdloan assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None)); assert_ok!(Crowdloan::contribute(Origin::signed(2), para, 100, None)); run_to_block(10); - let account_id = Crowdloan::fund_account_id(para); + let account_id = Crowdloan::fund_account_id(index); // user sends the crowdloan funds trying to make an accounting error assert_ok!(Balances::transfer(Origin::signed(1), account_id, 10)); @@ -1583,7 +1590,8 @@ mod tests { fn refund_works() { new_test_ext().execute_with(|| { let para = new_para(); - let account_id = Crowdloan::fund_account_id(para); + let index = NextFundIndex::::get(); + let account_id = Crowdloan::fund_account_id(index); // Set up a crowdloan ending on 9 assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None)); @@ -1617,7 +1625,8 @@ mod tests { fn multiple_refund_works() { new_test_ext().execute_with(|| { let para = new_para(); - let account_id = Crowdloan::fund_account_id(para); + let index = NextFundIndex::::get(); + let account_id = Crowdloan::fund_account_id(index); // Set up a crowdloan ending on 9 assert_ok!(Crowdloan::create(Origin::signed(1), para, 100000, 1, 1, 9, None)); @@ -1727,7 +1736,8 @@ mod tests { fn withdraw_from_finished_works() { new_test_ext().execute_with(|| { let para = new_para(); - let account_id = Crowdloan::fund_account_id(para); + let index = NextFundIndex::::get(); + let account_id = Crowdloan::fund_account_id(index); // Set up a crowdloan assert_ok!(Crowdloan::create(Origin::signed(1), para, 1000, 1, 1, 9, None)); @@ -2079,7 +2089,7 @@ mod benchmarking { verify { let fund = Funds::::get(fund_index).expect("fund was created..."); assert_eq!( - Crowdloan::::contribution_get(fund.trie_index, &caller), + Crowdloan::::contribution_get(fund.fund_index, &caller), (T::MinContribution::get(), worst_memo), ); } diff --git a/runtime/common/src/integration_tests.rs b/runtime/common/src/integration_tests.rs index 5c1dc9f13251..b6c89e2294b0 100644 --- a/runtime/common/src/integration_tests.rs +++ b/runtime/common/src/integration_tests.rs @@ -401,7 +401,8 @@ fn basic_end_to_end_works() { 200 + offset, // Block End None, )); - let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(para_2)); + 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); @@ -723,7 +724,8 @@ fn competing_bids() { run_to_block(starting_block + 110); // Appropriate Paras should have won slots - let crowdloan_1 = Crowdloan::fund_account_id(ParaId::from(2000)); + let fund_1 = Crowdloan::funds(ParaId::from(2000)).unwrap(); + let crowdloan_1 = Crowdloan::fund_account_id(fund_1.fund_index); assert_eq!( slots::Leases::::get(ParaId::from(2000)), // -- 1 --- 2 --- 3 --- 4 --- 5 ------------- 6 ------------------------ 7 ------------- @@ -793,7 +795,8 @@ fn basic_swap_works() { 200, // Block End None, )); - let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(2000)); + 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; @@ -921,8 +924,7 @@ fn parachain_swap_works() { 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(ParaId::from(2000))), 0); - + 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| { @@ -945,7 +947,8 @@ fn parachain_swap_works() { end, // Block End None, )); - let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(winner)); + 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; @@ -997,7 +1000,7 @@ fn parachain_swap_works() { assert_eq!(slots::Leases::::get(ParaId::from(2001)).len(), 8); let fund_1 = Crowdloan::funds(ParaId::from(2000)).unwrap(); - assert_eq!(Balances::reserved_balance(&Crowdloan::fund_account_id(ParaId::from(2000))), fund_1.raised); + assert_eq!(Balances::reserved_balance(&Crowdloan::fund_account_id(fund_1.fund_index)), fund_1.raised); // Now we swap them. assert_ok!(Registrar::swap( @@ -1109,7 +1112,8 @@ fn crowdloan_ending_period_bid() { 200, // Block End None, )); - let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(2000)); + 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; @@ -1412,7 +1416,8 @@ fn cant_bid_on_existing_lease_periods() { 400, // Long block end None, )); - let crowdloan_account = Crowdloan::fund_account_id(ParaId::from(2000)); + 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;