token-swap: Allow for huge swaps that almost entirely drain one side (#3334)

This commit is contained in:
Jon Cinque 2022-07-19 19:08:12 +02:00 committed by GitHub
parent 62ede3262f
commit 042da2b687
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 34 additions and 2 deletions

View File

@ -123,6 +123,8 @@ fn compute_new_destination_amount(
let leverage: U256 = leverage.into();
let new_source_amount: U256 = new_source_amount.into();
let d_val: U256 = d_val.into();
let zero = U256::from(0u128);
let one = U256::from(1u128);
// sum' = prod' = x
// c = D ** (n + 1) / (n ** (2 * n) * prod' * A)
@ -135,8 +137,18 @@ fn compute_new_destination_amount(
// Solve for y by approximating: y**2 + b*y = c
let mut y = d_val;
for _ in 0..ITERATIONS {
let (y_new, _) = (checked_u8_power(&y, 2)?.checked_add(c)?)
.checked_ceil_div(checked_u8_mul(&y, 2)?.checked_add(b)?.checked_sub(d_val)?)?;
let numerator = checked_u8_power(&y, 2)?.checked_add(c)?;
let denominator = checked_u8_mul(&y, 2)?.checked_add(b)?.checked_sub(d_val)?;
// checked_ceil_div is conservative, not allowing for a 0 return, but we can
// ceiling to 1 token in this case since we're solving through approximation,
// and not doing a constant product calculation
let (y_new, _) = numerator.checked_ceil_div(denominator).unwrap_or_else(|| {
if numerator == U256::from(0u128) {
(zero, zero)
} else {
(one, zero)
}
});
if y_new == y {
break;
} else {
@ -630,4 +642,24 @@ mod tests {
);
}
}
// this test comes from a failed proptest
#[test]
fn withdraw_token_conversion_huge_withdrawal() {
let pool_token_supply: u64 = 12798273514859089136;
let pool_token_amount: u64 = 12798243809352362806;
let swap_token_a_amount: u64 = 10000000000000000000;
let swap_token_b_amount: u64 = 6000000000000000000;
let amp = 72;
let curve = StableCurve { amp };
check_withdraw_token_conversion(
&curve,
pool_token_amount as u128,
pool_token_supply as u128,
swap_token_a_amount as u128,
swap_token_b_amount as u128,
TradeDirection::AtoB,
CONVERSION_BASIS_POINTS_GUARANTEE,
);
}
}