Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit fcbc0d3

Browse files
authored
token-swap: Add comment for stable curve A calculation (#2556)
1 parent 8aef395 commit fcbc0d3

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

token-swap/program/src/curve/stable.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ const N_COINS: u8 = 2;
2020
const N_COINS_SQUARED: u8 = 4;
2121
const ITERATIONS: u8 = 32;
2222

23+
/// Calculates A for deriving D
24+
///
25+
/// Per discussion with the designer and writer of stable curves, this A is not
26+
/// the same as the A from the whitepaper, it's actually `A * n**(n-1)`, so when
27+
/// you set A, you actually set `A * n**(n-1)`. This is because `D**n / prod(x)`
28+
/// loses precision with a huge A value.
29+
///
30+
/// There is little information to document this choice, but the original contracts
31+
/// use this same convention, see a comment in the code at:
32+
/// https://github.com/curvefi/curve-contract/blob/b0bbf77f8f93c9c5f4e415bce9cd71f0cdee960e/contracts/pool-templates/base/SwapTemplateBase.vy#L136
33+
fn compute_a(amp: u64) -> Option<u64> {
34+
amp.checked_mul(N_COINS as u64)
35+
}
36+
2337
/// Returns self to the power of b
2438
fn checked_u8_power(a: &U256, b: u8) -> Option<U256> {
2539
let mut result = *a;
@@ -141,7 +155,7 @@ impl CurveCalculator for StableCurve {
141155
swap_destination_amount: u128,
142156
_trade_direction: TradeDirection,
143157
) -> Option<SwapWithoutFeesResult> {
144-
let leverage = self.amp.checked_mul(N_COINS as u64)?;
158+
let leverage = compute_a(self.amp)?;
145159

146160
let new_source_amount = swap_source_amount.checked_add(source_amount)?;
147161
let new_destination_amount = compute_new_destination_amount(
@@ -215,7 +229,7 @@ impl CurveCalculator for StableCurve {
215229
if source_amount == 0 {
216230
return Some(0);
217231
}
218-
let leverage = self.amp.checked_mul(N_COINS as u64)?;
232+
let leverage = compute_a(self.amp)?;
219233
let d0 = PreciseNumber::new(compute_d(
220234
leverage,
221235
swap_token_a_amount,
@@ -248,7 +262,7 @@ impl CurveCalculator for StableCurve {
248262
if source_amount == 0 {
249263
return Some(0);
250264
}
251-
let leverage = self.amp.checked_mul(N_COINS as u64)?;
265+
let leverage = compute_a(self.amp)?;
252266
let d0 = PreciseNumber::new(compute_d(
253267
leverage,
254268
swap_token_a_amount,
@@ -277,7 +291,7 @@ impl CurveCalculator for StableCurve {
277291
) -> Option<PreciseNumber> {
278292
#[cfg(not(any(test, feature = "fuzz")))]
279293
{
280-
let leverage = self.amp.checked_mul(N_COINS as u64)?;
294+
let leverage = compute_a(self.amp)?;
281295
PreciseNumber::new(compute_d(
282296
leverage,
283297
swap_token_a_amount,

0 commit comments

Comments
 (0)