@@ -123,6 +123,8 @@ fn compute_new_destination_amount(
123123 let leverage: U256 = leverage. into ( ) ;
124124 let new_source_amount: U256 = new_source_amount. into ( ) ;
125125 let d_val: U256 = d_val. into ( ) ;
126+ let zero = U256 :: from ( 0u128 ) ;
127+ let one = U256 :: from ( 1u128 ) ;
126128
127129 // sum' = prod' = x
128130 // c = D ** (n + 1) / (n ** (2 * n) * prod' * A)
@@ -135,8 +137,18 @@ fn compute_new_destination_amount(
135137 // Solve for y by approximating: y**2 + b*y = c
136138 let mut y = d_val;
137139 for _ in 0 ..ITERATIONS {
138- let ( y_new, _) = ( checked_u8_power ( & y, 2 ) ?. checked_add ( c) ?)
139- . checked_ceil_div ( checked_u8_mul ( & y, 2 ) ?. checked_add ( b) ?. checked_sub ( d_val) ?) ?;
140+ let numerator = checked_u8_power ( & y, 2 ) ?. checked_add ( c) ?;
141+ let denominator = checked_u8_mul ( & y, 2 ) ?. checked_add ( b) ?. checked_sub ( d_val) ?;
142+ // checked_ceil_div is conservative, not allowing for a 0 return, but we can
143+ // ceiling to 1 token in this case since we're solving through approximation,
144+ // and not doing a constant product calculation
145+ let ( y_new, _) = numerator. checked_ceil_div ( denominator) . unwrap_or_else ( || {
146+ if numerator == U256 :: from ( 0u128 ) {
147+ ( zero, zero)
148+ } else {
149+ ( one, zero)
150+ }
151+ } ) ;
140152 if y_new == y {
141153 break ;
142154 } else {
@@ -630,4 +642,24 @@ mod tests {
630642 ) ;
631643 }
632644 }
645+
646+ // this test comes from a failed proptest
647+ #[ test]
648+ fn withdraw_token_conversion_huge_withdrawal ( ) {
649+ let pool_token_supply: u64 = 12798273514859089136 ;
650+ let pool_token_amount: u64 = 12798243809352362806 ;
651+ let swap_token_a_amount: u64 = 10000000000000000000 ;
652+ let swap_token_b_amount: u64 = 6000000000000000000 ;
653+ let amp = 72 ;
654+ let curve = StableCurve { amp } ;
655+ check_withdraw_token_conversion (
656+ & curve,
657+ pool_token_amount as u128 ,
658+ pool_token_supply as u128 ,
659+ swap_token_a_amount as u128 ,
660+ swap_token_b_amount as u128 ,
661+ TradeDirection :: AtoB ,
662+ CONVERSION_BASIS_POINTS_GUARANTEE ,
663+ ) ;
664+ }
633665}
0 commit comments