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

# Request Withdraw

> CPI instruction to initiate a withdrawal from a Voltr vault

The `request_withdraw_vault` instruction initiates a withdrawal by transferring the user's LP tokens into an escrow receipt account. This is the first step of the two-step withdrawal process.

<Warning>
  After calling `request_withdraw_vault`, the user must wait for the vault's `withdrawal_waiting_period` to pass before calling [`withdraw_vault`](/protocols/cpi-integration/withdraw) to claim the underlying assets.
</Warning>

## Discriminator

```rust theme={null}
/// sha256("global:request_withdraw_vault")[0..8]
fn get_request_withdraw_vault_discriminator() -> [u8; 8] {
    [248, 225, 47, 22, 116, 144, 23, 143]
}
```

## Parameters

| Parameter         | Type   | Description                                                                             |
| ----------------- | ------ | --------------------------------------------------------------------------------------- |
| `amount`          | `u64`  | The withdrawal amount (interpretation depends on `is_amount_in_lp`)                     |
| `is_amount_in_lp` | `bool` | If `true`, `amount` is in LP tokens. If `false`, `amount` is in underlying asset tokens |
| `is_withdraw_all` | `bool` | If `true`, withdraws the user's entire LP balance regardless of `amount`                |

## Accounts

| Account                          | Mutability | Signer | Description                                     |
| -------------------------------- | ---------- | ------ | ----------------------------------------------- |
| `payer`                          | Mutable    | Yes    | Pays rent for the receipt account               |
| `user_transfer_authority`        | Immutable  | Yes    | The user requesting the withdrawal              |
| `protocol`                       | Immutable  | No     | Global Voltr protocol state account             |
| `vault`                          | Immutable  | No     | The vault to withdraw from                      |
| `vault_lp_mint`                  | Immutable  | No     | The vault's LP mint                             |
| `user_lp_ata`                    | Mutable    | No     | The user's LP token account (source)            |
| `request_withdraw_lp_ata`        | Mutable    | No     | The receipt's ATA to hold escrowed LP tokens    |
| `request_withdraw_vault_receipt` | Mutable    | No     | PDA receipt account storing the request details |
| `lp_token_program`               | Immutable  | No     | Token Program for LP tokens                     |
| `system_program`                 | Immutable  | No     | Solana System Program                           |

## CPI Struct

```rust theme={null}
pub struct RequestWithdrawVaultParams<'info> {
    pub payer: AccountInfo<'info>,
    pub user_transfer_authority: AccountInfo<'info>,
    pub protocol: AccountInfo<'info>,
    pub vault: AccountInfo<'info>,
    pub vault_lp_mint: AccountInfo<'info>,
    pub user_lp_ata: AccountInfo<'info>,
    pub request_withdraw_lp_ata: AccountInfo<'info>,
    pub request_withdraw_vault_receipt: 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> RequestWithdrawVaultParams<'info> {
    pub fn request_withdraw_vault(
        &self,
        amount: u64,
        is_amount_in_lp: bool,
        is_withdraw_all: bool,
    ) -> Result<()> {
        let mut instruction_data = get_request_withdraw_vault_discriminator().to_vec();
        instruction_data.extend_from_slice(&amount.to_le_bytes());
        instruction_data.push(is_amount_in_lp as u8);
        instruction_data.push(is_withdraw_all as u8);

        let account_metas = vec![
            AccountMeta::new(*self.payer.key, true),
            AccountMeta::new_readonly(*self.user_transfer_authority.key, true),
            AccountMeta::new_readonly(*self.protocol.key, false),
            AccountMeta::new_readonly(*self.vault.key, false),
            AccountMeta::new_readonly(*self.vault_lp_mint.key, false),
            AccountMeta::new(*self.user_lp_ata.key, false),
            AccountMeta::new(*self.request_withdraw_lp_ata.key, false),
            AccountMeta::new(*self.request_withdraw_vault_receipt.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>
  The `request_withdraw_vault_receipt` PDA is derived from seeds `["request_withdraw_vault_receipt", vault_key, user_key]`. This means each user can have one active withdrawal request per vault at a time.
</Info>

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