v4-core
v4-core copied to clipboard
Refactor and optimize `SwapMath`
Related Issue
Which issue does this pull request resolve?
Obscure control flow related to SwapMath.
Description of changes
Improvements to the SwapMath library have been implemented. A new function, getSqrtRatioTarget, written in Yul using bitwise operations, has been introduced to replace a nested ternary operation within Pool.swap:
(
params.zeroForOne
? step.sqrtPriceNextX96 < params.sqrtPriceLimitX96
: step.sqrtPriceNextX96 > params.sqrtPriceLimitX96
) ? params.sqrtPriceLimitX96 : step.sqrtPriceNextX96
which basically was doing
zeroForOne ? max(sqrtPriceNextX96, sqrtPriceLimitX96) : min(sqrtPriceNextX96, sqrtPriceLimitX96)
Furthermore, the computeSwapStep function has been refactored, resulting in a cleaner control flow and significant gas savings. The gas savings achieved range from 10% to 28%, as can be seen in SwapMath.spec.ts.snap. In conjunction with the changes introduced in pull request #258, the maximum savings on computeSwapStep can reach up to 40%.
All tests pass except for SwapMath::#computeSwapStep::entire input amount taken as fee, where amountIn changes from 0 to 9, and feeAmount changes from 10 to 1.
I wonder if "entire input amount taken as fee when output is zero" is an intended feature and the invariant amountIn == 0 && feeAmount == 10 should be kept. Adjusting the invariant to amountIn + feeAmount == 10 appears to be acceptable and reasonable.
Please can you merge main so we can re-review the gas improvements 🙏
Please can you merge main so we can re-review the gas improvements 🙏
@hensha256 Done. As stated before, I had to modify test_entireInputAmountTakenAsFee, which I believe to be an artifact of the previous control flow instead of an intended feature.