> ## Documentation Index
> Fetch the complete documentation index at: https://docs.voltr.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Withdraw

> CPI instruction to complete a withdrawal from a Voltr vault

The `withdraw_vault` instruction completes a withdrawal by burning the escrowed LP tokens and transferring the underlying assets back to the user. This is the second step of the two-step withdrawal process.

<Warning>
  This instruction will fail with `WithdrawalNotYetAvailable` if the vault's `withdrawal_waiting_period` has not passed since the [`request_withdraw_vault`](/protocols/cpi-integration/request-withdraw) call.
</Warning>

## Discriminator

```rust theme={null}
/// sha256("global:withdraw_vault")[0..8]
fn get_withdraw_vault_discriminator() -> [u8; 8] {
    [135, 7, 237, 120, 149, 94, 95, 7]
}
```

## Parameters

This instruction takes no parameters beyond the discriminator.

## Accounts

| Account                          | Mutability | Signer | Description                                       |
| -------------------------------- | ---------- | ------ | ------------------------------------------------- |
| `user_transfer_authority`        | Mutable    | Yes    | The user finalizing the withdrawal                |
| `protocol`                       | Immutable  | No     | Global Voltr protocol state account               |
| `vault`                          | Mutable    | No     | The vault state account                           |
| `vault_asset_mint`               | Immutable  | No     | The mint of the asset being withdrawn             |
| `vault_lp_mint`                  | Mutable    | No     | The vault's LP mint                               |
| `request_withdraw_lp_ata`        | Mutable    | No     | The receipt's ATA holding escrowed LP tokens      |
| `vault_asset_idle_ata`           | Mutable    | No     | The vault's idle asset token account              |
| `vault_asset_idle_auth`          | Mutable    | No     | PDA authority over `vault_asset_idle_ata`         |
| `user_asset_ata`                 | Mutable    | No     | The user's asset token account (destination)      |
| `request_withdraw_vault_receipt` | Mutable    | No     | The PDA receipt account (closed after withdrawal) |
| `asset_token_program`            | Immutable  | No     | Token Program or Token-2022 for assets            |
| `lp_token_program`               | Immutable  | No     | Token Program for LP tokens                       |
| `system_program`                 | Immutable  | No     | Solana System Program                             |

## CPI Struct

```rust theme={null}
pub struct WithdrawVaultParams<'info> {
    pub user_transfer_authority: AccountInfo<'info>,
    pub protocol: AccountInfo<'info>,
    pub vault: AccountInfo<'info>,
    pub vault_asset_mint: AccountInfo<'info>,
    pub vault_lp_mint: AccountInfo<'info>,
    pub request_withdraw_lp_ata: AccountInfo<'info>,
    pub vault_asset_idle_ata: AccountInfo<'info>,
    pub vault_asset_idle_auth: AccountInfo<'info>,
    pub user_asset_ata: AccountInfo<'info>,
    pub request_withdraw_vault_receipt: AccountInfo<'info>,
    pub asset_token_program: AccountInfo<'info>,
    pub lp_token_program: AccountInfo<'info>,
    pub system_program: AccountInfo<'info>,
    pub voltr_vault_program: AccountInfo<'info>,
}
```

## Implementation

```rust theme={null}
use anchor_lang::prelude::*;
use anchor_lang::solana_program::{
    account_info::AccountInfo,
    instruction::{ AccountMeta, Instruction },
    program::invoke,
};

impl<'info> WithdrawVaultParams<'info> {
    pub fn withdraw_vault(&self) -> Result<()> {
        let instruction_data = get_withdraw_vault_discriminator().to_vec();

        let account_metas = vec![
            AccountMeta::new(*self.user_transfer_authority.key, true),
            AccountMeta::new_readonly(*self.protocol.key, false),
            AccountMeta::new(*self.vault.key, false),
            AccountMeta::new_readonly(*self.vault_asset_mint.key, false),
            AccountMeta::new(*self.vault_lp_mint.key, false),
            AccountMeta::new(*self.request_withdraw_lp_ata.key, false),
            AccountMeta::new(*self.vault_asset_idle_ata.key, false),
            AccountMeta::new(*self.vault_asset_idle_auth.key, false),
            AccountMeta::new(*self.user_asset_ata.key, false),
            AccountMeta::new(*self.request_withdraw_vault_receipt.key, false),
            AccountMeta::new_readonly(*self.asset_token_program.key, false),
            AccountMeta::new_readonly(*self.lp_token_program.key, false),
            AccountMeta::new_readonly(*self.system_program.key, false),
        ];

        let instruction = Instruction {
            program_id: *self.voltr_vault_program.key,
            accounts: account_metas,
            data: instruction_data,
        };

        invoke(&instruction, &self.to_account_infos())
            .map_err(|_| ErrorCodes::CpiToVoltrVaultFailed.into())
    }
}
```

<Info>
  After a successful `withdraw_vault` call, the `request_withdraw_vault_receipt` account is closed and its rent is returned. The user can then create a new withdrawal request if needed.
</Info>

Full reference implementation: [withdraw\_vault.rs](https://github.com/voltrxyz/vault-cpi/blob/main/references/withdraw_vault.rs)
