@@ -5,6 +5,8 @@ import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol";
5
5
import {IEVault} from "evk/EVault/IEVault.sol " ;
6
6
import {IEulerSwapPeriphery} from "./interfaces/IEulerSwapPeriphery.sol " ;
7
7
import {IERC20 , IEulerSwap, SafeERC20} from "./EulerSwap.sol " ;
8
+ import {Math} from "openzeppelin-contracts/utils/math/Math.sol " ;
9
+ import "@uniswap/v4-core/libraries/FullMath.sol " ;
8
10
9
11
contract EulerSwapPeriphery is IEulerSwapPeriphery {
10
12
using SafeERC20 for IERC20 ;
@@ -188,4 +190,57 @@ contract EulerSwapPeriphery is IEulerSwapPeriphery {
188
190
else output = uint256 (dy);
189
191
}
190
192
}
193
+
194
+ /**
195
+ * @notice Computes the inverse of the `f()` function for the EulerSwap liquidity curve.
196
+ * @dev Solves for `x` given `y` using the quadratic formula derived from the liquidity curve:
197
+ * x = (-b + sqrt(b^2 + 4ac)) / 2a
198
+ * Utilises Uniswap's FullMath to avoid overflow and ensures precision with upward rounding.
199
+ *
200
+ * @param y The y-coordinate input value (must be greater than `y0`).
201
+ * @param px Price factor for the x-axis (scaled by 1e18, between 1e18 and 1e36).
202
+ * @param py Price factor for the y-axis (scaled by 1e18, between 1e18 and 1e36).
203
+ * @param x0 Reference x-value on the liquidity curve (≤ 2^112 - 1).
204
+ * @param y0 Reference y-value on the liquidity curve (≤ 2^112 - 1).
205
+ * @param c Curve parameter shaping liquidity concentration (scaled by 1e18, between 0 and 1e18).
206
+ *
207
+ * @return x The computed x-coordinate on the liquidity curve.
208
+ *
209
+ * @custom:precision Uses rounding up to maintain precision in all calculations.
210
+ * @custom:safety FullMath handles potential overflow in the b^2 computation.
211
+ * @custom:requirement Input `y` must be strictly greater than `y0`; otherwise, the function will revert.
212
+ */
213
+ function fInverse (uint256 y , uint256 px , uint256 py , uint256 x0 , uint256 y0 , uint256 c )
214
+ external
215
+ pure
216
+ returns (uint256 )
217
+ {
218
+ // A component of the quadratic formula: a = 2 * c
219
+ uint256 A = 2 * c;
220
+
221
+ // B component of the quadratic formula
222
+ int256 B = int256 ((px * (y - y0) + py - 1 ) / py) - int256 ((x0 * (2 * c - 1e18 ) + 1e18 - 1 ) / 1e18 );
223
+
224
+ // B^2 component, using FullMath for overflow safety
225
+ uint256 absB = B < 0 ? uint256 (- B) : uint256 (B);
226
+ uint256 squaredB = FullMath.mulDiv (absB, absB, 1e18 ) + (absB * absB % 1e18 == 0 ? 0 : 1 );
227
+
228
+ // 4 * A * C component of the quadratic formula
229
+ uint256 AC4 = Math.mulDiv (
230
+ Math.mulDiv (4 * c, (1e18 - c), 1e18 , Math.Rounding.Ceil),
231
+ Math.mulDiv (x0, x0, 1e18 , Math.Rounding.Ceil),
232
+ 1e18 ,
233
+ Math.Rounding.Ceil
234
+ );
235
+
236
+ // Discriminant: b^2 + 4ac, scaled up to maintain precision
237
+ uint256 discriminant = (squaredB + AC4) * 1e18 ;
238
+
239
+ // Square root of the discriminant (rounded up)
240
+ uint256 sqrt = Math.sqrt (discriminant);
241
+ sqrt = (sqrt * sqrt < discriminant) ? sqrt + 1 : sqrt;
242
+
243
+ // Compute and return x = fInverse(y) using the quadratic formula
244
+ return Math.mulDiv (uint256 (int256 (sqrt) - B), 1e18 , A, Math.Rounding.Ceil);
245
+ }
191
246
}
0 commit comments