I am kinda a novice in blockchain developement, I am working on a blockchain powered academic certificate issuance project
Now I have built my smart contract and have it deployed on the sepolia testnet, it deploys successfully, i will provide you with all the necessary codes to show this.
But i am not sure all my functions for my contract is working, they all work on remix though, so i cretaed a test script to test it but here is the error i get:
Error:
(base) ACV % npx hardhat test
CertificateManagement
✔ Should add and verify a new issuer
✔ Should remove and verify an issuer
1) Should issue a certificate
2) Should revoke a certificate
3) Should verify certificate validity
2 passing (516ms)
3 failing
1) CertificateManagement
Should issue a certificate:
TypeError: Cannot read properties of undefined (reading 'find')
at Context.<anonymous> (test/CertificateManagement.js:33:34)
2) CertificateManagement
Should revoke a certificate:
TypeError: Cannot read properties of undefined (reading 'find')
at Context.<anonymous> (test/CertificateManagement.js:48:34)
3) CertificateManagement
Should verify certificate validity:
TypeError: Cannot read properties of undefined (reading 'find')
at Context.<anonymous> (test/CertificateManagement.js:61:34)
contracts/CertificateManagement.sol:
pragma solidity ^0.8.19;
contract CertificateManagement {
// Struct to store certificate information
struct Certificate {
uint256 id;
string studentName;
string course;
uint256 issueDate;
bool isValid;
string issuer;
}
// Mapping from certificate ID to certificate details
mapping(uint256 => Certificate) public certificates;
// Mapping from an address to a boolean indicating if it is authorized to issue and revoke certificates
mapping(address => bool) public authorizedIssuers;
// Event emitted when a certificate is issued
event CertificateIssued(uint256 indexed certificateID, string studentName, string issuer);
// Event emitted when a certificate is revoked
event CertificateRevoked(uint256 indexed certificateID);
// Modifier to check if the caller is an authorized issuer
modifier onlyAuthorized() {
require(authorizedIssuers[msg.sender], "Caller is not authorized");
_;
}
constructor() {
// The deployer of the contract is the initial authorized issuer
authorizedIssuers[msg.sender] = true;
}
// Function to authorize a new issuer
function addIssuer(address issuer) external onlyAuthorized {
authorizedIssuers[issuer] = true;
}
// Function to revoke issuer rights
function removeIssuer(address issuer) external onlyAuthorized {
authorizedIssuers[issuer] = false;
}
// Function to issue a new certificate
function issueCertificate(string memory studentName, string memory course, string memory issuer) public onlyAuthorized returns (uint256) {
uint256 newCertificateID = uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender, studentName, course)));
certificates[newCertificateID] = Certificate(newCertificateID, studentName, course, block.timestamp, true, issuer);
emit CertificateIssued(newCertificateID, studentName, issuer);
return newCertificateID;
}
// Function to revoke a certificate
function revokeCertificate(uint256 certificateID) public onlyAuthorized {
require(certificates[certificateID].isValid, "Certificate already revoked");
certificates[certificateID].isValid = false;
emit CertificateRevoked(certificateID);
}
// Function to verify the validity of a certificate
function verifyCertificate(uint256 certificateID) public view returns (bool) {
return certificates[certificateID].isValid;
}
}
scripts/deploy.js:
const { ethers } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
const CertificateManagement = await ethers.getContractFactory("CertificateManagement");
const certManagement = await CertificateManagement.deploy();
await certManagement.waitForDeployment();
console.log("CertificateManagement deployed to:", await certManagement.getAddress());
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error("Deployment failed:", error);
process.exit(1);
});
test/CeritificateManagement.js:
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("CertificateManagement", function () {
let certManagement;
let owner;
let addr1;
let addr2;
beforeEach(async function () {
const CertificateManagement = await ethers.getContractFactory("CertificateManagement");
[owner, addr1, addr2] = await ethers.getSigners();
certManagement = await CertificateManagement.deploy();
await certManagement.deployed();
});
it("Should add and verify a new issuer", async function () {
await certManagement.addIssuer(addr1.address);
expect(await certManagement.authorizedIssuers(addr1.address)).to.equal(true);
});
it("Should remove and verify an issuer", async function () {
await certManagement.addIssuer(addr1.address);
await certManagement.removeIssuer(addr1.address);
expect(await certManagement.authorizedIssuers(addr1.address)).to.equal(false);
});
it("Should issue a certificate", async function () {
await certManagement.addIssuer(addr1.address);
const tx = await certManagement.connect(addr1).issueCertificate("John Doe", "Blockchain 101", "University");
const receipt = await tx.wait();
const event = receipt.events.find(event => event.event === 'CertificateIssued');
const certificateID = event.args.certificateID;
const certificate = await certManagement.certificates(certificateID);
expect(certificate.studentName).to.equal("John Doe");
expect(certificate.course).to.equal("Blockchain 101");
expect(certificate.issuer).to.equal("University");
expect(certificate.isValid).to.equal(true);
});
it("Should revoke a certificate", async function () {
await certManagement.addIssuer(addr1.address);
const tx = await certManagement.connect(addr1).issueCertificate("John Doe", "Blockchain 101", "University");
const receipt = await tx.wait();
const event = receipt.events.find(event => event.event === 'CertificateIssued');
const certificateID = event.args.certificateID;
await certManagement.connect(addr1).revokeCertificate(certificateID);
const certificate = await certManagement.certificates(certificateID);
expect(certificate.isValid).to.equal(false);
});
it("Should verify certificate validity", async function () {
await certManagement.addIssuer(addr1.address);
const tx = await certManagement.connect(addr1).issueCertificate("John Doe", "Blockchain 101", "University");
const receipt = await tx.wait();
const event = receipt.events.find(event => event.event === 'CertificateIssued');
const certificateID = event.args.certificateID;
let isValid = await certManagement.verifyCertificate(certificateID);
expect(isValid).to.equal(true);
await certManagement.connect(addr1).revokeCertificate(certificateID);
isValid = await certManagement.verifyCertificate(certificateID);
expect(isValid).to.equal(false);
});
});
hardhat.config.js:
require("@nomicfoundation/hardhat-toolbox");
module.exports = {
solidity: "0.8.19",
networks: {
sepolia: {
url: "https://sepolia.infura.io/v3/xxxxxxxxxxx",
accounts: ['xxxxxxxxxxxxxxxxx']
}
}
};