// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import {OMNLJurisdictionPolicyRegistry} from "../../contracts/hybx-omnl/OMNLJurisdictionPolicyRegistry.sol"; import {OMNLNotaryRegistry} from "../../contracts/hybx-omnl/OMNLNotaryRegistry.sol"; import {OMNLComplianceMultisig} from "../../contracts/hybx-omnl/OMNLComplianceMultisig.sol"; contract NotaryAndMultisigTest is Test { uint256 internal constant PK1 = 0xA11CE; uint256 internal constant PK2 = 0xB0B; OMNLJurisdictionPolicyRegistry public jurisdiction; OMNLNotaryRegistry public notary; OMNLComplianceMultisig public multisig; bytes32 internal constant JUR_ID = keccak256("ID"); bytes32 internal constant ROW_ID = keccak256("ID-OMNL-001"); bytes32 internal constant CONTENT = keccak256("package-hash"); function setUp() public { jurisdiction = new OMNLJurisdictionPolicyRegistry(address(this)); notary = new OMNLNotaryRegistry(address(this), address(jurisdiction)); multisig = new OMNLComplianceMultisig(address(this), address(notary)); jurisdiction.publishPolicy(JUR_ID, keccak256("policy-v1"), 2, 2, 2, true); address s1 = vm.addr(PK1); address s2 = vm.addr(PK2); notary.setNotarySigner(s1, true); notary.setNotarySigner(s2, true); notary.setGlobalNotaryThreshold(2); multisig.grantRole(multisig.ADMIN_SIGNER_ROLE(), s1); multisig.grantRole(multisig.ADMIN_SIGNER_ROLE(), s2); multisig.grantRole(multisig.PROPOSER_ROLE(), address(this)); multisig.setAdminThreshold(2); } function testNotarizeAttested() public { bytes[] memory sigs = _notarySigs(0); vm.prank(address(0xBEEF)); bytes32 key = notary.notarizeAttested( JUR_ID, ROW_ID, CONTENT, bytes32(uint256(1)), bytes32(uint256(2)), OMNLNotaryRegistry.NotarizationKind.EvidencePackage, 0, sigs ); assertTrue(notary.isNotarized(JUR_ID, ROW_ID, CONTENT)); OMNLNotaryRegistry.NotarizationRecord memory r = notary.getNotarization(key); assertEq(r.version, 1); } function testMultisigGatedExecution() public { bytes[] memory sigs = _notarySigs(0); notary.notarizeAttested( JUR_ID, ROW_ID, CONTENT, bytes32(uint256(1)), bytes32(uint256(2)), OMNLNotaryRegistry.NotarizationKind.EvidencePackage, 0, sigs ); Target t = new Target(); uint256 executionId = multisig.submitExecution(JUR_ID, address(t), 0, abi.encodeCall(Target.touch, ()), true, CONTENT, ROW_ID); vm.prank(vm.addr(PK1)); multisig.confirmExecution(executionId); multisig.executePending(executionId); assertTrue(t.touched()); } function _notarySigs(uint256 nonce) internal view returns (bytes[] memory sigs) { sigs = new bytes[](2); sigs[0] = _signNotary(PK1, nonce); sigs[1] = _signNotary(PK2, nonce); } function _signNotary(uint256 pk, uint256 nonce) internal view returns (bytes memory) { bytes32 digest = keccak256( abi.encode( notary.NOTARIZATION_TYPEHASH(), block.chainid, address(notary), JUR_ID, ROW_ID, CONTENT, bytes32(uint256(1)), bytes32(uint256(2)), nonce ) ); bytes32 ethSignedMessageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", digest)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(pk, ethSignedMessageHash); return abi.encodePacked(r, s, v); } } contract Target { bool public touched; function touch() external { touched = true; } }