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
5 changes: 5 additions & 0 deletions rust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to this project will be documented in this file.

## [0.4.1] - 2025-11-20

### Changed
- Update reCLAMM pricing functions to use scaling factors instead of decimals.

## [0.4.1] - 2025-11-13

### Changed
Expand Down
2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "balancer-maths-rust"
version = "0.4.1"
version = "0.4.2"
edition = "2021"
description = "Balancer V3 mathematics library in Rust"
license = "MIT"
Expand Down
17 changes: 7 additions & 10 deletions rust/src/pools/reclamm/reclamm_pricing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,12 @@ pub fn calculate_reclamm_price(
#[allow(clippy::too_many_arguments)]
pub fn swap_reclamm_to_price(
token_rates: &[U256],
scaling_factors: &[U256],
balances_live_scaled_18: &[U256],
current_virtual_balances: &[U256],
swap_fee_percentage: &U256,
_protocol_fee_percentage: &U256,
_pool_creator_fee_percentage: &U256,
decimals_a: u8,
decimals_b: u8,
target_price_scaled_18: &U256,
) -> Result<SwapToTargetPriceResult, String> {
// Input validation
Expand All @@ -88,6 +87,8 @@ pub fn swap_reclamm_to_price(
let rate_a = u256_to_f64(&token_rates[0]) / 1e18;
let rate_b = u256_to_f64(&token_rates[1]) / 1e18;
let target_price = u256_to_f64(target_price_scaled_18) / 1e18;
let scaling_factor_a = u256_to_f64(&scaling_factors[0]) / 1e18;
let scaling_factor_b = u256_to_f64(&scaling_factors[1]) / 1e18;

// Validate non-zero values
if balance_a + virtual_a == 0.0 || balance_b + virtual_b == 0.0 {
Expand Down Expand Up @@ -127,11 +128,9 @@ pub fn swap_reclamm_to_price(
Ok(SwapToTargetPriceResult {
token_in_index: 1,
token_out_index: 0,
amount_in_raw: U256::from(
(amount_in_scaled * 10f64.powi(decimals_b as i32) / rate_b).ceil() as u128,
),
amount_in_raw: U256::from((amount_in_scaled / scaling_factor_b * rate_b).ceil() as u128),
amount_out_raw: U256::from(
(amount_out_scaled * 10f64.powi(decimals_a as i32) / rate_a).floor() as u128,
(amount_out_scaled / scaling_factor_a * rate_a).floor() as u128
),
})
} else {
Expand All @@ -156,11 +155,9 @@ pub fn swap_reclamm_to_price(
Ok(SwapToTargetPriceResult {
token_in_index: 0,
token_out_index: 1,
amount_in_raw: U256::from(
(amount_in_scaled * 10f64.powi(decimals_a as i32) / rate_a).ceil() as u128,
),
amount_in_raw: U256::from((amount_in_scaled / scaling_factor_a * rate_a).ceil() as u128),
amount_out_raw: U256::from(
(amount_out_scaled * 10f64.powi(decimals_b as i32) / rate_b).floor() as u128,
(amount_out_scaled / scaling_factor_b * rate_b).floor() as u128
),
})
}
Expand Down
39 changes: 8 additions & 31 deletions rust/tests/test_reclamm_swap_to_price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ struct TestPool {
// Token information
tokens: Vec<String>,
token_rates: Vec<U256>,
decimals_a: u8,
decimals_b: u8,

// Pool balances
balances_live_scaled_18: Vec<U256>,
Expand Down Expand Up @@ -62,8 +60,6 @@ impl TestPool {
U256::from_str_radix("1000000000000000000", 10).unwrap(),
U256::from_str_radix("1000000000000000000", 10).unwrap(),
],
decimals_a: 18,
decimals_b: 18,
balances_live_scaled_18: vec![
U256::from_str_radix("122255177411753308470", 10).unwrap(),
U256::from_str_radix("13599963412925271409", 10).unwrap(),
Expand Down Expand Up @@ -161,28 +157,14 @@ fn get_swap_tokens(
// Helper to apply swap to balances
fn update_balances(
balances: &mut [U256],
scaling_factors: &[U256],
token_in_index: usize,
token_out_index: usize,
amount_in_raw: U256,
amount_out_raw: U256,
decimals_a: u8,
decimals_b: u8,
) {
// Convert raw amounts to scaled18
let scaling_factor_in = if token_in_index == 0 {
U256::from(10u128.pow((18 - decimals_a) as u32))
} else {
U256::from(10u128.pow((18 - decimals_b) as u32))
};

let scaling_factor_out = if token_out_index == 0 {
U256::from(10u128.pow((18 - decimals_a) as u32))
} else {
U256::from(10u128.pow((18 - decimals_b) as u32))
};

let amount_in_scaled = amount_in_raw * scaling_factor_in;
let amount_out_scaled = amount_out_raw * scaling_factor_out;
let amount_in_scaled = amount_in_raw * scaling_factors[token_in_index];
let amount_out_scaled = amount_out_raw * scaling_factors[token_out_index];

balances[token_in_index] += amount_in_scaled;
balances[token_out_index] -= amount_out_scaled;
Expand Down Expand Up @@ -213,25 +195,23 @@ macro_rules! generate_tests {

let result = swap_reclamm_to_price(
&test_pool.token_rates,
&test_pool.scaling_factors,
&balances_live_scaled_18,
&test_pool.current_virtual_balances,
&test_pool.swap_fee_percentage,
&test_pool.protocol_fee_percentage,
&test_pool.pool_creator_fee_percentage,
test_pool.decimals_a,
test_pool.decimals_b,
&target_price_scaled_18,
)
.unwrap();

update_balances(
&mut balances_live_scaled_18,
&test_pool.scaling_factors,
result.token_in_index,
result.token_out_index,
result.amount_in_raw,
result.amount_out_raw,
test_pool.decimals_a,
test_pool.decimals_b,
);

let new_price_scaled_18 = calculate_reclamm_price(&balances_live_scaled_18, &test_pool.current_virtual_balances);
Expand All @@ -253,13 +233,12 @@ macro_rules! generate_tests {

let price_result = swap_reclamm_to_price(
&test_pool.token_rates,
&test_pool.scaling_factors,
&test_pool.balances_live_scaled_18,
&test_pool.current_virtual_balances,
&test_pool.swap_fee_percentage,
&test_pool.protocol_fee_percentage,
&test_pool.pool_creator_fee_percentage,
test_pool.decimals_a,
test_pool.decimals_b,
&target_price_scaled_18
)
.unwrap();
Expand Down Expand Up @@ -320,13 +299,12 @@ fn test_amount_out_exceeds_balance_greater() {

let result = swap_reclamm_to_price(
&test_pool.token_rates,
&test_pool.scaling_factors,
&test_pool.balances_live_scaled_18,
&test_pool.current_virtual_balances,
&test_pool.swap_fee_percentage,
&test_pool.protocol_fee_percentage,
&test_pool.pool_creator_fee_percentage,
test_pool.decimals_a,
test_pool.decimals_b,
&target_price_scaled_18,
);

Expand Down Expand Up @@ -359,13 +337,12 @@ fn test_amount_out_exceeds_balance_less() {

let result = swap_reclamm_to_price(
&test_pool.token_rates,
&test_pool.scaling_factors,
&test_pool.balances_live_scaled_18,
&test_pool.current_virtual_balances,
&test_pool.swap_fee_percentage,
&test_pool.protocol_fee_percentage,
&test_pool.pool_creator_fee_percentage,
test_pool.decimals_a,
test_pool.decimals_b,
&target_price_scaled_18,
);

Expand Down
Loading