Merge pull request #281 from propeller-heads/dc/ENG-4804-tycho-encoder-send-sync
fix: Make TychoEncode Send + Sync
This commit is contained in:
@@ -93,9 +93,7 @@ contract TychoRouter is
|
|||||||
address indexed token, uint256 amount, address indexed receiver
|
address indexed token, uint256 amount, address indexed receiver
|
||||||
);
|
);
|
||||||
|
|
||||||
constructor(address _permit2, address weth)
|
constructor(address _permit2, address weth) RestrictTransferFrom(_permit2) {
|
||||||
RestrictTransferFrom(_permit2)
|
|
||||||
{
|
|
||||||
if (_permit2 == address(0) || weth == address(0)) {
|
if (_permit2 == address(0) || weth == address(0)) {
|
||||||
revert TychoRouter__AddressZero();
|
revert TychoRouter__AddressZero();
|
||||||
}
|
}
|
||||||
@@ -808,6 +806,7 @@ contract TychoRouter is
|
|||||||
/**
|
/**
|
||||||
* @dev Gets balance of a token for a given address. Supports both native ETH and ERC20 tokens.
|
* @dev Gets balance of a token for a given address. Supports both native ETH and ERC20 tokens.
|
||||||
*/
|
*/
|
||||||
|
// forgefmt: disable-start
|
||||||
function _balanceOf(address token, address owner)
|
function _balanceOf(address token, address owner)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
@@ -815,7 +814,7 @@ contract TychoRouter is
|
|||||||
{
|
{
|
||||||
return
|
return
|
||||||
token == address(0) ? owner.balance : IERC20(token).balanceOf(owner);
|
token == address(0) ? owner.balance : IERC20(token).balanceOf(owner);
|
||||||
}
|
}// forgefmt: disable-end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Verifies that the expected amount of output tokens was received by the receiver.
|
* @dev Verifies that the expected amount of output tokens was received by the receiver.
|
||||||
|
|||||||
@@ -43,7 +43,12 @@ contract BalancerV3Executor is IExecutor, RestrictTransferFrom, ICallback {
|
|||||||
calculatedAmount = abi.decode(abi.decode(result, (bytes)), (uint256));
|
calculatedAmount = abi.decode(abi.decode(result, (bytes)), (uint256));
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyCallback(bytes calldata /*data*/ ) public view {
|
function verifyCallback(
|
||||||
|
bytes calldata /*data*/
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
{
|
||||||
if (msg.sender != address(VAULT)) {
|
if (msg.sender != address(VAULT)) {
|
||||||
revert BalancerV3Executor__SenderIsNotVault(msg.sender);
|
revert BalancerV3Executor__SenderIsNotVault(msg.sender);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ contract BebopExecutor is IExecutor, RestrictTransferFrom {
|
|||||||
constructor(address _bebopSettlement, address _permit2)
|
constructor(address _bebopSettlement, address _permit2)
|
||||||
RestrictTransferFrom(_permit2)
|
RestrictTransferFrom(_permit2)
|
||||||
{
|
{
|
||||||
if (_bebopSettlement == address(0)) revert BebopExecutor__ZeroAddress();
|
if (_bebopSettlement == address(0)) {
|
||||||
|
revert BebopExecutor__ZeroAddress();
|
||||||
|
}
|
||||||
bebopSettlement = _bebopSettlement;
|
bebopSettlement = _bebopSettlement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ contract CurveExecutor is IExecutor, RestrictTransferFrom {
|
|||||||
payable
|
payable
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
if (data.length != 85) revert CurveExecutor__InvalidDataLength();
|
if (data.length != 85) {
|
||||||
|
revert CurveExecutor__InvalidDataLength();
|
||||||
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
@@ -91,13 +93,15 @@ contract CurveExecutor is IExecutor, RestrictTransferFrom {
|
|||||||
// crypto or llamma
|
// crypto or llamma
|
||||||
if (tokenIn == nativeToken || tokenOut == nativeToken) {
|
if (tokenIn == nativeToken || tokenOut == nativeToken) {
|
||||||
// slither-disable-next-line arbitrary-send-eth
|
// slither-disable-next-line arbitrary-send-eth
|
||||||
CryptoPoolETH(pool).exchange{value: ethAmount}(
|
CryptoPoolETH(pool)
|
||||||
uint256(int256(i)), uint256(int256(j)), amountIn, 0, true
|
.exchange{
|
||||||
);
|
value: ethAmount
|
||||||
|
}(uint256(int256(i)), uint256(int256(j)), amountIn, 0, true);
|
||||||
} else {
|
} else {
|
||||||
CryptoPool(pool).exchange(
|
CryptoPool(pool)
|
||||||
uint256(int256(i)), uint256(int256(j)), amountIn, 0
|
.exchange(
|
||||||
);
|
uint256(int256(i)), uint256(int256(j)), amountIn, 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,11 +153,7 @@ contract CurveExecutor is IExecutor, RestrictTransferFrom {
|
|||||||
require(msg.sender.code.length != 0);
|
require(msg.sender.code.length != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _balanceOf(address token)
|
function _balanceOf(address token) internal view returns (uint256 balance) {
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (uint256 balance)
|
|
||||||
{
|
|
||||||
balance = token == nativeToken
|
balance = token == nativeToken
|
||||||
? address(this).balance
|
? address(this).balance
|
||||||
: IERC20(token).balanceOf(address(this));
|
: IERC20(token).balanceOf(address(this));
|
||||||
|
|||||||
@@ -102,15 +102,18 @@ contract EkuboExecutor is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function payCallback(uint256, address /*token*/ ) external coreOnly {
|
function payCallback(
|
||||||
|
uint256,
|
||||||
|
address /*token*/
|
||||||
|
)
|
||||||
|
external
|
||||||
|
coreOnly
|
||||||
|
{
|
||||||
// Without selector and locker id
|
// Without selector and locker id
|
||||||
_payCallback(msg.data[36:]);
|
_payCallback(msg.data[36:]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _lock(bytes memory data)
|
function _lock(bytes memory data) internal returns (uint128 swappedAmount) {
|
||||||
internal
|
|
||||||
returns (uint128 swappedAmount)
|
|
||||||
{
|
|
||||||
address target = address(core);
|
address target = address(core);
|
||||||
|
|
||||||
// slither-disable-next-line assembly
|
// slither-disable-next-line assembly
|
||||||
|
|||||||
@@ -67,9 +67,8 @@ contract HashflowExecutor is IExecutor, RestrictTransferFrom {
|
|||||||
|
|
||||||
if (approvalNeeded && quote.baseToken != NATIVE_TOKEN) {
|
if (approvalNeeded && quote.baseToken != NATIVE_TOKEN) {
|
||||||
// slither-disable-next-line unused-return
|
// slither-disable-next-line unused-return
|
||||||
IERC20(quote.baseToken).forceApprove(
|
IERC20(quote.baseToken)
|
||||||
hashflowRouter, type(uint256).max
|
.forceApprove(hashflowRouter, type(uint256).max);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 ethValue = 0;
|
uint256 ethValue = 0;
|
||||||
|
|||||||
@@ -42,13 +42,13 @@ contract MaverickV2Executor is IExecutor, RestrictTransferFrom {
|
|||||||
|
|
||||||
bool isTokenAIn = pool.tokenA() == tokenIn;
|
bool isTokenAIn = pool.tokenA() == tokenIn;
|
||||||
int32 tickLimit = isTokenAIn ? type(int32).max : type(int32).min;
|
int32 tickLimit = isTokenAIn ? type(int32).max : type(int32).min;
|
||||||
IMaverickV2Pool.SwapParams memory swapParams = IMaverickV2Pool
|
IMaverickV2Pool.SwapParams memory swapParams =
|
||||||
.SwapParams({
|
IMaverickV2Pool.SwapParams({
|
||||||
amount: givenAmount,
|
amount: givenAmount,
|
||||||
tokenAIn: isTokenAIn,
|
tokenAIn: isTokenAIn,
|
||||||
exactOutput: false,
|
exactOutput: false,
|
||||||
tickLimit: tickLimit
|
tickLimit: tickLimit
|
||||||
});
|
});
|
||||||
|
|
||||||
_transfer(target, transferType, address(tokenIn), givenAmount);
|
_transfer(target, transferType, address(tokenIn), givenAmount);
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,9 @@ contract UniswapV3Executor is IExecutor, ICallback, RestrictTransferFrom {
|
|||||||
int256, /* amount0Delta */
|
int256, /* amount0Delta */
|
||||||
int256, /* amount1Delta */
|
int256, /* amount1Delta */
|
||||||
bytes calldata /* data */
|
bytes calldata /* data */
|
||||||
) external {
|
)
|
||||||
|
external
|
||||||
|
{
|
||||||
handleCallback(msg.data);
|
handleCallback(msg.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,23 @@ import {
|
|||||||
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
|
||||||
import {SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol";
|
import {SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol";
|
||||||
import {
|
import {
|
||||||
Currency, CurrencyLibrary
|
Currency,
|
||||||
|
CurrencyLibrary
|
||||||
} from "@uniswap/v4-core/src/types/Currency.sol";
|
} from "@uniswap/v4-core/src/types/Currency.sol";
|
||||||
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
|
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
|
||||||
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
|
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
|
||||||
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
|
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
|
||||||
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
|
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
|
||||||
import {PathKey} from "@uniswap/v4-periphery/src/libraries/PathKey.sol";
|
import {PathKey} from "@uniswap/v4-periphery/src/libraries/PathKey.sol";
|
||||||
import {IUnlockCallback} from
|
import {
|
||||||
"@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
|
IUnlockCallback
|
||||||
import {SafeCast as V4SafeCast} from
|
} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
|
||||||
"@uniswap/v4-core/src/libraries/SafeCast.sol";
|
import {
|
||||||
import {TransientStateLibrary} from
|
SafeCast as V4SafeCast
|
||||||
"@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";
|
} from "@uniswap/v4-core/src/libraries/SafeCast.sol";
|
||||||
|
import {
|
||||||
|
TransientStateLibrary
|
||||||
|
} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";
|
||||||
import "../RestrictTransferFrom.sol";
|
import "../RestrictTransferFrom.sol";
|
||||||
import "@openzeppelin/contracts/utils/Address.sol";
|
import "@openzeppelin/contracts/utils/Address.sol";
|
||||||
import "../../lib/bytes/LibPrefixLengthEncodedByteArray.sol";
|
import "../../lib/bytes/LibPrefixLengthEncodedByteArray.sol";
|
||||||
@@ -115,7 +119,9 @@ contract UniswapV4Executor is
|
|||||||
PathKey[] memory path = new PathKey[](pools.length);
|
PathKey[] memory path = new PathKey[](pools.length);
|
||||||
for (uint256 i = 0; i < pools.length; i++) {
|
for (uint256 i = 0; i < pools.length; i++) {
|
||||||
path[i] = PathKey({
|
path[i] = PathKey({
|
||||||
intermediateCurrency: Currency.wrap(pools[i].intermediaryToken),
|
intermediateCurrency: Currency.wrap(
|
||||||
|
pools[i].intermediaryToken
|
||||||
|
),
|
||||||
fee: pools[i].fee,
|
fee: pools[i].fee,
|
||||||
tickSpacing: pools[i].tickSpacing,
|
tickSpacing: pools[i].tickSpacing,
|
||||||
hooks: IHooks(pools[i].hook),
|
hooks: IHooks(pools[i].hook),
|
||||||
@@ -305,8 +311,8 @@ contract UniswapV4Executor is
|
|||||||
Currency currencyIn = zeroForOne ? poolKey.currency0 : poolKey.currency1;
|
Currency currencyIn = zeroForOne ? poolKey.currency0 : poolKey.currency1;
|
||||||
_settle(currencyIn, amountIn, transferType);
|
_settle(currencyIn, amountIn, transferType);
|
||||||
uint128 amountOut = _swap(
|
uint128 amountOut = _swap(
|
||||||
poolKey, zeroForOne, -int256(uint256(amountIn)), hookData
|
poolKey, zeroForOne, -int256(uint256(amountIn)), hookData
|
||||||
).toUint128();
|
).toUint128();
|
||||||
|
|
||||||
Currency currencyOut =
|
Currency currencyOut =
|
||||||
zeroForOne ? poolKey.currency1 : poolKey.currency0;
|
zeroForOne ? poolKey.currency1 : poolKey.currency0;
|
||||||
@@ -343,11 +349,11 @@ contract UniswapV4Executor is
|
|||||||
pathKey.getPoolAndSwapDirection(swapCurrencyIn);
|
pathKey.getPoolAndSwapDirection(swapCurrencyIn);
|
||||||
// The output delta will always be positive, except for when interacting with certain hook pools
|
// The output delta will always be positive, except for when interacting with certain hook pools
|
||||||
amountOut = _swap(
|
amountOut = _swap(
|
||||||
poolKey,
|
poolKey,
|
||||||
zeroForOne,
|
zeroForOne,
|
||||||
-int256(uint256(swapAmountIn)),
|
-int256(uint256(swapAmountIn)),
|
||||||
pathKey.hookData
|
pathKey.hookData
|
||||||
).toUint128();
|
).toUint128();
|
||||||
|
|
||||||
swapAmountIn = amountOut;
|
swapAmountIn = amountOut;
|
||||||
swapCurrencyIn = pathKey.intermediateCurrency;
|
swapCurrencyIn = pathKey.intermediateCurrency;
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ contract UniswapXFiller is AccessControl, IReactorCallback {
|
|||||||
address _reactor,
|
address _reactor,
|
||||||
address _native_address
|
address _native_address
|
||||||
) {
|
) {
|
||||||
if (_tychoRouter == address(0)) revert UniswapXFiller__AddressZero();
|
if (_tychoRouter == address(0)) {
|
||||||
|
revert UniswapXFiller__AddressZero();
|
||||||
|
}
|
||||||
if (_reactor == address(0)) revert UniswapXFiller__AddressZero();
|
if (_reactor == address(0)) revert UniswapXFiller__AddressZero();
|
||||||
|
|
||||||
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
||||||
@@ -73,9 +75,8 @@ contract UniswapXFiller is AccessControl, IReactorCallback {
|
|||||||
// The TychoRouter will take the input tokens from the filler
|
// The TychoRouter will take the input tokens from the filler
|
||||||
if (tokenInApprovalNeeded) {
|
if (tokenInApprovalNeeded) {
|
||||||
// Native ETH input is not supported by UniswapX
|
// Native ETH input is not supported by UniswapX
|
||||||
IERC20(order.input.token).forceApprove(
|
IERC20(order.input.token)
|
||||||
tychoRouter, type(uint256).max
|
.forceApprove(tychoRouter, type(uint256).max);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// slither-disable-next-line low-level-calls
|
// slither-disable-next-line low-level-calls
|
||||||
@@ -125,7 +126,9 @@ contract UniswapXFiller is AccessControl, IReactorCallback {
|
|||||||
external
|
external
|
||||||
onlyRole(DEFAULT_ADMIN_ROLE)
|
onlyRole(DEFAULT_ADMIN_ROLE)
|
||||||
{
|
{
|
||||||
if (receiver == address(0)) revert UniswapXFiller__AddressZero();
|
if (receiver == address(0)) {
|
||||||
|
revert UniswapXFiller__AddressZero();
|
||||||
|
}
|
||||||
|
|
||||||
for (uint256 i = 0; i < tokens.length; i++) {
|
for (uint256 i = 0; i < tokens.length; i++) {
|
||||||
// slither-disable-next-line calls-loop
|
// slither-disable-next-line calls-loop
|
||||||
@@ -144,7 +147,9 @@ contract UniswapXFiller is AccessControl, IReactorCallback {
|
|||||||
external
|
external
|
||||||
onlyRole(DEFAULT_ADMIN_ROLE)
|
onlyRole(DEFAULT_ADMIN_ROLE)
|
||||||
{
|
{
|
||||||
if (receiver == address(0)) revert UniswapXFiller__AddressZero();
|
if (receiver == address(0)) {
|
||||||
|
revert UniswapXFiller__AddressZero();
|
||||||
|
}
|
||||||
|
|
||||||
uint256 amount = address(this).balance;
|
uint256 amount = address(this).balance;
|
||||||
if (amount > 0) {
|
if (amount > 0) {
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ contract Constants is Test, BaseConstants {
|
|||||||
address LDO_POOL = 0x9409280DC1e6D33AB7A8C6EC03e5763FB61772B5;
|
address LDO_POOL = 0x9409280DC1e6D33AB7A8C6EC03e5763FB61772B5;
|
||||||
address CRV_POOL = 0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511;
|
address CRV_POOL = 0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511;
|
||||||
address AAVE_POOL = 0xDeBF20617708857ebe4F679508E7b7863a8A8EeE;
|
address AAVE_POOL = 0xDeBF20617708857ebe4F679508E7b7863a8A8EeE;
|
||||||
address FRAXPYUSD_POOL = address(0xA5588F7cdf560811710A2D82D3C9c99769DB1Dcb);
|
address FRAXPYUSD_POOL =
|
||||||
|
address(0xA5588F7cdf560811710A2D82D3C9c99769DB1Dcb);
|
||||||
address TRICRYPTO2_POOL = 0xD51a44d3FaE010294C616388b506AcdA1bfAAE46;
|
address TRICRYPTO2_POOL = 0xD51a44d3FaE010294C616388b506AcdA1bfAAE46;
|
||||||
address SUSD_POOL = 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD;
|
address SUSD_POOL = 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD;
|
||||||
address FRAX_USDC_POOL = 0xDcEF968d416a41Cdac0ED8702fAC8128A64241A2;
|
address FRAX_USDC_POOL = 0xDcEF968d416a41Cdac0ED8702fAC8128A64241A2;
|
||||||
|
|||||||
@@ -176,17 +176,17 @@ contract GasTest is Commands, Test, Constants {
|
|||||||
returns (IAllowanceTransfer.PermitSingle memory, bytes memory)
|
returns (IAllowanceTransfer.PermitSingle memory, bytes memory)
|
||||||
{
|
{
|
||||||
IERC20(tokenIn).approve(PERMIT2_ADDRESS, amount_in);
|
IERC20(tokenIn).approve(PERMIT2_ADDRESS, amount_in);
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle = IAllowanceTransfer
|
IAllowanceTransfer.PermitSingle memory permitSingle =
|
||||||
.PermitSingle({
|
IAllowanceTransfer.PermitSingle({
|
||||||
details: IAllowanceTransfer.PermitDetails({
|
details: IAllowanceTransfer.PermitDetails({
|
||||||
token: tokenIn,
|
token: tokenIn,
|
||||||
amount: uint160(amount_in),
|
amount: uint160(amount_in),
|
||||||
expiration: uint48(block.timestamp + 1 days),
|
expiration: uint48(block.timestamp + 1 days),
|
||||||
nonce: 0
|
nonce: 0
|
||||||
}),
|
}),
|
||||||
spender: UNIVERSAL_ROUTER,
|
spender: UNIVERSAL_ROUTER,
|
||||||
sigDeadline: block.timestamp + 1 days
|
sigDeadline: block.timestamp + 1 days
|
||||||
});
|
});
|
||||||
|
|
||||||
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
|
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
|
||||||
return (permitSingle, signature);
|
return (permitSingle, signature);
|
||||||
@@ -223,8 +223,9 @@ contract GasTest is Commands, Test, Constants {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
bytes32 digest =
|
bytes32 digest = keccak256(
|
||||||
keccak256(abi.encodePacked("\x19\x01", domainSeparator, permitHash));
|
abi.encodePacked("\x19\x01", domainSeparator, permitHash)
|
||||||
|
);
|
||||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest);
|
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest);
|
||||||
|
|
||||||
return abi.encodePacked(r, s, v);
|
return abi.encodePacked(r, s, v);
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
pragma solidity ^0.8.26;
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
import {Test} from "forge-std/Test.sol";
|
import {Test} from "forge-std/Test.sol";
|
||||||
import {LibPrefixLengthEncodedByteArray} from
|
import {
|
||||||
"../lib/bytes/LibPrefixLengthEncodedByteArray.sol";
|
LibPrefixLengthEncodedByteArray
|
||||||
|
} from "../lib/bytes/LibPrefixLengthEncodedByteArray.sol";
|
||||||
|
|
||||||
contract LibPrefixLengthEncodedByteArrayTest is Test {
|
contract LibPrefixLengthEncodedByteArrayTest is Test {
|
||||||
using LibPrefixLengthEncodedByteArray for bytes;
|
using LibPrefixLengthEncodedByteArray for bytes;
|
||||||
|
|||||||
@@ -25,17 +25,17 @@ contract Permit2TestHelper is Constants {
|
|||||||
uint256 amount_in
|
uint256 amount_in
|
||||||
) internal returns (IAllowanceTransfer.PermitSingle memory, bytes memory) {
|
) internal returns (IAllowanceTransfer.PermitSingle memory, bytes memory) {
|
||||||
IERC20(tokenIn).approve(PERMIT2_ADDRESS, amount_in);
|
IERC20(tokenIn).approve(PERMIT2_ADDRESS, amount_in);
|
||||||
IAllowanceTransfer.PermitSingle memory permitSingle = IAllowanceTransfer
|
IAllowanceTransfer.PermitSingle memory permitSingle =
|
||||||
.PermitSingle({
|
IAllowanceTransfer.PermitSingle({
|
||||||
details: IAllowanceTransfer.PermitDetails({
|
details: IAllowanceTransfer.PermitDetails({
|
||||||
token: tokenIn,
|
token: tokenIn,
|
||||||
amount: uint160(amount_in),
|
amount: uint160(amount_in),
|
||||||
expiration: uint48(block.timestamp + 1 days),
|
expiration: uint48(block.timestamp + 1 days),
|
||||||
nonce: 0
|
nonce: 0
|
||||||
}),
|
}),
|
||||||
spender: spender,
|
spender: spender,
|
||||||
sigDeadline: block.timestamp + 1 days
|
sigDeadline: block.timestamp + 1 days
|
||||||
});
|
});
|
||||||
|
|
||||||
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
|
bytes memory signature = signPermit2(permitSingle, ALICE_PK);
|
||||||
return (permitSingle, signature);
|
return (permitSingle, signature);
|
||||||
@@ -78,8 +78,9 @@ contract Permit2TestHelper is Constants {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
bytes32 digest =
|
bytes32 digest = keccak256(
|
||||||
keccak256(abi.encodePacked("\x19\x01", domainSeparator, permitHash));
|
abi.encodePacked("\x19\x01", domainSeparator, permitHash)
|
||||||
|
);
|
||||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest);
|
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest);
|
||||||
|
|
||||||
return abi.encodePacked(r, s, v);
|
return abi.encodePacked(r, s, v);
|
||||||
|
|||||||
@@ -183,16 +183,13 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
|||||||
vm.startPrank(ALICE);
|
vm.startPrank(ALICE);
|
||||||
|
|
||||||
IAllowanceTransfer.PermitSingle memory emptyPermitSingle =
|
IAllowanceTransfer.PermitSingle memory emptyPermitSingle =
|
||||||
IAllowanceTransfer.PermitSingle({
|
IAllowanceTransfer.PermitSingle({
|
||||||
details: IAllowanceTransfer.PermitDetails({
|
details: IAllowanceTransfer.PermitDetails({
|
||||||
token: address(0),
|
token: address(0), amount: 0, expiration: 0, nonce: 0
|
||||||
amount: 0,
|
}),
|
||||||
expiration: 0,
|
spender: address(0),
|
||||||
nonce: 0
|
sigDeadline: 0
|
||||||
}),
|
});
|
||||||
spender: address(0),
|
|
||||||
sigDeadline: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
bytes[] memory swaps = new bytes[](2);
|
bytes[] memory swaps = new bytes[](2);
|
||||||
// WETH -> DAI
|
// WETH -> DAI
|
||||||
@@ -219,7 +216,9 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
uint256 amountOut = tychoRouter.sequentialSwapPermit2{value: amountIn}(
|
uint256 amountOut = tychoRouter.sequentialSwapPermit2{
|
||||||
|
value: amountIn
|
||||||
|
}(
|
||||||
amountIn,
|
amountIn,
|
||||||
address(0),
|
address(0),
|
||||||
USDC_ADDR,
|
USDC_ADDR,
|
||||||
@@ -502,8 +501,9 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
|||||||
// Approve permit2
|
// Approve permit2
|
||||||
vm.startPrank(ALICE);
|
vm.startPrank(ALICE);
|
||||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||||
bytes memory callData =
|
bytes memory callData = loadCallDataFromFile(
|
||||||
loadCallDataFromFile("test_sequential_swap_strategy_encoder_unwrap");
|
"test_sequential_swap_strategy_encoder_unwrap"
|
||||||
|
);
|
||||||
(bool success,) = tychoRouterAddr.call(callData);
|
(bool success,) = tychoRouterAddr.call(callData);
|
||||||
|
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|||||||
@@ -203,16 +203,13 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
|||||||
vm.startPrank(ALICE);
|
vm.startPrank(ALICE);
|
||||||
|
|
||||||
IAllowanceTransfer.PermitSingle memory emptyPermitSingle =
|
IAllowanceTransfer.PermitSingle memory emptyPermitSingle =
|
||||||
IAllowanceTransfer.PermitSingle({
|
IAllowanceTransfer.PermitSingle({
|
||||||
details: IAllowanceTransfer.PermitDetails({
|
details: IAllowanceTransfer.PermitDetails({
|
||||||
token: address(0),
|
token: address(0), amount: 0, expiration: 0, nonce: 0
|
||||||
amount: 0,
|
}),
|
||||||
expiration: 0,
|
spender: address(0),
|
||||||
nonce: 0
|
sigDeadline: 0
|
||||||
}),
|
});
|
||||||
spender: address(0),
|
|
||||||
sigDeadline: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
bytes memory protocolData = encodeUniswapV2Swap(
|
bytes memory protocolData = encodeUniswapV2Swap(
|
||||||
WETH_ADDR,
|
WETH_ADDR,
|
||||||
@@ -225,7 +222,9 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
|||||||
bytes memory swap =
|
bytes memory swap =
|
||||||
encodeSingleSwap(address(usv2Executor), protocolData);
|
encodeSingleSwap(address(usv2Executor), protocolData);
|
||||||
|
|
||||||
uint256 amountOut = tychoRouter.singleSwapPermit2{value: amountIn}(
|
uint256 amountOut = tychoRouter.singleSwapPermit2{
|
||||||
|
value: amountIn
|
||||||
|
}(
|
||||||
amountIn,
|
amountIn,
|
||||||
address(0),
|
address(0),
|
||||||
DAI_ADDR,
|
DAI_ADDR,
|
||||||
@@ -338,8 +337,9 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup {
|
|||||||
|
|
||||||
vm.startPrank(ALICE);
|
vm.startPrank(ALICE);
|
||||||
IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
||||||
bytes memory callData =
|
bytes memory callData = loadCallDataFromFile(
|
||||||
loadCallDataFromFile("test_single_swap_strategy_encoder_no_permit2");
|
"test_single_swap_strategy_encoder_no_permit2"
|
||||||
|
);
|
||||||
(bool success,) = tychoRouterAddr.call(callData);
|
(bool success,) = tychoRouterAddr.call(callData);
|
||||||
|
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|||||||
@@ -250,16 +250,13 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
vm.startPrank(ALICE);
|
vm.startPrank(ALICE);
|
||||||
|
|
||||||
IAllowanceTransfer.PermitSingle memory emptyPermitSingle =
|
IAllowanceTransfer.PermitSingle memory emptyPermitSingle =
|
||||||
IAllowanceTransfer.PermitSingle({
|
IAllowanceTransfer.PermitSingle({
|
||||||
details: IAllowanceTransfer.PermitDetails({
|
details: IAllowanceTransfer.PermitDetails({
|
||||||
token: address(0),
|
token: address(0), amount: 0, expiration: 0, nonce: 0
|
||||||
amount: 0,
|
}),
|
||||||
expiration: 0,
|
spender: address(0),
|
||||||
nonce: 0
|
sigDeadline: 0
|
||||||
}),
|
});
|
||||||
spender: address(0),
|
|
||||||
sigDeadline: 0
|
|
||||||
});
|
|
||||||
bytes memory protocolData = encodeUniswapV2Swap(
|
bytes memory protocolData = encodeUniswapV2Swap(
|
||||||
WETH_ADDR,
|
WETH_ADDR,
|
||||||
WETH_DAI_POOL,
|
WETH_DAI_POOL,
|
||||||
@@ -274,7 +271,9 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup {
|
|||||||
bytes[] memory swaps = new bytes[](1);
|
bytes[] memory swaps = new bytes[](1);
|
||||||
swaps[0] = swap;
|
swaps[0] = swap;
|
||||||
|
|
||||||
uint256 amountOut = tychoRouter.splitSwapPermit2{value: amountIn}(
|
uint256 amountOut = tychoRouter.splitSwapPermit2{
|
||||||
|
value: amountIn
|
||||||
|
}(
|
||||||
amountIn,
|
amountIn,
|
||||||
address(0),
|
address(0),
|
||||||
DAI_ADDR,
|
DAI_ADDR,
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
pragma solidity ^0.8.26;
|
pragma solidity ^0.8.26;
|
||||||
|
|
||||||
import "../TychoRouterTestSetup.sol";
|
import "../TychoRouterTestSetup.sol";
|
||||||
import {BalancerV3Executor__InvalidDataLength} from
|
import {
|
||||||
"../../src/executors/BalancerV3Executor.sol";
|
BalancerV3Executor__InvalidDataLength
|
||||||
|
} from "../../src/executors/BalancerV3Executor.sol";
|
||||||
|
|
||||||
contract BalancerV3ExecutorExposed is BalancerV3Executor {
|
contract BalancerV3ExecutorExposed is BalancerV3Executor {
|
||||||
constructor(address _permit2) BalancerV3Executor(_permit2) {}
|
constructor(address _permit2) BalancerV3Executor(_permit2) {}
|
||||||
@@ -31,7 +32,8 @@ contract BalancerV3ExecutorTest is Constants, TestUtils {
|
|||||||
address WETH_osETH_pool =
|
address WETH_osETH_pool =
|
||||||
address(0x57c23c58B1D8C3292c15BEcF07c62C5c52457A42);
|
address(0x57c23c58B1D8C3292c15BEcF07c62C5c52457A42);
|
||||||
address osETH_ADDR = address(0xf1C9acDc66974dFB6dEcB12aA385b9cD01190E38);
|
address osETH_ADDR = address(0xf1C9acDc66974dFB6dEcB12aA385b9cD01190E38);
|
||||||
address waEthWETH_ADDR = address(0x0bfc9d54Fc184518A81162F8fB99c2eACa081202);
|
address waEthWETH_ADDR =
|
||||||
|
address(0x0bfc9d54Fc184518A81162F8fB99c2eACa081202);
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
uint256 forkBlock = 22625131;
|
uint256 forkBlock = 22625131;
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import "@src/executors/BebopExecutor.sol";
|
|||||||
import {Constants} from "../Constants.sol";
|
import {Constants} from "../Constants.sol";
|
||||||
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
import {Permit2TestHelper} from "../Permit2TestHelper.sol";
|
import {Permit2TestHelper} from "../Permit2TestHelper.sol";
|
||||||
import {SafeERC20} from
|
import {
|
||||||
"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
SafeERC20
|
||||||
|
} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
|
|
||||||
contract BebopExecutorExposed is BebopExecutor {
|
contract BebopExecutorExposed is BebopExecutor {
|
||||||
constructor(address _bebopSettlement, address _permit2)
|
constructor(address _bebopSettlement, address _permit2)
|
||||||
@@ -114,7 +115,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
address tokenIn = WETH_ADDR;
|
address tokenIn = WETH_ADDR;
|
||||||
address tokenOut = WBTC_ADDR;
|
address tokenOut = WBTC_ADDR;
|
||||||
RestrictTransferFrom.TransferType transferType =
|
RestrictTransferFrom.TransferType transferType =
|
||||||
RestrictTransferFrom.TransferType.None;
|
RestrictTransferFrom.TransferType.None;
|
||||||
uint8 partialFillOffset = 12;
|
uint8 partialFillOffset = 12;
|
||||||
uint256 amountIn = 1000000000000000000;
|
uint256 amountIn = 1000000000000000000;
|
||||||
bool approvalNeeded = true;
|
bool approvalNeeded = true;
|
||||||
@@ -165,7 +166,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
address tokenIn = address(0);
|
address tokenIn = address(0);
|
||||||
address tokenOut = WBTC_ADDR;
|
address tokenOut = WBTC_ADDR;
|
||||||
RestrictTransferFrom.TransferType transferType =
|
RestrictTransferFrom.TransferType transferType =
|
||||||
RestrictTransferFrom.TransferType.None;
|
RestrictTransferFrom.TransferType.None;
|
||||||
uint8 partialFillOffset = 12;
|
uint8 partialFillOffset = 12;
|
||||||
uint256 amountIn = 1000000000000000000;
|
uint256 amountIn = 1000000000000000000;
|
||||||
bool approvalNeeded = false;
|
bool approvalNeeded = false;
|
||||||
@@ -212,7 +213,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
address tokenIn = WETH_ADDR;
|
address tokenIn = WETH_ADDR;
|
||||||
address tokenOut = WBTC_ADDR;
|
address tokenOut = WBTC_ADDR;
|
||||||
RestrictTransferFrom.TransferType transferType =
|
RestrictTransferFrom.TransferType transferType =
|
||||||
RestrictTransferFrom.TransferType.None;
|
RestrictTransferFrom.TransferType.None;
|
||||||
uint8 partialFillOffset = 12;
|
uint8 partialFillOffset = 12;
|
||||||
// filling only half of the quote
|
// filling only half of the quote
|
||||||
uint256 amountIn = 1000000000000000000 / 2;
|
uint256 amountIn = 1000000000000000000 / 2;
|
||||||
@@ -264,7 +265,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
address tokenIn = USDC_ADDR;
|
address tokenIn = USDC_ADDR;
|
||||||
address tokenOut = ONDO_ADDR;
|
address tokenOut = ONDO_ADDR;
|
||||||
RestrictTransferFrom.TransferType transferType =
|
RestrictTransferFrom.TransferType transferType =
|
||||||
RestrictTransferFrom.TransferType.None;
|
RestrictTransferFrom.TransferType.None;
|
||||||
uint8 partialFillOffset = 2;
|
uint8 partialFillOffset = 2;
|
||||||
// filling only half of the quote
|
// filling only half of the quote
|
||||||
uint256 amountIn = 20000000000;
|
uint256 amountIn = 20000000000;
|
||||||
@@ -318,7 +319,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
address tokenIn = USDC_ADDR;
|
address tokenIn = USDC_ADDR;
|
||||||
address tokenOut = ONDO_ADDR;
|
address tokenOut = ONDO_ADDR;
|
||||||
RestrictTransferFrom.TransferType transferType =
|
RestrictTransferFrom.TransferType transferType =
|
||||||
RestrictTransferFrom.TransferType.None;
|
RestrictTransferFrom.TransferType.None;
|
||||||
uint8 partialFillOffset = 2;
|
uint8 partialFillOffset = 2;
|
||||||
// filling only half of the quote
|
// filling only half of the quote
|
||||||
uint256 amountIn = 20000000000 / 2;
|
uint256 amountIn = 20000000000 / 2;
|
||||||
|
|||||||
@@ -31,11 +31,9 @@ contract HashflowUtils is Test {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeRfqtQuoteWithDefaults(IHashflowRouter.RFQTQuote memory quote)
|
function encodeRfqtQuoteWithDefaults(
|
||||||
internal
|
IHashflowRouter.RFQTQuote memory quote
|
||||||
pure
|
) internal pure returns (bytes memory) {
|
||||||
returns (bytes memory)
|
|
||||||
{
|
|
||||||
return
|
return
|
||||||
encodeRfqtQuote(quote, true, RestrictTransferFrom.TransferType.None);
|
encodeRfqtQuote(quote, true, RestrictTransferFrom.TransferType.None);
|
||||||
}
|
}
|
||||||
@@ -183,7 +181,9 @@ contract HashflowExecutorECR20Test is Constants, TestUtils, HashflowUtils {
|
|||||||
{
|
{
|
||||||
return IHashflowRouter.RFQTQuote({
|
return IHashflowRouter.RFQTQuote({
|
||||||
pool: address(0x5d8853028fbF6a2da43c7A828cc5f691E9456B44),
|
pool: address(0x5d8853028fbF6a2da43c7A828cc5f691E9456B44),
|
||||||
externalAccount: address(0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31),
|
externalAccount: address(
|
||||||
|
0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31
|
||||||
|
),
|
||||||
trader: address(ALICE),
|
trader: address(ALICE),
|
||||||
effectiveTrader: address(ALICE),
|
effectiveTrader: address(ALICE),
|
||||||
baseToken: WETH_ADDR,
|
baseToken: WETH_ADDR,
|
||||||
@@ -243,7 +243,9 @@ contract HashflowExecutorNativeTest is Constants, HashflowUtils {
|
|||||||
{
|
{
|
||||||
return IHashflowRouter.RFQTQuote({
|
return IHashflowRouter.RFQTQuote({
|
||||||
pool: address(0x713DC4Df480235dBe2fB766E7120Cbd4041Dcb58),
|
pool: address(0x713DC4Df480235dBe2fB766E7120Cbd4041Dcb58),
|
||||||
externalAccount: address(0x111BB8c3542F2B92fb41B8d913c01D3788431111),
|
externalAccount: address(
|
||||||
|
0x111BB8c3542F2B92fb41B8d913c01D3788431111
|
||||||
|
),
|
||||||
trader: address(ALICE),
|
trader: address(ALICE),
|
||||||
effectiveTrader: address(ALICE),
|
effectiveTrader: address(ALICE),
|
||||||
baseToken: address(0x0000000000000000000000000000000000000000),
|
baseToken: address(0x0000000000000000000000000000000000000000),
|
||||||
|
|||||||
@@ -92,9 +92,7 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup {
|
|||||||
additionalValidationData: ""
|
additionalValidationData: ""
|
||||||
}),
|
}),
|
||||||
input: InputToken({
|
input: InputToken({
|
||||||
token: address(WETH_ADDR),
|
token: address(WETH_ADDR), amount: amountIn, maxAmount: amountIn
|
||||||
amount: amountIn,
|
|
||||||
maxAmount: amountIn
|
|
||||||
}),
|
}),
|
||||||
outputs: outputs,
|
outputs: outputs,
|
||||||
sig: "",
|
sig: "",
|
||||||
@@ -132,9 +130,10 @@ contract UniswapXFillerTest is Test, TychoRouterTestSetup {
|
|||||||
|
|
||||||
vm.startPrank(address(0xD213e6F6dCB2DBaC03FA28b893F6dA1BD822e852));
|
vm.startPrank(address(0xD213e6F6dCB2DBaC03FA28b893F6dA1BD822e852));
|
||||||
// Approve Permit2
|
// Approve Permit2
|
||||||
IERC20(DAI_ADDR).approve(
|
IERC20(DAI_ADDR)
|
||||||
address(0x000000000022D473030F116dDEE9F6B43aC78BA3), amountIn
|
.approve(
|
||||||
);
|
address(0x000000000022D473030F116dDEE9F6B43aC78BA3), amountIn
|
||||||
|
);
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|
||||||
// Tx 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d
|
// Tx 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use crate::encoding::{
|
|||||||
/// Tycho is only responsible for generating the internal swap plan. **The user must encode the
|
/// Tycho is only responsible for generating the internal swap plan. **The user must encode the
|
||||||
/// outer function call arguments themselves** and verify that they enforce correct and secure
|
/// outer function call arguments themselves** and verify that they enforce correct and secure
|
||||||
/// behavior.
|
/// behavior.
|
||||||
pub trait TychoEncoder {
|
pub trait TychoEncoder: Send + Sync {
|
||||||
/// Encodes a list of [`Solution`]s into [`EncodedSolution`]s, which include the function
|
/// Encodes a list of [`Solution`]s into [`EncodedSolution`]s, which include the function
|
||||||
/// signature and internal swap call data.
|
/// signature and internal swap call data.
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user