// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; // Command implementations import {Dispatcher} from './base/Dispatcher.sol'; import {RouteSigner} from './base/RouteSigner.sol'; import {RouterParameters} from './types/RouterParameters.sol'; import {PaymentsImmutables, PaymentsParameters} from './modules/PaymentsImmutables.sol'; import {UniswapImmutables, UniswapParameters} from './modules/uniswap/UniswapImmutables.sol'; import {V4SwapRouter} from './modules/uniswap/v4/V4SwapRouter.sol'; import {Commands} from './libraries/Commands.sol'; import {IUniversalRouter} from './interfaces/IUniversalRouter.sol'; import {MigratorImmutables, MigratorParameters} from './modules/MigratorImmutables.sol'; import {EIP712} from '@openzeppelin/contracts/utils/cryptography/EIP712.sol'; import {ChainedActions} from './modules/ChainedActions.sol'; contract UniversalRouter is IUniversalRouter, ChainedActions, RouteSigner, Dispatcher { constructor(RouterParameters memory params) UniswapImmutables(UniswapParameters( params.v2Factory, params.v3Factory, params.pairInitCodeHash, params.poolInitCodeHash )) V4SwapRouter(params.v4PoolManager) PaymentsImmutables(PaymentsParameters(params.permit2, params.weth9)) MigratorImmutables(MigratorParameters(params.v3NFTPositionManager, params.v4PositionManager)) ChainedActions(params.spokePool) EIP712('UniversalRouter', '2') {} modifier checkDeadline(uint256 deadline) { if (block.timestamp > deadline) revert TransactionDeadlinePassed(); _; } /// @notice To receive ETH from WETH receive() external payable { if (msg.sender != address(WETH9) && msg.sender != address(poolManager)) revert InvalidEthSender(); } /// @inheritdoc IUniversalRouter function execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline) external payable checkDeadline(deadline) { execute(commands, inputs); } /// @inheritdoc IUniversalRouter function executeSigned( bytes calldata commands, bytes[] calldata inputs, bytes32 intent, bytes32 data, bool verifySender, bytes32 nonce, bytes calldata signature, uint256 deadline ) external payable checkDeadline(deadline) { // Set signature context and verify _setSignatureContext(commands, inputs, intent, data, verifySender, nonce, signature, deadline); // Execute commands execute(commands, inputs); // Clear signature context _resetSignatureContext(); } /// @inheritdoc Dispatcher function execute(bytes calldata commands, bytes[] calldata inputs) public payable override isNotLocked { bool success; bytes memory output; uint256 numCommands = commands.length; if (inputs.length != numCommands) revert LengthMismatch(); // loop through all given commands, execute them and pass along outputs as defined for (uint256 commandIndex = 0; commandIndex < numCommands; commandIndex++) { bytes1 command = commands[commandIndex]; bytes calldata input = inputs[commandIndex]; (success, output) = dispatch(command, input); if (!success && successRequired(command)) { revert ExecutionFailed({commandIndex: commandIndex, message: output}); } } } /// @inheritdoc IUniversalRouter function signedRouteContext() external view returns (address signer, bytes32 intent, bytes32 data) { return _signedRouteContext(); } function successRequired(bytes1 command) internal pure returns (bool) { return command & Commands.FLAG_ALLOW_REVERT == 0; } }