Skip to content

Commit

Permalink
Merge branch 'udpate_to_new_ur' into ur-v4
Browse files Browse the repository at this point in the history
  • Loading branch information
ewilz committed Sep 19, 2024
2 parents 6ca09e4 + 99ea1dd commit cfa4443
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 94 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/trufflehog.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
name: Trufflehog

on:
push:
branches:
- main
pull_request:
types:
- opened
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@

# dependencies
node_modules

# Intellij IDEA artifacts
.idea/
13 changes: 11 additions & 2 deletions sdks/router-sdk/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@ export const ADDRESS_THIS = '0x0000000000000000000000000000000000000002'
export const ZERO = JSBI.BigInt(0)
export const ONE = JSBI.BigInt(1)

// = 1 << 23 or 100000000000000000000000
export const V2_FEE_PATH_PLACEHOLDER = 8388608
// = 1 << 23 or 0b0100000000000000000000000
export const MIXED_QUOTER_V1_V2_FEE_PATH_PLACEHOLDER = 1 << 23

// = 10 << 4 or 0b00100000
export const MIXED_QUOTER_V2_V2_FEE_PATH_PLACEHOLDER = 2 << 4

// = 11 << 20 or 0b001100000000000000000000
export const MIXED_QUOTER_V2_V3_FEE_PATH_PLACEHOLDER = 3 << 20

// = 100 << 20 or 0b010000000000000000000000
export const MIXED_QUOTER_V2_V4_FEE_PATH_PLACEHOLDER = 4 << 20

export const ZERO_PERCENT = new Percent(ZERO)
export const ONE_HUNDRED_PERCENT = new Percent(100, 100)
37 changes: 33 additions & 4 deletions sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ describe('#encodeMixedRouteToPath', () => {
const pool_V3_1_weth = new V3Pool(token1, weth, FeeAmount.MEDIUM, encodeSqrtRatioX96(1, 1), 0, 0, [])

const pool_V4_0_1 = new V4Pool(token0, token1, FeeAmount.MEDIUM, 30, ADDRESS_ZERO, encodeSqrtRatioX96(1, 1), 0, 0, [])
const pool_V4_0_eth = new V4Pool(
token0,
ETHER,
FeeAmount.MEDIUM,
30,
ADDRESS_ZERO,
encodeSqrtRatioX96(1, 1),
0,
0,
[]
)

const pair_0_1 = new Pair(CurrencyAmount.fromRawAmount(token0, '100'), CurrencyAmount.fromRawAmount(token1, '200'))
const pair_1_2 = new Pair(CurrencyAmount.fromRawAmount(token1, '150'), CurrencyAmount.fromRawAmount(token2, '150'))
Expand Down Expand Up @@ -47,6 +58,8 @@ describe('#encodeMixedRouteToPath', () => {
const route_0_V3_weth_V2_1_V2_2 = new MixedRouteSDK([pool_V3_0_weth, pair_1_weth, pair_1_2], token0, token2)
const route_0_V3_1_v3_weth_V2_2 = new MixedRouteSDK([pool_V3_0_1_medium, pool_V3_1_weth, pair_2_weth], token0, token2)
const route_0_V3_weth_V4_1 = new MixedRouteSDK([pool_V3_0_weth, pool_V4_0_1], ETHER, token1)
const route_eth_V4_0_V3_1 = new MixedRouteSDK([pool_V4_0_eth, pool_V3_0_1_medium], ETHER, token1)
const route_eth_V3_0_V4_1 = new MixedRouteSDK([pool_V3_0_weth, pool_V4_0_1], ETHER, token1)

describe('pure V3', () => {
it('packs them for exact input single hop', () => {
Expand Down Expand Up @@ -87,8 +100,10 @@ describe('#encodeMixedRouteToPath', () => {
})

describe('pure v4', () => {
it('throws if MixedRouteSDK is a pure v4 route', () => {
expect(() => encodeMixedRouteToPath(route_0_V4_1)).toThrow('Encoding mixed routes with V4 not supported')
it('packs them for exact input single hop', () => {
expect(encodeMixedRouteToPath(route_0_V4_1)).toEqual(
'0x0000000000000000000000000000000000000001400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000002'
)
})
})

Expand Down Expand Up @@ -149,8 +164,22 @@ describe('#encodeMixedRouteToPath', () => {
)
})

it('throws if it contains a v4 pool', () => {
expect(() => encodeMixedRouteToPath(route_0_V3_weth_V4_1)).toThrow('Encoding mixed routes with V4 not supported')
it('packs them for exact input v3 -> v4', () => {
expect(encodeMixedRouteToPath(route_0_V3_weth_V4_1)).toEqual(
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2300bb80000000000000000000000000000000000000001400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000002'
)
})

it('packs them for exact input native eth v4 -> v3', () => {
expect(encodeMixedRouteToPath(route_eth_V4_0_V3_1)).toEqual(
'0x0000000000000000000000000000000000000000400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001300bb80000000000000000000000000000000000000002'
)
})

it('packs them for exact input native eth v3 -> v4', () => {
expect(encodeMixedRouteToPath(route_eth_V3_0_V4_1)).toEqual(
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2300bb80000000000000000000000000000000000000001400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000002'
)
})
})
})
110 changes: 81 additions & 29 deletions sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { pack } from '@ethersproject/solidity'
import { Currency } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { Pool as V3Pool } from '@uniswap/v3-sdk'
import { Pool as V4Pool } from '@uniswap/v4-sdk'
import {
ADDRESS_ZERO,
MIXED_QUOTER_V2_V2_FEE_PATH_PLACEHOLDER,
MIXED_QUOTER_V2_V3_FEE_PATH_PLACEHOLDER,
MIXED_QUOTER_V2_V4_FEE_PATH_PLACEHOLDER,
MIXED_QUOTER_V1_V2_FEE_PATH_PLACEHOLDER,
} from '../constants'
import { MixedRouteSDK } from '../entities/mixedRoute/route'
import { V2_FEE_PATH_PLACEHOLDER } from '../constants'
import { TPool } from './TPool'

/**
Expand All @@ -13,36 +20,81 @@ import { TPool } from './TPool'
* @returns the exactIn encoded path
*/
export function encodeMixedRouteToPath(route: MixedRouteSDK<Currency, Currency>): string {
const firstInputToken: Currency = route.input.wrapped

const { path, types } = route.pools.reduce(
(
{ inputToken, path, types }: { inputToken: Currency; path: (string | number)[]; types: string[] },
pool: TPool,
index
): { inputToken: Currency; path: (string | number)[]; types: string[] } => {
if (pool instanceof V4Pool) throw 'Encoding mixed routes with V4 not supported'
const outputToken: Currency = pool.token0.equals(inputToken) ? pool.token1 : pool.token0
if (index === 0) {
return {
inputToken: outputToken,
types: ['address', 'uint24', 'address'],
path: [
inputToken.wrapped.address,
pool instanceof V3Pool ? pool.fee : V2_FEE_PATH_PLACEHOLDER,
outputToken.wrapped.address,
],
}
const containsV4Pool = route.pools.some((pool) => pool instanceof V4Pool)

let path: (string | number)[]
let types: string[]

if (containsV4Pool) {
path = [route.adjustedInput.isNative ? ADDRESS_ZERO : route.adjustedInput.address]
types = ['address']
let currencyIn = route.adjustedInput

for (const pool of route.pools) {
const currencyOut = currencyIn.equals(pool.token0) ? pool.token1 : pool.token0

if (pool instanceof V4Pool) {
const v4Fee = pool.fee + MIXED_QUOTER_V2_V4_FEE_PATH_PLACEHOLDER
path.push(
v4Fee,
pool.tickSpacing,
pool.hooks,
currencyOut.isNative ? ADDRESS_ZERO : currencyOut.wrapped.address
)
types.push('uint24', 'uint24', 'address', 'address')
} else if (pool instanceof V3Pool) {
const v3Fee = pool.fee + MIXED_QUOTER_V2_V3_FEE_PATH_PLACEHOLDER
path.push(v3Fee, currencyOut.wrapped.address)
types.push('uint24', 'address')
} else if (pool instanceof Pair) {
const v2Fee = MIXED_QUOTER_V2_V2_FEE_PATH_PLACEHOLDER
path.push(v2Fee, currencyOut.wrapped.address)
types.push('uint8', 'address')
} else {
return {
inputToken: outputToken,
types: [...types, 'uint24', 'address'],
path: [...path, pool instanceof V3Pool ? pool.fee : V2_FEE_PATH_PLACEHOLDER, outputToken.wrapped.address],
}
throw new Error(`Unsupported pool type ${JSON.stringify(pool)}`)
}
},
{ inputToken: firstInputToken, path: [], types: [] }
)

currencyIn = currencyOut
}
} else {
// TODO: ROUTE-276 - delete this else block
// We introduced this else block as a safety measure to prevent non-v4 mixed routes from potentially regressing
// We'd like to gain more confidence in the new implementation before removing this block
const result = route.pools.reduce(
(
{ inputToken, path, types }: { inputToken: Currency; path: (string | number)[]; types: string[] },
pool: TPool,
index
): { inputToken: Currency; path: (string | number)[]; types: string[] } => {
const outputToken: Currency = pool.token0.equals(inputToken) ? pool.token1 : pool.token0
if (index === 0) {
return {
inputToken: outputToken,
types: ['address', 'uint24', 'address'],
path: [
inputToken.wrapped.address,
pool instanceof V3Pool ? pool.fee : MIXED_QUOTER_V1_V2_FEE_PATH_PLACEHOLDER,
outputToken.wrapped.address,
],
}
} else {
return {
inputToken: outputToken,
types: [...types, 'uint24', 'address'],
path: [
...path,
pool instanceof V3Pool ? pool.fee : MIXED_QUOTER_V1_V2_FEE_PATH_PLACEHOLDER,
outputToken.wrapped.address,
],
}
}
},
{ inputToken: route.input, path: [], types: [] }
)

path = result.path
types = result.types
}

return pack(types, path)
}
3 changes: 3 additions & 0 deletions sdks/sdk-core/src/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type ChainAddresses = {
tickLensAddress?: string
swapRouter02Address?: string
mixedRouteQuoterV1Address?: string
mixedRouteQuoterV2Address?: string
}

const DEFAULT_NETWORKS = [ChainId.MAINNET, ChainId.GOERLI, ChainId.SEPOLIA]
Expand Down Expand Up @@ -162,6 +163,8 @@ const SEPOLIA_ADDRESSES: ChainAddresses = {
nonfungiblePositionManagerAddress: '0x1238536071E1c677A632429e3655c799b22cDA52',
tickLensAddress: '0xd7f33bcdb21b359c8ee6f0251d30e94832baad07',
swapRouter02Address: '0x3bFA4769FB09eefC5a80d6E87c3B9C650f7Ae48E',
// TODO: ROUTE-277 - update deploy address once after quoter refactoring.
mixedRouteQuoterV2Address: '0xa8b0be287acB850952DE4287b84B7222cc654C09',
}

// Avalanche v3 addresses
Expand Down
2 changes: 1 addition & 1 deletion sdks/universal-router-sdk/lib/permit2
Submodule permit2 updated 41 files
+1 −1 .forge-snapshots/batchTransferFrom.snap
+1 −1 .forge-snapshots/batchTransferFromMultiToken.snap
+1 −0 .forge-snapshots/permit2 + transferFrom2 with WETH9's mainnet address.snap
+1 −0 .forge-snapshots/permit2 + transferFrom2 with a non EIP-2612 native token with fallback.snap
+1 −1 .forge-snapshots/permit2 + transferFrom2 with a non EIP-2612 native token.snap
+1 −1 .forge-snapshots/permit2 + transferFrom2 with an EIP-2612 native token.snap
+1 −0 .forge-snapshots/simplePermit2 + transferFrom2 with a non EIP-2612 native token.snap
+113 −103 .gas-snapshot
+17 −3 README.md
+1 −1 lib/forge-std
+16 −0 package.json
+1 −1 src/AllowanceTransfer.sol
+4 −2 src/EIP712.sol
+9 −4 src/interfaces/IAllowanceTransfer.sol
+1 −1 src/interfaces/IDAIPermit.sol
+6 −0 src/interfaces/IEIP712.sol
+1 −1 src/interfaces/IERC1271.sol
+11 −0 src/interfaces/IPermit2.sol
+4 −2 src/interfaces/ISignatureTransfer.sol
+64 −32 src/libraries/Permit2Lib.sol
+5 −5 test/AllowanceTransferInvariants.t.sol
+3 −3 test/AllowanceTransferTest.t.sol
+3 −2 test/AllowanceUnitTest.sol
+2 −2 test/CompactSignature.t.sol
+1 −1 test/EIP712.t.sol
+1 −1 test/NonceBitmap.t.sol
+187 −2 test/Permit2Lib.t.sol
+1 −1 test/SignatureTransfer.t.sol
+1 −1 test/TypehashGeneration.t.sol
+3 −1 test/actors/Permitter.sol
+1 −1 test/integration/Argent.t.sol
+1 −1 test/integration/GnosisSafe.t.sol
+1 −1 test/integration/MainnetToken.t.sol
+118 −0 test/mocks/MockFallbackERC20.sol
+0 −2 test/mocks/MockHash.sol
+33 −11 test/mocks/MockPermit2Lib.sol
+23 −0 test/utils/DeployPermit2.sol
+81 −0 test/utils/DeployPermit2.t.sol
+0 −36 test/utils/InvariantTest.sol
+13 −12 test/utils/PermitSignature.sol
+1 −1 test/utils/TokenProvider.sol
2 changes: 1 addition & 1 deletion sdks/universal-router-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"@uniswap/permit2-sdk": "^1.3.0",
"@uniswap/router-sdk": "^1.11.2",
"@uniswap/sdk-core": "^5.3.1",
"@uniswap/universal-router": "1.6.0",
"@uniswap/universal-router": "2.0.0-beta.1",
"@uniswap/v2-sdk": "^4.4.1",
"@uniswap/v3-sdk": "^3.13.1",
"@uniswap/v4-sdk": "^1.2.0",
Expand Down
2 changes: 0 additions & 2 deletions sdks/universal-router-sdk/remappings.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
@ensdomains/=node_modules/@uniswap/universal-router/node_modules/@ensdomains/
@openzeppelin/=lib/openzeppelin-contracts/
@uniswap/=node_modules/@uniswap/
base64-sol/=node_modules/base64-sol/
ds-test/=lib/forge-std/lib/ds-test/src/
forge-std/=lib/forge-std/src/
Expand Down
36 changes: 7 additions & 29 deletions sdks/universal-router-sdk/test/forge/utils/DeployRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,14 @@ import {Permit2} from "permit2/src/Permit2.sol";
import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol";

contract DeployRouter is Test {
address public constant LOOKS_TOKEN = 0xf4d2888d29D722226FafA5d9B24F9164c092421E;
address public constant V2_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
address public constant V3_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
bytes32 public constant PAIR_INIT_CODE_HASH = 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;
bytes32 public constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
address public constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant SEAPORT_V1_5 = 0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC;
address public constant SEAPORT_V1_4 = 0x00000000000001ad428e4906aE43D8F9852d0dD6;
address public constant NFTX_ZAP = 0x941A6d105802CCCaa06DE58a13a6F49ebDCD481C;
address public constant X2Y2 = 0x74312363e45DCaBA76c59ec49a7Aa8A65a67EeD3;
address public constant FOUNDATION = 0xcDA72070E455bb31C7690a170224Ce43623d0B6f;
address public constant SUDOSWAP = 0x2B2e8cDA09bBA9660dCA5cB6233787738Ad68329;
address public constant NFT20_ZAP = 0xA42f6cADa809Bcf417DeefbdD69C5C5A909249C0;
address public constant CRYPTOPUNKS = 0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB;
address public constant LOOKS_RARE_V2 = 0x0000000000E655fAe4d56241588680F86E3b2377;
address public constant ROUTER_REWARDS_DISTRIBUTOR = 0x0000000000000000000000000000000000000000;
address public constant LOOKSRARE_REWARDS_DISTRIBUTOR = 0x0554f068365eD43dcC98dcd7Fd7A8208a5638C72;
address public constant OPENSEA_CONDUIT = 0x1E0049783F008A0085193E00003D00cd54003c71;
address public constant ELEMENT_MARKET = 0x20F780A973856B93f63670377900C1d2a50a77c4;
address public constant V4_POOL_MANAGER_PLACEHOLDER = 0x4444444444444444444444444444444444444444;
address public constant V4_POSITION_MANAGER_PLACEHOLDER = 0x4444444444444444400000000000000000000000;
address public constant V3_POSITION_MANAGER = 0xC36442b4a4522E871399CD717aBDD847Ab11FE88;

address internal constant RECIPIENT = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa;
address internal constant FEE_RECIPIENT = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;
Expand All @@ -48,24 +37,13 @@ contract DeployRouter is Test {
RouterParameters({
permit2: _permit2,
weth9: WETH9,
seaportV1_5: SEAPORT_V1_5,
seaportV1_4: SEAPORT_V1_4,
openseaConduit: OPENSEA_CONDUIT,
nftxZap: NFTX_ZAP,
x2y2: X2Y2,
foundation: FOUNDATION,
sudoswap: SUDOSWAP,
elementMarket: ELEMENT_MARKET,
nft20Zap: NFT20_ZAP,
cryptopunks: CRYPTOPUNKS,
looksRareV2: LOOKS_RARE_V2,
routerRewardsDistributor: ROUTER_REWARDS_DISTRIBUTOR,
looksRareRewardsDistributor: LOOKSRARE_REWARDS_DISTRIBUTOR,
looksRareToken: LOOKS_TOKEN,
v2Factory: V2_FACTORY,
v3Factory: V3_FACTORY,
pairInitCodeHash: PAIR_INIT_CODE_HASH,
poolInitCodeHash: POOL_INIT_CODE_HASH
poolInitCodeHash: POOL_INIT_CODE_HASH,
v4PoolManager: V4_POOL_MANAGER_PLACEHOLDER,
v3NFTPositionManager: V3_POSITION_MANAGER,
v4PositionManager: V4_POSITION_MANAGER_PLACEHOLDER
})
);
}
Expand Down
13 changes: 0 additions & 13 deletions sdks/universal-router-sdk/test/forge/utils/ICryptopunksMarket.sol

This file was deleted.

6 changes: 6 additions & 0 deletions sdks/v3-sdk/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export function poolInitCodeHash(chainId?: ChainId): string {
*/
export enum FeeAmount {
LOWEST = 100,
LOW_200 = 200,
LOW_300 = 300,
LOW_400 = 400,
LOW = 500,
MEDIUM = 3000,
HIGH = 10000,
Expand All @@ -31,6 +34,9 @@ export enum FeeAmount {
*/
export const TICK_SPACINGS: { [amount in FeeAmount]: number } = {
[FeeAmount.LOWEST]: 1,
[FeeAmount.LOW_200]: 4,
[FeeAmount.LOW_300]: 6,
[FeeAmount.LOW_400]: 8,
[FeeAmount.LOW]: 10,
[FeeAmount.MEDIUM]: 60,
[FeeAmount.HIGH]: 200,
Expand Down
Loading

0 comments on commit cfa4443

Please sign in to comment.