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 May 15, 2024
2 parents a2e59b5 + e427108 commit 8e77696
Show file tree
Hide file tree
Showing 57 changed files with 379 additions and 167 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactInPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3038
3016
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactOutPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3278
3256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
151023
150975
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
329389
329315
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 @@
284024
283956
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 @@
141199
141108
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
150999
150951
Original file line number Diff line number Diff line change
@@ -1 +1 @@
299551
299503
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 @@
108887
108687
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 @@
149382
149222
Original file line number Diff line number Diff line change
@@ -1 +1 @@
594
572
Original file line number Diff line number Diff line change
@@ -1 +1 @@
878
856
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23386
23658
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
184962
184802
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 @@
120980
120846
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 @@
117755
117621
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
120968
120834
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 @@
131040
117339
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
149399
132578
1 change: 1 addition & 0 deletions .forge-snapshots/sparse external sload.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2023
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 @@
139399
135860
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 @@
184879
184809
Original file line number Diff line number Diff line change
@@ -1 +1 @@
113935
113800
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125313
125221
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 @@
137318
137207
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 @@
126418
126323
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 @@
148453
148385
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 @@
165348
165202
Original file line number Diff line number Diff line change
@@ -1 +1 @@
225042
224701
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 @@
149615
149469
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125325
125233
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 @@
181967
181791
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 @@
160258
160022
3 changes: 3 additions & 0 deletions .github/workflows/tests-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: Tests

on:
pull_request:
branches:
- main
- dev

jobs:
forge-tests:
Expand Down
19 changes: 19 additions & 0 deletions src/Extsload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,23 @@ 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
function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
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, sload(calldataload(calldataptr)))
memptr := add(memptr, 0x20)
calldataptr := add(calldataptr, 0x20)
if iszero(lt(memptr, end)) { break }
}
return(0, end)
}
}
}
7 changes: 4 additions & 3 deletions src/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {ProtocolFees} from "./ProtocolFees.sol";
import {ERC6909Claims} from "./ERC6909Claims.sol";
import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
import {BalanceDelta, BalanceDeltaLibrary, toBalanceDelta} from "./types/BalanceDelta.sol";
import {BeforeSwapDelta} from "./types/BeforeSwapDelta.sol";
import {Lock} from "./libraries/Lock.sol";
import {CurrencyDelta} from "./libraries/CurrencyDelta.sol";
import {NonZeroDeltaCount} from "./libraries/NonZeroDeltaCount.sol";
Expand Down Expand Up @@ -174,7 +175,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim

key.hooks.afterInitialize(key, sqrtPriceX96, tick, hookData);

// On intitalize we emit the key's fee, which tells us all fee settings a pool can have: either a static swap fee or dynamic swap fee and if the hook has enabled swap or withdraw fees.
// On initialize we emit the key's fee, which tells us all fee settings a pool can have: either a static swap fee or dynamic swap fee and if the hook has enabled swap or withdraw fees.
emit Initialize(id, key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks);
}

Expand Down Expand Up @@ -270,7 +271,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
PoolId id = key.toId();
_checkPoolInitialized(id);

(int256 amountToSwap, int128 hookDeltaSpecified) = key.hooks.beforeSwap(key, params, hookData);
(int256 amountToSwap, BeforeSwapDelta beforeSwapDelta) = key.hooks.beforeSwap(key, params, hookData);

// execute swap, account protocol fees, and emit swap event
swapDelta = _swap(
Expand All @@ -285,7 +286,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
);

BalanceDelta hookDelta;
(swapDelta, hookDelta) = key.hooks.afterSwap(key, params, swapDelta, hookData, hookDeltaSpecified);
(swapDelta, hookDelta) = key.hooks.afterSwap(key, params, swapDelta, hookData, beforeSwapDelta);

// if the hook doesnt have the flag to be able to return deltas, hookDelta will always be 0
if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks));
Expand Down
5 changes: 5 additions & 0 deletions src/interfaces/IExtsload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ interface IExtsload {
/// @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);

/// @notice Called by external contracts to access sparse pool state
/// @param slots List of slots to SLOAD from.
/// @return values List of loaded values.
function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values);
}
5 changes: 3 additions & 2 deletions src/interfaces/IHooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.24;
import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {IPoolManager} from "./IPoolManager.sol";
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";

/// @notice The PoolManager contract decides whether to invoke specific hooks by inspecting the leading bits
/// of the hooks contract address. For example, a 1 bit in the first bit of the address will
Expand Down Expand Up @@ -97,13 +98,13 @@ interface IHooks {
/// @param params The parameters for the swap
/// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook
/// @return bytes4 The function selector for the hook
/// @return int128 The hook's delta in specified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
/// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
function beforeSwap(
address sender,
PoolKey calldata key,
IPoolManager.SwapParams calldata params,
bytes calldata hookData
) external returns (bytes4, int128);
) external returns (bytes4, BeforeSwapDelta);

/// @notice The hook called after a swap
/// @param sender The initial msg.sender for the swap call
Expand Down
50 changes: 33 additions & 17 deletions src/libraries/Hooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {IHooks} from "../interfaces/IHooks.sol";
import {SafeCast} from "../libraries/SafeCast.sol";
import {LPFeeLibrary} from "./LPFeeLibrary.sol";
import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";

/// @notice V4 decides whether to invoke specific hooks by inspecting the leading bits of the address that
Expand All @@ -16,6 +17,7 @@ library Hooks {
using LPFeeLibrary for uint24;
using Hooks for IHooks;
using SafeCast for int256;
using BeforeSwapDeltaLibrary for BeforeSwapDelta;

uint256 internal constant BEFORE_INITIALIZE_FLAG = 1 << 159;
uint256 internal constant AFTER_INITIALIZE_FLAG = 1 << 158;
Expand Down Expand Up @@ -141,6 +143,7 @@ library Hooks {
{
bytes memory result = callHook(self, data);

// If this hook wasnt meant to return something, default to 0 delta
if (!parseReturn) return 0;
(, delta) = abi.decode(result, (bytes4, int256));
}
Expand Down Expand Up @@ -233,21 +236,31 @@ library Hooks {
/// @notice calls beforeSwap hook if permissioned and validates return value
function beforeSwap(IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData)
internal
returns (int256 amountToSwap, int128 hookDeltaSpecified)
returns (int256 amountToSwap, BeforeSwapDelta hookReturn)
{
amountToSwap = params.amountSpecified;
if (msg.sender == address(self)) return (amountToSwap, hookDeltaSpecified);
if (msg.sender == address(self)) return (amountToSwap, BeforeSwapDeltaLibrary.ZERO_DELTA);

if (self.hasPermission(BEFORE_SWAP_FLAG)) {
hookDeltaSpecified = self.callHookWithReturnDelta(
abi.encodeWithSelector(IHooks.beforeSwap.selector, msg.sender, key, params, hookData),
self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)
).toInt128();
bool canReturnDelta = self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG);
hookReturn = BeforeSwapDelta.wrap(
self.callHookWithReturnDelta(
abi.encodeWithSelector(IHooks.beforeSwap.selector, msg.sender, key, params, hookData),
canReturnDelta
)
);

// Update the swap amount according to the hook's return, and check that the swap type doesnt change (exact input/output)
if (hookDeltaSpecified != 0) {
bool exactInput = amountToSwap < 0;
amountToSwap += hookDeltaSpecified;
if (exactInput ? amountToSwap > 0 : amountToSwap < 0) revert HookDeltaExceedsSwapAmount();
// skip this logic for the case where the hook return is 0
if (canReturnDelta) {
// any return in unspecified is passed to the afterSwap hook for handling
int128 hookDeltaSpecified = hookReturn.getSpecifiedDelta();

// Update the swap amount according to the hook's return, and check that the swap type doesnt change (exact input/output)
if (hookDeltaSpecified != 0) {
bool exactInput = amountToSwap < 0;
amountToSwap += hookDeltaSpecified;
if (exactInput ? amountToSwap > 0 : amountToSwap < 0) revert HookDeltaExceedsSwapAmount();
}
}
}
}
Expand All @@ -259,27 +272,30 @@ library Hooks {
IPoolManager.SwapParams memory params,
BalanceDelta swapDelta,
bytes calldata hookData,
int128 hookDeltaSpecified
) internal returns (BalanceDelta swapperDelta, BalanceDelta hookDelta) {
BeforeSwapDelta beforeSwapHookReturn
) internal returns (BalanceDelta, BalanceDelta) {
if (msg.sender == address(self)) return (swapDelta, BalanceDeltaLibrary.ZERO_DELTA);

int128 hookDeltaUnspecified;
swapperDelta = swapDelta;
int128 hookDeltaSpecified = beforeSwapHookReturn.getSpecifiedDelta();
int128 hookDeltaUnspecified = beforeSwapHookReturn.getUnspecifiedDelta();

if (self.hasPermission(AFTER_SWAP_FLAG)) {
hookDeltaUnspecified = self.callHookWithReturnDelta(
hookDeltaUnspecified += self.callHookWithReturnDelta(
abi.encodeWithSelector(IHooks.afterSwap.selector, msg.sender, key, params, swapDelta, hookData),
self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)
).toInt128();
}

BalanceDelta hookDelta;
if (hookDeltaUnspecified != 0 || hookDeltaSpecified != 0) {
hookDelta = (params.amountSpecified < 0 == params.zeroForOne)
? toBalanceDelta(hookDeltaSpecified, hookDeltaUnspecified)
: toBalanceDelta(hookDeltaUnspecified, hookDeltaSpecified);

// the caller has to pay for (or receive) the hook's delta
swapperDelta = swapDelta - hookDelta;
swapDelta = swapDelta - hookDelta;
}
return (swapDelta, hookDelta);
}

/// @notice calls beforeDonate hook if permissioned and validates return value
Expand Down
Loading

0 comments on commit 8e77696

Please sign in to comment.