Merge pull request #92 from propeller-heads/router/hr/ENG-4280-gas-test

test: add GasTest to compare with Universal Router gas usage
This commit is contained in:
Harsh Vardhan Roy
2025-03-05 21:35:45 +05:30
committed by GitHub
5 changed files with 410 additions and 14 deletions

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.24;
interface IUniversalRouter {
/// @notice Thrown when a required command has failed
error ExecutionFailed(uint256 commandIndex, bytes message);
/// @notice Thrown when attempting to send ETH directly to the contract
error ETHNotAccepted();
/// @notice Thrown when executing commands with an expired deadline
error TransactionDeadlinePassed();
/// @notice Thrown when attempting to execute commands and an incorrect number of inputs are provided
error LengthMismatch();
// @notice Thrown when an address that isn't WETH tries to send ETH to the router without calldata
error InvalidEthSender();
/// @notice Executes encoded commands along with provided inputs. Reverts if deadline has expired.
/// @param commands A set of concatenated commands, each 1 byte in length
/// @param inputs An array of byte strings containing abi encoded inputs for each command
/// @param deadline The deadline by which the transaction must be executed
function execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline) external payable;
}

View File

@@ -7,7 +7,7 @@ contract BaseConstants {
address BASE_USDC = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913; address BASE_USDC = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
address BASE_MAG7 = 0x9E6A46f294bB67c20F1D1E7AfB0bBEf614403B55; address BASE_MAG7 = 0x9E6A46f294bB67c20F1D1E7AfB0bBEf614403B55;
// uniswap v2 // Uniswap v2
address USDC_MAG7_POOL = 0x739c2431670A12E2cF8e11E3603eB96e6728a789; address USDC_MAG7_POOL = 0x739c2431670A12E2cF8e11E3603eB96e6728a789;
} }
@@ -40,17 +40,23 @@ contract Constants is Test, BaseConstants {
address USDT_ADDR = address(0xdAC17F958D2ee523a2206206994597C13D831ec7); address USDT_ADDR = address(0xdAC17F958D2ee523a2206206994597C13D831ec7);
address PEPE_ADDR = address(0x6982508145454Ce325dDbE47a25d4ec3d2311933); address PEPE_ADDR = address(0x6982508145454Ce325dDbE47a25d4ec3d2311933);
// uniswap v2 // Uniswap v2
address WETH_DAI_POOL = 0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11; address WETH_DAI_POOL = 0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11;
address DAI_USDC_POOL = 0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5; address DAI_USDC_POOL = 0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5;
address WETH_WBTC_POOL = 0xBb2b8038a1640196FbE3e38816F3e67Cba72D940; address WETH_WBTC_POOL = 0xBb2b8038a1640196FbE3e38816F3e67Cba72D940;
address USDC_WBTC_POOL = 0x004375Dff511095CC5A197A54140a24eFEF3A416; address USDC_WBTC_POOL = 0x004375Dff511095CC5A197A54140a24eFEF3A416;
// uniswap v3 // Uniswap v3
address USV3_FACTORY_ETHEREUM = 0x1F98431c8aD98523631AE4a59f267346ea31F984; address USV3_FACTORY_ETHEREUM = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
address USV2_FACTORY_ETHEREUM = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; address USV2_FACTORY_ETHEREUM = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
address DAI_WETH_USV3 = 0xC2e9F25Be6257c210d7Adf0D4Cd6E3E881ba25f8; address DAI_WETH_USV3 = 0xC2e9F25Be6257c210d7Adf0D4Cd6E3E881ba25f8;
// Uniswap universal router
address UNIVERSAL_ROUTER = 0x66a9893cC07D91D95644AEDD05D03f95e1dBA8Af;
// Permit2
address PERMIT2_ADDRESS = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
/** /**
* @dev Deploys a dummy contract with non-empty bytecode * @dev Deploys a dummy contract with non-empty bytecode
*/ */

232
foundry/test/GasTest.t.sol Normal file
View File

@@ -0,0 +1,232 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.24;
import {IUniversalRouter} from "../interfaces/IUniversalRouter.sol";
import {IPermit2} from "../lib/permit2/src/interfaces/IPermit2.sol";
import {Constants} from "./Constants.sol";
import {Actions} from "../lib/v4-periphery/src/libraries/Actions.sol";
import {PoolKey} from "../lib/v4-core/src/types/PoolKey.sol";
import {IV4Router} from "../lib/v4-periphery/src/interfaces/IV4Router.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Currency} from "../lib/v4-core/src/types/Currency.sol";
import {IHooks} from "../lib/v4-core/src/interfaces/IHooks.sol";
import "forge-std/Test.sol";
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
contract Commands {
uint256 constant V2_SWAP_EXACT_IN = 0x08;
uint256 constant V3_SWAP_EXACT_IN = 0x00;
uint256 constant V4_SWAP = 0x10;
uint256 constant PERMIT2_PERMIT = 0x0a;
}
// A gas test to compare the gas usage of the UniversalRouter with the TychoRouter
contract GasTest is Commands, Test, Constants {
IUniversalRouter universalRouter = IUniversalRouter(UNIVERSAL_ROUTER);
IPermit2 permit2 = IPermit2(PERMIT2_ADDRESS);
function setUp() public {
uint256 forkBlock = 21817316;
vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock);
}
function testUniversalRouterUniswapV2() public {
bool isPermit2 = false;
uint256 amountIn = 10 ** 18;
bytes memory commands =
abi.encodePacked(uint8(Commands.V2_SWAP_EXACT_IN));
address[] memory path = new address[](2);
path[0] = WETH_ADDR;
path[1] = DAI_ADDR;
bytes[] memory inputs = new bytes[](1);
inputs[0] = abi.encode(BOB, amountIn, uint256(0), path, isPermit2);
deal(WETH_ADDR, address(universalRouter), amountIn);
universalRouter.execute(commands, inputs, block.timestamp + 1000);
}
function testUniversalRouterUniswapV2Permit2() public {
bool isPermit2 = true;
uint256 amountIn = 10 ** 18;
bytes memory commands = abi.encodePacked(
uint8(Commands.PERMIT2_PERMIT), uint8(Commands.V2_SWAP_EXACT_IN)
);
vm.startPrank(ALICE);
(
IAllowanceTransfer.PermitSingle memory permitSingle,
bytes memory signature
) = handlePermit2Approval(WETH_ADDR, amountIn);
address[] memory path = new address[](2);
path[0] = WETH_ADDR;
path[1] = DAI_ADDR;
bytes[] memory inputs = new bytes[](2);
inputs[0] = abi.encode(permitSingle, signature);
inputs[1] = abi.encode(ALICE, amountIn, uint256(0), path, isPermit2);
deal(WETH_ADDR, ALICE, amountIn);
universalRouter.execute(commands, inputs, block.timestamp + 1000);
}
function testUniversalRouterUniswapV3() public {
bool isPermit2 = false;
uint256 amountIn = 10 ** 18;
bytes memory commands =
abi.encodePacked(uint8(Commands.V3_SWAP_EXACT_IN));
uint24 poolFee = 3000;
bytes memory path = abi.encodePacked(WETH_ADDR, poolFee, DAI_ADDR);
bytes[] memory inputs = new bytes[](1);
inputs[0] = abi.encode(BOB, amountIn, uint256(0), path, isPermit2);
deal(WETH_ADDR, address(universalRouter), amountIn);
universalRouter.execute(commands, inputs, block.timestamp + 1000);
}
function testUniversalRouterUniswapV3Permit2() public {
bool isPermit2 = true;
uint256 amountIn = 10 ** 18;
bytes memory commands = abi.encodePacked(
uint8(Commands.PERMIT2_PERMIT), uint8(Commands.V3_SWAP_EXACT_IN)
);
vm.startPrank(ALICE);
(
IAllowanceTransfer.PermitSingle memory permitSingle,
bytes memory signature
) = handlePermit2Approval(WETH_ADDR, amountIn);
uint24 poolFee = 3000;
bytes memory path = abi.encodePacked(WETH_ADDR, poolFee, DAI_ADDR);
bytes[] memory inputs = new bytes[](2);
inputs[0] = abi.encode(permitSingle, signature);
inputs[1] = abi.encode(ALICE, amountIn, uint256(0), path, isPermit2);
deal(WETH_ADDR, ALICE, amountIn);
universalRouter.execute(commands, inputs, block.timestamp + 1000);
}
function testUniversalRouterUniswapV4Permit2() public {
uint128 amountIn = uint128(100 ether);
uint128 amountOutMinimum = uint128(0);
uint256 deadline = block.timestamp + 1000;
bytes memory commands = abi.encodePacked(
uint8(Commands.PERMIT2_PERMIT), uint8(Commands.V4_SWAP)
);
bytes memory actions = abi.encodePacked(
uint8(Actions.SWAP_EXACT_IN_SINGLE),
uint8(Actions.SETTLE_ALL),
uint8(Actions.TAKE_ALL)
);
vm.startPrank(ALICE);
(
IAllowanceTransfer.PermitSingle memory permitSingle,
bytes memory signature
) = handlePermit2Approval(USDE_ADDR, amountIn);
PoolKey memory key = PoolKey({
currency0: Currency.wrap(USDE_ADDR),
currency1: Currency.wrap(USDT_ADDR),
fee: 100,
tickSpacing: int24(1),
hooks: IHooks(address(0))
});
bytes[] memory params = new bytes[](3);
params[0] = abi.encode(
IV4Router.ExactInputSingleParams({
poolKey: key,
zeroForOne: true,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum,
hookData: bytes("")
})
);
params[1] = abi.encode(key.currency0, amountIn);
params[2] = abi.encode(key.currency1, amountOutMinimum);
bytes[] memory inputs = new bytes[](2);
inputs[0] = abi.encode(permitSingle, signature);
inputs[1] = abi.encode(actions, params);
deal(USDE_ADDR, ALICE, amountIn);
universalRouter.execute(commands, inputs, deadline);
}
function handlePermit2Approval(address tokenIn, uint256 amount_in)
internal
returns (IAllowanceTransfer.PermitSingle memory, bytes memory)
{
IERC20(tokenIn).approve(PERMIT2_ADDRESS, amount_in);
IAllowanceTransfer.PermitSingle memory permitSingle = IAllowanceTransfer
.PermitSingle({
details: IAllowanceTransfer.PermitDetails({
token: tokenIn,
amount: uint160(amount_in),
expiration: uint48(block.timestamp + 1 days),
nonce: 0
}),
spender: UNIVERSAL_ROUTER,
sigDeadline: block.timestamp + 1 days
});
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
return (permitSingle, signature);
}
function signPermit2(
IAllowanceTransfer.PermitSingle memory permit,
uint256 privateKey
) internal view returns (bytes memory) {
bytes32 _PERMIT_DETAILS_TYPEHASH = keccak256(
"PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)"
);
bytes32 _PERMIT_SINGLE_TYPEHASH = keccak256(
"PermitSingle(PermitDetails details,address spender,uint256 sigDeadline)PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)"
);
bytes32 domainSeparator = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,uint256 chainId,address verifyingContract)"
),
keccak256("Permit2"),
block.chainid,
PERMIT2_ADDRESS
)
);
bytes32 detailsHash =
keccak256(abi.encode(_PERMIT_DETAILS_TYPEHASH, permit.details));
bytes32 permitHash = keccak256(
abi.encode(
_PERMIT_SINGLE_TYPEHASH,
detailsHash,
permit.spender,
permit.sigDeadline
)
);
bytes32 digest =
keccak256(abi.encodePacked("\x19\x01", domainSeparator, permitHash));
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest);
return abi.encodePacked(r, s, v);
}
}

View File

@@ -231,6 +231,50 @@ contract TychoRouterTest is TychoRouterTestSetup {
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
} }
function testSwapSimplePermit2() public {
// Trade 1 WETH for DAI with 1 swap on Uniswap V2 using Permit2
// 1 WETH -> DAI
// (USV2)
vm.startPrank(ALICE);
uint256 amountIn = 1 ether;
deal(WETH_ADDR, ALICE, amountIn);
(
IAllowanceTransfer.PermitSingle memory permitSingle,
bytes memory signature
) = handlePermit2Approval(WETH_ADDR, amountIn);
bytes memory protocolData = encodeUniswapV2Swap(
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
);
bytes memory swap = encodeSwap(
uint8(0), uint8(1), uint24(0), address(usv2Executor), protocolData
);
bytes[] memory swaps = new bytes[](1);
swaps[0] = swap;
tychoRouter.swapPermit2(
amountIn,
WETH_ADDR,
DAI_ADDR,
0,
false,
false,
2,
ALICE,
permitSingle,
signature,
pleEncode(swaps)
);
uint256 daiBalance = IERC20(DAI_ADDR).balanceOf(ALICE);
assertEq(daiBalance, 2659881924818443699787);
assertEq(IERC20(WETH_ADDR).balanceOf(ALICE), 0);
vm.stopPrank();
}
function testSwapMultipleHops() public { function testSwapMultipleHops() public {
// Trade 1 WETH for USDC through DAI with 2 swaps on Uniswap V2 // Trade 1 WETH for USDC through DAI with 2 swaps on Uniswap V2
// 1 WETH -> DAI -> USDC // 1 WETH -> DAI -> USDC
@@ -633,6 +677,50 @@ contract TychoRouterTest is TychoRouterTestSetup {
assertGe(finalBalance, expAmountOut); assertGe(finalBalance, expAmountOut);
} }
function testSwapSingleUSV3Permit2() public {
// Trade 1 WETH for DAI with 1 swap on Uniswap V3 using Permit2
// 1 WETH -> DAI
// (USV3)
vm.startPrank(ALICE);
uint256 amountIn = 10 ** 18;
deal(WETH_ADDR, ALICE, amountIn);
(
IAllowanceTransfer.PermitSingle memory permitSingle,
bytes memory signature
) = handlePermit2Approval(WETH_ADDR, amountIn);
uint256 expAmountOut = 1205_128428842122129186; //Swap 1 WETH for 1205.12 DAI
bool zeroForOne = false;
bytes memory protocolData = encodeUniswapV3Swap(
WETH_ADDR, DAI_ADDR, tychoRouterAddr, DAI_WETH_USV3, zeroForOne
);
bytes memory swap = encodeSwap(
uint8(0), uint8(1), uint24(0), address(usv3Executor), protocolData
);
bytes[] memory swaps = new bytes[](1);
swaps[0] = swap;
tychoRouter.swapPermit2(
amountIn,
WETH_ADDR,
DAI_ADDR,
0,
false,
false,
2,
ALICE,
permitSingle,
signature,
pleEncode(swaps)
);
uint256 finalBalance = IERC20(DAI_ADDR).balanceOf(ALICE);
assertGe(finalBalance, expAmountOut);
vm.stopPrank();
}
function testEmptySwapsRevert() public { function testEmptySwapsRevert() public {
uint256 amountIn = 10 ** 18; uint256 amountIn = 10 ** 18;
bytes memory swaps = ""; bytes memory swaps = "";
@@ -650,7 +738,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
// Approve permit2 // Approve permit2
vm.startPrank(ALICE); vm.startPrank(ALICE);
IERC20(WETH_ADDR).approve(address(permit2Address), type(uint256).max); IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
// Encoded solution generated using `test_split_swap_strategy_encoder_simple` // Encoded solution generated using `test_split_swap_strategy_encoder_simple`
// but manually replacing the executor address // but manually replacing the executor address
// `5c2f5a71f67c01775180adc06909288b4c329308` with the one in this test // `5c2f5a71f67c01775180adc06909288b4c329308` with the one in this test
@@ -688,7 +776,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
assertEq(balancerAfter - balancerBefore, 2659881924818443699787); assertEq(balancerAfter - balancerBefore, 2659881924818443699787);
} }
function testUSV4Integration4() public { function testUSV4Integration() public {
// Test created with calldata from our router encoder. // Test created with calldata from our router encoder.
// Performs a sequential swap from USDC to PEPE though ETH using two // Performs a sequential swap from USDC to PEPE though ETH using two
@@ -701,7 +789,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
// Approve permit2 // Approve permit2
vm.startPrank(ALICE); vm.startPrank(ALICE);
IERC20(USDC_ADDR).approve(address(permit2Address), type(uint256).max); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
// Encoded solution generated using `test_split_encoding_strategy_usv4` // Encoded solution generated using `test_split_encoding_strategy_usv4`
// and ensuring that the encoded executor address is the one in this test // and ensuring that the encoded executor address is the one in this test
// `f62849f9a0b5bf2913b396098f7c7019b51a820a` // `f62849f9a0b5bf2913b396098f7c7019b51a820a`
@@ -754,7 +842,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
// Approve permit2 // Approve permit2
vm.startPrank(ALICE); vm.startPrank(ALICE);
IERC20(USDC_ADDR).approve(address(permit2Address), type(uint256).max); IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
// Encoded solution generated using `test_split_encoding_strategy_usv4_eth_out` // Encoded solution generated using `test_split_encoding_strategy_usv4_eth_out`
// and ensuring that the encoded executor address is the one in this test // and ensuring that the encoded executor address is the one in this test
@@ -783,7 +871,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
// Approve permit2 // Approve permit2
vm.startPrank(ALICE); vm.startPrank(ALICE);
// IERC20(WETH_ADDR).approve(address(permit2Address), type(uint256).max); // IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
// Encoded solution generated using // Encoded solution generated using
// `test_split_swap_strategy_encoder_simple_route_wrap` // `test_split_swap_strategy_encoder_simple_route_wrap`
// but manually replacing the executor address // but manually replacing the executor address
@@ -812,7 +900,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
// Approve permit2 // Approve permit2
vm.startPrank(ALICE); vm.startPrank(ALICE);
IERC20(DAI_ADDR).approve(address(permit2Address), type(uint256).max); IERC20(DAI_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
// Encoded solution generated using // Encoded solution generated using
// `test_split_swap_strategy_encoder_simple_route_unwrap` // `test_split_swap_strategy_encoder_simple_route_unwrap`
// but manually replacing the executor address // but manually replacing the executor address
@@ -844,7 +932,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
// Approve permit2 // Approve permit2
vm.startPrank(ALICE); vm.startPrank(ALICE);
IERC20(WETH_ADDR).approve(address(permit2Address), type(uint256).max); IERC20(WETH_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
// Encoded solution generated using `test_split_swap_strategy_encoder_complex` // Encoded solution generated using `test_split_swap_strategy_encoder_complex`
// but manually replacing the executor address // but manually replacing the executor address
// `5c2f5a71f67c01775180adc06909288b4c329308` with the one in this test // `5c2f5a71f67c01775180adc06909288b4c329308` with the one in this test
@@ -946,6 +1034,52 @@ contract TychoRouterTest is TychoRouterTestSetup {
assertEq(IERC20(USDT_ADDR).balanceOf(tychoRouterAddr), 99943852); assertEq(IERC20(USDT_ADDR).balanceOf(tychoRouterAddr), 99943852);
} }
function testSwapSingleUSV4CallbackPermit2() public {
vm.startPrank(ALICE);
uint256 amountIn = 100 ether;
deal(USDE_ADDR, ALICE, amountIn);
(
IAllowanceTransfer.PermitSingle memory permitSingle,
bytes memory signature
) = handlePermit2Approval(USDE_ADDR, amountIn);
UniswapV4Executor.UniswapV4Pool[] memory pools =
new UniswapV4Executor.UniswapV4Pool[](1);
pools[0] = UniswapV4Executor.UniswapV4Pool({
intermediaryToken: USDT_ADDR,
fee: uint24(100),
tickSpacing: int24(1)
});
bytes memory protocolData = UniswapV4Utils.encodeExactInput(
USDE_ADDR, USDT_ADDR, true, address(usv4Executor), pools
);
bytes memory swap = encodeSwap(
uint8(0), uint8(1), uint24(0), address(usv4Executor), protocolData
);
bytes[] memory swaps = new bytes[](1);
swaps[0] = swap;
tychoRouter.swapPermit2(
amountIn,
USDE_ADDR,
USDT_ADDR,
0,
false,
false,
2,
ALICE,
permitSingle,
signature,
pleEncode(swaps)
);
assertEq(IERC20(USDT_ADDR).balanceOf(ALICE), 99943852);
vm.stopPrank();
}
function testSwapMultipleUSV4Callback() public { function testSwapMultipleUSV4Callback() public {
// This test has two uniswap v4 hops that will be executed inside of the V4 pool manager // This test has two uniswap v4 hops that will be executed inside of the V4 pool manager
// USDE -> USDT -> WBTC // USDE -> USDT -> WBTC

View File

@@ -34,7 +34,6 @@ contract TychoRouterExposed is TychoRouter {
contract TychoRouterTestSetup is Test, Constants { contract TychoRouterTestSetup is Test, Constants {
TychoRouterExposed tychoRouter; TychoRouterExposed tychoRouter;
address tychoRouterAddr; address tychoRouterAddr;
address permit2Address = address(0x000000000022D473030F116dDEE9F6B43aC78BA3);
UniswapV2Executor public usv2Executor; UniswapV2Executor public usv2Executor;
UniswapV3Executor public usv3Executor; UniswapV3Executor public usv3Executor;
UniswapV4Executor public usv4Executor; UniswapV4Executor public usv4Executor;
@@ -49,7 +48,7 @@ contract TychoRouterTestSetup is Test, Constants {
address factoryV2 = USV2_FACTORY_ETHEREUM; address factoryV2 = USV2_FACTORY_ETHEREUM;
address poolManagerAddress = 0x000000000004444c5dc75cB358380D2e3dE08A90; address poolManagerAddress = 0x000000000004444c5dc75cB358380D2e3dE08A90;
IPoolManager poolManager = IPoolManager(poolManagerAddress); IPoolManager poolManager = IPoolManager(poolManagerAddress);
tychoRouter = new TychoRouterExposed(permit2Address, WETH_ADDR); tychoRouter = new TychoRouterExposed(PERMIT2_ADDRESS, WETH_ADDR);
tychoRouterAddr = address(tychoRouter); tychoRouterAddr = address(tychoRouter);
tychoRouter.grantRole(keccak256("FUND_RESCUER_ROLE"), FUND_RESCUER); tychoRouter.grantRole(keccak256("FUND_RESCUER_ROLE"), FUND_RESCUER);
tychoRouter.grantRole(keccak256("FEE_SETTER_ROLE"), FEE_SETTER); tychoRouter.grantRole(keccak256("FEE_SETTER_ROLE"), FEE_SETTER);
@@ -108,7 +107,7 @@ contract TychoRouterTestSetup is Test, Constants {
internal internal
returns (IAllowanceTransfer.PermitSingle memory, bytes memory) returns (IAllowanceTransfer.PermitSingle memory, bytes memory)
{ {
IERC20(tokenIn).approve(permit2Address, amount_in); IERC20(tokenIn).approve(PERMIT2_ADDRESS, amount_in);
IAllowanceTransfer.PermitSingle memory permitSingle = IAllowanceTransfer IAllowanceTransfer.PermitSingle memory permitSingle = IAllowanceTransfer
.PermitSingle({ .PermitSingle({
details: IAllowanceTransfer.PermitDetails({ details: IAllowanceTransfer.PermitDetails({
@@ -148,7 +147,7 @@ contract TychoRouterTestSetup is Test, Constants {
), ),
keccak256("Permit2"), keccak256("Permit2"),
block.chainid, block.chainid,
permit2Address PERMIT2_ADDRESS
) )
); );
bytes32 detailsHash = bytes32 detailsHash =