// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "forge-std/Test.sol"; import { EvidenceRegistryV3 } from "../../contracts/evidence/EvidenceRegistryV3.sol"; contract EvidenceRegistryV3Test is Test { uint256 internal constant ATTESTER_KEY = 0xA771; address internal owner = address(0xBEEF); address internal attester = vm.addr(ATTESTER_KEY); EvidenceRegistryV3 internal evidence; function setUp() public { evidence = new EvidenceRegistryV3(owner); vm.prank(owner); evidence.setAttester(attester, true); } function test_attesterNonceIsIsolatedAndObservationWindowIsValidated() external { EvidenceRegistryV3.Attestation memory a = EvidenceRegistryV3.Attestation({ attester: attester, attesterAuthority: keccak256("authority"), subject: keccak256("subject"), bondOrMandate: keccak256("bond"), evidenceSchema: keccak256("schema"), evidenceCommitment: keccak256("commitment"), observationStart: uint64(block.timestamp), observationEnd: uint64(block.timestamp), timestamp: uint64(block.timestamp), expiresAt: uint64(block.timestamp + 1 days), nonce: 7, independenceClass: 2, round: 1 }); bytes memory sig = _sign(a); evidence.register(a, sig); assertTrue(evidence.nonceUsed(attester, 7)); a.round = 2; a.evidenceCommitment = keccak256("different"); bytes memory reusedNonceSig = _sign(a); vm.expectRevert(EvidenceRegistryV3.NonceUsed.selector); evidence.register(a, reusedNonceSig); a.nonce = 8; a.observationEnd = a.observationStart - 1; vm.expectRevert(EvidenceRegistryV3.BadAttestation.selector); evidence.register(a, hex""); a.observationEnd = uint64(block.timestamp + 1); a.timestamp = a.observationEnd; vm.expectRevert(EvidenceRegistryV3.BadAttestation.selector); evidence.register(a, hex""); } function _sign(EvidenceRegistryV3.Attestation memory a) private returns (bytes memory) { bytes32 digest = keccak256(abi.encodePacked("\x19\x01", evidence.DOMAIN_SEPARATOR(), evidence.hashAttestation(a))); (uint8 v, bytes32 r, bytes32 s) = vm.sign(ATTESTER_KEY, digest); return abi.encodePacked(r, s, v); } }