// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract H11XPegOracle is AccessControl { bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE"); string public constant REFERENCE_BOUNDARY = "Internal protocol reference only; not fiat backing, redemption rights, banking functionality, or market price."; IERC20 public immutable h11xToken; uint256 private constant H11X_DECIMALS = 11; uint256 private constant H11X_UNIT = 10 ** H11X_DECIMALS; uint256 private priceUsd18; bool public pegEnabled; event PegConfigured(uint256 priceUsd18, bool enabled); error ZeroAddress(); error InvalidPrice(); constructor(address h11xTokenAddress, address initialGovernor) { if (h11xTokenAddress == address(0) || initialGovernor == address(0)) { revert ZeroAddress(); } h11xToken = IERC20(h11xTokenAddress); _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(GOVERNOR_ROLE, initialGovernor); priceUsd18 = 1e18; pegEnabled = false; emit PegConfigured(priceUsd18, pegEnabled); } function priceUsd() external view returns (uint256) { return priceUsd18; } function setPriceUsd(uint256 newPriceUsd18) external onlyRole(GOVERNOR_ROLE) { if (newPriceUsd18 == 0) { revert InvalidPrice(); } priceUsd18 = newPriceUsd18; emit PegConfigured(priceUsd18, pegEnabled); } function setPegEnabled(bool enabled) external onlyRole(GOVERNOR_ROLE) { pegEnabled = enabled; emit PegConfigured(priceUsd18, pegEnabled); } function grantGovernor(address account) external onlyRole(DEFAULT_ADMIN_ROLE) { _grantRole(GOVERNOR_ROLE, account); } function revokeGovernor(address account) external onlyRole(DEFAULT_ADMIN_ROLE) { _revokeRole(GOVERNOR_ROLE, account); } function usdValue(uint256 h11xUnits) external view returns (uint256) { if (!pegEnabled) { return 0; } uint256 whole = h11xUnits / H11X_UNIT; uint256 remainder = h11xUnits % H11X_UNIT; return whole * priceUsd18 + (remainder * priceUsd18) / H11X_UNIT; } function h11xUnitsForUsd(uint256 usdValue18) external view returns (uint256) { if (!pegEnabled) { return 0; } return (usdValue18 * H11X_UNIT) / priceUsd18; } }