# dissolve-crowdloan (/docs/tx/dissolve-crowdloan)

Removes a non-finalized crowdloan from chain state once every non-creator
contribution has been returned (run `refund_crowdloan` until no other
contributors remain). Dissolving automatically transfers the creator's
remaining contribution — including the deposit — back to them. Only the
creator may dissolve. Dissolving while other contributions are still
outstanding fails — refund first.

| Signer    | Origin                                 | Pallet    | Wraps                                                                |
| --------- | -------------------------------------- | --------- | -------------------------------------------------------------------- |
| `coldkey` | signed account (pallet role may apply) | Crowdloan | [`Crowdloan.dissolve`](/code/pallets/crowdloan/src/lib.rs#L761-L805) |

## Parameters [#parameters]

| Parameter      | Type    | Required | Description                                                |
| -------------- | ------- | -------- | ---------------------------------------------------------- |
| `crowdloan_id` | integer | yes      | Identifier of the crowdloan, assigned when it was created. |

Address parameters (`--hotkey`, `--coldkey`, `--dest`, ...) accept a raw ss58
address, an address-book or proxy-book name, or a local wallet/hotkey name.

## CLI [#cli]

Preview with `--dry-run` (shows fee, effects, and policy result without
submitting), then submit:

```bash
btcli tx dissolve-crowdloan \
  --crowdloan-id <int> --dry-run
btcli tx dissolve-crowdloan \
  --crowdloan-id <int> -w my_coldkey
```

## Python [#python]

```python
import bittensor as bt
from bittensor.wallet import Wallet

wallet = Wallet(name="my_coldkey", hotkey="my_hotkey")
intent = bt.DissolveCrowdloan(crowdloan_id=0)

sub = bt.Subtensor()
plan = sub.plan(intent, wallet)   # fee, effects, policy — no submission
result = sub.execute(intent, wallet)
if not result.success:
    print(result.error.code, result.error.remediation)
```

(`bt.Subtensor` is also the async client — `async with bt.Subtensor() as client:`
— see [The client](/docs/concepts/client).) Or build the intent by op name, as
an agent would:

```python
result = sub.execute_tool("dissolve_crowdloan", {...}, wallet)
```

## On-chain implementation [#on-chain-implementation]

`Crowdloan.dissolve` — [`pallets/crowdloan/src/lib.rs#L763`](/code/pallets/crowdloan/src/lib.rs#L761-L805):

```rust
#[pallet::call_index(5)]
#[pallet::weight(T::WeightInfo::dissolve())]
pub fn dissolve(
    origin: OriginFor<T>,
    #[pallet::compact] crowdloan_id: CrowdloanId,
) -> DispatchResult {
    let who = ensure_signed(origin)?;

    let crowdloan = Self::ensure_crowdloan_exists(crowdloan_id)?;
    ensure!(!crowdloan.finalized, Error::<T>::AlreadyFinalized);

    // Only the creator can dissolve the crowdloan
    ensure!(who == crowdloan.creator, Error::<T>::InvalidOrigin);

    // It can only be dissolved if the raised amount is the creator's contribution,
    // meaning there is no contributions or every contribution has been refunded
    let creator_contribution = Contributions::<T>::get(crowdloan_id, &crowdloan.creator)
        .ok_or(Error::<T>::NoContribution)?;
    ensure!(
        creator_contribution == crowdloan.raised,
        Error::<T>::NotReadyToDissolve
    );

    // Refund the creator's contribution
    CurrencyOf::<T>::transfer(
        &crowdloan.funds_account,
        &crowdloan.creator,
        creator_contribution,
        Preservation::Expendable,
    )?;
    Contributions::<T>::remove(crowdloan_id, &crowdloan.creator);

    // Clear the call from the preimage storage
    if let Some(call) = crowdloan.call {
        T::Preimages::drop(&call);
    }

    // Remove the crowdloan
    let _ = frame_system::Pallet::<T>::dec_providers(&crowdloan.funds_account).defensive();
    Crowdloans::<T>::remove(crowdloan_id);
    MaxContributions::<T>::remove(crowdloan_id);

    Self::deposit_event(Event::<T>::Dissolved { crowdloan_id });
    Ok(())
}
```

Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/<path>` (index: [`/code/index.json`](/code/index.json)).
