feat: add back uniswapV3SwapCallback in router

This commit is contained in:
royvardhan
2025-02-14 23:00:23 +05:30
parent 5853de679a
commit 260f9d866f
3 changed files with 36 additions and 16 deletions

View File

@@ -2,6 +2,7 @@
pragma solidity ^0.8.26; pragma solidity ^0.8.26;
import "@interfaces/IExecutor.sol"; import "@interfaces/IExecutor.sol";
import "forge-std/console.sol";
error ExecutionDispatcher__UnapprovedExecutor(); error ExecutionDispatcher__UnapprovedExecutor();
error ExecutionDispatcher__NonContractExecutor(); error ExecutionDispatcher__NonContractExecutor();
@@ -80,19 +81,25 @@ contract ExecutionDispatcher {
calculatedAmount = abi.decode(result, (uint256)); calculatedAmount = abi.decode(result, (uint256));
} }
function _handleCallback(bytes calldata data) internal { function _handleCallback(bytes4 selector, bytes memory data) internal {
// Take last 20 bytes (excluding the final byte) // Access the last 20 bytes of the bytes memory data using assembly
address executor = address executor;
address(bytes20(data[data.length - 21:data.length - 1])); // slither-disable-next-line assembly
assembly {
let pos := sub(add(add(data, 0x20), mload(data)), 20)
executor := mload(pos)
executor := shr(96, executor)
}
if (!executors[executor]) { if (!executors[executor]) {
revert ExecutionDispatcher__UnapprovedExecutor(); revert ExecutionDispatcher__UnapprovedExecutor();
} }
selector =
selector == bytes4(0) ? IExecutor.handleCallback.selector : selector;
// slither-disable-next-line controlled-delegatecall,low-level-calls // slither-disable-next-line controlled-delegatecall,low-level-calls
(bool success, bytes memory result) = executor.delegatecall( (bool success, bytes memory result) =
abi.encodeWithSelector(IExecutor.handleCallback.selector, data) executor.delegatecall(abi.encodeWithSelector(selector, data));
);
if (!success) { if (!success) {
revert( revert(

View File

@@ -15,6 +15,7 @@ import "./ExecutionDispatcher.sol";
import {LibSwap} from "../lib/LibSwap.sol"; import {LibSwap} from "../lib/LibSwap.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol"; import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol";
import "forge-std/console.sol";
error TychoRouter__WithdrawalFailed(); error TychoRouter__WithdrawalFailed();
error TychoRouter__AddressZero(); error TychoRouter__AddressZero();
@@ -228,9 +229,10 @@ contract TychoRouter is
* This function will static call a verifier contract and should revert if the * This function will static call a verifier contract and should revert if the
* caller is not a pool. * caller is not a pool.
*/ */
fallback() external { // fallback() external {
_handleCallback(msg.data); // bytes4 selector = bytes4(msg.data[:4]);
} // _handleCallback(selector, msg.data[4:]);
// }
/** /**
* @dev Pauses the contract * @dev Pauses the contract
@@ -388,6 +390,20 @@ contract TychoRouter is
*/ */
receive() external payable {} receive() external payable {}
/**
* @dev Called by UniswapV3 pool when swapping on it.
* See in IUniswapV3SwapCallback for documentation.
*/
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata msgData
) external {
_handleCallback(
bytes4(0), abi.encodePacked(amount0Delta, amount1Delta, msgData)
);
}
function _unlockCallback(bytes calldata data) function _unlockCallback(bytes calldata data)
internal internal
override override

View File

@@ -5,6 +5,7 @@ import "@interfaces/IExecutor.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
import "@uniswap/v3-updated/CallbackValidationV2.sol"; import "@uniswap/v3-updated/CallbackValidationV2.sol";
import "forge-std/console.sol";
error UniswapV3Executor__InvalidDataLength(); error UniswapV3Executor__InvalidDataLength();
error UniswapV3Executor__InvalidFactory(); error UniswapV3Executor__InvalidFactory();
@@ -69,11 +70,10 @@ contract UniswapV3Executor is IExecutor {
external external
returns (bytes memory result) returns (bytes memory result)
{ {
// Skip first 4 bytes of function selector and decode the two int256 values
(int256 amount0Delta, int256 amount1Delta) = (int256 amount0Delta, int256 amount1Delta) =
abi.decode(msgData[4:68], (int256, int256)); abi.decode(msgData[:64], (int256, int256));
bytes calldata remainingData = msgData[68:]; bytes calldata remainingData = msgData[64:];
(uint256 amountOwed, address tokenOwed) = (uint256 amountOwed, address tokenOwed) =
_verifyUSV3Callback(amount0Delta, amount1Delta, remainingData); _verifyUSV3Callback(amount0Delta, amount1Delta, remainingData);
@@ -87,9 +87,6 @@ contract UniswapV3Executor is IExecutor {
int256 amount1Delta, int256 amount1Delta,
bytes calldata data bytes calldata data
) internal view returns (uint256 amountIn, address tokenIn) { ) internal view returns (uint256 amountIn, address tokenIn) {
// Skip the first 64 bytes (32 bytes offset + 32 bytes length)
data = data[64:];
tokenIn = address(bytes20(data[0:20])); tokenIn = address(bytes20(data[0:20]));
address tokenOut = address(bytes20(data[20:40])); address tokenOut = address(bytes20(data[20:40]));
uint24 poolFee = uint24(bytes3(data[40:43])); uint24 poolFee = uint24(bytes3(data[40:43]));