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];
}
}