Skip to content

Commit

Permalink
Merge pull request #9 from radixdlt/feature/caviarnine-fee-optimization
Browse files Browse the repository at this point in the history
[Caviarnine v1 Adapter v1]: Optimize fees for opening positions.
  • Loading branch information
0xOmarA authored Mar 6, 2024
2 parents 591a344 + 727818d commit 3fe2412
Show file tree
Hide file tree
Showing 2 changed files with 297 additions and 7 deletions.
11 changes: 4 additions & 7 deletions packages/caviarnine-v1-adapter-v1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ pub mod adapter {
}

let (receipt, change_x, change_y) =
pool.add_liquidity(bucket_x, bucket_y, positions);
pool.add_liquidity(bucket_x, bucket_y, positions.clone());

let receipt_global_id = {
let resource_address = receipt.resource_address();
Expand All @@ -483,14 +483,11 @@ pub mod adapter {

let adapter_specific_information =
CaviarnineV1AdapterSpecificInformation {
bin_contributions: pool
.get_redemption_bin_values(
receipt_global_id.local_id().clone(),
)
bin_contributions: positions
.into_iter()
.map(|(tick, amount_x, amount_y)| {
.map(|(bin, amount_x, amount_y)| {
(
tick,
bin,
ResourceIndexedData {
resource_x: amount_x,
resource_y: amount_y,
Expand Down
293 changes: 293 additions & 0 deletions tests/tests/caviarnine_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1466,3 +1466,296 @@ fn user_resources_are_contributed_in_full_when_oracle_price_is_lower_than_pool_p

Ok(())
}

#[test]
fn bin_amounts_reported_on_receipt_match_whats_reported_by_caviarnine(
) -> Result<(), RuntimeError> {
// Arrange
let Environment {
environment: ref mut env,
mut caviarnine_v1,
resources,
..
} = ScryptoTestEnv::new_with_configuration(Configuration {
maximum_allowed_relative_price_difference: dec!(0.05),
..Default::default()
})?;

let user_resource = resources.bitcoin;
let pool = caviarnine_v1.pools.bitcoin;

let [user_resource_bucket, xrd_bucket] =
[user_resource, XRD].map(|resource| {
ResourceManager(resource)
.mint_fungible(dec!(100), env)
.unwrap()
});

// Act
let OpenLiquidityPositionOutput {
pool_units,
adapter_specific_information,
..
} = caviarnine_v1.adapter.open_liquidity_position(
pool.try_into().unwrap(),
(user_resource_bucket, xrd_bucket),
env,
)?;

// Assert
let mut caviarnine_reported_redemption_value = pool
.get_redemption_bin_values(
pool_units
.non_fungible_local_ids(env)?
.first()
.unwrap()
.clone(),
env,
)?;
caviarnine_reported_redemption_value.sort_by(|a, b| a.0.cmp(&b.0));
let adapter_reported_redemption_value = adapter_specific_information
.as_typed::<CaviarnineV1AdapterSpecificInformation>()
.unwrap()
.bin_contributions;

assert_eq!(
caviarnine_reported_redemption_value.len(),
adapter_reported_redemption_value.len(),
);

for (
i,
(
caviarnine_reported_bin,
caviarnine_reported_amount_x,
caviarnine_reported_amount_y,
),
) in caviarnine_reported_redemption_value.into_iter().enumerate()
{
let Some(ResourceIndexedData {
resource_x: adapter_reported_amount_x,
resource_y: adapter_reported_amount_y,
}) = adapter_reported_redemption_value
.get(&caviarnine_reported_bin)
.copied()
else {
panic!(
"Bin {} does not have an entry in the adapter data",
caviarnine_reported_bin
)
};

assert_eq!(
round_down_to_5_decimal_places(caviarnine_reported_amount_x),
round_down_to_5_decimal_places(adapter_reported_amount_x),
"Failed at bin with index: {i}"
);
assert_eq!(
round_down_to_5_decimal_places(caviarnine_reported_amount_y),
round_down_to_5_decimal_places(adapter_reported_amount_y),
"Failed at bin with index: {i}"
);
}

Ok(())
}

#[test]
fn bin_amounts_reported_on_receipt_match_whats_reported_by_caviarnine_with_price_movement1(
) -> Result<(), RuntimeError> {
// Arrange
let Environment {
environment: ref mut env,
mut caviarnine_v1,
resources,
..
} = ScryptoTestEnv::new_with_configuration(Configuration {
maximum_allowed_relative_price_difference: dec!(0.05),
..Default::default()
})?;

let user_resource = resources.bitcoin;
let mut pool = caviarnine_v1.pools.bitcoin;

let _ = ResourceManager(user_resource)
.mint_fungible(dec!(1_000_000_000), env)
.and_then(|bucket| pool.swap(bucket, env))?;

let [user_resource_bucket, xrd_bucket] =
[user_resource, XRD].map(|resource| {
ResourceManager(resource)
.mint_fungible(dec!(100), env)
.unwrap()
});

// Act
let OpenLiquidityPositionOutput {
pool_units,
adapter_specific_information,
..
} = caviarnine_v1.adapter.open_liquidity_position(
pool.try_into().unwrap(),
(user_resource_bucket, xrd_bucket),
env,
)?;

// Assert
let mut caviarnine_reported_redemption_value = pool
.get_redemption_bin_values(
pool_units
.non_fungible_local_ids(env)?
.first()
.unwrap()
.clone(),
env,
)?;
caviarnine_reported_redemption_value.sort_by(|a, b| a.0.cmp(&b.0));
let adapter_reported_redemption_value = adapter_specific_information
.as_typed::<CaviarnineV1AdapterSpecificInformation>()
.unwrap()
.bin_contributions;

assert_eq!(
caviarnine_reported_redemption_value.len(),
adapter_reported_redemption_value.len(),
);

for (
i,
(
caviarnine_reported_bin,
caviarnine_reported_amount_x,
caviarnine_reported_amount_y,
),
) in caviarnine_reported_redemption_value.into_iter().enumerate()
{
let Some(ResourceIndexedData {
resource_x: adapter_reported_amount_x,
resource_y: adapter_reported_amount_y,
}) = adapter_reported_redemption_value
.get(&caviarnine_reported_bin)
.copied()
else {
panic!(
"Bin {} does not have an entry in the adapter data",
caviarnine_reported_bin
)
};

assert_eq!(
round_down_to_5_decimal_places(caviarnine_reported_amount_x),
round_down_to_5_decimal_places(adapter_reported_amount_x),
"Failed at bin with index: {i}"
);
assert_eq!(
round_down_to_5_decimal_places(caviarnine_reported_amount_y),
round_down_to_5_decimal_places(adapter_reported_amount_y),
"Failed at bin with index: {i}"
);
}

Ok(())
}

#[test]
fn bin_amounts_reported_on_receipt_match_whats_reported_by_caviarnine_with_price_movement2(
) -> Result<(), RuntimeError> {
// Arrange
let Environment {
environment: ref mut env,
mut caviarnine_v1,
resources,
..
} = ScryptoTestEnv::new_with_configuration(Configuration {
maximum_allowed_relative_price_difference: dec!(0.05),
..Default::default()
})?;

let user_resource = resources.bitcoin;
let mut pool = caviarnine_v1.pools.bitcoin;

let _ = ResourceManager(XRD)
.mint_fungible(dec!(1_000_000_000), env)
.and_then(|bucket| pool.swap(bucket, env))?;

let [user_resource_bucket, xrd_bucket] =
[user_resource, XRD].map(|resource| {
ResourceManager(resource)
.mint_fungible(dec!(100), env)
.unwrap()
});

// Act
let OpenLiquidityPositionOutput {
pool_units,
adapter_specific_information,
..
} = caviarnine_v1.adapter.open_liquidity_position(
pool.try_into().unwrap(),
(user_resource_bucket, xrd_bucket),
env,
)?;

// Assert
let mut caviarnine_reported_redemption_value = pool
.get_redemption_bin_values(
pool_units
.non_fungible_local_ids(env)?
.first()
.unwrap()
.clone(),
env,
)?;
caviarnine_reported_redemption_value.sort_by(|a, b| a.0.cmp(&b.0));
let adapter_reported_redemption_value = adapter_specific_information
.as_typed::<CaviarnineV1AdapterSpecificInformation>()
.unwrap()
.bin_contributions;

assert_eq!(
caviarnine_reported_redemption_value.len(),
adapter_reported_redemption_value.len(),
);

for (
i,
(
caviarnine_reported_bin,
caviarnine_reported_amount_x,
caviarnine_reported_amount_y,
),
) in caviarnine_reported_redemption_value.into_iter().enumerate()
{
let Some(ResourceIndexedData {
resource_x: adapter_reported_amount_x,
resource_y: adapter_reported_amount_y,
}) = adapter_reported_redemption_value
.get(&caviarnine_reported_bin)
.copied()
else {
panic!(
"Bin {} does not have an entry in the adapter data",
caviarnine_reported_bin
)
};

assert_eq!(
round_down_to_5_decimal_places(caviarnine_reported_amount_x),
round_down_to_5_decimal_places(adapter_reported_amount_x),
"Failed at bin with index: {i}"
);
assert_eq!(
round_down_to_5_decimal_places(caviarnine_reported_amount_y),
round_down_to_5_decimal_places(adapter_reported_amount_y),
"Failed at bin with index: {i}"
);
}

Ok(())
}

fn round_down_to_5_decimal_places(decimal: Decimal) -> Decimal {
decimal
.checked_round(5, RoundingMode::ToNegativeInfinity)
.unwrap()
}

0 comments on commit 3fe2412

Please sign in to comment.