Skip to content

Commit

Permalink
Use packed stack-based version of Slot0 structure (#613)
Browse files Browse the repository at this point in the history
* Add stack-based Slot0 structure version

* Optimize initialization

* Update snapshots

* Remove memory-based structure

* Simplify initialization

* Change types for offsets

Co-authored-by: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com>

* Change types for masks

Co-authored-by: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com>

* Use signextend instead of INT24_MASK

Co-authored-by: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com>

* Update snapshots

* Update Slot0 type spec

* Enhance comments for Slot0

* Add line with layout to Slot0 comments

* Add tests for Slot0

* Add tests

* Remove INT24_MASK

* Update snapshots

* Run fmt

* Rename test

* Rename masks

* Remove Slot0 import in PoolManager

---------

Co-authored-by: Shuhui Luo <107524008+shuhuiluo@users.noreply.github.com>
  • Loading branch information
0xVolosnikov and shuhuiluo committed May 17, 2024
1 parent 2e30d65 commit 285b53e
Show file tree
Hide file tree
Showing 35 changed files with 210 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
153625
153643
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
331641
331635
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity with empty hook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
286634
286628
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity with native token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
143835
143853
Original file line number Diff line number Diff line change
@@ -1 +1 @@
302153
302147
2 changes: 1 addition & 1 deletion .forge-snapshots/initialize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
62194
61902
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22083
21934
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
187083
187101
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity with empty hook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
123451
123469
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity with native token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
120238
120256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
104914
104932
2 changes: 1 addition & 1 deletion .forge-snapshots/simple addLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
167756
167750
Original file line number Diff line number Diff line change
@@ -1 +1 @@
98511
98529
2 changes: 1 addition & 1 deletion .forge-snapshots/simple removeLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
90877
90895
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap with native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
117344
117057
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132505
132218
2 changes: 1 addition & 1 deletion .forge-snapshots/swap CA custom curve + swap noop.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
134660
134432
2 changes: 1 addition & 1 deletion .forge-snapshots/swap CA fee on unspecified.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
183643
183356
Original file line number Diff line number Diff line change
@@ -1 +1 @@
112984
112697
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
124327
124040
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
136380
136081
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn native 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125508
125221
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint native output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
147569
147270
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
164359
164072
Original file line number Diff line number Diff line change
@@ -1 +1 @@
223152
222578
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
148560
148273
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
124339
124052
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with lp fee and protocol fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
180754
180456
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with return dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
156425
156132
2 changes: 1 addition & 1 deletion .forge-snapshots/update dynamic fee in before swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
159033
158735
60 changes: 26 additions & 34 deletions src/libraries/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {TickMath} from "./TickMath.sol";
import {SqrtPriceMath} from "./SqrtPriceMath.sol";
import {SwapMath} from "./SwapMath.sol";
import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
import {Slot0} from "../types/Slot0.sol";
import {ProtocolFeeLibrary} from "./ProtocolFeeLibrary.sol";
import {LiquidityMath} from "./LiquidityMath.sol";
import {LPFeeLibrary} from "./LPFeeLibrary.sol";
Expand Down Expand Up @@ -64,20 +65,6 @@ library Pool {
/// @notice Thrown when trying to swap with max lp fee and specifying an output amount
error InvalidFeeForExactOut();

struct Slot0 {
// the current price
uint160 sqrtPriceX96;
// the current tick
int24 tick;
// protocol fee, expressed in hundredths of a bip
// upper 12 bits are for 1->0, and the lower 12 are for 0->1
// the maximum is 1000 - meaning the maximum protocol fee is 0.1%
// the protocolFee is taken from the input first, then the lpFee is taken from the remaining input
uint24 protocolFee;
// used for the lp fee, either static at initialize or dynamic via hook
uint24 lpFee;
}

// info stored for each initialized individual tick
struct TickInfo {
// the total position liquidity that references this tick
Expand Down Expand Up @@ -112,23 +99,24 @@ library Pool {
internal
returns (int24 tick)
{
if (self.slot0.sqrtPriceX96 != 0) revert PoolAlreadyInitialized();
if (self.slot0.sqrtPriceX96() != 0) revert PoolAlreadyInitialized();

tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96);

self.slot0 = Slot0({sqrtPriceX96: sqrtPriceX96, tick: tick, protocolFee: protocolFee, lpFee: lpFee});
self.slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setProtocolFee(protocolFee)
.setLpFee(lpFee);
}

function setProtocolFee(State storage self, uint24 protocolFee) internal {
if (self.isNotInitialized()) revert PoolNotInitialized();

self.slot0.protocolFee = protocolFee;
self.slot0 = self.slot0.setProtocolFee(protocolFee);
}

/// @notice Only dynamic fee pools may update the lp fee.
function setLPFee(State storage self, uint24 lpFee) internal {
if (self.isNotInitialized()) revert PoolNotInitialized();
self.slot0.lpFee = lpFee;
self.slot0 = self.slot0.setLpFee(lpFee);
}

struct ModifyLiquidityParams {
Expand Down Expand Up @@ -218,7 +206,8 @@ library Pool {
}

if (liquidityDelta != 0) {
(int24 tick, uint160 sqrtPriceX96) = (self.slot0.tick, self.slot0.sqrtPriceX96);
Slot0 _slot0 = self.slot0;
(int24 tick, uint160 sqrtPriceX96) = (_slot0.tick(), _slot0.sqrtPriceX96());
if (tick < tickLower) {
// current tick is below the passed range; liquidity can only become in range by crossing from left to
// right, when we'll need _more_ currency0 (it's becoming more valuable) so user must provide it
Expand Down Expand Up @@ -297,25 +286,28 @@ library Pool {
internal
returns (BalanceDelta result, uint256 feeForProtocol, uint24 swapFee, SwapState memory state)
{
Slot0 memory slot0Start = self.slot0;
Slot0 slot0Start = self.slot0;
bool zeroForOne = params.zeroForOne;

uint128 liquidityStart = self.liquidity;
uint256 protocolFee =
zeroForOne ? slot0Start.protocolFee.getZeroForOneFee() : slot0Start.protocolFee.getOneForZeroFee();
zeroForOne ? slot0Start.protocolFee().getZeroForOneFee() : slot0Start.protocolFee().getOneForZeroFee();

state.amountSpecifiedRemaining = params.amountSpecified;
state.amountCalculated = 0;
state.sqrtPriceX96 = slot0Start.sqrtPriceX96;
state.tick = slot0Start.tick;
state.sqrtPriceX96 = slot0Start.sqrtPriceX96();
state.tick = slot0Start.tick();
state.feeGrowthGlobalX128 = zeroForOne ? self.feeGrowthGlobal0X128 : self.feeGrowthGlobal1X128;
state.liquidity = liquidityStart;

// if the beforeSwap hook returned a valid fee override, use that as the LP fee, otherwise load from storage
slot0Start.lpFee =
params.lpFeeOverride.isOverride() ? params.lpFeeOverride.removeOverrideAndValidate() : slot0Start.lpFee;
{
uint24 lpFee = params.lpFeeOverride.isOverride()
? params.lpFeeOverride.removeOverrideAndValidate()
: slot0Start.lpFee();

swapFee = protocolFee == 0 ? slot0Start.lpFee : uint24(protocolFee).calculateSwapFee(slot0Start.lpFee);
swapFee = protocolFee == 0 ? lpFee : uint24(protocolFee).calculateSwapFee(lpFee);
}

bool exactInput = params.amountSpecified < 0;

Expand All @@ -326,15 +318,15 @@ library Pool {
if (params.amountSpecified == 0) return (BalanceDeltaLibrary.ZERO_DELTA, 0, swapFee, state);

if (zeroForOne) {
if (params.sqrtPriceLimitX96 >= slot0Start.sqrtPriceX96) {
revert PriceLimitAlreadyExceeded(slot0Start.sqrtPriceX96, params.sqrtPriceLimitX96);
if (params.sqrtPriceLimitX96 >= slot0Start.sqrtPriceX96()) {
revert PriceLimitAlreadyExceeded(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96);
}
if (params.sqrtPriceLimitX96 <= TickMath.MIN_SQRT_PRICE) {
revert PriceLimitOutOfBounds(params.sqrtPriceLimitX96);
}
} else {
if (params.sqrtPriceLimitX96 <= slot0Start.sqrtPriceX96) {
revert PriceLimitAlreadyExceeded(slot0Start.sqrtPriceX96, params.sqrtPriceLimitX96);
if (params.sqrtPriceLimitX96 <= slot0Start.sqrtPriceX96()) {
revert PriceLimitAlreadyExceeded(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96);
}
if (params.sqrtPriceLimitX96 >= TickMath.MAX_SQRT_PRICE) {
revert PriceLimitOutOfBounds(params.sqrtPriceLimitX96);
Expand Down Expand Up @@ -439,7 +431,7 @@ library Pool {
}
}

(self.slot0.tick, self.slot0.sqrtPriceX96) = (state.tick, state.sqrtPriceX96);
self.slot0 = slot0Start.setTick(state.tick).setSqrtPriceX96(state.sqrtPriceX96);

// update liquidity if it changed
if (liquidityStart != state.liquidity) self.liquidity = state.liquidity;
Expand Down Expand Up @@ -495,7 +487,7 @@ library Pool {
{
TickInfo storage lower = self.ticks[tickLower];
TickInfo storage upper = self.ticks[tickUpper];
int24 tickCurrent = self.slot0.tick;
int24 tickCurrent = self.slot0.tick();

unchecked {
if (tickCurrent < tickLower) {
Expand Down Expand Up @@ -544,7 +536,7 @@ library Pool {

if (liquidityGrossBefore == 0) {
// by convention, we assume that all growth before a tick was initialized happened _below_ the tick
if (tick <= self.slot0.tick) {
if (tick <= self.slot0.tick()) {
info.feeGrowthOutside0X128 = self.feeGrowthGlobal0X128;
info.feeGrowthOutside1X128 = self.feeGrowthGlobal1X128;
}
Expand Down Expand Up @@ -583,7 +575,7 @@ library Pool {
}

function isNotInitialized(State storage self) internal view returns (bool) {
return self.slot0.sqrtPriceX96 == 0;
return self.slot0.sqrtPriceX96() == 0;
}

/// @notice Clears tick data
Expand Down
Loading

0 comments on commit 285b53e

Please sign in to comment.