Skip to content

Commit

Permalink
feat: #8 return early (gas optimization) (#13)
Browse files Browse the repository at this point in the history
* feat: updated pancake-v4-periphery

* feat: update test cases based on latest v4-periphery

* feat: updated v4-periphery

* feat: update code based on latest commit

* chore: clean up commented code

* feat: #8 return early

* feat: add missing early return for 1 command

* chore: forge-test after merge

* feat: prevent permit2.permit frontrun (#14)
  • Loading branch information
ChefMist authored Sep 13, 2024
1 parent 39ed001 commit e655693
Show file tree
Hide file tree
Showing 31 changed files with 266 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146358
146304
Original file line number Diff line number Diff line change
@@ -1 +1 @@
123415
123362
Original file line number Diff line number Diff line change
@@ -1 +1 @@
147320
147266
Original file line number Diff line number Diff line change
@@ -1 +1 @@
178729
178676
Original file line number Diff line number Diff line change
@@ -1 +1 @@
149114
149062
Original file line number Diff line number Diff line change
@@ -1 +1 @@
182570
182517
Original file line number Diff line number Diff line change
@@ -1 +1 @@
153487
153435
Original file line number Diff line number Diff line change
@@ -1 +1 @@
151699
151645
Original file line number Diff line number Diff line change
@@ -1 +1 @@
172360
172308
Original file line number Diff line number Diff line change
@@ -1 +1 @@
174610
174558
Original file line number Diff line number Diff line change
@@ -1 +1 @@
181709
181657
Original file line number Diff line number Diff line change
@@ -1 +1 @@
247024
246971
Original file line number Diff line number Diff line change
@@ -1 +1 @@
183250
183197
Original file line number Diff line number Diff line change
@@ -1 +1 @@
186048
185996
Original file line number Diff line number Diff line change
@@ -1 +1 @@
250783
250730
Original file line number Diff line number Diff line change
@@ -1 +1 @@
187582
187529
Original file line number Diff line number Diff line change
@@ -1 +1 @@
100147
100125
Original file line number Diff line number Diff line change
@@ -1 +1 @@
117028
100754
Original file line number Diff line number Diff line change
@@ -1 +1 @@
151799
151862
Original file line number Diff line number Diff line change
@@ -1 +1 @@
152677
152659
Original file line number Diff line number Diff line change
@@ -1 +1 @@
193217
193198
Original file line number Diff line number Diff line change
@@ -1 +1 @@
192673
192654
2 changes: 1 addition & 1 deletion .forge-snapshots/UniversalRouterBytecodeSize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24025
24160
2 changes: 1 addition & 1 deletion .forge-snapshots/UniversalRouterTest#test_sweep_token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
55442
55441
Original file line number Diff line number Diff line change
@@ -1 +1 @@
559387
559373
Original file line number Diff line number Diff line change
@@ -1 +1 @@
291669
291590
Original file line number Diff line number Diff line change
@@ -1 +1 @@
594200
594191
Original file line number Diff line number Diff line change
@@ -1 +1 @@
570042
570028
Original file line number Diff line number Diff line change
@@ -1 +1 @@
583553
583544
34 changes: 32 additions & 2 deletions src/base/Dispatcher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ abstract contract Dispatcher is
bytes calldata path = inputs.toBytes(3);
address payer = payerIsUser ? msgSender() : address(this);
v3SwapExactInput(map(recipient), amountIn, amountOutMin, path, payer);
return (success, output);
} else if (command == Commands.V3_SWAP_EXACT_OUT) {
// equivalent: abi.decode(inputs, (address, uint256, uint256, bytes, bool))
address recipient;
Expand All @@ -97,6 +98,7 @@ abstract contract Dispatcher is
bytes calldata path = inputs.toBytes(3);
address payer = payerIsUser ? msgSender() : address(this);
v3SwapExactOutput(map(recipient), amountOut, amountInMax, path, payer);
return (success, output);
} else if (command == Commands.PERMIT2_TRANSFER_FROM) {
// equivalent: abi.decode(inputs, (address, address, uint160))
address token;
Expand All @@ -108,6 +110,7 @@ abstract contract Dispatcher is
amount := calldataload(add(inputs.offset, 0x40))
}
permit2TransferFrom(token, msgSender(), map(recipient), amount);
return (success, output);
} else if (command == Commands.PERMIT2_PERMIT_BATCH) {
IAllowanceTransfer.PermitBatch calldata permitBatch;
assembly {
Expand All @@ -116,7 +119,12 @@ abstract contract Dispatcher is
permitBatch := add(inputs.offset, calldataload(inputs.offset))
}
bytes calldata data = inputs.toBytes(1);
PERMIT2.permit(msgSender(), permitBatch, data);
try PERMIT2.permit(msgSender(), permitBatch, data) {}
catch (bytes memory reason) {
output = reason;
success = false;
}
return (success, output);
} else if (command == Commands.SWEEP) {
// equivalent: abi.decode(inputs, (address, address, uint256))
address token;
Expand All @@ -128,6 +136,7 @@ abstract contract Dispatcher is
amountMin := calldataload(add(inputs.offset, 0x40))
}
Payments.sweep(token, map(recipient), amountMin);
return (success, output);
} else if (command == Commands.TRANSFER) {
// equivalent: abi.decode(inputs, (address, address, uint256))
address token;
Expand All @@ -139,6 +148,7 @@ abstract contract Dispatcher is
value := calldataload(add(inputs.offset, 0x40))
}
Payments.pay(token, map(recipient), value);
return (success, output);
} else if (command == Commands.PAY_PORTION) {
// equivalent: abi.decode(inputs, (address, address, uint256))
address token;
Expand All @@ -150,6 +160,7 @@ abstract contract Dispatcher is
bips := calldataload(add(inputs.offset, 0x40))
}
Payments.payPortion(token, map(recipient), bips);
return (success, output);
} else {
// placeholder area for command 0x07
revert InvalidCommandType(command);
Expand All @@ -172,6 +183,7 @@ abstract contract Dispatcher is
address[] calldata path = inputs.toAddressArray(3);
address payer = payerIsUser ? msgSender() : address(this);
v2SwapExactInput(map(recipient), amountIn, amountOutMin, path, payer);
return (success, output);
} else if (command == Commands.V2_SWAP_EXACT_OUT) {
// equivalent: abi.decode(inputs, (address, uint256, uint256, bytes, bool))
address recipient;
Expand All @@ -188,14 +200,20 @@ abstract contract Dispatcher is
address[] calldata path = inputs.toAddressArray(3);
address payer = payerIsUser ? msgSender() : address(this);
v2SwapExactOutput(map(recipient), amountOut, amountInMax, path, payer);
return (success, output);
} else if (command == Commands.PERMIT2_PERMIT) {
// equivalent: abi.decode(inputs, (IAllowanceTransfer.PermitSingle, bytes))
IAllowanceTransfer.PermitSingle calldata permitSingle;
assembly {
permitSingle := inputs.offset
}
bytes calldata data = inputs.toBytes(6); // PermitSingle takes first 6 slots (0..5)
PERMIT2.permit(msgSender(), permitSingle, data);
try PERMIT2.permit(msgSender(), permitSingle, data) {}
catch (bytes memory reason) {
output = reason;
success = false;
}
return (success, output);
} else if (command == Commands.WRAP_ETH) {
// equivalent: abi.decode(inputs, (address, uint256))
address recipient;
Expand All @@ -205,6 +223,7 @@ abstract contract Dispatcher is
amount := calldataload(add(inputs.offset, 0x20))
}
Payments.wrapETH(map(recipient), amount);
return (success, output);
} else if (command == Commands.UNWRAP_WETH) {
// equivalent: abi.decode(inputs, (address, uint256))
address recipient;
Expand All @@ -214,6 +233,7 @@ abstract contract Dispatcher is
amountMin := calldataload(add(inputs.offset, 0x20))
}
Payments.unwrapWETH9(map(recipient), amountMin);
return (success, output);
} else if (command == Commands.PERMIT2_TRANSFER_FROM_BATCH) {
IAllowanceTransfer.AllowanceTransferDetails[] calldata batchDetails;
(uint256 length, uint256 offset) = inputs.toLengthOffset(0);
Expand All @@ -222,6 +242,7 @@ abstract contract Dispatcher is
batchDetails.offset := offset
}
permit2TransferFrom(batchDetails, msgSender());
return (success, output);
} else if (command == Commands.BALANCE_CHECK_ERC20) {
// equivalent: abi.decode(inputs, (address, address, uint256))
address owner;
Expand All @@ -234,6 +255,7 @@ abstract contract Dispatcher is
}
success = (ERC20(token).balanceOf(owner) >= minBalance);
if (!success) output = abi.encodePacked(BalanceTooLow.selector);
return (success, output);
} else {
// placeholder area for command 0x0f
revert InvalidCommandType(command);
Expand All @@ -244,6 +266,7 @@ abstract contract Dispatcher is
if (command == Commands.V4_SWAP) {
// pass the calldata provided to V4SwapRouter._executeActions (defined in BaseActionsRouter)
_executeActions(inputs);
return (success, output);
// This contract MUST be approved to spend the token since its going to be doing the call on the position manager
} else if (command == Commands.V3_POSITION_MANAGER_PERMIT) {
bytes4 selector;
Expand All @@ -255,6 +278,7 @@ abstract contract Dispatcher is
}

(success, output) = address(V3_POSITION_MANAGER).call(inputs);
return (success, output);
} else if (command == Commands.V3_POSITION_MANAGER_CALL) {
bytes4 selector;
assembly {
Expand All @@ -279,14 +303,17 @@ abstract contract Dispatcher is
}

(success, output) = address(V3_POSITION_MANAGER).call(inputs);
return (success, output);
} else if (command == Commands.V4_CL_POSITION_CALL) {
// should only call modifyLiquidities() with Actions.CL_MINT_POSITION
// do not permit or approve this contract over a v4 position or someone could use this command to decrease, burn, or transfer your position
(success, output) = address(V4_CL_POSITION_MANAGER).call{value: address(this).balance}(inputs);
return (success, output);
} else if (command == Commands.V4_BIN_POSITION_CALL) {
// should only call modifyLiquidities() with Actions.BIN_ADD_LIQUIDITY
// do not permit or approve this contract over a v4 position or someone could use this command to decrease, burn, or transfer your position
(success, output) = address(V4_BIN_POSITION_MANAGER).call{value: address(this).balance}(inputs);
return (success, output);
} else {
// placeholder area for commands 0x15-0x20
revert InvalidCommandType(command);
Expand All @@ -297,6 +324,7 @@ abstract contract Dispatcher is
if (command == Commands.EXECUTE_SUB_PLAN) {
(bytes calldata _commands, bytes[] calldata _inputs) = inputs.decodeCommandsAndInputs();
(success, output) = (address(this)).call(abi.encodeCall(Dispatcher.execute, (_commands, _inputs)));
return (success, output);
} else if (command == Commands.STABLE_SWAP_EXACT_IN) {
// equivalent: abi.decode(inputs, (address, uint256, uint256, bytes, bytes, bool))
address recipient;
Expand All @@ -314,6 +342,7 @@ abstract contract Dispatcher is
uint256[] calldata flag = inputs.toUintArray(4);
address payer = payerIsUser ? msgSender() : address(this);
stableSwapExactInput(map(recipient), amountIn, amountOutMin, path, flag, payer);
return (success, output);
} else if (command == Commands.STABLE_SWAP_EXACT_OUT) {
// equivalent: abi.decode(inputs, (address, uint256, uint256, bytes, bytes, bool))
address recipient;
Expand All @@ -334,6 +363,7 @@ abstract contract Dispatcher is
/// @dev structured this way as stack too deep by Yul
uint256 amountIn = stableSwapExactOutputAmountIn(amountOut, amountInMax, path, flag);
stableSwapExactOutput(map(recipient), amountIn, amountOut, path, flag, payer);
return (success, output);
} else {
// placeholder area for commands 0x24-0x3f
revert InvalidCommandType(command);
Expand Down
Loading

0 comments on commit e655693

Please sign in to comment.