Files
smom-dbis-138/contracts/hybx-omnl/ReserveCommitmentStore.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

176 lines
6.3 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
/**
* @title ReserveCommitmentStore
* @notice Stores attested reserve R per line with TTL, merkle evidence root, versioning, primary + mirror,
* and optional threshold ECDSA attestation for commits.
*/
contract ReserveCommitmentStore is AccessControl {
bytes32 public constant RESERVE_COMMITTER_ROLE = keccak256("RESERVE_COMMITTER_ROLE");
bytes32 public constant ATTESTATION_ADMIN_ROLE = keccak256("ATTESTATION_ADMIN_ROLE");
/// @notice EIP-191 structured preimage prefix for attested commits (see commitReserveAttested).
bytes32 public constant ATTESTATION_TYPEHASH =
keccak256("OMNLReserveCommit(uint256 chainId,address store,bytes32 lineId,uint256 R,uint256 validUntil,bytes32 evidenceHash,bytes32 merkleRoot,uint256 nonce)");
struct Commitment {
uint256 R;
uint256 validUntil;
bytes32 evidenceHash;
bytes32 merkleRoot;
uint256 version;
}
address public mirrorReceiver;
mapping(bytes32 lineId => Commitment) private _commitments;
mapping(bytes32 lineId => uint256) public lineAttestationNonce;
mapping(address => bool) public isAttestationSigner;
uint256 public attestationThreshold;
event ReserveCommitted(
bytes32 indexed lineId,
uint256 R,
uint256 validUntil,
bytes32 evidenceHash,
bytes32 merkleRoot,
uint256 version,
address indexed by
);
event MirrorReceiverUpdated(address indexed oldReceiver, address indexed newReceiver);
event AttestationSignersUpdated(uint256 threshold);
event AttestationSignerSet(address indexed signer, bool active);
constructor(address admin) {
require(admin != address(0), "ReserveCommitmentStore: zero admin");
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(RESERVE_COMMITTER_ROLE, admin);
_grantRole(ATTESTATION_ADMIN_ROLE, admin);
}
function setMirrorReceiver(address receiver) external onlyRole(DEFAULT_ADMIN_ROLE) {
address old = mirrorReceiver;
mirrorReceiver = receiver;
emit MirrorReceiverUpdated(old, receiver);
}
function setAttestationSigner(address signer, bool active) external onlyRole(ATTESTATION_ADMIN_ROLE) {
isAttestationSigner[signer] = active;
emit AttestationSignerSet(signer, active);
}
function setAttestationThreshold(uint256 threshold) external onlyRole(ATTESTATION_ADMIN_ROLE) {
attestationThreshold = threshold;
emit AttestationSignersUpdated(threshold);
}
/// @notice Primary chain (or designated committer) updates reserves.
function commitReserve(
bytes32 lineId,
uint256 R,
uint256 validUntil,
bytes32 evidenceHash,
bytes32 merkleRoot
) external onlyRole(RESERVE_COMMITTER_ROLE) {
_commit(lineId, R, validUntil, evidenceHash, merkleRoot, msg.sender);
}
/// @notice Threshold ECDSA attestation (any EOA may submit once enough distinct signers included).
function commitReserveAttested(
bytes32 lineId,
uint256 R,
uint256 validUntil,
bytes32 evidenceHash,
bytes32 merkleRoot,
uint256 nonce,
bytes[] calldata signatures
) external {
require(attestationThreshold > 0, "ReserveCommitmentStore: attestation off");
require(nonce == lineAttestationNonce[lineId], "ReserveCommitmentStore: nonce");
bytes32 digest = keccak256(
abi.encode(
ATTESTATION_TYPEHASH,
block.chainid,
address(this),
lineId,
R,
validUntil,
evidenceHash,
merkleRoot,
nonce
)
);
bytes32 ethSignedMessageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", digest));
uint256 n = signatures.length;
require(n >= attestationThreshold, "ReserveCommitmentStore: sig count");
address[] memory seen = new address[](n);
uint256 uniq = 0;
for (uint256 i = 0; i < n; i++) {
address recovered = ECDSA.recover(ethSignedMessageHash, signatures[i]);
require(isAttestationSigner[recovered], "ReserveCommitmentStore: not signer");
for (uint256 j = 0; j < uniq; j++) {
require(seen[j] != recovered, "ReserveCommitmentStore: duplicate signer");
}
seen[uniq] = recovered;
unchecked {
++uniq;
}
}
require(uniq >= attestationThreshold, "ReserveCommitmentStore: threshold");
lineAttestationNonce[lineId] = nonce + 1;
_commit(lineId, R, validUntil, evidenceHash, merkleRoot, msg.sender);
}
function _commit(
bytes32 lineId,
uint256 R,
uint256 validUntil,
bytes32 evidenceHash,
bytes32 merkleRoot,
address by
) internal {
Commitment storage c = _commitments[lineId];
unchecked {
c.version += 1;
}
c.R = R;
c.validUntil = validUntil;
c.evidenceHash = evidenceHash;
c.merkleRoot = merkleRoot;
emit ReserveCommitted(lineId, R, validUntil, evidenceHash, merkleRoot, c.version, by);
}
/// @notice Applied by OMNLMirrorReceiver after CCIP validation (monotonic version).
function applyMirrorCommit(
bytes32 lineId,
uint256 R,
uint256 validUntil,
bytes32 evidenceHash,
bytes32 merkleRoot,
uint256 version
) external {
require(msg.sender == mirrorReceiver, "ReserveCommitmentStore: only mirror");
Commitment storage c = _commitments[lineId];
require(version > c.version, "ReserveCommitmentStore: version");
c.version = version;
c.R = R;
c.validUntil = validUntil;
c.evidenceHash = evidenceHash;
c.merkleRoot = merkleRoot;
emit ReserveCommitted(lineId, R, validUntil, evidenceHash, merkleRoot, version, msg.sender);
}
function getCommitment(bytes32 lineId) external view returns (Commitment memory) {
return _commitments[lineId];
}
}