// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // Educational example: deploy only in Remix VM for this course. contract Attendance { address public immutable owner; mapping(bytes32 => bool) public events; mapping(bytes32 => bool) public certificates; event Issued(bytes32 indexed eventId, bytes32 indexed guestId, bytes32 certificateId); constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "Not authorized"); _; } function createEvent(string calldata id) external onlyOwner { require(bytes(id).length > 0, "Empty event"); bytes32 key = keccak256(bytes(id)); require(!events[key], "Duplicate event"); events[key] = true; } function issue(string calldata eventId, string calldata guestId) external onlyOwner returns (bytes32) { require(bytes(guestId).length > 0, "Empty guest"); bytes32 eventKey = keccak256(bytes(eventId)); require(events[eventKey], "Unknown event"); bytes32 key = keccak256(abi.encode(eventId, guestId)); require(!certificates[key], "Duplicate certificate"); certificates[key] = true; emit Issued(eventKey, keccak256(bytes(guestId)), key); return key; } function verify(string calldata eventId, string calldata guestId) external view returns (bool) { return certificates[keccak256(abi.encode(eventId, guestId))]; } }