From a82bab4ed76339499f3e0beacae3e1eea250aaeb Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Tue, 19 Jul 2022 11:36:23 +0200 Subject: [PATCH] Better error when vault doesn't have enough funds The spl_token transfer cpi instruction just says "error code: 1", which is too opaque. --- programs/mango-v4/src/error.rs | 2 ++ .../mango-v4/src/instructions/flash_loan3.rs | 10 ++++++++++ .../src/instructions/serum3_place_order.rs | 16 +++++++++++++++- .../mango-v4/src/instructions/token_withdraw.rs | 10 ++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/programs/mango-v4/src/error.rs b/programs/mango-v4/src/error.rs index faab3e97a..535a8e017 100644 --- a/programs/mango-v4/src/error.rs +++ b/programs/mango-v4/src/error.rs @@ -29,6 +29,8 @@ pub enum MangoError { NoFreePerpPositionIndex, #[msg("serum3 open orders exist already")] Serum3OpenOrdersExistAlready, + #[msg("bank vault has insufficent funds")] + InsufficentBankVaultFunds, } pub trait Contextable { diff --git a/programs/mango-v4/src/instructions/flash_loan3.rs b/programs/mango-v4/src/instructions/flash_loan3.rs index 12926b682..35e853318 100644 --- a/programs/mango-v4/src/instructions/flash_loan3.rs +++ b/programs/mango-v4/src/instructions/flash_loan3.rs @@ -82,6 +82,16 @@ pub fn flash_loan3_begin<'key, 'accounts, 'remaining, 'info>( // Transfer the loaned funds if *amount > 0 { + // Provide a readable error message in case the vault doesn't have enough tokens + if token_account.amount < *amount { + return err!(MangoError::InsufficentBankVaultFunds).with_context(|| { + format!( + "bank vault {} does not have enough tokens, need {} but have {}", + vault_ai.key, amount, token_account.amount + ) + }); + } + let transfer_ctx = CpiContext::new( ctx.accounts.token_program.to_account_info(), token::Transfer { diff --git a/programs/mango-v4/src/instructions/serum3_place_order.rs b/programs/mango-v4/src/instructions/serum3_place_order.rs index 935e8fd00..60beae834 100644 --- a/programs/mango-v4/src/instructions/serum3_place_order.rs +++ b/programs/mango-v4/src/instructions/serum3_place_order.rs @@ -1,4 +1,4 @@ -use crate::error::MangoError; +use crate::error::*; use crate::serum3_cpi::load_open_orders_ref; use crate::state::*; @@ -209,6 +209,20 @@ pub fn serum3_place_order( let before_base_vault = ctx.accounts.base_vault.amount; let before_quote_vault = ctx.accounts.quote_vault.amount; + // Provide a readable error message in case the vault doesn't have enough tokens + let (vault_amount, needed_amount) = match side { + Serum3Side::Ask => (before_base_vault, max_base_qty), + Serum3Side::Bid => (before_quote_vault, max_native_quote_qty_including_fees), + }; + if vault_amount < needed_amount { + return err!(MangoError::InsufficentBankVaultFunds).with_context(|| { + format!( + "bank vault does not have enough tokens, need {} but have {}", + needed_amount, vault_amount + ) + }); + } + // TODO: pre-health check // diff --git a/programs/mango-v4/src/instructions/token_withdraw.rs b/programs/mango-v4/src/instructions/token_withdraw.rs index b8a5bd015..a02bf6a2a 100644 --- a/programs/mango-v4/src/instructions/token_withdraw.rs +++ b/programs/mango-v4/src/instructions/token_withdraw.rs @@ -99,6 +99,16 @@ pub fn token_withdraw(ctx: Context, amount: u64, allow_borrow: bo // Update the bank and position let position_is_active = bank.withdraw_with_fee(position, amount_i80f48)?; + // Provide a readable error message in case the vault doesn't have enough tokens + if ctx.accounts.vault.amount < amount { + return err!(MangoError::InsufficentBankVaultFunds).with_context(|| { + format!( + "bank vault does not have enough tokens, need {} but have {}", + amount, ctx.accounts.vault.amount + ) + }); + } + // Transfer the actual tokens let group_seeds = group_seeds!(group); token::transfer(