Skip to content

Repository files navigation

🎓 CredChain

Blockchain-based university credential issuance & verification. Degrees you can verify in seconds, not days.

Solidity Hardhat React Vite ethers.js Node Tests Network


What is CredChain?

Universities issue academic degrees as entries in a Solidity smart contract instead of paper certificates alone. Each credential gets a unique ID and a QR code. Anyone — an employer, another institution, an immigration office — can scan that code and get a cryptographically verified answer straight from the blockchain, in seconds, with no phone calls and no waiting on the registrar's office.

TRADITIONAL WAY:  Employer calls the university  →  waits 3–7 days  →  maybe gets confirmation
CREDCHAIN WAY:     Employer scans a QR code       →  blockchain answers in seconds  →  done

A credential recorded on-chain cannot be silently edited or forged — only wallets the issuing university has explicitly authorized can create one, and any tampering after the fact is immediately visible.

Table of Contents


How It Works

flowchart TD
    A["🏛️ University Admin<br/>fills in student, degree, CGPA"] -->|"signs transaction<br/>(must be an authorized issuer)"| B["📜 Smart Contract<br/>CredentialRegistry.sol"]
    B --> C["✅ Credential stored on-chain<br/>permanent, tamper-proof"]
    C --> D["🔳 QR Code generated<br/>encodes the credential ID"]
    D --> E["🎓 Student<br/>receives & shares the QR code"]
    E --> F["🏢 Employer / Verifier<br/>scans QR or pastes the ID"]
    F -->|"read-only, free,<br/>no wallet required"| B
    B --> G{"Status?"}
    G -->|"valid"| H["✅ Verified<br/>full details shown"]
    G -->|"revoked"| I["⚠️ Revoked<br/>flagged, not trusted"]
    G -->|"unknown ID"| J["❌ Not Found"]

    style B fill:#1b2444,stroke:#a9772c,color:#fff
    style C fill:#e5f4ec,stroke:#137a56,color:#12162a
    style H fill:#e5f4ec,stroke:#137a56,color:#12162a
    style I fill:#fbf2e1,stroke:#a9772c,color:#12162a
    style J fill:#fbeaec,stroke:#b23a45,color:#12162a
Loading

Architecture

flowchart LR
    subgraph Frontend ["Frontend — React + Vite"]
        UI["Issue / Verify UI"]
        Wallet["useWallet hook"]
    end

    subgraph Chain ["Blockchain"]
        SC["CredentialRegistry.sol<br/>(Hardhat local or Polygon Amoy)"]
    end

    MM["🦊 MetaMask<br/>(issuing only)"]

    UI -- "ethers.js v6" --> SC
    UI --> Wallet
    Wallet -- "sign & send tx" --> MM
    MM -- "broadcasts" --> SC
    UI -. "read-only query<br/>(verification, no wallet)" .-> SC

    style SC fill:#1b2444,stroke:#a9772c,color:#fff
    style MM fill:#fbf2e1,stroke:#a9772c,color:#12162a
Loading

Tech Stack

Layer Technology Why
Smart contract Solidity 0.8.24 Access-controlled issuance, revocation, on-chain storage
Contract tooling Hardhat Compile, test, deploy, local blockchain node
Blockchain calls ethers.js v6 Talks to the contract from the browser
Frontend React 18 + Vite Fast dev server, modern build tooling
Routing react-router-dom Home / Issue / Verify pages
QR generation qrcode.react, qrcode On-screen QR + downloadable credential card
QR scanning html5-qrcode Camera-based scanning on the Verify page
Wallet MetaMask Only needed by university admins issuing credentials
Target network Polygon Amoy (public) / Hardhat Local (dev) Free testnet — no real funds involved anywhere in this project

Features

  • 🔐 Institution-bound issuing — each authorized wallet is bound on-chain to exactly one institution, and the contract stamps that institution onto every credential it issues. The university name is never caller-supplied, so an authorized wallet cannot mint a degree in another university's name
  • 🏛️ Layered authorization — issuing requires a verified institution and an explicitly authorized account and a registered wallet. An institutional email alone grants nothing
  • 🆔 Roll number field — stored on-chain alongside the student's name, so two students who happen to share a name are never ambiguous when verifying
  • 🚫 Revocation — a mistaken or fraudulent credential can be revoked by its issuer or the contract owner, and the Verify page clearly distinguishes revoked from never existed
  • 📷 Two ways to verify — paste a credential ID, or scan the student's QR code with a camera
  • 🖼️ Shareable credential card — a downloadable/shareable image (QR + full details, styled like a certificate) generated entirely client-side, with no app branding overpowering the university's own
  • ⚠️ Demo mode safety — in demo mode every issued record is clearly marked as a test credential, on screen and on the downloadable card, so it can't be passed off as an official document
  • 🌗 Light & dark mode
  • 13 passing unit tests covering issuer binding, institution-name forgery, revoked issuers, duplicate IDs, verification, and revocation rules

Access Model

Verification is public. Issuing is not.

Area Access
Home No login
Verify a credential (ID or QR) No login, no wallet, no gas
Institution Portal Login required
Institution onboarding Submitted for review — approval is a separate step
Issue a credential Verified institution + authorized account + on-chain registered wallet

The trust chain enforced end to end:

Account created → Email verified → Institution verified
   → Account explicitly authorized → Wallet bound on-chain → Credential issued

Each link proves something different, and the design deliberately keeps them separate: an institutional email proves affiliation, institution verification proves legitimacy, an explicit invitation proves permission, and MetaMask proves transaction ownership. None of them substitutes for another.

What is simulated here: accounts, email verification, and institution review are mocked with demo data (src/config/demo.js) — a hackathon prototype has no access to official university registries. What is real is the blockchain half: the contract independently enforces which wallet may issue and which institution it issues for, so bypassing the UI gains nothing. Swapping the mock layer for a real backend does not change the flow around it.

Beginner's Guide — What You Need & Where to Get It

If you are new to this: you need five things installed before touching any code. Click through, install, then come back.

# Tool What it's for Direct link
1 Node.js (LTS 18.x or 20.x) Runs everything JavaScript-related (npm, Hardhat, Vite) nodejs.org
2 Git Version control git-scm.com
3 A code editor (VS Code recommended) Where you'll read/edit the code code.visualstudio.com
4 MetaMask (browser extension) Wallet — only needed to issue credentials; verifying needs no wallet at all metamask.io
5 (optional, public deploy only) Test POL tokens Free fake currency to pay gas on Polygon Amoy faucet.polygon.technology

No real money is ever involved anywhere in this project. Everything runs on a free local blockchain by default, and the public option (Polygon Amoy) is a free testnet — the faucet gives away test tokens that have no real-world value.

Verify Node and Git installed correctly:

node --version
npm --version
git --version

Quick Start (Local, No Real Crypto Needed)

This is the fastest path — a full working app on your own machine in under five minutes.

# 1. Install backend (Hardhat) dependencies
npm install

# 2. Start a local blockchain — keep this terminal running
npx hardhat node

# 3. In a NEW terminal — deploy the contract to that local chain
npx hardhat run scripts/deploy.js --network localhost

# 4. Install frontend dependencies
cd frontend
npm install

# 5. Run the frontend
npm run dev

Open the printed local URL (typically http://localhost:5173).

  • The Home and Verify pages work immediately — no wallet needed.
  • To use Issue Credential, connect MetaMask to the Hardhat Local network:
    • Network name: Hardhat Local
    • RPC URL: http://127.0.0.1:8545
    • Chain ID: 31337
    • Import one of the private keys npx hardhat node printed in your terminal (these are well-known public test keys — perfectly fine for localhost, never use them anywhere real).

Public Testnet Deployment (Polygon Amoy)

Use this if you want a link you can share, or you're demoing at a hackathon.

  1. Copy .env.example to .env and fill in PRIVATE_KEY — use a throwaway MetaMask wallet's key, never one holding real funds.

  2. Add the Amoy network to MetaMask (it can prompt you automatically, or add manually):

    Field Value
    Network name Polygon Amoy Testnet
    RPC URL https://rpc-amoy.polygon.technology
    Chain ID 80002
    Currency symbol POL
    Explorer amoy.polygonscan.com
  3. Get free test POL from the official faucet (select Amoy).

  4. Deploy:

    npx hardhat run scripts/deploy.js --network amoy
  5. The script writes the new contract address + ABI straight into frontend/src/config/contract.json — restart npm run dev to pick it up.

Project Structure

Cred_Chain/
├── contracts/
│   └── CredentialRegistry.sol      # the smart contract
├── scripts/
│   └── deploy.js                   # deploy + auto-writes frontend config
├── test/
│   └── CredentialRegistry.test.js  # 13 unit tests
├── hardhat.config.js
├── package.json                    # Hardhat / backend deps
├── .env.example
├── frontend/
│   ├── public/favicon.svg
│   ├── src/
│   │   ├── components/             # Header, Home, IssueCredential, VerifyCredential, ...
│   │   │   └── portal/             # login, email verification, onboarding, dashboard, guard
│   │   ├── hooks/                  # useWallet, useSession, useIssuerStatus, useTheme, useToast
│   │   ├── utils/                  # network switching, password hashing, credential-card image
│   │   ├── config/
│   │   │   ├── contract.json       # address + ABI (written by deploy script)
│   │   │   └── demo.js             # demo/mock institution + account data
│   │   ├── App.jsx / App.css
│   │   ├── index.css
│   │   └── main.jsx
│   ├── vite.config.js
│   └── package.json
└── README.md

Testing

npx hardhat test

Covers: issuer authorization and institution binding, rejection of unauthorized issuers, institution-name forgery (a wallet bound to one university cannot issue under another's name), revoked issuers losing the ability to issue, duplicate credential IDs, verification of valid/unknown IDs, revocation by the issuer and by the owner, and rejection of revocation attempts by unrelated wallets — 13/13 passing.

Security Notes

  • issueCredential() is restricted to wallets the contract owner has authorized via authorizeIssuer(wallet, institution) — an unauthorized wallet cannot mint a "verified" degree.
  • The institution name is not a parameter. It is read from the caller's on-chain binding, so a wallet authorized for one university cannot issue a credential in another university's name. This is enforced in the contract, not the UI, so bypassing the frontend gains nothing.
  • Issuer authorization can be withdrawn (revokeIssuer); credentials already issued stay valid, which is the correct behaviour — losing issuing rights should not retroactively void real degrees.
  • .env (holding a private key) is git-ignored. Never paste a private key into any source file.
  • Verification is entirely read-only — no wallet, no gas, no signature required. Safe for anyone, including non-technical employers, to use directly.
  • For a production system beyond a demo, having credential data (name, degree, CGPA) fully public on-chain is a privacy tradeoff worth revisiting — e.g. hashing personal fields on-chain and releasing full details off-chain with consent.

Troubleshooting

Problem Fix
MetaMask doesn't pop up Confirm the extension is installed/unlocked and has permission for the site (MetaMask icon → Connected sites)
"Not authorized" when issuing Your connected wallet hasn't been granted issuer access — the contract owner must call authorizeIssuer(wallet, institution) for it first
Verify page says "not found" for a real ID Wrong network selected, or the transaction hasn't confirmed yet — wait a few seconds and retry
--network amoy deploy fails Check .env has a valid PRIVATE_KEY and that wallet holds test POL from the faucet
Frontend shows a stale contract address Restart npm run dev after redeploying — contract.json is only re-read on server (re)start

Corrections From the Original Guide

This project started from a beginner hackathon guide. A few things in that original guide were outdated, insecure, or incomplete — corrected here and documented so nothing is silently different:

Guide said This project uses Why
Polygon Mumbai testnet Polygon Amoy testnet Mumbai was fully shut down by Polygon in 2024
Create React App Vite + React CRA is deprecated/unmaintained; Vite is the current standard
ethers v5 (Web3Provider) ethers v6 (BrowserProvider) v5 is legacy
Anyone can issueCredential() Only owner-authorized university wallets can The open version lets anyone forge a "verified" degree
No revoke function revokeCredential() added Mistakes and fraud need to be correctable
Private key pasted into hardhat.config.js Loaded from a git-ignored .env Never commit secrets
QR generation only Camera-based QR scanning added The guide described scanning but never implemented it

About

A decentralized academic credential verification platform that enables institutes and universities to issue blockchain-backed certificates, while students and employers can securely verify credentials using unique IDs and QR codes.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages