From ad91e485d3a7b125f4db39cb84bb504f2d6064cf Mon Sep 17 00:00:00 2001 From: royvardhan Date: Sat, 15 Feb 2025 00:44:28 +0530 Subject: [PATCH] feat: rename execution dispatcher to dispatcher and use dispatcher for USV4 callback --- .../{ExecutionDispatcher.sol => Dispatcher.sol} | 14 +++++++------- foundry/src/TychoRouter.sol | 16 +++------------- foundry/test/ExecutionDispatcher.t.sol | 14 ++++++-------- 3 files changed, 16 insertions(+), 28 deletions(-) rename foundry/src/{ExecutionDispatcher.sol => Dispatcher.sol} (89%) diff --git a/foundry/src/ExecutionDispatcher.sol b/foundry/src/Dispatcher.sol similarity index 89% rename from foundry/src/ExecutionDispatcher.sol rename to foundry/src/Dispatcher.sol index 01e6ff4..d2a9128 100644 --- a/foundry/src/ExecutionDispatcher.sol +++ b/foundry/src/Dispatcher.sol @@ -5,11 +5,11 @@ import "@interfaces/IExecutor.sol"; import "@interfaces/ICallback.sol"; import "forge-std/console.sol"; -error ExecutionDispatcher__UnapprovedExecutor(); -error ExecutionDispatcher__NonContractExecutor(); +error Dispatcher__UnapprovedExecutor(); +error Dispatcher__NonContractExecutor(); /** - * @title ExecutionDispatcher - Dispatch execution to external contracts + * @title Dispatcher - Dispatch execution to external contracts * @author PropellerHeads Devs * @dev Provides the ability to delegate execution of swaps to external * contracts. This allows dynamically adding new supported protocols @@ -20,7 +20,7 @@ error ExecutionDispatcher__NonContractExecutor(); * Note: Executor contracts need to implement the IExecutor interface unless * an alternate selector is specified. */ -contract ExecutionDispatcher { +contract Dispatcher { mapping(address => bool) public executors; event ExecutorSet(address indexed executor); @@ -33,7 +33,7 @@ contract ExecutionDispatcher { */ function _setExecutor(address target) internal { if (target.code.length == 0) { - revert ExecutionDispatcher__NonContractExecutor(); + revert Dispatcher__NonContractExecutor(); } executors[target] = true; emit ExecutorSet(target); @@ -60,7 +60,7 @@ contract ExecutionDispatcher { bytes calldata data ) internal returns (uint256 calculatedAmount) { if (!executors[executor]) { - revert ExecutionDispatcher__UnapprovedExecutor(); + revert Dispatcher__UnapprovedExecutor(); } selector = selector == bytes4(0) ? IExecutor.swap.selector : selector; @@ -93,7 +93,7 @@ contract ExecutionDispatcher { } if (!executors[executor]) { - revert ExecutionDispatcher__UnapprovedExecutor(); + revert Dispatcher__UnapprovedExecutor(); } selector = diff --git a/foundry/src/TychoRouter.sol b/foundry/src/TychoRouter.sol index 08ed017..5c26097 100644 --- a/foundry/src/TychoRouter.sol +++ b/foundry/src/TychoRouter.sol @@ -11,11 +11,10 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@permit2/src/interfaces/IAllowanceTransfer.sol"; -import "./ExecutionDispatcher.sol"; +import "./Dispatcher.sol"; import {LibSwap} from "../lib/LibSwap.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol"; -import "forge-std/console.sol"; error TychoRouter__WithdrawalFailed(); error TychoRouter__AddressZero(); @@ -26,7 +25,7 @@ error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount); contract TychoRouter is AccessControl, - ExecutionDispatcher, + Dispatcher, Pausable, ReentrancyGuard, SafeCallback @@ -390,16 +389,7 @@ contract TychoRouter is bytes4 selector = bytes4(data[data.length - 24:data.length - 20]); address executor = address(uint160(bytes20(data[data.length - 20:]))); bytes memory protocolData = data[:data.length - 24]; - - if (!executors[executor]) { - revert ExecutionDispatcher__UnapprovedExecutor(); - } - - // slither-disable-next-line controlled-delegatecall,low-level-calls - (bool success,) = executor.delegatecall( - abi.encodeWithSelector(selector, protocolData) - ); - require(success, "delegatecall to uniswap v4 callback failed"); + _handleCallback(selector, abi.encodePacked(protocolData, executor)); return ""; } } diff --git a/foundry/test/ExecutionDispatcher.t.sol b/foundry/test/ExecutionDispatcher.t.sol index 7f2fb81..4f12df0 100644 --- a/foundry/test/ExecutionDispatcher.t.sol +++ b/foundry/test/ExecutionDispatcher.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.26; -import "@src/ExecutionDispatcher.sol"; +import "@src/Dispatcher.sol"; import "./TychoRouterTestSetup.sol"; -contract ExecutionDispatcherExposed is ExecutionDispatcher { +contract DispatcherExposed is Dispatcher { function exposedCallExecutor( address executor, bytes4 selector, @@ -23,8 +23,8 @@ contract ExecutionDispatcherExposed is ExecutionDispatcher { } } -contract ExecutionDispatcherTest is Constants { - ExecutionDispatcherExposed dispatcherExposed; +contract DispatcherTest is Constants { + DispatcherExposed dispatcherExposed; event ExecutorSet(address indexed executor); event ExecutorRemoved(address indexed executor); @@ -32,7 +32,7 @@ contract ExecutionDispatcherTest is Constants { function setUp() public { uint256 forkBlock = 20673900; vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); - dispatcherExposed = new ExecutionDispatcherExposed(); + dispatcherExposed = new DispatcherExposed(); deal(WETH_ADDR, address(dispatcherExposed), 15 ether); deployDummyContract(); } @@ -61,9 +61,7 @@ contract ExecutionDispatcherTest is Constants { function testSetExecutorNonContract() public { vm.expectRevert( - abi.encodeWithSelector( - ExecutionDispatcher__NonContractExecutor.selector - ) + abi.encodeWithSelector(Dispatcher__NonContractExecutor.selector) ); dispatcherExposed.exposedSetExecutor(BOB); }