feat: rename execution dispatcher to dispatcher and use dispatcher for USV4 callback

This commit is contained in:
royvardhan
2025-02-15 00:44:28 +05:30
parent 9d3b96f997
commit ad91e485d3
3 changed files with 16 additions and 28 deletions

View File

@@ -5,11 +5,11 @@ import "@interfaces/IExecutor.sol";
import "@interfaces/ICallback.sol"; import "@interfaces/ICallback.sol";
import "forge-std/console.sol"; import "forge-std/console.sol";
error ExecutionDispatcher__UnapprovedExecutor(); error Dispatcher__UnapprovedExecutor();
error ExecutionDispatcher__NonContractExecutor(); error Dispatcher__NonContractExecutor();
/** /**
* @title ExecutionDispatcher - Dispatch execution to external contracts * @title Dispatcher - Dispatch execution to external contracts
* @author PropellerHeads Devs * @author PropellerHeads Devs
* @dev Provides the ability to delegate execution of swaps to external * @dev Provides the ability to delegate execution of swaps to external
* contracts. This allows dynamically adding new supported protocols * 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 * Note: Executor contracts need to implement the IExecutor interface unless
* an alternate selector is specified. * an alternate selector is specified.
*/ */
contract ExecutionDispatcher { contract Dispatcher {
mapping(address => bool) public executors; mapping(address => bool) public executors;
event ExecutorSet(address indexed executor); event ExecutorSet(address indexed executor);
@@ -33,7 +33,7 @@ contract ExecutionDispatcher {
*/ */
function _setExecutor(address target) internal { function _setExecutor(address target) internal {
if (target.code.length == 0) { if (target.code.length == 0) {
revert ExecutionDispatcher__NonContractExecutor(); revert Dispatcher__NonContractExecutor();
} }
executors[target] = true; executors[target] = true;
emit ExecutorSet(target); emit ExecutorSet(target);
@@ -60,7 +60,7 @@ contract ExecutionDispatcher {
bytes calldata data bytes calldata data
) internal returns (uint256 calculatedAmount) { ) internal returns (uint256 calculatedAmount) {
if (!executors[executor]) { if (!executors[executor]) {
revert ExecutionDispatcher__UnapprovedExecutor(); revert Dispatcher__UnapprovedExecutor();
} }
selector = selector == bytes4(0) ? IExecutor.swap.selector : selector; selector = selector == bytes4(0) ? IExecutor.swap.selector : selector;
@@ -93,7 +93,7 @@ contract ExecutionDispatcher {
} }
if (!executors[executor]) { if (!executors[executor]) {
revert ExecutionDispatcher__UnapprovedExecutor(); revert Dispatcher__UnapprovedExecutor();
} }
selector = selector =

View File

@@ -11,11 +11,10 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/Address.sol";
import "@permit2/src/interfaces/IAllowanceTransfer.sol"; import "@permit2/src/interfaces/IAllowanceTransfer.sol";
import "./ExecutionDispatcher.sol"; import "./Dispatcher.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();
@@ -26,7 +25,7 @@ error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount);
contract TychoRouter is contract TychoRouter is
AccessControl, AccessControl,
ExecutionDispatcher, Dispatcher,
Pausable, Pausable,
ReentrancyGuard, ReentrancyGuard,
SafeCallback SafeCallback
@@ -390,16 +389,7 @@ contract TychoRouter is
bytes4 selector = bytes4(data[data.length - 24:data.length - 20]); bytes4 selector = bytes4(data[data.length - 24:data.length - 20]);
address executor = address(uint160(bytes20(data[data.length - 20:]))); address executor = address(uint160(bytes20(data[data.length - 20:])));
bytes memory protocolData = data[:data.length - 24]; bytes memory protocolData = data[:data.length - 24];
_handleCallback(selector, abi.encodePacked(protocolData, executor));
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");
return ""; return "";
} }
} }

View File

@@ -1,10 +1,10 @@
// SPDX-License-Identifier: UNLICENSED // SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26; pragma solidity ^0.8.26;
import "@src/ExecutionDispatcher.sol"; import "@src/Dispatcher.sol";
import "./TychoRouterTestSetup.sol"; import "./TychoRouterTestSetup.sol";
contract ExecutionDispatcherExposed is ExecutionDispatcher { contract DispatcherExposed is Dispatcher {
function exposedCallExecutor( function exposedCallExecutor(
address executor, address executor,
bytes4 selector, bytes4 selector,
@@ -23,8 +23,8 @@ contract ExecutionDispatcherExposed is ExecutionDispatcher {
} }
} }
contract ExecutionDispatcherTest is Constants { contract DispatcherTest is Constants {
ExecutionDispatcherExposed dispatcherExposed; DispatcherExposed dispatcherExposed;
event ExecutorSet(address indexed executor); event ExecutorSet(address indexed executor);
event ExecutorRemoved(address indexed executor); event ExecutorRemoved(address indexed executor);
@@ -32,7 +32,7 @@ contract ExecutionDispatcherTest is Constants {
function setUp() public { function setUp() public {
uint256 forkBlock = 20673900; uint256 forkBlock = 20673900;
vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock);
dispatcherExposed = new ExecutionDispatcherExposed(); dispatcherExposed = new DispatcherExposed();
deal(WETH_ADDR, address(dispatcherExposed), 15 ether); deal(WETH_ADDR, address(dispatcherExposed), 15 ether);
deployDummyContract(); deployDummyContract();
} }
@@ -61,9 +61,7 @@ contract ExecutionDispatcherTest is Constants {
function testSetExecutorNonContract() public { function testSetExecutorNonContract() public {
vm.expectRevert( vm.expectRevert(
abi.encodeWithSelector( abi.encodeWithSelector(Dispatcher__NonContractExecutor.selector)
ExecutionDispatcher__NonContractExecutor.selector
)
); );
dispatcherExposed.exposedSetExecutor(BOB); dispatcherExposed.exposedSetExecutor(BOB);
} }