Skip to content

Commit

Permalink
Decode router params calldata (#230)
Browse files Browse the repository at this point in the history
* router decode calldata

* add as functions to library

* fuzz tests
  • Loading branch information
hensha256 authored Aug 2, 2024
1 parent a44f768 commit 1bbeef5
Show file tree
Hide file tree
Showing 32 changed files with 204 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
134624
134171
Original file line number Diff line number Diff line change
@@ -1 +1 @@
127419
126966
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_Bytecode.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7256
6942
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn1Hop_nativeIn.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
120842
120501
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
120037
119696
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
128909
128568
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
135739
135398
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn2Hops.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
187091
186897
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn2Hops_nativeIn.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
179026
178832
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn3Hops.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
238470
238421
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactIn3Hops_nativeIn.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
230429
230380
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactInputSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
134624
134171
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactInputSingle_nativeIn.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
119727
119274
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
118900
118447
Original file line number Diff line number Diff line change
@@ -1 +1 @@
126645
126298
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
120878
120531
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
129750
129403
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
134551
134204
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut2Hops.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
186512
186306
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
183407
183201
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut3Hops.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
238515
238448
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
235434
235367
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
229667
229600
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOutputSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
133428
132975
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125522
125069
2 changes: 1 addition & 1 deletion .forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
119813
119360
26 changes: 15 additions & 11 deletions src/V4Router.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver {
// swap actions and payment actions in different blocks for gas efficiency
if (action < Actions.SETTLE) {
if (action == Actions.SWAP_EXACT_IN) {
_swapExactInput(abi.decode(params, (IV4Router.ExactInputParams)));
IV4Router.ExactInputParams calldata swapParams = params.decodeSwapExactInParams();
_swapExactInput(swapParams);
} else if (action == Actions.SWAP_EXACT_IN_SINGLE) {
_swapExactInputSingle(abi.decode(params, (IV4Router.ExactInputSingleParams)));
IV4Router.ExactInputSingleParams calldata swapParams = params.decodeSwapExactInSingleParams();
_swapExactInputSingle(swapParams);
} else if (action == Actions.SWAP_EXACT_OUT) {
_swapExactOutput(abi.decode(params, (IV4Router.ExactOutputParams)));
IV4Router.ExactOutputParams calldata swapParams = params.decodeSwapExactOutParams();
_swapExactOutput(swapParams);
} else if (action == Actions.SWAP_EXACT_OUT_SINGLE) {
_swapExactOutputSingle(abi.decode(params, (IV4Router.ExactOutputSingleParams)));
IV4Router.ExactOutputSingleParams calldata swapParams = params.decodeSwapExactOutSingleParams();
_swapExactOutputSingle(swapParams);
} else {
revert UnsupportedAction(action);
}
Expand All @@ -62,7 +66,7 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver {
}
}

function _swapExactInputSingle(IV4Router.ExactInputSingleParams memory params) private {
function _swapExactInputSingle(IV4Router.ExactInputSingleParams calldata params) private {
uint128 amountOut = _swap(
params.poolKey,
params.zeroForOne,
Expand All @@ -73,14 +77,14 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver {
if (amountOut < params.amountOutMinimum) revert TooLittleReceived();
}

function _swapExactInput(IV4Router.ExactInputParams memory params) private {
function _swapExactInput(IV4Router.ExactInputParams calldata params) private {
unchecked {
// Caching for gas savings
uint256 pathLength = params.path.length;
uint128 amountOut;
uint128 amountIn = params.amountIn;
Currency currencyIn = params.currencyIn;
PathKey memory pathKey;
PathKey calldata pathKey;

for (uint256 i = 0; i < pathLength; i++) {
pathKey = params.path[i];
Expand All @@ -96,7 +100,7 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver {
}
}

function _swapExactOutputSingle(IV4Router.ExactOutputSingleParams memory params) private {
function _swapExactOutputSingle(IV4Router.ExactOutputSingleParams calldata params) private {
uint128 amountIn = (
-_swap(
params.poolKey,
Expand All @@ -109,14 +113,14 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver {
if (amountIn > params.amountInMaximum) revert TooMuchRequested();
}

function _swapExactOutput(IV4Router.ExactOutputParams memory params) private {
function _swapExactOutput(IV4Router.ExactOutputParams calldata params) private {
unchecked {
// Caching for gas savings
uint256 pathLength = params.path.length;
uint128 amountIn;
uint128 amountOut = params.amountOut;
Currency currencyOut = params.currencyOut;
PathKey memory pathKey;
PathKey calldata pathKey;

for (uint256 i = pathLength; i > 0; i--) {
pathKey = params.path[i - 1];
Expand All @@ -136,7 +140,7 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver {
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes memory hookData
bytes calldata hookData
) private returns (int128 reciprocalAmount) {
unchecked {
BalanceDelta delta = poolManager.swap(
Expand Down
10 changes: 5 additions & 5 deletions src/lens/Quoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ contract Quoter is IQuoter, SafeCallback {
}

/// @dev quote an ExactInput swap along a path of tokens, then revert with the result
function _quoteExactInput(QuoteExactParams memory params) public selfOnly returns (bytes memory) {
function _quoteExactInput(QuoteExactParams calldata params) public selfOnly returns (bytes memory) {
uint256 pathLength = params.path.length;

QuoteResult memory result = QuoteResult({
Expand Down Expand Up @@ -198,7 +198,7 @@ contract Quoter is IQuoter, SafeCallback {
}

/// @dev quote an ExactInput swap on a pool, then revert with the result
function _quoteExactInputSingle(QuoteExactSingleParams memory params) public selfOnly returns (bytes memory) {
function _quoteExactInputSingle(QuoteExactSingleParams calldata params) public selfOnly returns (bytes memory) {
(, int24 tickBefore,,) = poolManager.getSlot0(params.poolKey.toId());

(BalanceDelta deltas, uint160 sqrtPriceX96After, int24 tickAfter) = _swap(
Expand All @@ -223,7 +223,7 @@ contract Quoter is IQuoter, SafeCallback {
}

/// @dev quote an ExactOutput swap along a path of tokens, then revert with the result
function _quoteExactOutput(QuoteExactParams memory params) public selfOnly returns (bytes memory) {
function _quoteExactOutput(QuoteExactParams calldata params) public selfOnly returns (bytes memory) {
uint256 pathLength = params.path.length;

QuoteResult memory result = QuoteResult({
Expand Down Expand Up @@ -269,7 +269,7 @@ contract Quoter is IQuoter, SafeCallback {
}

/// @dev quote an ExactOutput swap on a pool, then revert with the result
function _quoteExactOutputSingle(QuoteExactSingleParams memory params) public selfOnly returns (bytes memory) {
function _quoteExactOutputSingle(QuoteExactSingleParams calldata params) public selfOnly returns (bytes memory) {
// if no price limit has been specified, cache the output amount for comparison in the swap callback
if (params.sqrtPriceLimitX96 == 0) amountOutCached = params.exactAmount;

Expand Down Expand Up @@ -303,7 +303,7 @@ contract Quoter is IQuoter, SafeCallback {
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes memory hookData
bytes calldata hookData
) private returns (BalanceDelta deltas, uint160 sqrtPriceX96After, int24 tickAfter) {
deltas = poolManager.swap(
poolKey,
Expand Down
49 changes: 49 additions & 0 deletions src/libraries/CalldataDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.0;

import {PositionConfig} from "./PositionConfig.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {IV4Router} from "../interfaces/IV4Router.sol";

/// @title Library for abi decoding in calldata
library CalldataDecoder {
Expand Down Expand Up @@ -110,6 +111,54 @@ library CalldataDecoder {
hookData = params.toBytes(10);
}

/// @dev equivalent to: abi.decode(params, (IV4Router.ExactInputParams))
function decodeSwapExactInParams(bytes calldata params)
internal
pure
returns (IV4Router.ExactInputParams calldata swapParams)
{
// ExactInputParams is a variable length struct so we just have to look up its location
assembly ("memory-safe") {
swapParams := add(params.offset, calldataload(params.offset))
}
}

/// @dev equivalent to: abi.decode(params, (IV4Router.ExactInputSingleParams))
function decodeSwapExactInSingleParams(bytes calldata params)
internal
pure
returns (IV4Router.ExactInputSingleParams calldata swapParams)
{
// ExactInputSingleParams is a variable length struct so we just have to look up its location
assembly ("memory-safe") {
swapParams := add(params.offset, calldataload(params.offset))
}
}

/// @dev equivalent to: abi.decode(params, (IV4Router.ExactOutputParams))
function decodeSwapExactOutParams(bytes calldata params)
internal
pure
returns (IV4Router.ExactOutputParams calldata swapParams)
{
// ExactOutputParams is a variable length struct so we just have to look up its location
assembly ("memory-safe") {
swapParams := add(params.offset, calldataload(params.offset))
}
}

/// @dev equivalent to: abi.decode(params, (IV4Router.ExactInputSingleParams))
function decodeSwapExactOutSingleParams(bytes calldata params)
internal
pure
returns (IV4Router.ExactOutputSingleParams calldata swapParams)
{
// ExactOutputSingleParams is a variable length struct so we just have to look up its location
assembly ("memory-safe") {
swapParams := add(params.offset, calldataload(params.offset))
}
}

/// @dev equivalent to: abi.decode(params, (Currency)) in calldata
function decodeCurrency(bytes calldata params) internal pure returns (Currency currency) {
assembly ("memory-safe") {
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/PathKey.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct PathKey {
}

library PathKeyLib {
function getPoolAndSwapDirection(PathKey memory params, Currency currencyIn)
function getPoolAndSwapDirection(PathKey calldata params, Currency currencyIn)
internal
pure
returns (PoolKey memory poolKey, bool zeroForOne)
Expand Down
Loading

0 comments on commit 1bbeef5

Please sign in to comment.