Skip to content

Commit

Permalink
Pool.State Library (extsload) (#579)
Browse files Browse the repository at this point in the history
* initial extsload library for Pool.State

* example use of PoolStateLibrary in test

* formatting

* cleanup

* wip liquidity fuzzers

* more testing

* round out fuzz testing

* remove native getters from PoolManager; update tests to use lib

* resync deps; regenerate snapshots

* use syntatic sugar

* gas benchmarks

* regenerate gas snapshots

* add a gas snapshot for getting reserves

* cleanup

* remove legacy getters

* regenerate gas snapshots

* move repeated code into helper functions

* make pools internal

* fix fuzz rejections

* Add exttload to read transient storage from outside the contract (#635)

* Add exttload to read transient storage from outside the contract

* regenerate snapshots

* Separate Extsload and Exttload

* reduce amount of cases where vm.assume is used to reduce rejected inputs in high intensity fuzzing

* make variable public

* adjust natspec for exttload

* Move isUnlocked, getNonzeroDeltaCount and currencyDelta view functions to pool state library

* Don't bound swap amount to liquidity

* Don't revert within the view function

* regenerate gas snapshots

* regenerate gas snapshots

* regenerate gas snapshot for getting reserves

* adjust comment to reflect new behaviour

* include library code in gas snapshot

* make slots bytes32

* rename PoolStateLibrary to StateLibrary

* Separate transient and storage state libraries

* adjust naming of test file

* adjust comments to reflect new behaviour

* Add sparse exttload

* regenerate gas snapshots

* code comments

* move natspec comment to inline

* review comments; fix getTickInfo out-of-order return; add test for getTickInfo == getTickLiquidity

* renaming

* move code comment to function

* regenerate gas snapshots

---------

Signed-off-by: saucepoint <[email protected]>
Co-authored-by: gretzke <[email protected]>
  • Loading branch information
saucepoint and gretzke authored May 15, 2024
1 parent 81a69c6 commit 7d97026
Show file tree
Hide file tree
Showing 65 changed files with 1,165 additions and 173 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
151104
153625
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
329444
331831
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 @@
284085
286606
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 @@
141249
143835
Original file line number Diff line number Diff line change
@@ -1 +1 @@
299632
302153
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 @@
108687
107894
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 @@
149222
148384
2 changes: 1 addition & 1 deletion .forge-snapshots/erc20 collect protocol fees.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
57342
57275
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getFeeGrowthGlobals.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1344
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getFeeGrowthInside.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
446
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getLiquidity.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
446
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getPositionInfo.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1606
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getPositionLiquidity.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
446
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getSlot0.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
446
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getTickBitmap.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
446
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getTickFeeGrowthOutside.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1344
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getTickInfo.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1606
1 change: 1 addition & 0 deletions .forge-snapshots/extsload getTickLiquidity.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
446
1 change: 1 addition & 0 deletions .forge-snapshots/getReserves.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1198
2 changes: 1 addition & 1 deletion .forge-snapshots/initialize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
62245
62202
2 changes: 1 addition & 1 deletion .forge-snapshots/native collect protocol fees.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
59587
59520
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23738
22099
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
184931
187273
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 @@
120975
123451
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 @@
117762
120238
Original file line number Diff line number Diff line change
@@ -1 +1 @@
104916
104914
2 changes: 1 addition & 1 deletion .forge-snapshots/simple addLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
167758
167756
Original file line number Diff line number Diff line change
@@ -1 +1 @@
98535
98511
2 changes: 1 addition & 1 deletion .forge-snapshots/simple removeLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
90901
90877
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 @@
117351
117304
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132578
132465
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 @@
135860
134799
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 @@
184809
183793
Original file line number Diff line number Diff line change
@@ -1 +1 @@
113812
112929
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125221
124272
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 @@
137207
136325
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 @@
126335
125453
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 @@
148397
147514
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 @@
165202
164319
Original file line number Diff line number Diff line change
@@ -1 +1 @@
224701
223093
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 @@
149469
148520
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125233
124284
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 @@
181791
180775
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 @@
160022
159006
7 changes: 6 additions & 1 deletion src/Extsload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ 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 {
/// @inheritdoc IExtsload
function extsload(bytes32 slot) external view returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
value := sload(slot)
}
}

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

Expand All @@ -26,8 +28,11 @@ abstract contract Extsload is IExtsload {
return value;
}

/// @dev since the function is external and enters a new call context and exits right after execution, Solidity's memory management convention can be disregarded and a direct slice of memory can be returned
/// @inheritdoc IExtsload
function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
// since the function is external and enters a new call context and exits right
// after execution, Solidity's memory management convention can be disregarded
// and a direct slice of memory can be returned
assembly ("memory-safe") {
// abi offset for dynamic array
mstore(0, 0x20)
Expand Down
38 changes: 38 additions & 0 deletions src/Exttload.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;

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

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

/// @inheritdoc IExttload
function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
// since the function is external and enters a new call context and exits right
// after execution, Solidity's memory management convention can be disregarded
// and a direct slice of memory can be returned
assembly ("memory-safe") {
// abi offset for dynamic array
mstore(0, 0x20)
mstore(0x20, slots.length)
let end := add(0x40, shl(5, slots.length))
let memptr := 0x40
let calldataptr := slots.offset
for {} 1 {} {
mstore(memptr, tload(calldataload(calldataptr)))
memptr := add(memptr, 0x20)
calldataptr := add(calldataptr, 0x20)
if iszero(lt(memptr, end)) { break }
}
return(0, end)
}
}
}
77 changes: 4 additions & 73 deletions src/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {NonZeroDeltaCount} from "./libraries/NonZeroDeltaCount.sol";
import {PoolGetters} from "./libraries/PoolGetters.sol";
import {Reserves} from "./libraries/Reserves.sol";
import {Extsload} from "./Extsload.sol";
import {Exttload} from "./Exttload.sol";

// 4
// 44
Expand Down Expand Up @@ -73,7 +74,8 @@ import {Extsload} from "./Extsload.sol";
// 44444 444
// 444
/// @notice Holds the state for all pools
contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload {

contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload, Exttload {
using PoolIdLibrary for PoolKey;
using SafeCast for *;
using Pool for *;
Expand All @@ -91,60 +93,14 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
/// @inheritdoc IPoolManager
int24 public constant MIN_TICK_SPACING = TickMath.MIN_TICK_SPACING;

mapping(PoolId id => Pool.State) public pools;
mapping(PoolId id => Pool.State) internal pools;

constructor(uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {}

function _getPool(PoolId id) internal view override returns (Pool.State storage) {
return pools[id];
}

/// @inheritdoc IPoolManager
function getSlot0(PoolId id)
external
view
override
returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)
{
Pool.Slot0 memory slot0 = pools[id].slot0;

return (slot0.sqrtPriceX96, slot0.tick, slot0.protocolFee, slot0.lpFee);
}

/// @inheritdoc IPoolManager
function getLiquidity(PoolId id) external view override returns (uint128 liquidity) {
return pools[id].liquidity;
}

/// @inheritdoc IPoolManager
function getLiquidity(PoolId id, address _owner, int24 tickLower, int24 tickUpper, bytes32 salt)
external
view
override
returns (uint128 liquidity)
{
return pools[id].positions.get(_owner, tickLower, tickUpper, salt).liquidity;
}

function getPosition(PoolId id, address _owner, int24 tickLower, int24 tickUpper, bytes32 salt)
external
view
override
returns (Position.Info memory position)
{
return pools[id].positions.get(_owner, tickLower, tickUpper, salt);
}

/// @inheritdoc IPoolManager
function currencyDelta(address caller, Currency currency) external view returns (int256) {
return currency.getDelta(caller);
}

/// @inheritdoc IPoolManager
function isUnlocked() external view override returns (bool) {
return Lock.isUnlocked();
}

/// @notice This will revert if the contract is locked
modifier onlyWhenUnlocked() {
if (!Lock.isUnlocked()) revert ManagerLocked();
Expand Down Expand Up @@ -372,29 +328,4 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
PoolId id = key.toId();
pools[id].setLPFee(newDynamicLPFee);
}

function getNonzeroDeltaCount() external view returns (uint256 _nonzeroDeltaCount) {
return NonZeroDeltaCount.read();
}

function getPoolTickInfo(PoolId id, int24 tick) external view returns (Pool.TickInfo memory) {
return pools[id].getPoolTickInfo(tick);
}

function getPoolBitmapInfo(PoolId id, int16 word) external view returns (uint256 tickBitmap) {
return pools[id].getPoolBitmapInfo(word);
}

/// @notice Temporary view function. Replaceable by transient EXTSLOAD.
function getReserves(Currency currency) external view returns (uint256 balance) {
return currency.getReserves();
}

function getFeeGrowthGlobals(PoolId id)
external
view
returns (uint256 feeGrowthGlobal0x128, uint256 feeGrowthGlobal1x128)
{
return pools[id].getFeeGrowthGlobals();
}
}
14 changes: 14 additions & 0 deletions src/interfaces/IExttload.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;

interface IExttload {
/// @notice Called by external contracts to access transient storage of the contract
/// @param slot Key of slot to tload
/// @return value The value of the slot as bytes32
function exttload(bytes32 slot) external view returns (bytes32 value);

/// @notice Called by external contracts to access sparse transient pool state
/// @param slots List of slots to tload
/// @return values List of loaded values
function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values);
}
Loading

0 comments on commit 7d97026

Please sign in to comment.