// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IAtomicSettlementAdapter} from "./interfaces/IAtomicSettlementAdapter.sol"; contract AtomicSettlementRouter is AccessControl { using SafeERC20 for IERC20; bytes32 public constant COORDINATOR_ROLE = keccak256("COORDINATOR_ROLE"); bytes32 public constant ADAPTER_MANAGER_ROLE = keccak256("ADAPTER_MANAGER_ROLE"); mapping(bytes32 => address) public adapters; event AdapterSet(bytes32 indexed settlementMode, address indexed adapter); event SettlementExecuted( bytes32 indexed obligationId, bytes32 indexed settlementMode, address indexed token, uint256 amount, bytes32 settlementId ); error MissingAdapter(); constructor(address admin) { _grantRole(DEFAULT_ADMIN_ROLE, admin); _grantRole(ADAPTER_MANAGER_ROLE, admin); } function setAdapter(bytes32 settlementMode, address adapter) external onlyRole(ADAPTER_MANAGER_ROLE) { adapters[settlementMode] = adapter; emit AdapterSet(settlementMode, adapter); } function executeSettlement( bytes32 obligationId, bytes32 settlementMode, address token, uint256 amount, address recipient, bytes calldata data ) external payable onlyRole(COORDINATOR_ROLE) returns (bytes32 settlementId) { address adapter = adapters[settlementMode]; if (adapter == address(0)) revert MissingAdapter(); IERC20(token).safeTransfer(adapter, amount); settlementId = IAtomicSettlementAdapter(adapter).executeSettlement{value: msg.value}( obligationId, token, amount, recipient, data ); emit SettlementExecuted(obligationId, settlementMode, token, amount, settlementId); } }