fix: Fix tests (not there yet)

Took 58 minutes
This commit is contained in:
Diana Carvalho
2025-05-16 17:57:29 +01:00
parent eeebd51114
commit d4244a7089
23 changed files with 417 additions and 300 deletions

View File

@@ -4,6 +4,7 @@ pragma solidity ^0.8.26;
import "@interfaces/IExecutor.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
import "@openzeppelin/contracts/utils/Address.sol";
error RestrictTransferFrom__AddressZero();
error RestrictTransferFrom__ExceededTransferFromAllowance();
@@ -57,10 +58,10 @@ contract RestrictTransferFrom {
) internal {
assembly {
tstore(_TOKEN_IN_SLOT, tokenIn)
tstore(_AMOUNT_IN_SLOT, amountIn)
tstore(_AMOUNT_ALLOWED_SLOT, amountIn)
tstore(_IS_PERMIT2_SLOT, isPermit2)
tstore(_SENDER_SLOT, caller())
tstore(_IS_TRANSFER_EXECUTED_SLOT, false)
tstore(_AMOUNT_SPENT_SLOT, 0)
}
}
@@ -71,18 +72,20 @@ contract RestrictTransferFrom {
address tokenIn,
uint256 amount
) internal {
if (transferType == TransferType.TransferFrom){
if (transferType == TransferType.TransferFrom) {
bool isPermit2;
address sender;
bool isTransferExecuted;
uint256 amountSpent;
uint256 amountAllowed;
assembly {
tokenIn := tload(_TOKEN_IN_SLOT)
amountPermitted := tload(_AMOUNT_IN_SLOT)
amountAllowed := tload(_AMOUNT_ALLOWED_SLOT)
isPermit2 := tload(_IS_PERMIT2_SLOT)
sender := tload(_SENDER_SLOT)
amountSpent := tload(_IS_TRANSFER_EXECUTED_SLOT)
amountSpent := tload(_AMOUNT_SPENT_SLOT)
}
if (amount + amountSpent > amountPermitted) {
if (amount + amountSpent > amountAllowed) {
revert RestrictTransferFrom__ExceededTransferFromAllowance();
}
assembly {

View File

@@ -71,7 +71,7 @@ contract TychoRouter is
Dispatcher,
Pausable,
ReentrancyGuard,
RestrictTransferFrom
RestrictTransferFrom
{
IWETH private immutable _weth;
@@ -93,7 +93,9 @@ RestrictTransferFrom
address indexed token, uint256 amount, address indexed receiver
);
constructor(address _permit2, address weth) RestrictTransferFrom(_permit2) {
constructor(address _permit2, address weth)
RestrictTransferFrom(_permit2)
{
if (_permit2 == address(0) || weth == address(0)) {
revert TychoRouter__AddressZero();
}
@@ -121,8 +123,6 @@ RestrictTransferFrom
* @param unwrapEth If true, unwraps the resulting WETH into native ETH and sends it to the receiver.
* @param nTokens The total number of tokens involved in the swap graph (used to initialize arrays for internal calculations).
* @param receiver The address to receive the output tokens.
* @param transferFromNeeded If true, the contract will transfer the input token from the caller to the router.
* Otherwise, assume funds are already in router or will be transferred later by the executors (This is the case for executors with callback).
* @param swaps Encoded swap graph data containing details of each swap.
*
* @return amountOut The total amount of the output token received by the receiver.
@@ -136,14 +136,11 @@ RestrictTransferFrom
bool unwrapEth,
uint256 nTokens,
address receiver,
bool transferFromNeeded,
bytes calldata swaps
) public payable whenNotPaused nonReentrant returns (uint256 amountOut) {
uint256 initialBalanceTokenOut = _balanceOf(tokenOut, receiver);
_tstoreTransferFromInfo(tokenIn, amountIn, false);
if (transferFromNeeded) {
_transfer(address(this));
}
return _splitSwapChecked(
amountIn,
tokenIn,
@@ -178,8 +175,6 @@ RestrictTransferFrom
* @param unwrapEth If true, unwraps the resulting WETH into native ETH and sends it to the receiver.
* @param nTokens The total number of tokens involved in the swap graph (used to initialize arrays for internal calculations).
* @param receiver The address to receive the output tokens.
* @param transferFromNeeded If true, the contract will transfer the input token from the caller to the router.
* Otherwise, assume funds are already in router or will be transferred later by the executors (This is the case for executors with callback).
* @param permitSingle A Permit2 structure containing token approval details for the input token. Ignored if `wrapEth` is true.
* @param signature A valid signature authorizing the Permit2 approval. Ignored if `wrapEth` is true.
* @param swaps Encoded swap graph data containing details of each swap.
@@ -195,7 +190,6 @@ RestrictTransferFrom
bool unwrapEth,
uint256 nTokens,
address receiver,
bool transferFromNeeded,
IAllowanceTransfer.PermitSingle calldata permitSingle,
bytes calldata signature,
bytes calldata swaps
@@ -206,9 +200,6 @@ RestrictTransferFrom
permit2.permit(msg.sender, permitSingle, signature);
}
_tstoreTransferFromInfo(tokenIn, amountIn, true);
if (transferFromNeeded) {
_transfer(address(this));
}
return _splitSwapChecked(
amountIn,
@@ -242,9 +233,6 @@ RestrictTransferFrom
* @param wrapEth If true, wraps the input token (native ETH) into WETH.
* @param unwrapEth If true, unwraps the resulting WETH into native ETH and sends it to the receiver.
* @param receiver The address to receive the output tokens.
* @param transferFromNeeded If true, the contract will transfer the input token from the caller to the tokenInReceiver.
* Otherwise, assume funds are already in router or will be transferred later by the executors (This is the case for executors with callback).
* @param tokenInReceiver The address to receive the input tokens. This is used when `transferFromNeeded` is true.
* @param swaps Encoded swap graph data containing details of each swap.
*
* @return amountOut The total amount of the output token received by the receiver.
@@ -257,15 +245,11 @@ RestrictTransferFrom
bool wrapEth,
bool unwrapEth,
address receiver,
bool transferFromNeeded,
address tokenInReceiver,
bytes calldata swaps
) public payable whenNotPaused nonReentrant returns (uint256 amountOut) {
uint256 initialBalanceTokenOut = _balanceOf(tokenOut, receiver);
_tstoreTransferFromInfo(tokenIn, amountIn, false);
if (transferFromNeeded) {
_transfer(tokenInReceiver);
}
return _sequentialSwapChecked(
amountIn,
tokenIn,
@@ -297,8 +281,6 @@ RestrictTransferFrom
* @param wrapEth If true, wraps the input token (native ETH) into WETH.
* @param unwrapEth If true, unwraps the resulting WETH into native ETH and sends it to the receiver.
* @param receiver The address to receive the output tokens.
* @param transferFromNeeded If true, the contract will transfer the input token from the caller to the tokenInReceiver.
* Otherwise, assume funds are already in router or will be transferred later by the executors (This is the case for executors with callback). * @param tokenInReceiver The address to receive the input tokens. This is used when `transferFromNeeded` is true.
* @param permitSingle A Permit2 structure containing token approval details for the input token. Ignored if `wrapEth` is true.
* @param signature A valid signature authorizing the Permit2 approval. Ignored if `wrapEth` is true.
* @param swaps Encoded swap graph data containing details of each swap.
@@ -313,8 +295,6 @@ RestrictTransferFrom
bool wrapEth,
bool unwrapEth,
address receiver,
bool transferFromNeeded,
address tokenInReceiver,
IAllowanceTransfer.PermitSingle calldata permitSingle,
bytes calldata signature,
bytes calldata swaps
@@ -326,9 +306,7 @@ RestrictTransferFrom
}
_tstoreTransferFromInfo(tokenIn, amountIn, true);
if (transferFromNeeded) {
_transfer(tokenInReceiver);
}
return _sequentialSwapChecked(
amountIn,
tokenIn,
@@ -358,8 +336,6 @@ RestrictTransferFrom
* @param wrapEth If true, wraps the input token (native ETH) into WETH.
* @param unwrapEth If true, unwraps the resulting WETH into native ETH and sends it to the receiver.
* @param receiver The address to receive the output tokens.
* @param transferFromNeeded If true, the contract will transfer the input token from the caller to the tokenInReceiver.
* Otherwise, assume funds are already in router or will be transferred later by the executors (This is the case for executors with callback). * @param tokenInReceiver The address to receive the input tokens. This is used when `transferFromNeeded` is true.
* @param swapData Encoded swap details.
*
* @return amountOut The total amount of the output token received by the receiver.
@@ -372,15 +348,11 @@ RestrictTransferFrom
bool wrapEth,
bool unwrapEth,
address receiver,
bool transferFromNeeded,
address tokenInReceiver,
bytes calldata swapData
) public payable whenNotPaused nonReentrant returns (uint256 amountOut) {
uint256 initialBalanceTokenOut = _balanceOf(tokenOut, receiver);
_tstoreTransferFromInfo(tokenIn, amountIn, false);
if (transferFromNeeded) {
_transfer(tokenInReceiver);
}
return _singleSwap(
amountIn,
tokenIn,
@@ -412,8 +384,6 @@ RestrictTransferFrom
* @param wrapEth If true, wraps the input token (native ETH) into WETH.
* @param unwrapEth If true, unwraps the resulting WETH into native ETH and sends it to the receiver.
* @param receiver The address to receive the output tokens.
* @param transferFromNeeded If true, the contract will transfer the input token from the caller to the tokenInReceiver.
* Otherwise, assume funds are already in router or will be transferred later by the executors (This is the case for executors with callback). * @param tokenInReceiver The address to receive the input tokens. This is used when `transferFromNeeded` is true.
* @param permitSingle A Permit2 structure containing token approval details for the input token. Ignored if `wrapEth` is true.
* @param signature A valid signature authorizing the Permit2 approval. Ignored if `wrapEth` is true.
* @param swapData Encoded swap details.
@@ -428,8 +398,6 @@ RestrictTransferFrom
bool wrapEth,
bool unwrapEth,
address receiver,
bool transferFromNeeded,
address tokenInReceiver,
IAllowanceTransfer.PermitSingle calldata permitSingle,
bytes calldata signature,
bytes calldata swapData
@@ -440,9 +408,7 @@ RestrictTransferFrom
permit2.permit(msg.sender, permitSingle, signature);
}
_tstoreTransferFromInfo(tokenIn, amountIn, true);
if (transferFromNeeded) {
_transfer(tokenInReceiver);
}
return _singleSwap(
amountIn,
tokenIn,

View File

@@ -12,7 +12,7 @@ import {IAsset} from "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol";
import {IVault} from "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
import {RestrictTransferFrom} from "../RestrictTransferFrom.sol";
error BalancerV2Executor__InvalidDataLength();
error BalancerV2Executor__InvalidDataLength();
contract BalancerV2Executor is IExecutor, RestrictTransferFrom {
using SafeERC20 for IERC20;
@@ -36,7 +36,7 @@ contract BalancerV2Executor is IExecutor, RestrictTransferFrom {
TransferType transferType
) = _decodeData(data);
_transfer(address(this), transferType, tokenIn, givenAmount);
_transfer(address(this), transferType, address(tokenIn), givenAmount);
if (approvalNeeded) {
// slither-disable-next-line unused-return
@@ -73,7 +73,8 @@ contract BalancerV2Executor is IExecutor, RestrictTransferFrom {
IERC20 tokenOut,
bytes32 poolId,
address receiver,
bool approvalNeeded
bool approvalNeeded,
TransferType transferType
)
{
if (data.length != 93) {
@@ -85,5 +86,6 @@ contract BalancerV2Executor is IExecutor, RestrictTransferFrom {
poolId = bytes32(data[40:72]);
receiver = address(bytes20(data[72:92]));
approvalNeeded = data[92] != 0;
transferType = TransferType(uint8(data[93]));
}
}

View File

@@ -6,7 +6,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import {RestrictTransferFrom} from "../RestrictTransferFrom.sol";
error CurveExecutor__AddressZero();
error CurveExecutor__AddressZero();
error CurveExecutor__InvalidDataLength();
interface CryptoPool {
@@ -40,7 +40,9 @@ contract CurveExecutor is IExecutor, RestrictTransferFrom {
address public immutable nativeToken;
constructor(address _nativeToken, address _permit2) RestrictTransferFrom(_permit2) {
constructor(address _nativeToken, address _permit2)
RestrictTransferFrom(_permit2)
{
if (_nativeToken == address(0)) {
revert CurveExecutor__AddressZero();
}

View File

@@ -11,7 +11,7 @@ import {SafeTransferLib} from "@solady/utils/SafeTransferLib.sol";
import {LibBytes} from "@solady/utils/LibBytes.sol";
import {Config, EkuboPoolKey} from "@ekubo/types/poolKey.sol";
import {MAX_SQRT_RATIO, MIN_SQRT_RATIO} from "@ekubo/types/sqrtRatio.sol";
import "../RestrictTransferFrom.sol";
import {RestrictTransferFrom} from "../RestrictTransferFrom.sol";
import "@openzeppelin/contracts/utils/Address.sol";
contract EkuboExecutor is
@@ -19,7 +19,7 @@ contract EkuboExecutor is
ILocker,
IPayer,
ICallback,
RestrictTransferFrom
RestrictTransferFrom
{
error EkuboExecutor__InvalidDataLength();
error EkuboExecutor__CoreOnly();
@@ -166,11 +166,9 @@ RestrictTransferFrom
return nextAmountIn;
}
function _pay(
address token,
uint128 amount,
TransferType transferType
) internal {
function _pay(address token, uint128 amount, TransferType transferType)
internal
{
address target = address(core);
if (token == NATIVE_TOKEN_ADDRESS) {
@@ -198,7 +196,7 @@ RestrictTransferFrom
address token = address(bytes20(payData[12:32])); // This arg is abi-encoded
uint128 amount = uint128(bytes16(payData[32:48]));
TransferType transferType = TransferType(uint8(payData[48]));
_transfer(core, transferType, token, amount);
_transfer(address(core), transferType, token, amount);
}
// To receive withdrawals from Core

View File

@@ -6,7 +6,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import {RestrictTransferFrom} from "../RestrictTransferFrom.sol";
error MaverickV2Executor__InvalidDataLength();
error MaverickV2Executor__InvalidDataLength();
error MaverickV2Executor__InvalidTarget();
error MaverickV2Executor__InvalidFactory();
@@ -15,7 +15,9 @@ contract MaverickV2Executor is IExecutor, RestrictTransferFrom {
address public immutable factory;
constructor(address _factory, address _permit2) RestrictTransferFrom(_permit2) {
constructor(address _factory, address _permit2)
RestrictTransferFrom(_permit2)
{
if (_factory == address(0)) {
revert MaverickV2Executor__InvalidFactory();
}
@@ -48,7 +50,7 @@ contract MaverickV2Executor is IExecutor, RestrictTransferFrom {
tickLimit: tickLimit
});
_transfer(target, transferType, tokenIn, givenAmount);
_transfer(target, transferType, address(tokenIn), givenAmount);
// slither-disable-next-line unused-return
(, calculatedAmount) = pool.swap(receiver, swapParams, "");

View File

@@ -6,7 +6,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@uniswap-v2/contracts/interfaces/IUniswapV2Pair.sol";
import {RestrictTransferFrom} from "../RestrictTransferFrom.sol";
error UniswapV2Executor__InvalidDataLength();
error UniswapV2Executor__InvalidDataLength();
error UniswapV2Executor__InvalidTarget();
error UniswapV2Executor__InvalidFactory();
error UniswapV2Executor__InvalidInitCode();
@@ -78,7 +78,7 @@ contract UniswapV2Executor is IExecutor, RestrictTransferFrom {
address target,
address receiver,
bool zeroForOne,
TransferType transferType,
TransferType transferType
)
{
if (data.length != 62) {

View File

@@ -51,7 +51,7 @@ contract UniswapV3Executor is IExecutor, ICallback, RestrictTransferFrom {
address receiver,
address target,
bool zeroForOne,
uint8 transferType
TransferType transferType
) = _decodeData(data);
_verifyPairAddress(tokenIn, tokenOut, fee, target);
@@ -60,9 +60,8 @@ contract UniswapV3Executor is IExecutor, ICallback, RestrictTransferFrom {
int256 amount1;
IUniswapV3Pool pool = IUniswapV3Pool(target);
bytes memory callbackData = _makeV3CallbackData(
tokenIn, tokenOut, fee, transferType
);
bytes memory callbackData =
_makeV3CallbackData(tokenIn, tokenOut, fee, transferType);
{
(amount0, amount1) = pool.swap(
@@ -98,7 +97,7 @@ contract UniswapV3Executor is IExecutor, ICallback, RestrictTransferFrom {
abi.decode(msgData[4:68], (int256, int256));
address tokenIn = address(bytes20(msgData[132:152]));
bool transferType = TransferType(uint8(msgData[175]));
TransferType transferType = TransferType(uint8(msgData[175]));
verifyCallback(msgData[132:]);
@@ -136,7 +135,7 @@ contract UniswapV3Executor is IExecutor, ICallback, RestrictTransferFrom {
address receiver,
address target,
bool zeroForOne,
uint8 transferType
TransferType transferType
)
{
if (data.length != 85) {
@@ -148,18 +147,16 @@ contract UniswapV3Executor is IExecutor, ICallback, RestrictTransferFrom {
receiver = address(bytes20(data[43:63]));
target = address(bytes20(data[63:83]));
zeroForOne = uint8(data[83]) > 0;
transferType = uint8(data[84]);
transferType = TransferType(uint8(data[84]));
}
function _makeV3CallbackData(
address tokenIn,
address tokenOut,
uint24 fee,
uint8 transferType
TransferType transferType
) internal pure returns (bytes memory) {
return abi.encodePacked(
tokenIn, tokenOut, fee, transferType
);
return abi.encodePacked(tokenIn, tokenOut, fee, uint8(transferType));
}
function _verifyPairAddress(

View File

@@ -399,7 +399,7 @@ RestrictTransferFrom
_transfer(
address(poolManager),
transferType,
address(currency),
Currency.unwrap(currency),
amount
);
// slither-disable-next-line unused-return