Smart Import-Export Documentation

What it does:
Digitizes and automates import/export documentation, enabling immutable storage, verification, and access for customs, banks, and trading partners.

Why it matters:
Reduces paperwork, prevents fraud, accelerates trade processing, and ensures verifiable and auditable trade documentation.

How it works:

  • Exporters and importers upload documents (invoices, bills of lading, certificates) to the blockchain via IPFS or other storage solutions

  • Each document is linked to a trade ID or batch

  • Access permissions are managed on-chain, allowing only authorized parties to view or approve

  • Smart contracts validate document integrity and timestamps

  • Automated workflows trigger approvals, customs clearance, or payment releases

  • All actions are auditable and immutable

  • Integrates with Automated Trade Finance, Supply Chain Traceability, and logistics systems

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title SmartImportExportDocs
 * @author Nam
 * @notice Manages import/export documents on-chain with verification and access control
 */
contract SmartImportExportDocs is Ownable {

    struct Document {
        string ipfsHash;       // IPFS link or hash of document
        address uploader;
        uint256 timestamp;
        bool exists;
    }

    mapping(uint256 => Document[]) private tradeDocuments; // tradeId => documents
    mapping(uint256 => mapping(address => bool)) private accessControl; // tradeId => authorized viewer => bool

    mapping(address => bool) public verifiers;

    // -------------------- EVENTS --------------------

    event DocumentUploaded(uint256 indexed tradeId, string ipfsHash, address indexed uploader);
    event AccessGranted(uint256 indexed tradeId, address indexed viewer);
    event DocumentVerified(uint256 indexed tradeId, uint256 docIndex, address verifier);
    event VerifierApproved(address verifier);

    // -------------------- VERIFIER MANAGEMENT --------------------

    function approveVerifier(address _verifier) external onlyOwner {
        verifiers[_verifier] = true;
        emit VerifierApproved(_verifier);
    }

    function revokeVerifier(address _verifier) external onlyOwner {
        verifiers[_verifier] = false;
    }

    // -------------------- DOCUMENT MANAGEMENT --------------------

    function uploadDocument(uint256 _tradeId, string calldata _ipfsHash) external {
        require(bytes(_ipfsHash).length > 0, "Invalid IPFS hash");

        tradeDocuments[_tradeId].push(Document({
            ipfsHash: _ipfsHash,
            uploader: msg.sender,
            timestamp: block.timestamp,
            exists: true
        }));

        accessControl[_tradeId][msg.sender] = true; // uploader automatically has access

        emit DocumentUploaded(_tradeId, _ipfsHash, msg.sender);
    }

    function grantAccess(uint256 _tradeId, address _viewer) external {
        require(accessControl[_tradeId][msg.sender], "Only uploader/authorized can grant access");
        accessControl[_tradeId][_viewer] = true;

        emit AccessGranted(_tradeId, _viewer);
    }

    function verifyDocument(uint256 _tradeId, uint256 _docIndex) external {
        require(verifiers[msg.sender], "Not an authorized verifier");
        require(_docIndex < tradeDocuments[_tradeId].length, "Invalid document index");

        emit DocumentVerified(_tradeId, _docIndex, msg.sender);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    function getDocuments(uint256 _tradeId) external view returns (Document[] memory) {
        require(accessControl[_tradeId][msg.sender], "Access denied");
        return tradeDocuments[_tradeId];
    }

    function hasAccess(uint256 _tradeId, address _user) external view returns (bool) {
        return accessControl[_tradeId][_user];
    }
}