Skip to content

Commit

Permalink
Routing (#58)
Browse files Browse the repository at this point in the history
* start routing

* start routing contract

* naive swapExactIn impl

* lint + bytecode snapshot

* change concept of hops to token hops

* UniswapV4Routing --> Routing

* use PathKey

* exactInputSingle

* save DRY progress

* no sqrtPriceLimit for multipool hops

* exactOut implemented w awkward loops/int conversions

single hops passing on exactOut

* gas savings from not doing  double negative number

* gas savings from unchecked math

* add swapExactOuputSingle

* break out structs into interface

* PR comments

* pass hook data along

* gas and coherency optimization

* updated lib/v4-core submodule to main branch

* feat: abstract router (#86)

* add PoolTicksCounter library

* quoter exact input single

* quoter test

* return deltas instead

* safe casting to correct types

* QuoteExactInput skeleton

* multiple entries

* break handleRevert by type

* quoteExactInput and unit tests

* more QuoteExactInput tests

* remove lgos

* remove commented out struct

* via-ir in ci

* remove unused imports/functions

* store iteration params locally instead of editing function input

* pull out sqrtPriceLimit to its own function

* PathKey to its own library

* rename initializedTicksCrossed to initializedTicksLoaded

* remove manual abi encoding in yul :p

* fix linter warnings for Quoter

* natspec for IQuoter

* feat: update v4-core

This commit updates v4 core to latest and fixes integration issues

* fix: tests

* style fixes

* inheritdoc

* ExactInSingleBatch

* fix: update tests

* fix: test router was borked

* exact out

* fix: alice comments

* fix ExactOutput

* add ExactOput unit tests

* add quoteExactOutputBatch

* remove solhint config

* remove newline

* add QuoteExactOutput in interface

* refactor lockAcquired

* move magic numbers to constants + doc

* add more natspec

* natspec

* named imports

* self-call branching

* remove old code

* remove console2 import

* refactor PathKeyLib

* amountOutCached

* inherit ILockCallback

* add base contracts and interfaces (#75)

* remove unused errors

* test lockAcquired reverts

* remove ...Batch interface

* REASON -> RESPONSE when valid

* complete natspec

* remove SwapInfo imports

* rename to SwapParameters

* move quoter structs into IQuoter interface

* update to latest core

* use prev values

* change twamm to use pool getters

* changes after merging main

* use --via-ir in cli

* fix formatting

* fix FullRange/TWAMM hook

* update ticks counter

* update Quoter test

* typo

* typo

* simplify handleRevertSingle

* merge QuoteInput/OutputSingle structs

* combine IQuoter structs

* using ... ordering

* update snapshots

* start routing

* start routing contract

* naive swapExactIn impl

* lint + bytecode snapshot

* change concept of hops to token hops

* UniswapV4Routing --> Routing

* use PathKey

* exactInputSingle

* save DRY progress

* no sqrtPriceLimit for multipool hops

* exactOut implemented w awkward loops/int conversions

single hops passing on exactOut

* gas savings from not doing  double negative number

* gas savings from unchecked math

* add swapExactOuputSingle

* break out structs into interface

* PR comments

* pass hook data along

* gas and coherency optimization

* merge Quoter

* remove SwapIntention

* IV4Router structs

* remove SwapIntention

* remove logs

* natspec

* rebase onto latest core

* simplify function naming

* Routing diana (#104)

* feat: Revert style quoter (#73)

* add PoolTicksCounter library

* quoter exact input single

* quoter test

* return deltas instead

* safe casting to correct types

* QuoteExactInput skeleton

* multiple entries

* break handleRevert by type

* quoteExactInput and unit tests

* more QuoteExactInput tests

* remove lgos

* remove commented out struct

* via-ir in ci

* remove unused imports/functions

* store iteration params locally instead of editing function input

* pull out sqrtPriceLimit to its own function

* PathKey to its own library

* rename initializedTicksCrossed to initializedTicksLoaded

* remove manual abi encoding in yul :p

* fix linter warnings for Quoter

* natspec for IQuoter

* feat: update v4-core

This commit updates v4 core to latest and fixes integration issues

* fix: tests

* style fixes

* inheritdoc

* ExactInSingleBatch

* fix: update tests

* fix: test router was borked

* exact out

* fix: alice comments

* fix ExactOutput

* add ExactOput unit tests

* add quoteExactOutputBatch

* remove solhint config

* remove newline

* add QuoteExactOutput in interface

* refactor lockAcquired

* move magic numbers to constants + doc

* add more natspec

* natspec

* named imports

* self-call branching

* remove old code

* remove console2 import

* refactor PathKeyLib

* amountOutCached

* inherit ILockCallback

* add base contracts and interfaces (#75)

* remove unused errors

* test lockAcquired reverts

* remove ...Batch interface

* REASON -> RESPONSE when valid

* complete natspec

* remove SwapInfo imports

* rename to SwapParameters

* move quoter structs into IQuoter interface

* update to latest core

* use prev values

* change twamm to use pool getters

* changes after merging main

* use --via-ir in cli

* fix formatting

* fix FullRange/TWAMM hook

* update ticks counter

* update Quoter test

* typo

* typo

* simplify handleRevertSingle

* merge QuoteInput/OutputSingle structs

* combine IQuoter structs

* using ... ordering

* update snapshots

* move amountOutCached into inner call

* using PathKeyLib for PathKey

* fix amountOutCached

* remove console2 import

* resurface revert reason

* clean up validateRevert

* update natsppec

* remove unused

---------

Co-authored-by: Mark Toda <toda.mark@gmail.com>
Co-authored-by: Tina <59578595+tinaszheng@users.noreply.github.com>
Co-authored-by: Sara Reynolds <snreynolds2506@gmail.com>

* (Quoter) Avoid IR (#93)

* avoid stack too deep

* pack local variables into structs; remove need for IR

* reorg struct

* snapshots

* forge fmt

* restore settings

* remove IR

* ensure tokens are ordered properly by using salts

* gas snapshot

* remove console logs

* chore: update v4-core:latest (#89)

* update v4-core

* update to new liquidity hooks

* forge fmt; reuse v4-core justfile

* snapshots

* rename getHooksCalls --> getHookPermissions

* enforce permanent liquidity with beforeRemoveLiquidity

* snapshot

* update v4-core (again)

* snapshots with new v4-core

* v4-core:latest

* pin 0.8.24

* merge in remote; regenerate snapshots

* remove justfile

* repin cancun

* pin token addresses using vm.etch

* snapshots

* forge fmt

* remove via-ir and custom solc from CI

* test nit

* Update v4-core submodule to use https (#97)

Co-authored-by: saucepoint <98790946+saucepoint@users.noreply.github.com>

* chore: add semgrep (#94)

* [Chore] Update v4-core:latest (#100)

* Update v4-core

* Update various examples, BaseHook, Quoter and tests

* Remove nested locking for LimitOrder

* Fix Quoter

* update v4-core

* fix: remove getLocker as its a bool now

* update v4-core: flipped signs, push dynamic fees

* fix: flip delta signs

* flip delta signs

* flip delta signs

* flip delta signs

* fix getSlot0 calls

* snapshots

* remove deadcode

* remove unused param

* update core

* update for modifyLiquidity; misc doc updates

* correct min int256

* allow for manual fee updates

---------

Co-authored-by: saucepoint <saucepoint@protonmail.com>

* changes with core update

* fix casing

* switch versions back

* Updated lib/v4-core submodule to main branch

* switch to 0.8.19

---------

Co-authored-by: Zach Yang <zhiyuan.zach.yang@gmail.com>
Co-authored-by: Mark Toda <toda.mark@gmail.com>
Co-authored-by: Tina <59578595+tinaszheng@users.noreply.github.com>
Co-authored-by: Sara Reynolds <snreynolds2506@gmail.com>
Co-authored-by: saucepoint <98790946+saucepoint@users.noreply.github.com>
Co-authored-by: 0x57 <wqi@umich.edu>
Co-authored-by: mr-uniswap <144828035+mr-uniswap@users.noreply.github.com>
Co-authored-by: 0x57 <qi.wu@coinbase.com>
Co-authored-by: saucepoint <saucepoint@protonmail.com>
Co-authored-by: Alice Henshaw <henshawalice@gmail.com>

* update imports

---------

Co-authored-by: Mark Toda <toda.mark@gmail.com>
Co-authored-by: Tina <59578595+tinaszheng@users.noreply.github.com>
Co-authored-by: Sara Reynolds <snreynolds2506@gmail.com>
Co-authored-by: Emily Williams <emag3m@gmail.com>
Co-authored-by: Alice Henshaw <henshawalice@gmail.com>
Co-authored-by: diana <dlkocsis04@gmail.com>
Co-authored-by: saucepoint <98790946+saucepoint@users.noreply.github.com>
Co-authored-by: 0x57 <wqi@umich.edu>
Co-authored-by: mr-uniswap <144828035+mr-uniswap@users.noreply.github.com>
Co-authored-by: 0x57 <qi.wu@coinbase.com>
Co-authored-by: saucepoint <saucepoint@protonmail.com>

* allow payer and recipient to be different

* try to fix ci

* improve casting

* reverting 3 commits to make branch

* remove unused recipient param

* remove payment logic from swap logic

* factor out payment functions

* gas opt removing struct

* gas opt: decode in assembly

* merge error

* use base actions router in v4router

* use isolate

* merge conflicts

* removing submodules

* renaming to stop clashes in UR

* PR comments and gas optimisations

* add _getLocker

* Amount field on settle and take

* rename snaps

* correcy casting order

* Add deltaresolver to router

* take_all command, remove from delta resolver

* Routing test helper

* Separate gas tests and regular tests

* remove duplicate snapshot name

* another gas test

* PR comments

* remove unused function

* PR cmments

* handle hook edgecase

---------

Co-authored-by: Diana Kocsis <diana.kocsis@uniswap.org>
Co-authored-by: Alice Henshaw <henshawalice@gmail.com>
Co-authored-by: Zach Yang <zhiyuan.zach.yang@gmail.com>
Co-authored-by: Mark Toda <toda.mark@gmail.com>
Co-authored-by: Tina <59578595+tinaszheng@users.noreply.github.com>
Co-authored-by: Sara Reynolds <snreynolds2506@gmail.com>
Co-authored-by: diana <dlkocsis04@gmail.com>
Co-authored-by: saucepoint <98790946+saucepoint@users.noreply.github.com>
Co-authored-by: 0x57 <wqi@umich.edu>
Co-authored-by: mr-uniswap <144828035+mr-uniswap@users.noreply.github.com>
Co-authored-by: 0x57 <qi.wu@coinbase.com>
Co-authored-by: saucepoint <saucepoint@protonmail.com>
Co-authored-by: Alice <34962750+hensha256@users.noreply.github.com>
  • Loading branch information
14 people authored Jul 29, 2024
1 parent 2603731 commit de79c94
Show file tree
Hide file tree
Showing 28 changed files with 925 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/BaseActionsRouter_mock10commands.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
62824
62960
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_Bytecode.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6214
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
129205
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
136035
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactIn2Hops.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
187387
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactIn3Hops.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
238768
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactInputSingle.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
134822
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
130046
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
134847
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactOut2Hops.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
186808
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactOut3Hops.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
238813
1 change: 1 addition & 0 deletions .forge-snapshots/V4Router_ExactOutputSingle.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
133356
169 changes: 169 additions & 0 deletions src/V4Router.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";

import {PathKey, PathKeyLib} from "./libraries/PathKey.sol";
import {CalldataDecoder} from "./libraries/CalldataDecoder.sol";
import {IV4Router} from "./interfaces/IV4Router.sol";
import {BaseActionsRouter} from "./base/BaseActionsRouter.sol";
import {DeltaResolver} from "./base/DeltaResolver.sol";
import {Actions} from "./libraries/Actions.sol";
import {SafeCast} from "./libraries/SafeCast.sol";

/// @title UniswapV4Router
/// @notice Abstract contract that contains all internal logic needed for routing through Uniswap V4 pools
/// @dev the entry point to executing actions in this contract is calling `BaseActionsRouter._executeActions`
/// An inheriting contract should call _executeActions at the point that they wish actions to be executed
abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver {
using SafeCast for *;
using PathKeyLib for PathKey;
using CalldataDecoder for bytes;
using TransientStateLibrary for IPoolManager;

constructor(IPoolManager _poolManager) BaseActionsRouter(_poolManager) {}

// TODO native support !!
function _handleAction(uint256 action, bytes calldata params) internal override {
// 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)));
} else if (action == Actions.SWAP_EXACT_IN_SINGLE) {
_swapExactInputSingle(abi.decode(params, (IV4Router.ExactInputSingleParams)));
} else if (action == Actions.SWAP_EXACT_OUT) {
_swapExactOutput(abi.decode(params, (IV4Router.ExactOutputParams)));
} else if (action == Actions.SWAP_EXACT_OUT_SINGLE) {
_swapExactOutputSingle(abi.decode(params, (IV4Router.ExactOutputSingleParams)));
} else {
revert UnsupportedAction(action);
}
} else {
if (action == Actions.SETTLE_ALL) {
// equivalent: abi.decode(params, (Currency))
Currency currency;
assembly ("memory-safe") {
currency := calldataload(params.offset)
}

int256 delta = poolManager.currencyDelta(address(this), currency);
if (delta > 0) revert InvalidDeltaForAction();

// TODO support address(this) paying too
// TODO should it have a maxAmountOut added slippage protection?
_settle(currency, _msgSender(), uint256(-delta));
} else if (action == Actions.TAKE_ALL) {
// equivalent: abi.decode(params, (Currency, address))
Currency currency;
address recipient;
assembly ("memory-safe") {
currency := calldataload(params.offset)
recipient := calldataload(add(params.offset, 0x20))
}

int256 delta = poolManager.currencyDelta(address(this), currency);
if (delta < 0) revert InvalidDeltaForAction();

// TODO should _take have a minAmountOut added slippage check?
// TODO recipient mapping
_take(currency, recipient, uint256(delta));
} else {
revert UnsupportedAction(action);
}
}
}

function _swapExactInputSingle(IV4Router.ExactInputSingleParams memory params) private {
_swap(
params.poolKey,
params.zeroForOne,
int256(-int128(params.amountIn)),
params.sqrtPriceLimitX96,
params.hookData
);
}

function _swapExactInput(IV4Router.ExactInputParams memory 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;

for (uint256 i = 0; i < pathLength; i++) {
pathKey = params.path[i];
(PoolKey memory poolKey, bool zeroForOne) = pathKey.getPoolAndSwapDirection(currencyIn);
// The output delta will always be positive, except for when interacting with certain hook pools
amountOut = _swap(poolKey, zeroForOne, -int256(uint256(amountIn)), 0, pathKey.hookData).toUint128();

amountIn = amountOut;
currencyIn = pathKey.intermediateCurrency;
}

if (amountOut < params.amountOutMinimum) revert TooLittleReceived();
}
}

function _swapExactOutputSingle(IV4Router.ExactOutputSingleParams memory params) private {
_swap(
params.poolKey,
params.zeroForOne,
int256(int128(params.amountOut)),
params.sqrtPriceLimitX96,
params.hookData
);
}

function _swapExactOutput(IV4Router.ExactOutputParams memory 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;

for (uint256 i = pathLength; i > 0; i--) {
pathKey = params.path[i - 1];
(PoolKey memory poolKey, bool oneForZero) = pathKey.getPoolAndSwapDirection(currencyOut);
// The output delta will always be negative, except for when interacting with certain hook pools
amountIn = (-_swap(poolKey, !oneForZero, int256(uint256(amountOut)), 0, pathKey.hookData)).toUint128();

amountOut = amountIn;
currencyOut = pathKey.intermediateCurrency;
}
if (amountIn > params.amountInMaximum) revert TooMuchRequested();
}
}

function _swap(
PoolKey memory poolKey,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes memory hookData
) private returns (int128 reciprocalAmount) {
unchecked {
BalanceDelta delta = poolManager.swap(
poolKey,
IPoolManager.SwapParams(
zeroForOne,
amountSpecified,
sqrtPriceLimitX96 == 0
? (zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1)
: sqrtPriceLimitX96
),
hookData
);

reciprocalAmount = (zeroForOne == amountSpecified < 0) ? delta.amount1() : delta.amount0();
}
}
}
6 changes: 3 additions & 3 deletions src/base/BaseActionsRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ abstract contract BaseActionsRouter is SafeCallback {
using CalldataDecoder for bytes;

/// @notice emitted when different numbers of parameters and actions are provided
error LengthMismatch();
error InputLengthMismatch();

/// @notice emitted when an inheriting contract does not support an action
error UnsupportedAction(uint256 action);
Expand All @@ -30,7 +30,7 @@ abstract contract BaseActionsRouter is SafeCallback {
(uint256[] calldata actions, bytes[] calldata params) = data.decodeActionsRouterParams();

uint256 numActions = actions.length;
if (numActions != params.length) revert LengthMismatch();
if (numActions != params.length) revert InputLengthMismatch();

for (uint256 actionIndex = 0; actionIndex < numActions; actionIndex++) {
uint256 action = actions[actionIndex];
Expand All @@ -49,6 +49,6 @@ abstract contract BaseActionsRouter is SafeCallback {
/// @dev The other context functions, _msgData and _msgValue, are not supported by this contract
/// In many contracts this will be the address that calls the initial entry point that calls `_executeActions`
/// `msg.sender` shouldnt be used, as this will be the v4 pool manager contract that calls `unlockCallback`
/// If using ReentrancyLock.sol, this function can return Locker.get() - locker of the contract
/// If using ReentrancyLock.sol, this function can return _getLocker()
function _msgSender() internal view virtual returns (address);
}
3 changes: 3 additions & 0 deletions src/base/DeltaResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {ImmutableState} from "./ImmutableState.sol";
/// @notice Abstract contract used to sync, send, and settle funds to the pool manager
/// @dev Note that sync() is called before any erc-20 transfer in `settle`.
abstract contract DeltaResolver is ImmutableState {
/// @notice Emitted trying to settle a positive delta, or take a negative delta
error InvalidDeltaForAction();

/// @notice Take an amount of currency out of the PoolManager
/// @param currency Currency to take
/// @param recipient Address to receive the currency
Expand Down
51 changes: 51 additions & 0 deletions src/interfaces/IV4Router.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {PathKey} from "../libraries/PathKey.sol";

/// @title IV4Router
/// @notice Interface containing all the structs and errors for different v4 swap types
interface IV4Router {
/// @notice Emitted when an exactInput swap does not receive its minAmountOut
error TooLittleReceived();
/// @notice Emitted when an exactOutput is asked for more than its maxAmountIn
error TooMuchRequested();

/// @notice Parameters for a single-hop exact-input swap
struct ExactInputSingleParams {
PoolKey poolKey;
bool zeroForOne;
uint128 amountIn;
uint128 amountOutMinimum;
uint160 sqrtPriceLimitX96;
bytes hookData;
}

/// @notice Parameters for a multi-hop exact-input swap
struct ExactInputParams {
Currency currencyIn;
PathKey[] path;
uint128 amountIn;
uint128 amountOutMinimum;
}

/// @notice Parameters for a single-hop exact-output swap
struct ExactOutputSingleParams {
PoolKey poolKey;
bool zeroForOne;
uint128 amountOut;
uint128 amountInMaximum;
uint160 sqrtPriceLimitX96;
bytes hookData;
}

/// @notice Parameters for a multi-hop exact-output swap
struct ExactOutputParams {
Currency currencyOut;
PathKey[] path;
uint128 amountOut;
uint128 amountInMaximum;
}
}
24 changes: 16 additions & 8 deletions src/libraries/Actions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,25 @@ pragma solidity ^0.8.24;
/// @dev These are suggested common commands, however additional commands should be defined as required
library Actions {
// pool actions
uint256 constant SWAP = 0x00;
uint256 constant INCREASE_LIQUIDITY = 0x01;
uint256 constant DECREASE_LIQUIDITY = 0x02;
uint256 constant DONATE = 0x03;
uint256 constant INCREASE_LIQUIDITY = 0x00;
uint256 constant DECREASE_LIQUIDITY = 0x01;
uint256 constant SWAP_EXACT_IN_SINGLE = 0x02;
uint256 constant SWAP_EXACT_IN = 0x03;
uint256 constant SWAP_EXACT_OUT_SINGLE = 0x04;
uint256 constant SWAP_EXACT_OUT = 0x05;
uint256 constant DONATE = 0x06;

// closing deltas on the pool manager
uint256 constant SETTLE = 0x10;
uint256 constant TAKE = 0x11;
uint256 constant CLOSE_CURRENCY = 0x12;
uint256 constant CLOSE_PAIR = 0x13;
uint256 constant CLEAR = 0x14;
uint256 constant SETTLE_ALL = 0x11;

uint256 constant TAKE = 0x12;
uint256 constant TAKE_ALL = 0x13;
uint256 constant TAKE_PORTION = 0x14;

uint256 constant CLOSE_CURRENCY = 0x15;
uint256 constant CLOSE_PAIR = 0x16;
uint256 constant CLEAR = 0x17;

// minting/burning 6909s to close deltas
uint256 constant MINT_6909 = 0x20;
Expand Down
6 changes: 3 additions & 3 deletions src/libraries/PathKey.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ library PathKeyLib {
pure
returns (PoolKey memory poolKey, bool zeroForOne)
{
(Currency currency0, Currency currency1) = currencyIn < params.intermediateCurrency
? (currencyIn, params.intermediateCurrency)
: (params.intermediateCurrency, currencyIn);
Currency currencyOut = params.intermediateCurrency;
(Currency currency0, Currency currency1) =
currencyIn < currencyOut ? (currencyIn, currencyOut) : (currencyOut, currencyIn);

zeroForOne = currencyIn == currency0;
poolKey = PoolKey(currency0, currency1, params.fee, params.tickSpacing, params.hooks);
Expand Down
20 changes: 20 additions & 0 deletions src/libraries/SafeCast.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import {CustomRevert} from "@uniswap/v4-core/src/libraries/CustomRevert.sol";

/// @title Safe casting methods
/// @notice Contains methods for safely casting between types
library SafeCast {
using CustomRevert for bytes4;

error SafeCastOverflow();

/// @notice Cast a int128 to a uint128, revert on overflow or underflow
/// @param x The int128 to be casted
/// @return y The casted integer, now type uint128
function toUint128(int128 x) internal pure returns (uint128 y) {
if (x < 0) SafeCastOverflow.selector.revertWith();
y = uint128(x);
}
}
Loading

0 comments on commit de79c94

Please sign in to comment.