refactor: create Permit2TestHelper
- To avoid duplicating permit2 setup code for TychoRouter and executor tests.
This commit is contained in:
committed by
Diana Carvalho
parent
ca1d474f08
commit
30557e7e54
@@ -4,7 +4,6 @@ pragma solidity ^0.8.26;
|
|||||||
import "@interfaces/IExecutor.sol";
|
import "@interfaces/IExecutor.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
|
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
|
||||||
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
|
|
||||||
|
|
||||||
error ExecutorTransferMethods__InvalidPermit2();
|
error ExecutorTransferMethods__InvalidPermit2();
|
||||||
|
|
||||||
@@ -45,10 +44,7 @@ contract ExecutorTransferMethods {
|
|||||||
} else if (method == TransferMethod.TRANSFERPERMIT2) {
|
} else if (method == TransferMethod.TRANSFERPERMIT2) {
|
||||||
// Permit2.permit is already called from the TychoRouter
|
// Permit2.permit is already called from the TychoRouter
|
||||||
permit2.transferFrom(
|
permit2.transferFrom(
|
||||||
sender,
|
sender, receiver, uint160(amount), address(tokenIn)
|
||||||
receiver,
|
|
||||||
uint160(amount),
|
|
||||||
address(tokenIn)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Funds are likely already in pool. Do nothing.
|
// Funds are likely already in pool. Do nothing.
|
||||||
|
|||||||
87
foundry/test/Permit2TestHelper.sol
Normal file
87
foundry/test/Permit2TestHelper.sol
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// SPDX-License-Identifier: BUSL-1.1
|
||||||
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
|
import "./Constants.sol";
|
||||||
|
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
|
contract Permit2TestHelper is Constants {
|
||||||
|
/**
|
||||||
|
* @dev Handles the Permit2 approval process for Alice, allowing the TychoRouter contract
|
||||||
|
* to spend `amount_in` of `tokenIn` on her behalf.
|
||||||
|
*
|
||||||
|
* This function approves the Permit2 contract to transfer the specified token amount
|
||||||
|
* and constructs a `PermitSingle` struct for the approval. It also generates a valid
|
||||||
|
* EIP-712 signature for the approval using Alice's private key.
|
||||||
|
*
|
||||||
|
* @param tokenIn The address of the token being approved.
|
||||||
|
* @param amount_in The amount of tokens to approve for transfer.
|
||||||
|
* @return permitSingle The `PermitSingle` struct containing the approval details.
|
||||||
|
* @return signature The EIP-712 signature for the approval.
|
||||||
|
*/
|
||||||
|
function handlePermit2Approval(
|
||||||
|
address tokenIn,
|
||||||
|
address spender,
|
||||||
|
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: spender,
|
||||||
|
sigDeadline: block.timestamp + 1 days
|
||||||
|
});
|
||||||
|
|
||||||
|
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
|
||||||
|
return (permitSingle, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Signs a Permit2 `PermitSingle` struct with the given private key.
|
||||||
|
* @param permit The `PermitSingle` struct to sign.
|
||||||
|
* @param privateKey The private key of the signer.
|
||||||
|
* @return The signature as a `bytes` array.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes[] memory swaps = _getSequentialSwaps();
|
bytes[] memory swaps = _getSequentialSwaps();
|
||||||
tychoRouter.sequentialSwapPermit2(
|
tychoRouter.sequentialSwapPermit2(
|
||||||
@@ -150,7 +150,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes[] memory swaps = _getSequentialSwaps();
|
bytes[] memory swaps = _getSequentialSwaps();
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(USDC_ADDR, amountIn);
|
) = handlePermit2Approval(USDC_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes[] memory swaps = new bytes[](2);
|
bytes[] memory swaps = new bytes[](2);
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes memory protocolData = encodeUniswapV2Swap(
|
bytes memory protocolData = encodeUniswapV2Swap(
|
||||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||||
@@ -230,7 +230,7 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(DAI_ADDR, amountIn);
|
) = handlePermit2Approval(DAI_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes memory protocolData =
|
bytes memory protocolData =
|
||||||
encodeUniswapV2Swap(DAI_ADDR, WETH_DAI_POOL, tychoRouterAddr, true);
|
encodeUniswapV2Swap(DAI_ADDR, WETH_DAI_POOL, tychoRouterAddr, true);
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes[] memory swaps = _getSplitSwaps();
|
bytes[] memory swaps = _getSplitSwaps();
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes[] memory swaps = _getSplitSwaps();
|
bytes[] memory swaps = _getSplitSwaps();
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(DAI_ADDR, amountIn);
|
) = handlePermit2Approval(DAI_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes memory protocolData =
|
bytes memory protocolData =
|
||||||
encodeUniswapV2Swap(DAI_ADDR, WETH_DAI_POOL, tychoRouterAddr, true);
|
encodeUniswapV2Swap(DAI_ADDR, WETH_DAI_POOL, tychoRouterAddr, true);
|
||||||
@@ -325,7 +325,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
uint256 expAmountOut = 1205_128428842122129186; //Swap 1 WETH for 1205.12 DAI
|
uint256 expAmountOut = 1205_128428842122129186; //Swap 1 WETH for 1205.12 DAI
|
||||||
bool zeroForOne = false;
|
bool zeroForOne = false;
|
||||||
@@ -377,7 +377,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(WETH_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
bytes memory protocolData = encodeUniswapV2Swap(
|
bytes memory protocolData = encodeUniswapV2Swap(
|
||||||
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false
|
||||||
@@ -426,7 +426,7 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(USDE_ADDR, amountIn);
|
) = handlePermit2Approval(USDE_ADDR, tychoRouterAddr, amountIn);
|
||||||
|
|
||||||
UniswapV4Executor.UniswapV4Pool[] memory pools =
|
UniswapV4Executor.UniswapV4Pool[] memory pools =
|
||||||
new UniswapV4Executor.UniswapV4Pool[](1);
|
new UniswapV4Executor.UniswapV4Pool[](1);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import "@src/TychoRouter.sol";
|
|||||||
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
||||||
import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol";
|
import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol";
|
||||||
import {WETH} from "../lib/permit2/lib/solmate/src/tokens/WETH.sol";
|
import {WETH} from "../lib/permit2/lib/solmate/src/tokens/WETH.sol";
|
||||||
|
import {Permit2TestHelper} from "./Permit2TestHelper.sol";
|
||||||
|
|
||||||
contract TychoRouterExposed is TychoRouter {
|
contract TychoRouterExposed is TychoRouter {
|
||||||
constructor(address _permit2, address weth) TychoRouter(_permit2, weth) {}
|
constructor(address _permit2, address weth) TychoRouter(_permit2, weth) {}
|
||||||
@@ -41,7 +42,7 @@ contract TychoRouterExposed is TychoRouter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TychoRouterTestSetup is Constants {
|
contract TychoRouterTestSetup is Constants, Permit2TestHelper {
|
||||||
TychoRouterExposed tychoRouter;
|
TychoRouterExposed tychoRouter;
|
||||||
address tychoRouterAddr;
|
address tychoRouterAddr;
|
||||||
UniswapV2Executor public usv2Executor;
|
UniswapV2Executor public usv2Executor;
|
||||||
@@ -132,84 +133,6 @@ contract TychoRouterTestSetup is Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Handles the Permit2 approval process for Alice, allowing the TychoRouter contract
|
|
||||||
* to spend `amount_in` of `tokenIn` on her behalf.
|
|
||||||
*
|
|
||||||
* This function approves the Permit2 contract to transfer the specified token amount
|
|
||||||
* and constructs a `PermitSingle` struct for the approval. It also generates a valid
|
|
||||||
* EIP-712 signature for the approval using Alice's private key.
|
|
||||||
*
|
|
||||||
* @param tokenIn The address of the token being approved.
|
|
||||||
* @param amount_in The amount of tokens to approve for transfer.
|
|
||||||
* @return permitSingle The `PermitSingle` struct containing the approval details.
|
|
||||||
* @return signature The EIP-712 signature for the approval.
|
|
||||||
*/
|
|
||||||
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: tychoRouterAddr,
|
|
||||||
sigDeadline: block.timestamp + 1 days
|
|
||||||
});
|
|
||||||
|
|
||||||
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
|
|
||||||
return (permitSingle, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Signs a Permit2 `PermitSingle` struct with the given private key.
|
|
||||||
* @param permit The `PermitSingle` struct to sign.
|
|
||||||
* @param privateKey The private key of the signer.
|
|
||||||
* @return The signature as a `bytes` array.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
function pleEncode(bytes[] memory data)
|
function pleEncode(bytes[] memory data)
|
||||||
public
|
public
|
||||||
pure
|
pure
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import "@src/executors/UniswapV2Executor.sol";
|
|||||||
import "@src/executors/ExecutorTransferMethods.sol";
|
import "@src/executors/ExecutorTransferMethods.sol";
|
||||||
import {Test} from "../../lib/forge-std/src/Test.sol";
|
import {Test} from "../../lib/forge-std/src/Test.sol";
|
||||||
import {Constants} from "../Constants.sol";
|
import {Constants} from "../Constants.sol";
|
||||||
|
import {Permit2TestHelper} from "../Permit2TestHelper.sol";
|
||||||
|
|
||||||
contract UniswapV2ExecutorExposed is UniswapV2Executor {
|
contract UniswapV2ExecutorExposed is UniswapV2Executor {
|
||||||
constructor(address _factory, bytes32 _initCode, address _permit2)
|
constructor(address _factory, bytes32 _initCode, address _permit2)
|
||||||
@@ -48,7 +49,7 @@ contract FakeUniswapV2Pool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract UniswapV2ExecutorTest is Test, Constants {
|
contract UniswapV2ExecutorTest is Test, Constants, Permit2TestHelper {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
UniswapV2ExecutorExposed uniswapV2Exposed;
|
UniswapV2ExecutorExposed uniswapV2Exposed;
|
||||||
@@ -188,86 +189,6 @@ contract UniswapV2ExecutorTest is Test, Constants {
|
|||||||
assertGe(finalBalance, amountOut);
|
assertGe(finalBalance, amountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO generalize these next two methods - don't reuse from TychoRouterTestSetup
|
|
||||||
/**
|
|
||||||
* @dev Handles the Permit2 approval process for Alice, allowing the TychoRouter contract
|
|
||||||
* to spend `amount_in` of `tokenIn` on her behalf.
|
|
||||||
*
|
|
||||||
* This function approves the Permit2 contract to transfer the specified token amount
|
|
||||||
* and constructs a `PermitSingle` struct for the approval. It also generates a valid
|
|
||||||
* EIP-712 signature for the approval using Alice's private key.
|
|
||||||
*
|
|
||||||
* @param tokenIn The address of the token being approved.
|
|
||||||
* @param amount_in The amount of tokens to approve for transfer.
|
|
||||||
* @return permitSingle The `PermitSingle` struct containing the approval details.
|
|
||||||
* @return signature The EIP-712 signature for the approval.
|
|
||||||
*/
|
|
||||||
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: address(uniswapV2Exposed),
|
|
||||||
sigDeadline: block.timestamp + 1 days
|
|
||||||
});
|
|
||||||
|
|
||||||
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
|
|
||||||
return (permitSingle, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Signs a Permit2 `PermitSingle` struct with the given private key.
|
|
||||||
* @param permit The `PermitSingle` struct to sign.
|
|
||||||
* @param privateKey The private key of the signer.
|
|
||||||
* @return The signature as a `bytes` array.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testSwapWithPermit2TransferFrom() public {
|
function testSwapWithPermit2TransferFrom() public {
|
||||||
uint256 amountIn = 10 ** 18;
|
uint256 amountIn = 10 ** 18;
|
||||||
uint256 amountOut = 1847751195973566072891;
|
uint256 amountOut = 1847751195973566072891;
|
||||||
@@ -280,13 +201,14 @@ contract UniswapV2ExecutorTest is Test, Constants {
|
|||||||
uint8(ExecutorTransferMethods.TransferMethod.TRANSFERPERMIT2)
|
uint8(ExecutorTransferMethods.TransferMethod.TRANSFERPERMIT2)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
deal(WETH_ADDR, ALICE, amountIn);
|
deal(WETH_ADDR, ALICE, amountIn);
|
||||||
vm.startPrank(ALICE);
|
vm.startPrank(ALICE);
|
||||||
(
|
(
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle,
|
IAllowanceTransfer.PermitSingle memory permitSingle,
|
||||||
bytes memory signature
|
bytes memory signature
|
||||||
) = handlePermit2Approval(WETH_ADDR, amountIn);
|
) = handlePermit2Approval(
|
||||||
|
WETH_ADDR, address(uniswapV2Exposed), amountIn
|
||||||
|
);
|
||||||
|
|
||||||
// Assume the permit2.approve method will be called from the TychoRouter
|
// Assume the permit2.approve method will be called from the TychoRouter
|
||||||
// Replicate this secnario in this test.
|
// Replicate this secnario in this test.
|
||||||
|
|||||||
Reference in New Issue
Block a user