@@ -123,6 +123,8 @@ fn compute_new_destination_amount(
123
123
let leverage: U256 = leverage. into ( ) ;
124
124
let new_source_amount: U256 = new_source_amount. into ( ) ;
125
125
let d_val: U256 = d_val. into ( ) ;
126
+ let zero = U256 :: from ( 0u128 ) ;
127
+ let one = U256 :: from ( 1u128 ) ;
126
128
127
129
// sum' = prod' = x
128
130
// c = D ** (n + 1) / (n ** (2 * n) * prod' * A)
@@ -135,8 +137,18 @@ fn compute_new_destination_amount(
135
137
// Solve for y by approximating: y**2 + b*y = c
136
138
let mut y = d_val;
137
139
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
+ } ) ;
140
152
if y_new == y {
141
153
break ;
142
154
} else {
@@ -630,4 +642,24 @@ mod tests {
630
642
) ;
631
643
}
632
644
}
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
+ }
633
665
}
0 commit comments