// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract ThresholdReceiptWitness { event Attested(bytes32 indexed domain, bytes32 indexed receiptHash, address indexed attester, uint256 totalAttestations); uint256 public immutable threshold; mapping(bytes32 => mapping(address => bool)) private _attested; mapping(bytes32 => uint256) private _count; constructor(uint256 threshold_) { require(threshold_ > 0); threshold = threshold_; } function attest(bytes32 domain, bytes32 receiptHash) external returns (bool) { bytes32 id = keccak256(abi.encodePacked(domain, receiptHash)); if (_attested[id][msg.sender]) { return false; } _attested[id][msg.sender] = true; uint256 total = _count[id] + 1; _count[id] = total; emit Attested(domain, receiptHash, msg.sender, total); return true; } function isValid(bytes32 domain, bytes32 receiptHash) external view returns (bool) { bytes32 id = keccak256(abi.encodePacked(domain, receiptHash)); return _count[id] >= threshold; } }