// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/IAggregationRouter.sol"; import "../RouteTypesV2.sol"; import "../interfaces/IRouteExecutorAdapter.sol"; contract OneInchRouteExecutorAdapter is IRouteExecutorAdapter { using SafeERC20 for IERC20; function validate( RouteTypesV2.RouteLeg calldata leg ) external pure override returns (bool ok, string memory reason) { if (leg.provider != RouteTypesV2.Provider.OneInch) { return (false, "OneInchRouteExecutorAdapter: invalid provider"); } if (leg.target == address(0)) { return (false, "OneInchRouteExecutorAdapter: zero target"); } if (leg.providerData.length == 0) { return (false, "OneInchRouteExecutorAdapter: missing providerData"); } return (true, ""); } function quote( RouteTypesV2.RouteLeg calldata, uint256 ) external pure override returns (uint256 amountOut, uint256 gasEstimate) { return (0, 320000); } function execute( RouteTypesV2.RouteLeg calldata leg, uint256 amountIn ) external override returns (uint256 amountOut) { (address executor, address allowanceTarget, bytes memory data) = abi.decode(leg.providerData, (address, address, bytes)); address spender = allowanceTarget == address(0) ? leg.target : allowanceTarget; IERC20(leg.tokenIn).forceApprove(spender, 0); IERC20(leg.tokenIn).forceApprove(spender, amountIn); IAggregationRouter.SwapDescription memory desc = IAggregationRouter.SwapDescription({ srcToken: leg.tokenIn, dstToken: leg.tokenOut, srcReceiver: address(this), dstReceiver: msg.sender, amount: amountIn, minReturnAmount: leg.minAmountOut, flags: 0, permit: "" }); (amountOut,) = IAggregationRouter(leg.target).swap(executor, desc, "", data); } }