feat: rename execution dispatcher to dispatcher and use dispatcher for USV4 callback
This commit is contained in:
@@ -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 =
|
||||||
@@ -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 "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user