Files
LexiChain/blockchain/contracts/DocumentRegistry.sol
2026-04-22 11:04:59 +01:00

207 lines
7.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/**
* @title DocumentRegistry
* @author LexiChain BFSI Platform
* @notice This smart contract provides on-chain proof-of-deposit for BFSI
* contract documents. It stores SHA-256 hashes of documents along
* with their registration timestamp, making submission dates
* provable, tamper-proof, and legally opposable.
*
* @dev How it works:
* 1. The platform computes a SHA-256 hash of the uploaded PDF
* 2. The hash is registered on the blockchain via registerDocument()
* 3. The block.timestamp at the time of mining becomes the proof date
* 4. Anyone can verify a document's existence via verifyDocument()
*
* No actual document content is stored on-chain — only the hash.
* This preserves privacy while providing cryptographic proof.
*/
contract DocumentRegistry {
// ═══════════════════════════════════════════════════
// DATA STRUCTURES
// ═══════════════════════════════════════════════════
/**
* @notice Represents a registered document's on-chain record
* @param timestamp When the document was registered (block.timestamp)
* @param depositor The address that registered the document
* @param exists Whether this record is valid
*/
struct DocumentRecord {
uint256 timestamp;
address depositor;
bool exists;
}
// ═══════════════════════════════════════════════════
// STATE VARIABLES
// ═══════════════════════════════════════════════════
/// @notice Maps document hash → registration record
mapping(bytes32 => DocumentRecord) private documents;
/// @notice Maps depositor address → list of document hashes they registered
mapping(address => bytes32[]) private depositorDocuments;
/// @notice Total number of documents registered
uint256 public totalDocuments;
/// @notice Contract owner (the platform backend wallet)
address public owner;
// ═══════════════════════════════════════════════════
// EVENTS
// ═══════════════════════════════════════════════════
/**
* @notice Emitted when a new document is registered on-chain
* @param docHash The SHA-256 hash of the document
* @param timestamp The block timestamp at registration
* @param depositor The address that registered the document
*/
event DocumentRegistered(
bytes32 indexed docHash,
uint256 timestamp,
address indexed depositor
);
/**
* @notice Emitted when a document is verified
* @param docHash The document hash that was checked
* @param exists Whether the document was found on-chain
* @param verifier The address that performed the verification
*/
event DocumentVerified(
bytes32 indexed docHash,
bool exists,
address indexed verifier
);
// ═══════════════════════════════════════════════════
// MODIFIERS
// ═══════════════════════════════════════════════════
/// @notice Restricts function to contract owner
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}
// ═══════════════════════════════════════════════════
// CONSTRUCTOR
// ═══════════════════════════════════════════════════
constructor() {
owner = msg.sender;
}
// ═══════════════════════════════════════════════════
// CORE FUNCTIONS
// ═══════════════════════════════════════════════════
/**
* @notice Register a document hash on the blockchain
* @dev Creates an immutable record with the current block timestamp.
* Reverts if the same hash was already registered (no duplicates).
* @param _docHash The SHA-256 hash of the document (bytes32)
*/
function registerDocument(
bytes32 _docHash
) external onlyOwner {
// Prevent duplicate registrations
require(
!documents[_docHash].exists,
"Document already registered on-chain"
);
// Store the document record
documents[_docHash] = DocumentRecord({
timestamp: block.timestamp,
depositor: msg.sender,
exists: true
});
// Track documents per depositor
depositorDocuments[msg.sender].push(_docHash);
// Increment counter
totalDocuments++;
// Emit event for off-chain indexing
emit DocumentRegistered(
_docHash,
block.timestamp,
msg.sender
);
}
/**
* @notice Verify if a document exists on-chain and get its details
* @param _docHash The SHA-256 hash of the document to verify
* @return exists Whether the document is registered
* @return timestamp When it was registered (0 if not found)
* @return depositor Who registered it (address(0) if not found)
*/
function verifyDocument(
bytes32 _docHash
)
external
view
returns (
bool exists,
uint256 timestamp,
address depositor
)
{
DocumentRecord memory record = documents[_docHash];
return (
record.exists,
record.timestamp,
record.depositor
);
}
/**
* @notice Get the timestamp for a specific document hash
* @param _docHash The document hash to look up
* @return The registration timestamp (0 if not registered)
*/
function getTimestamp(bytes32 _docHash) external view returns (uint256) {
return documents[_docHash].timestamp;
}
/**
* @notice Get all document hashes registered by a specific address
* @param _depositor The address to query
* @return Array of document hashes
*/
function getDocumentsByDepositor(
address _depositor
) external view returns (bytes32[] memory) {
return depositorDocuments[_depositor];
}
/**
* @notice Get the number of documents registered by a specific address
* @param _depositor The address to query
* @return Number of documents
*/
function getDocumentCount(
address _depositor
) external view returns (uint256) {
return depositorDocuments[_depositor].length;
}
/**
* @notice Transfer ownership of the contract
* @dev Only the current owner can transfer ownership
* @param _newOwner The address of the new owner
*/
function transferOwnership(address _newOwner) external onlyOwner {
require(_newOwner != address(0), "New owner cannot be zero address");
owner = _newOwner;
}
}