diff --git a/programs/amm/src/error.rs b/programs/amm/src/error.rs index 193867e4..f584cfda 100644 --- a/programs/amm/src/error.rs +++ b/programs/amm/src/error.rs @@ -2,6 +2,8 @@ use anchor_lang::prelude::*; #[error_code] pub enum AmmError { + #[msg("An assertion failed")] + AssertFailed, #[msg("Can't get a TWAP before some observations have been stored")] NoSlotsPassed, #[msg("Can't swap through a pool without token reserves on either side")] diff --git a/programs/amm/src/instructions/add_liquidity.rs b/programs/amm/src/instructions/add_liquidity.rs index c0bc8c39..00b1e461 100644 --- a/programs/amm/src/instructions/add_liquidity.rs +++ b/programs/amm/src/instructions/add_liquidity.rs @@ -46,7 +46,7 @@ impl AddOrRemoveLiquidity<'_> { AmmError::InsufficientBalance ); - amm.update_twap(Clock::get()?.slot); + amm.update_twap(Clock::get()?.slot)?; // airlifted from uniswap v1: // https://github.com/Uniswap/v1-contracts/blob/c10c08d81d6114f694baa8bd32f555a40f6264da/contracts/uniswap_exchange.vy#L48 diff --git a/programs/amm/src/instructions/crank_that_twap.rs b/programs/amm/src/instructions/crank_that_twap.rs index 8a8b10d1..3e4b4f39 100644 --- a/programs/amm/src/instructions/crank_that_twap.rs +++ b/programs/amm/src/instructions/crank_that_twap.rs @@ -12,7 +12,7 @@ impl CrankThatTwap<'_> { pub fn handle(ctx: Context) -> Result<()> { let CrankThatTwap { amm } = ctx.accounts; - amm.update_twap(Clock::get()?.slot); + amm.update_twap(Clock::get()?.slot)?; Ok(()) } diff --git a/programs/amm/src/instructions/remove_liquidity.rs b/programs/amm/src/instructions/remove_liquidity.rs index b7e04e90..20d3209e 100644 --- a/programs/amm/src/instructions/remove_liquidity.rs +++ b/programs/amm/src/instructions/remove_liquidity.rs @@ -41,13 +41,13 @@ impl AddOrRemoveLiquidity<'_> { require!(lp_tokens_to_burn > 0, AmmError::ZeroLiquidityRemove); - amm.update_twap(Clock::get()?.slot); + amm.update_twap(Clock::get()?.slot)?; // airlifted from uniswap v1: // https://github.com/Uniswap/v1-contracts/blob/c10c08d81d6114f694baa8bd32f555a40f6264da/contracts/uniswap_exchange.vy#L83 let total_liquidity = lp_mint.supply; - assert!(total_liquidity > 0); + require_gt!(total_liquidity, 0, AmmError::AssertFailed); let (base_to_withdraw, quote_to_withdraw) = amm.get_base_and_quote_withdrawable(lp_tokens_to_burn, total_liquidity); diff --git a/programs/amm/src/instructions/swap.rs b/programs/amm/src/instructions/swap.rs index b978ee41..a3bdec4f 100644 --- a/programs/amm/src/instructions/swap.rs +++ b/programs/amm/src/instructions/swap.rs @@ -78,7 +78,7 @@ impl Swap<'_> { require!(input_amount > 0, AmmError::ZeroSwapAmount); - amm.update_twap(Clock::get()?.slot); + amm.update_twap(Clock::get()?.slot)?; let output_amount = amm.swap(input_amount, swap_type)?; diff --git a/programs/amm/src/state/amm.rs b/programs/amm/src/state/amm.rs index 25a9624b..e7221bbd 100644 --- a/programs/amm/src/state/amm.rs +++ b/programs/amm/src/state/amm.rs @@ -166,7 +166,7 @@ impl Amm { let slots_passed = (self.oracle.last_updated_slot - self.created_at_slot) as u128; require_neq!(slots_passed, 0, AmmError::NoSlotsPassed); - assert!(self.oracle.aggregator != 0); + require!(self.oracle.aggregator != 0, AmmError::AssertFailed); Ok(self.oracle.aggregator / slots_passed) } @@ -175,7 +175,7 @@ impl Amm { /// have been made. /// /// Returns an observation if one was recorded. - pub fn update_twap(&mut self, current_slot: Slot) -> Option { + pub fn update_twap(&mut self, current_slot: Slot) -> Result> { let oracle = &mut self.oracle; // a manipulator is likely to be "bursty" with their usage, such as a // validator who abuses their slots to manipulate the TWAP. @@ -196,11 +196,11 @@ impl Amm { // that trades near $1500 and you allow $25 updates per minute, it can double // over an hour. if current_slot < oracle.last_updated_slot + ONE_MINUTE_IN_SLOTS { - return None; + return Ok(None); } if self.base_amount == 0 || self.quote_amount == 0 { - return None; + return Ok(None); } // we store prices as quote units / base units scaled by 1e12. @@ -244,32 +244,32 @@ impl Amm { initial_observation: oracle.initial_observation, }; - assert!(new_oracle.last_updated_slot > oracle.last_updated_slot); + require!(new_oracle.last_updated_slot > oracle.last_updated_slot, AmmError::AssertFailed); // assert that the new observation is between price and last observation match price.cmp(&oracle.last_observation) { Ordering::Greater => { - assert!(new_observation > oracle.last_observation); - assert!(new_observation <= price); + require!(new_observation > oracle.last_observation, AmmError::AssertFailed); + require!(new_observation <= price, AmmError::AssertFailed); } Ordering::Equal => { - assert!(new_observation == price); + require!(new_observation == price, AmmError::AssertFailed); } Ordering::Less => { - assert!(new_observation < oracle.last_observation); - assert!(new_observation >= price); + require!(new_observation < oracle.last_observation, AmmError::AssertFailed); + require!(new_observation >= price, AmmError::AssertFailed); } } *oracle = new_oracle; - Some(new_observation) + Ok(Some(new_observation)) } pub fn invariant(&self) -> Result<()> { let oracle = &self.oracle; - assert!(oracle.last_price <= MAX_PRICE); - assert!(oracle.last_observation <= MAX_PRICE); + require!(oracle.last_price <= MAX_PRICE, AmmError::AssertFailed); + require!(oracle.last_observation <= MAX_PRICE, AmmError::AssertFailed); Ok(()) } @@ -359,7 +359,7 @@ mod simple_amm_tests { let slots_until_overflow = u128::MAX / (u64::MAX as u128 * PRICE_SCALE); amm.update_twap(slots_until_overflow as u64); - assert!(amm.oracle.aggregator > MAX_PRICE * 18_400_000); + require!(amm.oracle.aggregator > MAX_PRICE * 18_400_000); assert_ne!(amm.oracle.aggregator, u128::MAX); amm_clone.update_twap(slots_until_overflow as u64 + 1); diff --git a/programs/autocrat/src/instructions/finalize_proposal.rs b/programs/autocrat/src/instructions/finalize_proposal.rs index 71709731..94190296 100644 --- a/programs/autocrat/src/instructions/finalize_proposal.rs +++ b/programs/autocrat/src/instructions/finalize_proposal.rs @@ -178,12 +178,12 @@ impl FinalizeProposal<'_> { // match new_proposal_state { // ProposalState::Passed => { - // assert!(base_vault.status == VaultStatus::Finalized); - // assert!(quote_vault.status == VaultStatus::Finalized); + // require!(base_vault.status == VaultStatus::Finalized); + // require!(quote_vault.status == VaultStatus::Finalized); // } // ProposalState::Failed => { - // assert!(base_vault.status == VaultStatus::Reverted); - // assert!(quote_vault.status == VaultStatus::Reverted); + // require!(base_vault.status == VaultStatus::Reverted); + // require!(quote_vault.status == VaultStatus::Reverted); // } // _ => unreachable!("Encountered an unexpected proposal state"), // } diff --git a/programs/conditional_vault/src/error.rs b/programs/conditional_vault/src/error.rs index a7dab727..2c810f4d 100644 --- a/programs/conditional_vault/src/error.rs +++ b/programs/conditional_vault/src/error.rs @@ -2,6 +2,8 @@ use super::*; #[error_code] pub enum VaultError { + #[msg("An assertion failed")] + AssertFailed, #[msg("Insufficient underlying token balance to mint this amount of conditional tokens")] InsufficientUnderlyingTokens, #[msg("Insufficient conditional token balance to merge this `amount`")] diff --git a/programs/conditional_vault/src/instructions/merge_tokens.rs b/programs/conditional_vault/src/instructions/merge_tokens.rs index 5e86ebdc..8d48b0fa 100644 --- a/programs/conditional_vault/src/instructions/merge_tokens.rs +++ b/programs/conditional_vault/src/instructions/merge_tokens.rs @@ -65,13 +65,15 @@ impl<'info, 'c: 'info> InteractWithVault<'info> { ctx.accounts.user_underlying_token_account.reload()?; ctx.accounts.vault_underlying_token_account.reload()?; - assert!( - ctx.accounts.user_underlying_token_account.amount - == pre_user_underlying_balance + amount + require_eq!( + ctx.accounts.user_underlying_token_account.amount, + pre_user_underlying_balance + amount, + VaultError::AssertFailed ); - assert!( - ctx.accounts.vault_underlying_token_account.amount - == pre_vault_underlying_balance - amount + require_eq!( + ctx.accounts.vault_underlying_token_account.amount, + pre_vault_underlying_balance - amount, + VaultError::AssertFailed ); for (mint, expected_supply) in conditional_token_mints @@ -79,7 +81,7 @@ impl<'info, 'c: 'info> InteractWithVault<'info> { .zip(expected_future_supplies.iter()) { mint.reload()?; - assert!(mint.supply == *expected_supply); + require_eq!(mint.supply, *expected_supply, VaultError::AssertFailed); } for (account, expected_balance) in user_conditional_token_accounts @@ -87,7 +89,7 @@ impl<'info, 'c: 'info> InteractWithVault<'info> { .zip(expected_future_balances.iter()) { account.reload()?; - assert!(account.amount == *expected_balance); + require_eq!(account.amount, *expected_balance, VaultError::AssertFailed); } ctx.accounts.vault.invariant( diff --git a/programs/conditional_vault/src/instructions/redeem_tokens.rs b/programs/conditional_vault/src/instructions/redeem_tokens.rs index 389a0a86..dd1c300b 100644 --- a/programs/conditional_vault/src/instructions/redeem_tokens.rs +++ b/programs/conditional_vault/src/instructions/redeem_tokens.rs @@ -83,24 +83,26 @@ impl<'info, 'c: 'info> InteractWithVault<'info> { total_redeemable, )?; - assert!(max_redeemable >= total_redeemable); + require_gte!(max_redeemable, total_redeemable, VaultError::AssertFailed); ctx.accounts.user_underlying_token_account.reload()?; ctx.accounts.vault_underlying_token_account.reload()?; - assert!( - ctx.accounts.user_underlying_token_account.amount - == user_underlying_balance_before + total_redeemable + require_eq!( + ctx.accounts.user_underlying_token_account.amount, + user_underlying_balance_before + total_redeemable, + VaultError::AssertFailed ); - assert!( - ctx.accounts.vault_underlying_token_account.amount - == vault_underlying_balance_before - total_redeemable + require_eq!( + ctx.accounts.vault_underlying_token_account.amount, + vault_underlying_balance_before - total_redeemable, + VaultError::AssertFailed ); for acc in user_conditional_token_accounts.iter_mut() { acc.reload()?; - assert!(acc.amount == 0); + require_eq!(acc.amount, 0, VaultError::AssertFailed); } for (mint, expected_supply) in conditional_token_mints @@ -108,7 +110,7 @@ impl<'info, 'c: 'info> InteractWithVault<'info> { .zip(expected_future_supplies.iter()) { mint.reload()?; - assert!(mint.supply == *expected_supply); + require_eq!(mint.supply, *expected_supply, VaultError::AssertFailed); } ctx.accounts.vault.invariant( diff --git a/programs/conditional_vault/src/instructions/split_tokens.rs b/programs/conditional_vault/src/instructions/split_tokens.rs index 26e80762..b3592121 100644 --- a/programs/conditional_vault/src/instructions/split_tokens.rs +++ b/programs/conditional_vault/src/instructions/split_tokens.rs @@ -58,19 +58,20 @@ impl<'info, 'c: 'info> InteractWithVault<'info> { } ctx.accounts.vault_underlying_token_account.reload()?; - assert!( - ctx.accounts.vault_underlying_token_account.amount - == pre_vault_underlying_balance + amount + require_eq!( + ctx.accounts.vault_underlying_token_account.amount, + pre_vault_underlying_balance + amount, + VaultError::AssertFailed ); for (i, mint) in conditional_token_mints.iter_mut().enumerate() { mint.reload()?; - assert!(mint.supply == pre_conditional_mint_supplies[i] + amount); + require_eq!(mint.supply, pre_conditional_mint_supplies[i] + amount, VaultError::AssertFailed); } for (i, acc) in user_conditional_token_accounts.iter_mut().enumerate() { acc.reload()?; - assert!(acc.amount == pre_conditional_user_balances[i] + amount); + require_eq!(acc.amount, pre_conditional_user_balances[i] + amount, VaultError::AssertFailed); } ctx.accounts.vault.invariant( diff --git a/programs/conditional_vault/src/lib.rs b/programs/conditional_vault/src/lib.rs index 839bcb74..818ca252 100644 --- a/programs/conditional_vault/src/lib.rs +++ b/programs/conditional_vault/src/lib.rs @@ -7,7 +7,6 @@ use anchor_spl::{ associated_token::AssociatedToken, token::{self, Burn, Mint, MintTo, Token, TokenAccount, Transfer}, }; -// use mpl_token_metadata::state::DataV2; pub mod error; pub mod instructions; diff --git a/programs/conditional_vault/src/state/conditional_vault.rs b/programs/conditional_vault/src/state/conditional_vault.rs index 3bd4f2da..994c171d 100644 --- a/programs/conditional_vault/src/state/conditional_vault.rs +++ b/programs/conditional_vault/src/state/conditional_vault.rs @@ -51,7 +51,7 @@ impl ConditionalVault { .sum::() }; - assert!(vault_underlying_balance >= max_possible_liability); + require_gte!(vault_underlying_balance, max_possible_liability, VaultError::AssertFailed); Ok(()) }