Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions programs/zap/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ pub enum ZapError {

#[msg("Exceeded slippage tolerance")]
ExceededSlippage,

#[msg("Invalid dlmm zap in parameters")]
InvalidDlmmZapInParameters,

#[msg("Unsupported fee mode")]
UnsupportedFeeMode,
}
38 changes: 32 additions & 6 deletions programs/zap/src/instructions/ix_zap_in_damm_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use damm_v2::{
};

use crate::{
damm_v2_ultils::{calculate_swap_amount, get_price_change_bps},
damm_v2_utils::{calculate_swap_amount, get_price_change_bps},
error::ZapError,
new_transfer_fee_calculator, UserLedger,
};
Expand Down Expand Up @@ -193,17 +193,43 @@ pub fn handle_zap_in_damm_v2(
if remaining_amount > 0 {
let pool = ctx.accounts.pool.load()?;
let current_point = ActivationHandler::get_current_point(pool.activation_type)?;
let swap_amount = calculate_swap_amount(
let swap_result = calculate_swap_amount(
&pool,
&token_a_transfer_fee_calculator,
&token_b_transfer_fee_calculator,
remaining_amount,
trade_direction,
current_point,
)?;
if swap_amount > 0 {
drop(pool);
ctx.accounts.swap(swap_amount, trade_direction)?;
);
match swap_result {
Ok((swap_in_amount, swap_out_amount)) => {
if swap_in_amount == 0 || swap_out_amount == 0 {
msg!(
"max_deposit_amounts: {} {}, remaining_amounts: {} {}, swap_amounts: {} {}",
max_deposit_a_amount,
max_deposit_b_amount,
ledger.amount_a,
ledger.amount_b,
swap_in_amount,
swap_out_amount
);
return Ok(()); // no need to swap, just return
}
drop(pool);
ctx.accounts.swap(swap_in_amount, trade_direction)?;
}
Err(err) => {
// if calculation fail, we just skip swap and add liquidity with remaining amount
msg!("Calculate swap amount error: {:?}", err);
msg!(
"max_deposit_amounts: {} {}, remaining_amounts: {} {}",
max_deposit_a_amount,
max_deposit_b_amount,
ledger.amount_a,
ledger.amount_b
);
return Ok(());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use dlmm::{
types::{AddLiquidityParams, RebalanceLiquidityParams, RemainingAccountsInfo},
};

use crate::{StrategyType, UnparsedAddLiquidityParams, UserLedger, ZapInRebalancingParams};
use crate::{
error::ZapError, StrategyType, UnparsedAddLiquidityParams, UserLedger, ZapInRebalancingParams,
};

#[derive(Accounts)]
pub struct ZapInDlmmForInitializedPositionCtx<'info> {
Expand Down Expand Up @@ -106,6 +108,11 @@ pub fn handle_zap_in_dlmm_for_initialized_position<'c: 'info, 'info>(
strategy,
};

require!(
min_delta_id <= max_delta_id,
ZapError::InvalidDlmmZapInParameters
);

let UnparsedAddLiquidityParams {
x0,
y0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub struct ZapInDlmmForUnintializedPositionCtx<'info> {
pub lb_pair: AccountLoader<'info, LbPair>,

/// user position
/// Check it is different from owner to advoid user to pass owner address wrongly
#[account(mut, constraint = position.key.ne(owner.key))]
/// Check it is different from owner to avoid user to pass owner address wrongly
#[account(mut, constraint = position.key.ne(owner.key) && position.key.ne(rent_payer.key))]
pub position: Signer<'info>,

/// CHECK: will be validated in dlmm program
Expand Down Expand Up @@ -150,6 +150,11 @@ pub fn handle_zap_in_dlmm_for_uninitialized_position<'c: 'info, 'info>(
strategy,
};

require!(
min_delta_id <= max_delta_id,
ZapError::InvalidDlmmZapInParameters
);

let UnparsedAddLiquidityParams {
x0,
y0,
Expand Down
4 changes: 2 additions & 2 deletions programs/zap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ pub mod state;
#[cfg(test)]
pub mod tests;
pub use state::*;
pub mod ultils;
pub mod utils;
use dlmm::types::RemainingAccountsInfo;
pub use ultils::*;
pub use utils::*;
declare_id!("zapvX9M3uf5pvy4wRPAbQgdQsM1xmuiFnkfHKPvwMiz");

#[program]
Expand Down
12 changes: 9 additions & 3 deletions programs/zap/src/math/price_math.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use anchor_lang::prelude::*;

use crate::{error::ZapError, safe_math::SafeMath};
use crate::{constants::MAX_BASIS_POINT, error::ZapError, safe_math::SafeMath};

// Number of bits to scale. This will decide the position of the radix point.
const SCALE_OFFSET: u8 = 64;
const BASIS_POINT_MAX: i32 = 10000;

// 1.0000... representation of 64x64
pub const ONE: u128 = 1u128 << SCALE_OFFSET;
const MAX_EXPONENTIAL: u32 = 0x80000; // 1048576
Expand All @@ -23,13 +23,19 @@ pub fn get_price_base_factor(bin_step: u16) -> Result<u128> {
// Make bin_step into Q64x64, and divided by BASIS_POINT_MAX. If bin_step = 1, we get 0.0001 in Q64x64
let bps = u128::from(bin_step)
.safe_shl(SCALE_OFFSET.into())?
.safe_div(BASIS_POINT_MAX as u128)?;
.safe_div(MAX_BASIS_POINT as u128)?;
// Add 1 to bps, we get 1.0001 in Q64.64
let base = ONE.safe_add(bps)?;
Ok(base)
}

pub fn pow(base: u128, exp: i32) -> Option<u128> {
// https://doc.rust-lang.org/std/primitive.i32.html#method.abs
// The absolute value of i32::MIN cannot be represented as an i32, and attempting to calculate it will cause an overflow.
if exp == i32::MIN {
return None;
}

// If exponent is negative. We will invert the result later by 1 / base^exp.abs()
let mut invert = exp.is_negative();

Expand Down
22 changes: 13 additions & 9 deletions programs/zap/src/state/user_ledger.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
damm_v2_ultils::{get_liquidity_from_amount_a, get_liquidity_from_amount_b},
damm_v2_utils::{get_liquidity_from_amount_a, get_liquidity_from_amount_b},
error::ZapError,
math::safe_math::SafeMath,
TransferFeeCalculator,
};
Expand All @@ -22,14 +23,17 @@ impl UserLedger {
pre_amount_b: u64,
post_amount_b: u64,
) -> Result<()> {
self.amount_a = self
.amount_a
.safe_add(post_amount_a)?
.safe_sub(pre_amount_a)?;
self.amount_b = self
.amount_b
.safe_add(post_amount_b)?
.safe_sub(pre_amount_b)?;
self.amount_a = u128::from(self.amount_a)
.safe_add(post_amount_a.into())?
.safe_sub(pre_amount_a.into())?
.try_into()
.map_err(|_| ZapError::MathOverflow)?;

self.amount_b = u128::from(self.amount_b)
.safe_add(post_amount_b.into())?
.safe_sub(pre_amount_b.into())?
.try_into()
.map_err(|_| ZapError::MathOverflow)?;
Ok(())
}
// only needed for damm v2 function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@ use crate::{

const STRATEGY: StrategyType = StrategyType::BidAsk;

#[test]
fn test_strategy_only_ask_side_single_bin() {
let active_id = 100;
let bin_step = 100;
let total_amount_x = 100_000_000;
let min_delta_id = 100;
let max_delta_id = 100;
let favor_x_in_active_id = true;

let params = build_add_liquidity_params(
total_amount_x,
0,
active_id,
bin_step,
min_delta_id,
max_delta_id,
favor_x_in_active_id,
STRATEGY,
);

let amount_in_bins = get_bin_add_liquidity(&params, active_id, bin_step).unwrap();
let amount_in_bin = &amount_in_bins[0];

let diff = total_amount_x - amount_in_bin.amount_x;
assert_eq!(diff, 12);
}

#[test]
fn test_strategy_only_bid_side_favour_x() {
let active_id = 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@ use crate::{

const STRATEGY: StrategyType = StrategyType::Curve;

#[test]
fn test_strategy_only_ask_side_single_bin() {
let active_id = 100;
let bin_step = 100;
let total_amount_x = 100_000_000;
let min_delta_id = 100;
let max_delta_id = 100;
let favor_x_in_active_id = true;

let params = build_add_liquidity_params(
total_amount_x,
0,
active_id,
bin_step,
min_delta_id,
max_delta_id,
favor_x_in_active_id,
STRATEGY,
);

let amount_in_bins = get_bin_add_liquidity(&params, active_id, bin_step).unwrap();
let amount_in_bin = &amount_in_bins[0];

let diff = total_amount_x - amount_in_bin.amount_x;
assert_eq!(diff, 1);
}

#[test]
fn test_strategy_only_bid_side_favour_x() {
let active_id = 100;
Expand Down
2 changes: 1 addition & 1 deletion programs/zap/src/tests/zap_in_damm_v2_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn test_calculate_swap_result() {
epoch_transfer_fee: TransferFee::default(),
no_transfer_fee_extension: true,
};
let swap_amount = calculate_swap_amount(
let (swap_amount, _swap_out_amount) = calculate_swap_amount(
&pool,
&transfer_fee_calculator,
&transfer_fee_calculator,
Expand Down
Loading
Loading