Skip to content

Commit

Permalink
Remove HookReturnDelta type
Browse files Browse the repository at this point in the history
  • Loading branch information
hensha256 committed May 13, 2024
1 parent f577721 commit ea3cc17
Show file tree
Hide file tree
Showing 20 changed files with 70 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
329513
329498
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 @@
284148
284133
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23596
23597
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
185086
185071
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 @@
135847
135875
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 @@
184979
185033
Original file line number Diff line number Diff line change
@@ -1 +1 @@
225044
225009
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 @@
181954
181919
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 @@
160245
160210
6 changes: 3 additions & 3 deletions src/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +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 {HookReturnDelta} from "./types/HookReturnDelta.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 @@ -271,7 +271,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
PoolId id = key.toId();
_checkPoolInitialized(id);

(int256 amountToSwap, HookReturnDelta hookReturnDelta) = 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 @@ -286,7 +286,7 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
);

BalanceDelta hookDelta;
(swapDelta, hookDelta) = key.hooks.afterSwap(key, params, swapDelta, hookData, hookReturnDelta);
(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
2 changes: 1 addition & 1 deletion src/interfaces/IHooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +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/HookReturnDelta.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
74 changes: 44 additions & 30 deletions src/libraries/Hooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +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 {HookReturnDelta, HookReturnDeltaLibrary} from "../types/HookReturnDelta.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 @@ -17,7 +17,7 @@ library Hooks {
using LPFeeLibrary for uint24;
using Hooks for IHooks;
using SafeCast for int256;
using HookReturnDeltaLibrary for HookReturnDelta;
using BeforeSwapDeltaLibrary for BeforeSwapDelta;

uint256 internal constant BEFORE_INITIALIZE_FLAG = 1 << 159;
uint256 internal constant AFTER_INITIALIZE_FLAG = 1 << 158;
Expand Down Expand Up @@ -139,12 +139,13 @@ library Hooks {
/// @return delta The delta returned by the hook
function callHookWithReturnDelta(IHooks self, bytes memory data, bool parseReturn)
internal
returns (HookReturnDelta delta)
returns (int256 delta)
{
bytes memory result = callHook(self, data);

if (!parseReturn) return HookReturnDeltaLibrary.ZERO_DELTA;
(, delta) = abi.decode(result, (bytes4, HookReturnDelta));
// If this hook wasnt meant to return something, default to 0 delta
if (!parseReturn) return 0;
(, delta) = abi.decode(result, (bytes4, int256));
}

/// @notice modifier to prevent calling a hook if they initiated the action
Expand Down Expand Up @@ -207,20 +208,26 @@ library Hooks {
callerDelta = delta;
if (params.liquidityDelta > 0) {
if (self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG)) {
hookDelta = self.callHookWithReturnDelta(
abi.encodeWithSelector(IHooks.afterAddLiquidity.selector, msg.sender, key, params, delta, hookData),
self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)
).toBalanceDelta();
hookDelta = BalanceDelta.wrap(
self.callHookWithReturnDelta(
abi.encodeWithSelector(
IHooks.afterAddLiquidity.selector, msg.sender, key, params, delta, hookData
),
self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)
)
);
callerDelta = callerDelta - hookDelta;
}
} else {
if (self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG)) {
hookDelta = self.callHookWithReturnDelta(
abi.encodeWithSelector(
IHooks.afterRemoveLiquidity.selector, msg.sender, key, params, delta, hookData
),
self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)
).toBalanceDelta();
hookDelta = BalanceDelta.wrap(
self.callHookWithReturnDelta(
abi.encodeWithSelector(
IHooks.afterRemoveLiquidity.selector, msg.sender, key, params, delta, hookData
),
self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)
)
);
callerDelta = callerDelta - hookDelta;
}
}
Expand All @@ -229,24 +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, HookReturnDelta hookReturn)
returns (int256 amountToSwap, BeforeSwapDelta hookReturn)
{
amountToSwap = params.amountSpecified;
if (msg.sender == address(self)) return (amountToSwap, HookReturnDeltaLibrary.ZERO_DELTA);
if (msg.sender == address(self)) return (amountToSwap, BeforeSwapDeltaLibrary.ZERO_DELTA);

if (self.hasPermission(BEFORE_SWAP_FLAG)) {
hookReturn = self.callHookWithReturnDelta(
abi.encodeWithSelector(IHooks.beforeSwap.selector, msg.sender, key, params, hookData),
self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)
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
)
);
// 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();

// 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 @@ -258,7 +272,7 @@ library Hooks {
IPoolManager.SwapParams memory params,
BalanceDelta swapDelta,
bytes calldata hookData,
HookReturnDelta beforeSwapHookReturn
BeforeSwapDelta beforeSwapHookReturn
) internal returns (BalanceDelta, BalanceDelta) {
if (msg.sender == address(self)) return (swapDelta, BalanceDeltaLibrary.ZERO_DELTA);

Expand All @@ -269,7 +283,7 @@ library Hooks {
hookDeltaUnspecified += self.callHookWithReturnDelta(
abi.encodeWithSelector(IHooks.afterSwap.selector, msg.sender, key, params, swapDelta, hookData),
self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)
).getUnspecifiedDelta();
).toInt128();
}

BalanceDelta hookDelta;
Expand Down
2 changes: 1 addition & 1 deletion src/test/BaseTestHooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.24;
import {IHooks} from "../interfaces/IHooks.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {BeforeSwapDelta} from "../types/HookReturnDelta.sol";
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";

contract BaseTestHooks is IHooks {
Expand Down
2 changes: 1 addition & 1 deletion src/test/CustomCurveHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {SafeCast} from "../libraries/SafeCast.sol";
import {IHooks} from "../interfaces/IHooks.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/HookReturnDelta.sol";
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {Currency} from "../types/Currency.sol";
import {CurrencySettleTake} from "../libraries/CurrencySettleTake.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/test/DeltaReturningHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {Currency} from "../types/Currency.sol";
import {BaseTestHooks} from "./BaseTestHooks.sol";
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
import {CurrencyLibrary, Currency} from "../types/Currency.sol";
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/HookReturnDelta.sol";
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/BeforeSwapDelta.sol";

contract DeltaReturningHook is BaseTestHooks {
using Hooks for IHooks;
Expand Down
2 changes: 1 addition & 1 deletion src/test/DynamicFeesTestHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {BaseTestHooks} from "./BaseTestHooks.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";
import {IHooks} from "../interfaces/IHooks.sol";
import {BeforeSwapDelta} from "../types/HookReturnDelta.sol";
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";

contract DynamicFeesTestHook is BaseTestHooks {
uint24 internal fee;
Expand Down
2 changes: 1 addition & 1 deletion src/test/EmptyTestHooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {IHooks} from "../interfaces/IHooks.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
import {BeforeSwapDelta} from "../types/HookReturnDelta.sol";
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";

contract EmptyTestHooks is IHooks {
using Hooks for IHooks;
Expand Down
2 changes: 1 addition & 1 deletion src/test/MockHooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {IPoolManager} from "../interfaces/IPoolManager.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
import {BeforeSwapDelta} from "../types/HookReturnDelta.sol";
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";

contract MockHooks is IHooks {
using PoolIdLibrary for PoolKey;
Expand Down
2 changes: 1 addition & 1 deletion src/test/SkipCallsTestHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {PoolTestBase} from "./PoolTestBase.sol";
import {Constants} from "../../test/utils/Constants.sol";
import {Test} from "forge-std/Test.sol";
import {CurrencySettleTake} from "../libraries/CurrencySettleTake.sol";
import {BeforeSwapDelta} from "../types/HookReturnDelta.sol";
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";

contract SkipCallsTestHook is BaseTestHooks, Test {
using CurrencySettleTake for Currency;
Expand Down
26 changes: 6 additions & 20 deletions src/types/HookReturnDelta.sol → src/types/BeforeSwapDelta.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ pragma solidity ^0.8.20;

import {BalanceDelta} from "./BalanceDelta.sol";

// Type used only internally to decode the different types of deltas returned by hooks
// For afterAddLiquidity and afterRemoveLiquidity, HookReturnDelta is a BalanceDelta
// For beforeSwap, HookReturnDelta is a BeforeSwapDelta
// For afterSwap, HookReturnDelta is an int128 in the lower 128 bits
type HookReturnDelta is bytes32;

// Return type of the beforeSwap hook.
// Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook)
type BeforeSwapDelta is int256;
Expand All @@ -24,28 +18,20 @@ function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified)
}
}

library HookReturnDeltaLibrary {
HookReturnDelta public constant ZERO_DELTA = HookReturnDelta.wrap(bytes32(0));

/// converts a HookReturnDelta type to a BalanceDelta type
/// returned by afterAddLiquidity and afterRemoveLiquidity
function toBalanceDelta(HookReturnDelta delta) internal pure returns (BalanceDelta balanceDelta) {
assembly {
balanceDelta := delta
}
}
library BeforeSwapDeltaLibrary {
BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0);

/// extracts int128 from the upper 128 bits of the HookReturnDelta
/// extracts int128 from the upper 128 bits of the BeforeSwapDelta
/// returned by beforeSwap
function getSpecifiedDelta(HookReturnDelta delta) internal pure returns (int128 deltaSpecified) {
function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) {
assembly {
deltaSpecified := shr(128, delta)
}
}

/// extracts int128 from the lower 128 bits of the HookReturnDelta
/// extracts int128 from the lower 128 bits of the BeforeSwapDelta
/// returned by beforeSwap and afterSwap
function getUnspecifiedDelta(HookReturnDelta delta) internal pure returns (int128 deltaUnspecified) {
function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) {
/// @solidity memory-safe-assembly
assembly {
deltaUnspecified := delta
Expand Down

0 comments on commit ea3cc17

Please sign in to comment.