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

Contributors can pull their contribution back out of any crowdloan that
has not finalized, including while it is still raising. The creator may
only withdraw the part of their contribution above the initial deposit;
the deposit itself stays locked until `dissolve_crowdloan` returns it.
Fails once the crowdloan has finalized or if the signer has nothing left
to withdraw.

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

## 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 withdraw-crowdloan \
  --crowdloan-id <int> --dry-run
btcli tx withdraw-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.WithdrawCrowdloan(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("withdraw_crowdloan", {...}, wallet)
```

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

`Crowdloan.withdraw` — [`pallets/crowdloan/src/lib.rs#L548`](/code/pallets/crowdloan/src/lib.rs#L546-L592):

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

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

    // Ensure contributor has balance left in the crowdloan account
    let mut amount = Contributions::<T>::get(crowdloan_id, &who).unwrap_or_else(Zero::zero);
    ensure!(amount > Zero::zero(), Error::<T>::NoContribution);

    if who == crowdloan.creator {
        // Ensure the deposit is kept
        amount = amount.saturating_sub(crowdloan.deposit);
        ensure!(amount > Zero::zero(), Error::<T>::DepositCannotBeWithdrawn);
        Contributions::<T>::insert(crowdloan_id, &who, crowdloan.deposit);
    } else {
        Contributions::<T>::remove(crowdloan_id, &who);
        crowdloan.contributors_count = crowdloan
            .contributors_count
            .checked_sub(1)
            .ok_or(Error::<T>::Underflow)?;
    }

    CurrencyOf::<T>::transfer(
        &crowdloan.funds_account,
        &who,
        amount,
        Preservation::Expendable,
    )?;

    // Update the crowdloan raised amount to reflect the withdrawal.
    crowdloan.raised = crowdloan.raised.saturating_sub(amount);
    Crowdloans::<T>::insert(crowdloan_id, &crowdloan);

    Self::deposit_event(Event::<T>::Withdrew {
        contributor: who,
        crowdloan_id,
        amount,
    });

    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)).
