Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize liquidity flipping calculations in Pool #602

Closed
wants to merge 9 commits into from

Conversation

shuhuiluo
Copy link
Contributor

Related Issue

Which issue does this pull request resolve?

Description of changes

A new function LiquidityMath.flipLiquidityDelta is added to optimize the process of flipping the sign of a liquidity delta if certain conditions are met. Code complexity has been reduced by avoiding the need to use unchecked blocks and applied assembly for efficiency. The refactoring also resulted in changes in the snapshot files.

@hensha256
Copy link
Contributor

Replaces #569

Updated the way liquidity flipping is calculated in 'Pool.sol' to use bitwise XOR operations for efficiency. This modification improved overall bytecode size in multiple snapshots which demonstrates an optimization of gas usage in our smart contracts.
int128 liquidityNet = upper ? liquidityNetBefore - liquidityDelta : liquidityNetBefore + liquidityDelta;
// Equivalent to `liquidityNet = upper ? liquidityNetBefore - liquidityDelta : liquidityNetBefore + liquidityDelta;`
// `int128 liquidityDelta` is passed from `modifyLiquidity` and should be sanitized in `PoolManager`
liquidityDelta = LiquidityMath.flipLiquidityDelta(liquidityDelta, upper);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would love a comment here about why liquidityDelta cannot be min int128 to show the use of the new function is safe - thats already commented on the other use

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh ignore me thats what youre saying about the sanitization in PoolManager haha

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little different. So liquidityDelta in Pool.updateTick is passed from Pool.modifyLiquidity and PoolManager.modifyLiquidity. And PoolManager.modifyLiquidity calls toInt128() on params.liquidityDelta. But after toInt128() a int128 can still be type(int128).min.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, the original ternary expressions revert on the negation of type(int128).min.

I am not sure where the comment "safe because liquidityNet cannot be type(int128).min" came from inside Pool.swap. I guess the max liquidityNet is limited by tickSpacingToMaxLiquidityPerTick.

If a type(int128).min is flipped in flipLiquidityDelta, instead of reverting, 1 << 127 will be returned which is a valid int256 but not a valid int128.

There are two usages of flipLiquidityDelta.

  • When flipLiquidityDelta is used on liquidityNet in Pool.swap, liquidityNet is immediately consumed by addDelta which treats it as an int256 and only reverts if the resulting liquidity overflows uint128.
  • When flipLiquidityDelta is used on liquidityDelta in Pool.updateTick, it is then used by liquidityNet := add(liquidityNetBefore, liquidityDelta) in the assembly block which also treats it as an int256. The validity of the sum is checked by toInt128().

So even though the natspec of flipLiquidityDelta says "liquidityDelta should never be type(int128).min", its current usage is able to handle type(int128).min.

shuhuiluo added 3 commits May 18, 2024 18:21
…eration

A new function `flipLiquidityDelta` is added to optimize the process of flipping the sign of a liquidity delta if certain conditions are met. Code complexity has been reduced by avoiding the need to use unchecked blocks and applied assembly for efficiency. The refactoring also resulted in changes in the snapshot files.
shuhuiluo added 3 commits May 18, 2024 21:26
…(int128).min`

This commit refactors the `flipLiquidityDelta` function in `LiquidityMath` library that can now handle `type(int128).min` and returns a valid `int256`. It also modifies the use of `flipLiquidityDelta` in `Pool` library along with improved explanations with inline comments. Furthermore, it updates the tests in `LiquidityMath.t.sol` by refining the fuzzing, modifying import statements and introducing a new test case for `flipLiquidityDelta` handling `type(int128).min`.
gretzke
gretzke previously approved these changes May 25, 2024
@hensha256 hensha256 closed this Aug 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants