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.
After calling request_withdraw_vault, the user must wait for the vault’s withdrawal_waiting_period to pass before calling withdraw_vault to claim the underlying assets.
Discriminator
/// 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 Ranger Earn 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
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
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())
}
}
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.
Full reference implementation: request_withdraw_vault.rs