// 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 "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; interface IDODOPMMSwapPool { function _BASE_TOKEN_() external view returns (address); function _QUOTE_TOKEN_() external view returns (address); function sellBase(address to) external returns (uint256 receiveQuoteAmount); function sellQuote(address to) external returns (uint256 receiveBaseAmount); } /** * @notice Minimal public adapter for DVM-style Chain 138 PMM pools. * @dev Keeps the atomic-swap dapp's existing swapExactIn surface while using * the pool execution selectors exposed by the Chain 138 PMM pools. */ contract DODOPMMSwapAdapter is ReentrancyGuard { using SafeERC20 for IERC20; event SwapExecuted( address indexed pool, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, address trader ); function swapExactIn( address pool, address tokenIn, uint256 amountIn, uint256 minAmountOut ) external nonReentrant returns (uint256 amountOut) { require(pool != address(0), "DODOPMMSwapAdapter: zero pool"); require(tokenIn != address(0), "DODOPMMSwapAdapter: zero token"); require(amountIn > 0, "DODOPMMSwapAdapter: zero amount"); address baseToken = IDODOPMMSwapPool(pool)._BASE_TOKEN_(); address quoteToken = IDODOPMMSwapPool(pool)._QUOTE_TOKEN_(); address tokenOut; if (tokenIn == baseToken) { tokenOut = quoteToken; IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn); amountOut = IDODOPMMSwapPool(pool).sellBase(msg.sender); } else if (tokenIn == quoteToken) { tokenOut = baseToken; IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn); amountOut = IDODOPMMSwapPool(pool).sellQuote(msg.sender); } else { revert("DODOPMMSwapAdapter: token not in pool"); } require(amountOut >= minAmountOut, "DODOPMMSwapAdapter: insufficient output"); emit SwapExecuted(pool, tokenIn, tokenOut, amountIn, amountOut, msg.sender); } }