Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

beforeSwap returns dynamic fee #648

Merged
merged 26 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
36e7653
allow beforeSwap to return and set the lpFee
saucepoint May 13, 2024
07a9d30
fix tests; default to a sentinel for Hooks.beforeSwap
saucepoint May 13, 2024
28311ce
merge in main; regenerate snapshots
saucepoint May 14, 2024
7406eb9
define constant
saucepoint May 14, 2024
761ccb9
very smol optimization
saucepoint May 14, 2024
f424c1b
Optimise before swap return fee (#650)
hensha256 May 14, 2024
ad6dcf6
Try shared parse lib (#652)
snreynolds May 14, 2024
cd95832
Update src/interfaces/IHooks.sol
saucepoint May 14, 2024
52ef386
misc
saucepoint May 14, 2024
132a877
merge in main; regenerate snapshots
saucepoint May 14, 2024
616bc84
merge in main; regenerate snapshots; fix test
saucepoint May 15, 2024
f508681
review comments; abstract fee checks; add new test
saucepoint May 15, 2024
b5929ae
make ProtocolFeeLibrary similar to LPFeeLibrary
saucepoint May 15, 2024
3a9747c
fix test
saucepoint May 15, 2024
160e4c6
rename how protocol fee is validated
saucepoint May 16, 2024
196af36
fee masking
saucepoint May 16, 2024
525108e
trial new override mechanism
hensha256 May 16, 2024
fdfa579
remove assembly block
hensha256 May 16, 2024
afcda81
cleanup; some natspec
saucepoint May 16, 2024
2ffaa92
revert if override fee exceeds the maximum
saucepoint May 16, 2024
60e1060
review comments; consolidate fee flag
saucepoint May 16, 2024
9499de9
use 2nd bit of uint24 to signal override
saucepoint May 16, 2024
bac221f
naming
saucepoint May 16, 2024
ef84cb0
Update src/libraries/LPFeeLibrary.sol
saucepoint May 17, 2024
35a1402
Update src/libraries/LPFeeLibrary.sol
saucepoint May 17, 2024
abb6988
additional code comment
saucepoint May 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22114
22121
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 @@
117426
117431
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132587
132592
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 @@
134706
134711
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 @@
183725
183730
Original file line number Diff line number Diff line change
@@ -1 +1 @@
113051
113056
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
124394
124399
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 @@
136447
136452
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 @@
125575
125580
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 @@
147636
147641
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 @@
164441
164446
Original file line number Diff line number Diff line change
@@ -1 +1 @@
223302
223312
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 @@
148642
148647
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
124406
124411
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 @@
180879
180884
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 @@
156492
156577
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 @@
159116
159121
7 changes: 7 additions & 0 deletions src/libraries/LPFeeLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,11 @@ library LPFeeLibrary {
function removeOverrideFlag(uint24 self) internal pure returns (uint24) {
return self & FEE_MASK;
}

/// @notice Removes the override flag and validates the fee (reverts if the fee is too large)
function removeOverrideAndValidate(uint24 self) internal pure returns (uint24) {
uint24 fee = self.removeOverrideFlag();
fee.validate();
return fee;
}
}
9 changes: 2 additions & 7 deletions src/libraries/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,8 @@ library Pool {
state.liquidity = cache.liquidityStart;

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sooo much better ❤️


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

Expand Down
25 changes: 16 additions & 9 deletions test/DynamicReturnFees.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,23 @@ contract TestDynamicReturnFees is Test, Deployers, GasSnapshot {
}

function test_fuzz_dynamicReturnSwapFee(uint24 fee) public {
// hook will handle adding the override flag
dynamicReturnFeesHook.setFee(fee);

int256 amountSpecified = -10000;
BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
uint24 actualFee = fee.removeOverrideFlag();

int256 amountSpecified = -10000;
BalanceDelta result;
if (actualFee > LPFeeLibrary.MAX_LP_FEE) {
vm.expectRevert(LPFeeLibrary.FeeTooLarge.selector);
result = swap(key, true, amountSpecified, ZERO_BYTES);
return;
} else {
result = swap(key, true, amountSpecified, ZERO_BYTES);
}
// BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
assertEq(result.amount0(), amountSpecified);

uint24 actualFee = fee.removeOverrideFlag();
if (actualFee > LPFeeLibrary.MAX_LP_FEE) {
// if the fee is too large, the fee from beforeSwap is not used (and remains at 0 -- the default value)
assertApproxEqAbs(uint256(int256(result.amount1())), uint256(int256(-result.amount0())), 1 wei);
Expand Down Expand Up @@ -150,18 +159,16 @@ contract TestDynamicReturnFees is Test, Deployers, GasSnapshot {
assertEq(_fetchPoolSwapFee(key), initialFee);
}

function test_dynamicReturnSwapFee_notUsedWithTooLargeFee() public {
function test_dynamicReturnSwapFee_revertIfFeeTooLarge() public {
assertEq(_fetchPoolSwapFee(key), 0);

// hook adds the override flag
dynamicReturnFeesHook.setFee(1000001);

// a large fee is not used
int256 amountSpecified = -10000;
BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);

// after swapping ~1:1 on 0% fee, the amount out (amount1) should be equal to amount specified
assertEq(result.amount0(), amountSpecified);
assertApproxEqAbs(uint256(int256(result.amount1())), uint256(int256(-result.amount0())), 1 wei);
vm.expectRevert(LPFeeLibrary.FeeTooLarge.selector);
swap(key, true, amountSpecified, ZERO_BYTES);
}

function _fetchPoolSwapFee(PoolKey memory _key) internal view returns (uint256 swapFee) {
Expand Down
8 changes: 6 additions & 2 deletions test/libraries/Pool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,15 @@ contract PoolTest is Test {
);
Pool.Slot0 memory slot0 = state.slot0;

uint24 _lpFee = params.lpFeeOverride.isValid() ? params.lpFeeOverride : lpFee;
uint24 _lpFee = params.lpFeeOverride.isOverride() ? params.lpFeeOverride.removeOverrideFlag() : lpFee;
uint24 swapFee = protocolFee == 0 ? _lpFee : uint24(protocolFee).calculateSwapFee(_lpFee);
if (params.amountSpecified > 0 && swapFee == MAX_LP_FEE) {

if (params.amountSpecified >= 0 && swapFee == MAX_LP_FEE) {
vm.expectRevert(Pool.InvalidFeeForExactOut.selector);
state.swap(params);
} else if (!swapFee.isValid()) {
vm.expectRevert(LPFeeLibrary.FeeTooLarge.selector);
state.swap(params);
} else if (params.zeroForOne && params.amountSpecified != 0) {
if (params.sqrtPriceLimitX96 >= slot0.sqrtPriceX96) {
vm.expectRevert(
Expand Down
Loading