Crowdload burn remaining funds (#3707)

Crowdloan account should burn all funds after a crowd loan got dissolved
to ensure that the account is reaped correctly.

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
This commit is contained in:
Oliver Tale-Yazdi
2024-03-17 15:21:29 +02:00
committed by GitHub
parent 02e1a7f476
commit d2a7100e3b
+45 -4
View File
@@ -60,7 +60,7 @@ use frame_support::{
pallet_prelude::{DispatchResult, Weight},
storage::{child, ChildTriePrefixIterator},
traits::{
Currency,
Currency, Defensive,
ExistenceRequirement::{self, AllowDeath, KeepAlive},
Get, ReservableCurrency,
},
@@ -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,
@@ -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());
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 });
@@ -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));
@@ -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);
});
}
@@ -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(|| {