Exam Integrity Smart Contract

What it does:
Ensures that exams and assessments are conducted fairly, securely, and tamper-proof on-chain.

Why it matters:
Prevents cheating, guarantees exam authenticity, provides auditable proof of completion, and increases trust in digital education and certification.

How it works:

  • Exam metadata (start/end times, allowed participants, questions hash) is stored on-chain

  • Students submit encrypted or hashed answers through the smart contract

  • Contract verifies submission deadlines and participant eligibility

  • Optionally integrates with oracles or zero-knowledge proofs for answer validation

  • Grading can be automated or submitted by authorized educators on-chain

  • Exam completion status and scores are immutably recorded

  • Audit trail ensures all exam activities are transparent and verifiable

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title ExamIntegrity
 * @author Nam
 * @notice Ensures secure, verifiable, and tamper-proof exam submissions
 */
contract ExamIntegrity {

    address public admin;
    uint256 public examCount;

    struct Exam {
        string examHash; // hash of questions or exam metadata
        uint256 startTime;
        uint256 endTime;
        address[] allowedStudents;
        mapping(address => string) submissions; // student => submission hash
        mapping(address => bool) submitted;
    }

    mapping(uint256 => Exam) public exams;

    // -------------------- EVENTS --------------------

    event ExamCreated(uint256 indexed examId, uint256 startTime, uint256 endTime);
    event SubmissionMade(uint256 indexed examId, address indexed student, string submissionHash);

    // -------------------- MODIFIERS --------------------

    modifier onlyAdmin() {
        require(msg.sender == admin, "Not admin");
        _;
    }

    modifier onlyAllowedStudent(uint256 _examId) {
        Exam storage e = exams[_examId];
        bool allowed = false;
        for (uint256 i = 0; i < e.allowedStudents.length; i++) {
            if (e.allowedStudents[i] == msg.sender) {
                allowed = true;
                break;
            }
        }
        require(allowed, "Not allowed student");
        _;
    }

    // -------------------- CONSTRUCTOR --------------------

    constructor() {
        admin = msg.sender;
    }

    // -------------------- EXAM MANAGEMENT --------------------

    function createExam(string calldata _examHash, uint256 _startTime, uint256 _endTime, address[] calldata _students) external onlyAdmin {
        require(_startTime  0, "No students");

        examCount += 1;
        Exam storage e = exams[examCount];
        e.examHash = _examHash;
        e.startTime = _startTime;
        e.endTime = _endTime;
        e.allowedStudents = _students;

        emit ExamCreated(examCount, _startTime, _endTime);
    }

    function submitExam(uint256 _examId, string calldata _submissionHash) external onlyAllowedStudent(_examId) {
        Exam storage e = exams[_examId];
        require(block.timestamp >= e.startTime && block.timestamp <= e.endTime, "Outside submission window");
        require(!e.submitted[msg.sender], "Already submitted");

        e.submissions[msg.sender] = _submissionHash;
        e.submitted[msg.sender] = true;

        emit SubmissionMade(_examId, msg.sender, _submissionHash);
    }

    function getSubmission(uint256 _examId, address _student) external view returns (string memory) {
        return exams[_examId].submissions[_student];
    }
}