Files
smom-dbis-138/contracts/hybx-omnl/ComplianceCore.sol
defiQUG f3d2961b97
Some checks failed
CI/CD Pipeline / Lint and Format (push) Failing after 46s
CI/CD Pipeline / Terraform Validation (push) Failing after 35s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 37s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 1m50s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 2m19s
Validation / validate-genesis (push) Successful in 51s
Validation / validate-terraform (push) Failing after 39s
Validation / validate-kubernetes (push) Failing after 10s
CI/CD Pipeline / Solidity Contracts (push) Failing after 12m56s
Validation / validate-smart-contracts (push) Failing after 12s
CI/CD Pipeline / Security Scanning (push) Failing after 15m52s
Validation / validate-security (push) Failing after 10m59s
Validation / validate-documentation (push) Failing after 17s
Validate Token List / validate (push) Failing after 30s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 26s
Verify Deployment / Verify Deployment (push) Failing after 56s
feat: add hybx omnl stack and gas pmm tooling
2026-04-24 12:56:40 -07:00

163 lines
6.2 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {InstrumentRegistry} from "./InstrumentRegistry.sol";
import {ReserveCommitmentStore} from "./ReserveCommitmentStore.sol";
import {OMNLCircuitBreaker} from "./OMNLCircuitBreaker.sol";
import {PolicyMath} from "./PolicyMath.sol";
/**
* @title ComplianceCore
* @notice Aggregates on-chain supply + attested reserves; enforces policy; emits audit events.
* @dev Integrated minters call assertCanMintM0/M1 before minting.
*/
contract ComplianceCore {
InstrumentRegistry public immutable registry;
ReserveCommitmentStore public immutable reserves;
OMNLCircuitBreaker public immutable breakers;
event ComplianceSnapshot(
bytes32 indexed lineId,
uint256 s0,
uint256 s1,
uint256 r,
uint256 validUntil,
bytes32 evidenceHash,
bytes32 merkleRoot,
bool m0Ok,
bool m1Ok,
bool attestationStale,
bool policyOk,
bool reportingCompliant
);
error ComplianceBlocked(bytes32 lineId, string reason);
error UnknownLine(bytes32 lineId);
constructor(address registry_, address reserves_, address breakers_) {
require(registry_ != address(0) && reserves_ != address(0) && breakers_ != address(0), "ComplianceCore: zero");
registry = InstrumentRegistry(registry_);
reserves = ReserveCommitmentStore(reserves_);
breakers = OMNLCircuitBreaker(breakers_);
}
function _loadSupplies(bytes32 lineId) internal view returns (uint256 s0, uint256 s1) {
InstrumentRegistry.Line memory line = registry.getLine(lineId);
if (line.tokenM0 == address(0)) revert UnknownLine(lineId);
s0 = IERC20(line.tokenM0).totalSupply();
s1 = IERC20(line.tokenM1).totalSupply();
}
function _stale(uint256 validUntil) internal view returns (bool) {
return block.timestamp > validUntil;
}
/**
* @notice Full deterministic compliance view for dashboards and off-chain API.
* @dev reportingCompliant is false when attestation is stale or breakers trip, even if pure math (policyOk) holds.
*/
function getCompliance(bytes32 lineId)
external
view
returns (
uint256 s0,
uint256 s1,
uint256 r,
uint256 validUntil,
bytes32 evidenceHash,
bytes32 merkleRoot,
uint256 minR,
uint256 maxS1,
bool m0Ok,
bool m1Ok,
bool attestationStale,
bool policyOk,
bool operational,
bool reportingCompliant
)
{
(s0, s1) = _loadSupplies(lineId);
ReserveCommitmentStore.Commitment memory c = reserves.getCommitment(lineId);
r = c.R;
validUntil = c.validUntil;
evidenceHash = c.evidenceHash;
merkleRoot = c.merkleRoot;
minR = PolicyMath.minReservesForM0(s0);
maxS1 = PolicyMath.maxM1ForM0(s0);
attestationStale = _stale(validUntil);
m0Ok = PolicyMath.m0BackingOk(s0, r);
m1Ok = PolicyMath.m1ExpansionOk(s0, s1);
policyOk = PolicyMath.isCompliant(s0, s1, r);
operational = breakers.isLineOperational(lineId);
reportingCompliant = policyOk && !attestationStale && operational;
}
/// @notice Reverts if global/line pause or policy would fail after minting delta M0.
function assertCanMintM0(bytes32 lineId, uint256 mintAmount) external view {
if (!breakers.isLineOperational(lineId)) revert ComplianceBlocked(lineId, "paused");
InstrumentRegistry.Line memory line = registry.getLine(lineId);
if (line.tokenM0 == address(0)) revert UnknownLine(lineId);
if (!line.active) revert ComplianceBlocked(lineId, "inactive");
ReserveCommitmentStore.Commitment memory c = reserves.getCommitment(lineId);
if (breakers.enforceStaleBlockM0() && _stale(c.validUntil)) {
revert ComplianceBlocked(lineId, "stale_attestation");
}
uint256 s0 = IERC20(line.tokenM0).totalSupply();
if (!PolicyMath.canMintM0(s0, mintAmount, c.R)) {
revert ComplianceBlocked(lineId, "m0_backing");
}
}
/// @notice Reverts if global/line pause or M1 cap exceeded after mint.
function assertCanMintM1(bytes32 lineId, uint256 mintAmount) external view {
if (!breakers.isLineOperational(lineId)) revert ComplianceBlocked(lineId, "paused");
InstrumentRegistry.Line memory line = registry.getLine(lineId);
if (line.tokenM0 == address(0)) revert UnknownLine(lineId);
if (!line.active) revert ComplianceBlocked(lineId, "inactive");
ReserveCommitmentStore.Commitment memory c = reserves.getCommitment(lineId);
if (breakers.enforceStaleBlockM1() && _stale(c.validUntil)) {
revert ComplianceBlocked(lineId, "stale_attestation");
}
uint256 s0 = IERC20(line.tokenM0).totalSupply();
uint256 s1 = IERC20(line.tokenM1).totalSupply();
if (!PolicyMath.canMintM1(s0, s1, mintAmount)) {
revert ComplianceBlocked(lineId, "m1_cap");
}
}
/// @notice Permissionless heartbeat for indexers — emits current snapshot (costs gas for caller).
function emitComplianceSnapshot(bytes32 lineId) external {
InstrumentRegistry.Line memory line = registry.getLine(lineId);
if (line.tokenM0 == address(0)) revert UnknownLine(lineId);
uint256 s0 = IERC20(line.tokenM0).totalSupply();
uint256 s1 = IERC20(line.tokenM1).totalSupply();
ReserveCommitmentStore.Commitment memory c = reserves.getCommitment(lineId);
bool stale_ = _stale(c.validUntil);
bool m0Ok = PolicyMath.m0BackingOk(s0, c.R);
bool m1Ok = PolicyMath.m1ExpansionOk(s0, s1);
bool policyOk = PolicyMath.isCompliant(s0, s1, c.R);
bool operational = breakers.isLineOperational(lineId);
bool reporting = policyOk && !stale_ && operational;
emit ComplianceSnapshot(
lineId,
s0,
s1,
c.R,
c.validUntil,
c.evidenceHash,
c.merkleRoot,
m0Ok,
m1Ok,
stale_,
policyOk,
reporting
);
}
}