Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crowdload burn remaining funds #3707

Merged
merged 5 commits into from
Mar 17, 2024
Merged
Changes from all 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
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
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);
franciscoaguirre marked this conversation as resolved.
Show resolved Hide resolved
});
}

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_total_issuance_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
Loading