Skip to content

Commit

Permalink
Merge and update snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
shuhuiluo committed Apr 11, 2024
2 parents 48d7a25 + 6b69637 commit e483fb1
Show file tree
Hide file tree
Showing 33 changed files with 220 additions and 77 deletions.
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 @@
264533
264375
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 @@
139393
139216
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
144710
144552
2 changes: 1 addition & 1 deletion .forge-snapshots/donate gas with 1 token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
101128
101147
2 changes: 1 addition & 1 deletion .forge-snapshots/donate gas with 2 tokens.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132115
132153
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22511
22366
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 @@
55193
54720
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 @@
147379
146903
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
148843
148370
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146456
146475
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
60115
60134
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 @@
80276
80275
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 @@
138624
138642
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 @@
155271
155290
Original file line number Diff line number Diff line change
@@ -1 +1 @@
155683
155727
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 @@
89346
89365
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
60093
60112
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 @@
139972
139991
28 changes: 28 additions & 0 deletions src/Extsload.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;

import {IExtsload} from "./interfaces/IExtsload.sol";

/// @notice Enables public storage access for efficient state retrieval by external contracts.
/// https://eips.ethereum.org/EIPS/eip-2330#rationale
abstract contract Extsload is IExtsload {
function extsload(bytes32 slot) external view returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
value := sload(slot)
}
}

function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes memory) {
bytes memory value = new bytes(32 * nSlots);

/// @solidity memory-safe-assembly
assembly {
for { let i := 0 } lt(i, nSlots) { i := add(i, 1) } {
mstore(add(value, mul(add(i, 1), 32)), sload(add(startSlot, i)))
}
}

return value;
}
}
31 changes: 7 additions & 24 deletions src/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import {Lock} from "./libraries/Lock.sol";
import {CurrencyDelta} from "./libraries/CurrencyDelta.sol";
import {NonZeroDeltaCount} from "./libraries/NonZeroDeltaCount.sol";
import {PoolGetters} from "./libraries/PoolGetters.sol";
import {Extsload} from "./Extsload.sol";

/// @notice Holds the state for all pools
contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims {

contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload {
using PoolIdLibrary for PoolKey;
using SafeCast for *;
using Pool for *;
Expand Down Expand Up @@ -176,13 +178,13 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
PoolKey memory key,
IPoolManager.ModifyLiquidityParams memory params,
bytes calldata hookData
) external override onlyWhenUnlocked returns (BalanceDelta delta) {
) external override onlyWhenUnlocked returns (BalanceDelta delta, BalanceDelta feeDelta) {
PoolId id = key.toId();
_checkPoolInitialized(id);

key.hooks.beforeModifyLiquidity(key, params, hookData);

delta = pools[id].modifyLiquidity(
(delta, feeDelta) = pools[id].modifyLiquidity(
Pool.ModifyLiquidityParams({
owner: msg.sender,
tickLower: params.tickLower,
Expand All @@ -192,7 +194,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
})
);

_accountPoolBalanceDelta(key, delta);
_accountPoolBalanceDelta(key, delta + feeDelta);

emit ModifyLiquidity(id, msg.sender, params.tickLower, params.tickUpper, params.liquidityDelta);

Expand Down Expand Up @@ -269,6 +271,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
if (currency.isNative()) {
paid = msg.value;
} else {
if (msg.value > 0) revert NonZeroNativeValue();
uint256 reservesBefore = reservesOf[currency];
reservesOf[currency] = currency.balanceOfSelf();
paid = reservesOf[currency] - reservesBefore;
Expand Down Expand Up @@ -297,26 +300,6 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
pools[id].setSwapFee(newDynamicSwapFee);
}

function extsload(bytes32 slot) external view returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
value := sload(slot)
}
}

function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes memory) {
bytes memory value = new bytes(32 * nSlots);

/// @solidity memory-safe-assembly
assembly {
for { let i := 0 } lt(i, nSlots) { i := add(i, 1) } {
mstore(add(value, mul(add(i, 1), 32)), sload(add(startSlot, i)))
}
}

return value;
}

function getNonzeroDeltaCount() external view returns (uint256 _nonzeroDeltaCount) {
return NonZeroDeltaCount.read();
}
Expand Down
15 changes: 15 additions & 0 deletions src/interfaces/IExtsload.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;

interface IExtsload {
/// @notice Called by external contracts to access granular pool state
/// @param slot Key of slot to sload
/// @return value The value of the slot as bytes32
function extsload(bytes32 slot) external view returns (bytes32 value);

/// @notice Called by external contracts to access granular pool state
/// @param slot Key of slot to start sloading from
/// @param nSlots Number of slots to load into return value
/// @return value The value of the sload-ed slots concatenated as dynamic bytes
function extsload(bytes32 slot, uint256 nSlots) external view returns (bytes memory value);
}
22 changes: 8 additions & 14 deletions src/interfaces/IPoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import {IProtocolFees} from "./IProtocolFees.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {PoolId} from "../types/PoolId.sol";
import {Position} from "../libraries/Position.sol";
import {IExtsload} from "./IExtsload.sol";

interface IPoolManager is IProtocolFees, IERC6909Claims {
interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload {
/// @notice Thrown when a currency is not netted out after the contract is unlocked
error CurrencyNotSettled();

Expand All @@ -36,6 +37,9 @@ interface IPoolManager is IProtocolFees, IERC6909Claims {
/// or on a pool that does not have a dynamic swap fee.
error UnauthorizedDynamicSwapFeeUpdate();

///@notice Thrown when native currency is passed to a non native settlement
error NonZeroNativeValue();

/// @notice Emitted when a new pool is initialized
/// @param id The abi encoded hash of the pool key struct for the new pool
/// @param currency0 The first currency of the pool by address sort order
Expand Down Expand Up @@ -157,10 +161,11 @@ interface IPoolManager is IProtocolFees, IERC6909Claims {
/// @param key The pool to modify liquidity in
/// @param params The parameters for modifying the liquidity
/// @param hookData Any data to pass to the callback, via `IUnlockCallback(msg.sender).unlockCallback(data)`
/// @return delta The balance delta of the liquidity
/// @return delta The balance delta of the liquidity change
/// @return feeDelta The balance delta of the fees generated in the liquidity range
function modifyLiquidity(PoolKey memory key, ModifyLiquidityParams memory params, bytes calldata hookData)
external
returns (BalanceDelta);
returns (BalanceDelta, BalanceDelta);

struct SwapParams {
bool zeroForOne;
Expand Down Expand Up @@ -193,15 +198,4 @@ interface IPoolManager is IProtocolFees, IERC6909Claims {

/// @notice Updates the pools swap fees for the a pool that has enabled dynamic swap fees.
function updateDynamicSwapFee(PoolKey memory key, uint24 newDynamicSwapFee) external;

/// @notice Called by external contracts to access granular pool state
/// @param slot Key of slot to sload
/// @return value The value of the slot as bytes32
function extsload(bytes32 slot) external view returns (bytes32 value);

/// @notice Called by external contracts to access granular pool state
/// @param slot Key of slot to start sloading from
/// @param nSlots Number of slots to load into return value
/// @return value The value of the sload-ed slots concatenated as dynamic bytes
function extsload(bytes32 slot, uint256 nSlots) external view returns (bytes memory value);
}
20 changes: 20 additions & 0 deletions src/libraries/LiquidityMath.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.20;

/// @title Math library for liquidity
library LiquidityMath {
/// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows
/// @param x The liquidity before change
/// @param y The delta by which liquidity should be changed
/// @return z The liquidity delta
function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) {
assembly {
z := add(x, y)
if shr(128, z) {
// revert SafeCastOverflow()
mstore(0, 0x93dafdf1)
revert(0x1c, 0x04)
}
}
}
}
26 changes: 11 additions & 15 deletions src/libraries/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {SqrtPriceMath} from "./SqrtPriceMath.sol";
import {SwapMath} from "./SwapMath.sol";
import {BalanceDelta, toBalanceDelta} from "../types/BalanceDelta.sol";
import {ProtocolFeeLibrary} from "./ProtocolFeeLibrary.sol";
import {LiquidityMath} from "./LiquidityMath.sol";

library Pool {
using SafeCast for *;
Expand Down Expand Up @@ -151,10 +152,11 @@ library Pool {
/// @notice Effect changes to a position in a pool
/// @dev PoolManager checks that the pool is initialized before calling
/// @param params the position details and the change to the position's liquidity to effect
/// @return result the deltas of the token balances of the pool
/// @return delta the deltas of the token balances of the pool, from the liquidity change
/// @return feeDelta the fees generated by the liquidity range
function modifyLiquidity(State storage self, ModifyLiquidityParams memory params)
internal
returns (BalanceDelta result)
returns (BalanceDelta delta, BalanceDelta feeDelta)
{
int128 liquidityDelta = params.liquidityDelta;
int24 tickLower = params.tickLower;
Expand Down Expand Up @@ -214,27 +216,25 @@ library Pool {
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
result = toBalanceDelta(
delta = toBalanceDelta(
SqrtPriceMath.getAmount0Delta(
TickMath.getSqrtRatioAtTick(tickLower), TickMath.getSqrtRatioAtTick(tickUpper), liquidityDelta
).toInt128(),
0
);
} else if (tick < tickUpper) {
result = toBalanceDelta(
delta = toBalanceDelta(
SqrtPriceMath.getAmount0Delta(sqrtPriceX96, TickMath.getSqrtRatioAtTick(tickUpper), liquidityDelta)
.toInt128(),
SqrtPriceMath.getAmount1Delta(TickMath.getSqrtRatioAtTick(tickLower), sqrtPriceX96, liquidityDelta)
.toInt128()
);

self.liquidity = liquidityDelta < 0
? self.liquidity - uint128(-liquidityDelta)
: self.liquidity + uint128(liquidityDelta);
self.liquidity = LiquidityMath.addDelta(self.liquidity, liquidityDelta);
} else {
// current tick is above the passed range; liquidity can only become in range by crossing from right to
// left, when we'll need _more_ currency1 (it's becoming more valuable) so user must provide it
result = toBalanceDelta(
delta = toBalanceDelta(
0,
SqrtPriceMath.getAmount1Delta(
TickMath.getSqrtRatioAtTick(tickLower), TickMath.getSqrtRatioAtTick(tickUpper), liquidityDelta
Expand All @@ -244,7 +244,7 @@ library Pool {
}

// Fees earned from LPing are added to the user's currency delta.
result = result + toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128());
feeDelta = toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128());
}

struct SwapCache {
Expand Down Expand Up @@ -415,9 +415,7 @@ library Pool {
if (zeroForOne) liquidityNet = -liquidityNet;
}

state.liquidity = liquidityNet < 0
? state.liquidity - uint128(-liquidityNet)
: state.liquidity + uint128(liquidityNet);
state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
}

unchecked {
Expand Down Expand Up @@ -526,9 +524,7 @@ library Pool {
liquidityNetBefore := shr(128, liquidity)
}

liquidityGrossAfter = liquidityDelta < 0
? liquidityGrossBefore - uint128(-liquidityDelta)
: liquidityGrossBefore + uint128(liquidityDelta);
liquidityGrossAfter = LiquidityMath.addDelta(liquidityGrossBefore, liquidityDelta);

flipped = (liquidityGrossAfter == 0) != (liquidityGrossBefore == 0);

Expand Down
4 changes: 2 additions & 2 deletions src/libraries/Position.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.20;

import {FullMath} from "./FullMath.sol";
import {FixedPoint128} from "./FixedPoint128.sol";
import {LiquidityMath} from "./LiquidityMath.sol";

/// @title Position
/// @notice Positions represent an owner address' liquidity between a lower and upper tick boundary
Expand Down Expand Up @@ -63,8 +64,7 @@ library Position {
if (liquidity == 0) revert CannotUpdateEmptyPosition(); // disallow pokes for 0 liquidity positions
liquidityNext = liquidity;
} else {
liquidityNext =
liquidityDelta < 0 ? liquidity - uint128(-liquidityDelta) : liquidity + uint128(liquidityDelta);
liquidityNext = LiquidityMath.addDelta(liquidity, liquidityDelta);
}

// calculate accumulated fees. overflow in the subtraction of fee growth is expected
Expand Down
10 changes: 10 additions & 0 deletions src/test/LiquidityMathTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {LiquidityMath} from "../libraries/LiquidityMath.sol";

contract LiquidityMathTest {
function addDelta(uint128 x, int128 y) external pure returns (uint128 z) {
return LiquidityMath.addDelta(x, y);
}
}
Loading

0 comments on commit e483fb1

Please sign in to comment.