Skip to content
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions polkadot/runtime/common/src/crowdloan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use frame_support::{
pallet_prelude::{DispatchResult, Weight},
storage::{child, ChildTriePrefixIterator},
traits::{
Currency,
Currency, Defensive,
ExistenceRequirement::{self, AllowDeath, KeepAlive},
Get, ReservableCurrency,
},
Expand Down Expand Up @@ -563,6 +563,7 @@ pub mod pallet {
let who = ensure_signed(origin)?;

let fund = Self::funds(index).ok_or(Error::<T>::InvalidParaId)?;
let pot = Self::fund_account_id(fund.fund_index);
let now = frame_system::Pallet::<T>::block_number();

// Only allow dissolution when the raised funds goes to zero,
Expand All @@ -576,7 +577,10 @@ pub mod pallet {
// can take care of that.
debug_assert!(Self::contribution_iterator(fund.fund_index).count().is_zero());

frame_system::Pallet::<T>::dec_providers(&Self::fund_account_id(fund.fund_index))?;
// Crowdloan over, burn all funds.
let _imba = CurrencyOf::<T>::make_free_balance_be(&pot, Zero::zero());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dq but I don't get why this is needed; a CL is dissolve-able only when all funds are already returned, no? if not, I think it should be like this.

seems to be checked as a part of let can_dissolve = permitted && fund.raised.is_zero();

So the invariant is fund.raised should always be equal to CurrencyOf::<T>::free_balance(&pot)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh okay, reading the test I realize that this is catering for the cases where a manual transfer happens to the fund account.

let _ = frame_system::Pallet::<T>::dec_providers(&pot).defensive();

CurrencyOf::<T>::unreserve(&fund.depositor, fund.deposit);
Funds::<T>::remove(index);
Self::deposit_event(Event::<T>::Dissolved { para_id: index });
Expand Down Expand Up @@ -1609,6 +1613,7 @@ mod tests {
new_test_ext().execute_with(|| {
let para = new_para();
let index = NextFundIndex::<Test>::get();
let issuance = Balances::total_issuance();

// Set up a crowdloan
assert_ok!(Crowdloan::create(RuntimeOrigin::signed(1), para, 1000, 1, 1, 9, None));
Expand All @@ -1629,9 +1634,10 @@ mod tests {

// Some funds are left over
assert_eq!(Balances::free_balance(&account_id), 10);
// They wil be left in the account at the end
// Remaining funds will be burned
assert_ok!(Crowdloan::dissolve(RuntimeOrigin::signed(1), para));
assert_eq!(Balances::free_balance(&account_id), 10);
assert_eq!(Balances::free_balance(&account_id), 0);
assert_eq!(Balances::total_issuance(), issuance - 10);
});
}

Expand Down Expand Up @@ -1740,6 +1746,41 @@ mod tests {
});
}

// Regression test to check that a pot account with just one provider can be dissolved.
#[test]
fn dissolve_provider_refs_ti_works() {
new_test_ext().execute_with(|| {
let para = new_para();
let issuance = Balances::total_issuance();

// Set up a crowdloan
assert_ok!(Crowdloan::create(RuntimeOrigin::signed(1), para, 1000, 1, 1, 9, None));
assert_ok!(Crowdloan::contribute(RuntimeOrigin::signed(2), para, 100, None));
assert_ok!(Crowdloan::contribute(RuntimeOrigin::signed(3), para, 50, None));

run_to_block(10);

// We test the historic case where crowdloan accounts only have one provider:
{
let fund = Crowdloan::funds(para).unwrap();
let pot = Crowdloan::fund_account_id(fund.fund_index);
System::dec_providers(&pot).unwrap();
assert_eq!(System::providers(&pot), 1);
}

// All funds are refunded
assert_ok!(Crowdloan::refund(RuntimeOrigin::signed(2), para));

// Now that `fund.raised` is zero, it can be dissolved.
assert_ok!(Crowdloan::dissolve(RuntimeOrigin::signed(1), para));

assert_eq!(Balances::free_balance(1), 1000);
assert_eq!(Balances::free_balance(2), 2000);
assert_eq!(Balances::free_balance(3), 3000);
assert_eq!(Balances::total_issuance(), issuance);
});
}

#[test]
fn dissolve_works() {
new_test_ext().execute_with(|| {
Expand Down