Development of Academic Credentials System on Blockchain
Academic credentials — not just diploma. This is microcertificates, badges, conference participation confirmations, specializations, professional licenses. The system must support this entire spectrum and be compatible with international standards — primarily W3C Verifiable Credentials and IMS Open Badges 3.0.
ERC-1155 for Credential Portfolio
Unlike diploma (single document), credential portfolio is a collection of badges of different types. ERC-1155 multi-token standard is better suited than ERC-721: one contract serves all credential types, batch transfer for issuing multiple badges simultaneously.
contract AcademicCredentials is ERC1155, AccessControl {
bytes32 public constant ISSUER_ROLE = keccak256("ISSUER_ROLE");
struct CredentialType {
string name;
string description;
string category; // "DEGREE", "CERTIFICATE", "BADGE", "MICROCREDENTIAL"
uint256 totalIssued;
bool active;
}
// tokenId => CredentialType
mapping(uint256 => CredentialType) public credentialTypes;
// tokenId => recipient => metadata (excludes duplicates)
mapping(uint256 => mapping(address => bytes32)) public credentialMetadata;
// SBT: prevent credential transfer
function safeTransferFrom(address, address, uint256, uint256, bytes memory)
public pure override
{
revert("Credentials are non-transferable");
}
function safeBatchTransferFrom(address, address, uint256[] memory, uint256[] memory, bytes memory)
public pure override
{
revert("Credentials are non-transferable");
}
function issueCredential(
address recipient,
uint256 credentialTypeId,
bytes32 metadataHash
) external onlyRole(ISSUER_ROLE) {
require(credentialTypes[credentialTypeId].active, "Credential type inactive");
require(credentialMetadata[credentialTypeId][recipient] == 0, "Already issued");
_mint(recipient, credentialTypeId, 1, "");
credentialMetadata[credentialTypeId][recipient] = metadataHash;
credentialTypes[credentialTypeId].totalIssued++;
emit CredentialIssued(recipient, credentialTypeId, metadataHash);
}
// Batch issuance of multiple credential types to one recipient
function batchIssueCredentials(
address recipient,
uint256[] calldata credentialTypeIds,
bytes32[] calldata metadataHashes
) external onlyRole(ISSUER_ROLE) {
uint256[] memory amounts = new uint256[](credentialTypeIds.length);
for (uint i = 0; i < credentialTypeIds.length; i++) {
amounts[i] = 1;
}
_mintBatch(recipient, credentialTypeIds, amounts, "");
}
}
Metadata Standard
IPFS metadata for each credential per Open Badges 3.0 schema:
{
"@context": ["https://www.w3.org/2018/credentials/v1", "https://w3id.org/openbadges/v3"],
"type": ["VerifiableCredential", "OpenBadgeCredential"],
"name": "Advanced Solidity Developer",
"description": "Completion of Advanced Solidity course with score ≥ 85%",
"image": "ipfs://QmBadgeImage...",
"criteria": {
"narrative": "Complete all modules, pass final exam with score ≥ 85%"
},
"credentialSubject": {
"achievement": {
"achievementType": "Certificate",
"creator": { "id": "did:ethr:0xIssuerAddress", "name": "Blockchain Academy" },
"name": "Advanced Solidity Developer"
}
},
"issuanceDate": "2024-01-15T10:00:00Z"
}
Verification by Employer
Simplified flow for HR:
async function verifyCredentialPortfolio(
candidateAddress: string,
requiredCredentials: string[]
): Promise<PortfolioVerification> {
const tokenIds = await Promise.all(
requiredCredentials.map(name => getTokenIdByName(name))
);
const balances = await credentialsContract.balanceOfBatch(
tokenIds.map(() => candidateAddress),
tokenIds
);
const verifiedCredentials = await Promise.all(
tokenIds.map(async (tokenId, index) => {
if (balances[index].eq(0)) return { name: requiredCredentials[index], valid: false };
const metadataHash = await credentialsContract.credentialMetadata(tokenId, candidateAddress);
const metadata = await fetchFromIPFS(metadataHash);
return {
name: requiredCredentials[index],
valid: true,
issuedAt: metadata.issuanceDate,
issuer: metadata.credentialSubject?.achievement?.creator?.name,
};
})
);
return {
candidateAddress,
verifiedCredentials,
allRequirementsMet: verifiedCredentials.every(c => c.valid),
};
}
Academic credentials system with ERC-1155, Open Badges 3.0 metadata and HR verification portal — 4-6 weeks development. Adding W3C VC signatures and DID integration — another 2-3 weeks.







