// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/AccessControl.sol"; contract AtomicFeePolicy is AccessControl { bytes32 public constant POLICY_MANAGER_ROLE = keccak256("POLICY_MANAGER_ROLE"); struct CorridorPolicy { uint16 fulfillerFeeBps; uint16 protocolFeeBps; uint16 bondBps; uint16 slashPenaltyBps; uint256 maxFulfilmentDelay; uint256 maxSettlementDelay; } mapping(bytes32 => CorridorPolicy) public corridorPolicies; event CorridorPolicySet( bytes32 indexed corridorId, uint16 fulfillerFeeBps, uint16 protocolFeeBps, uint16 bondBps, uint16 slashPenaltyBps, uint256 maxFulfilmentDelay, uint256 maxSettlementDelay ); constructor(address admin) { _grantRole(DEFAULT_ADMIN_ROLE, admin); _grantRole(POLICY_MANAGER_ROLE, admin); } function setCorridorPolicy( bytes32 corridorId, uint16 fulfillerFeeBps, uint16 protocolFeeBps, uint16 bondBps, uint16 slashPenaltyBps, uint256 maxFulfilmentDelay, uint256 maxSettlementDelay ) external onlyRole(POLICY_MANAGER_ROLE) { corridorPolicies[corridorId] = CorridorPolicy({ fulfillerFeeBps: fulfillerFeeBps, protocolFeeBps: protocolFeeBps, bondBps: bondBps, slashPenaltyBps: slashPenaltyBps, maxFulfilmentDelay: maxFulfilmentDelay, maxSettlementDelay: maxSettlementDelay }); emit CorridorPolicySet( corridorId, fulfillerFeeBps, protocolFeeBps, bondBps, slashPenaltyBps, maxFulfilmentDelay, maxSettlementDelay ); } function quoteFees(bytes32 corridorId, uint256 amountIn) external view returns (uint256 fulfillerFee, uint256 protocolFee) { CorridorPolicy memory policy = corridorPolicies[corridorId]; fulfillerFee = (amountIn * policy.fulfillerFeeBps) / 10_000; protocolFee = (amountIn * policy.protocolFeeBps) / 10_000; } function requiredBond(bytes32 corridorId, uint256 reservedLiquidity) external view returns (uint256) { CorridorPolicy memory policy = corridorPolicies[corridorId]; uint256 effectiveBps = policy.bondBps; uint256 slashFloor = 10_000 + policy.slashPenaltyBps; if (effectiveBps < slashFloor) { effectiveBps = slashFloor; } return (reservedLiquidity * effectiveBps) / 10_000; } }