Files
LexiChain/docs/05-smart-contract.md
2026-05-13 21:08:27 +01:00

7.4 KiB

05 — Smart Contract: DocumentRegistry

File: blockchain/contracts/DocumentRegistry.sol
Solidity version: ^0.8.24
Network: Ethereum Sepolia Testnet (production) / Hardhat Local (development)
Purpose: Tamper-proof, timestamped proof-of-deposit for BFSI contract documents.


Design Philosophy

No document content is stored on-chain — only its SHA-256 hash.

This design provides:

  • Privacy: No sensitive data ever reaches the blockchain
  • Verifiability: Anyone with the original document can verify it existed at a specific time
  • Immutability: Once registered, the hash and timestamp cannot be altered
  • Legal Standing: Block timestamp provides a cryptographically provable submission date

How It Works

1. User uploads contract PDF to LexiChain
2. Server computes SHA-256 hash of the raw file bytes
3. Server wallet signs and sends registerDocument(bytes32) transaction
4. Transaction is mined → block.timestamp becomes the proof date
5. txHash, blockNumber, blockTimestamp saved to PostgreSQL
6. User can verify anytime via verifyDocument(bytes32)

Contract Architecture

State Variables

Variable Type Visibility Description
owner address public Platform backend wallet address
totalDocuments uint256 public Total number of registered document hashes
documents mapping(bytes32 => DocumentRecord) private Hash → registration record
depositorDocuments mapping(address => bytes32[]) private Address → list of hashes they registered

Structs

struct DocumentRecord {
    uint256 timestamp;   // block.timestamp at registration
    address depositor;   // msg.sender (platform wallet)
    bool exists;         // false = not registered
}

Events

event DocumentRegistered(
    bytes32 indexed docHash,
    uint256 timestamp,
    address indexed depositor
);

event DocumentVerified(
    bytes32 indexed docHash,
    bool exists,
    address indexed verifier
);

Modifiers

modifier onlyOwner() {
    require(msg.sender == owner, "Only owner can call this function");
    _;
}

Function Reference

registerDocument(bytes32 _docHash) — write

Access:    onlyOwner
Gas:       ~50,000 gas

Registers a document hash on-chain. Reverts if the same hash is already registered (idempotent via requires).

Parameters:

  • _docHash — SHA-256 hash of the document as bytes32

Emits: DocumentRegistered(docHash, block.timestamp, msg.sender)


verifyDocument(bytes32 _docHash) — view (free)

Access:    Anyone
Gas:       0 (read-only call)

Checks if a document hash is registered and returns its record.

Returns:

bool exists          // true if registered
uint256 timestamp    // Unix timestamp of registration (0 if not found)
address depositor    // Address that registered it (address(0) if not found)

getTimestamp(bytes32 _docHash) — view (free)

Returns only the registration timestamp for a given hash (0 if not registered).


getDocumentsByDepositor(address _depositor) — view (free)

Returns all document hashes registered by a specific address.


getDocumentCount(address _depositor) — view (free)

Returns the count of documents registered by a specific address.


transferOwnership(address _newOwner) — write

Access:    onlyOwner

Transfers contract ownership to a new address. Required if the platform wallet changes.


ABI (Application Binary Interface)

[
  "function registerDocument(bytes32 _docHash) external",
  "function verifyDocument(bytes32 _docHash) external view returns (bool exists, uint256 timestamp, address depositor)",
  "function getTimestamp(bytes32 _docHash) external view returns (uint256)",
  "function getDocumentsByDepositor(address _depositor) external view returns (bytes32[] memory)",
  "function getDocumentCount(address _depositor) external view returns (uint256)",
  "function totalDocuments() external view returns (uint256)",
  "function owner() external view returns (address)",
  "function transferOwnership(address _newOwner) external",
  "event DocumentRegistered(bytes32 indexed docHash, uint256 timestamp, address indexed depositor)"
]

Security Model

Property Implementation
Owner-only writes onlyOwner modifier prevents anyone else from registering
No duplicates require(!documents[hash].exists) prevents double-registration
Privacy Only hashes stored — no filename, no metadata, no user data
Immutability No update/delete functions — hashes are permanent once registered
Dedicated wallet Platform uses a separate wallet (not a personal wallet)

Deployment

Prerequisites

  1. Install Hardhat dependencies:

    cd blockchain
    npm install
    
  2. Compile the contract:

    npx hardhat compile
    

Local Development (Hardhat Node)

The npm run dev command in the root automatically:

  1. Starts a Hardhat node on http://localhost:8545
  2. Deploys DocumentRegistry.sol to the local chain
  3. Saves the contract address to blockchain/.dev-deploy.json
  4. Starts the Next.js dev server with the correct env vars

To deploy manually:

# Terminal 1: Start local node
cd blockchain
npx hardhat node

# Terminal 2: Deploy
npx hardhat run scripts/deploy.ts --network localhost

Production (Ethereum Sepolia Testnet)

Why Sepolia?

  • 100% free (no real ETH needed)
  • Stable Ethereum testnet maintained by the Ethereum Foundation
  • Supported by Etherscan, Alchemy, Infura, MetaMask
  • No node to run or maintain
  • Transactions viewable on https://sepolia.etherscan.io

Step 1: Get Sepolia ETH (free)

Use one of these faucets:

A few test ETH is enough for thousands of contract registrations (~0.0005 ETH per registration).

Step 2: Set environment variables

# In blockchain/.env or your shell:
SEPOLIA_RPC_URL=https://rpc.sepolia.org
DEPLOYER_PRIVATE_KEY=0x<your-dedicated-wallet-private-key>

⚠️ CRITICAL: Never use a wallet that holds real ETH. Create a dedicated deployment wallet.

Step 3: Deploy to Sepolia

cd blockchain
npx hardhat run scripts/deploy.ts --network sepolia

The script outputs:

DocumentRegistry deployed to: 0x<CONTRACT_ADDRESS>
BLOCKCHAIN_CONTRACT_ADDRESS=0x<CONTRACT_ADDRESS>

Step 4: Set app environment variables

BLOCKCHAIN_NETWORK=sepolia
BLOCKCHAIN_RPC_URL=https://rpc.sepolia.org
BLOCKCHAIN_CONTRACT_ADDRESS=0x<your-deployed-address>
BLOCKCHAIN_PRIVATE_KEY=0x<your-wallet-private-key>

Step 5: Verify deployment (optional)

Visit https://sepolia.etherscan.io/address/<CONTRACT_ADDRESS> to confirm deployment.


Running Tests

cd blockchain
npx hardhat test

Test file: blockchain/test/DocumentRegistry.test.ts


Deployed Contract Information

After deploying, record your contract address here for team reference:

Network Contract Address Deployer Deployed At
Sepolia 0x... 0x...
Hardhat (dev) Auto-deployed Account #0 Per session