← Back to Archive
Supply Chain / Trade Finance / Document Authentication Case Study

TruStamp

A blockchain-powered escrow platform for international trade using OpenAttestation document verification and NFT-based title transfer to eliminate counterparty risk in cross-border transactions.

NestJS 11 React 19 + Vite MongoDB (Mongoose ODM) Solidity 0.8 + Hardhat Ethers.js v5 OpenZeppelin Contracts OpenAttestation SDK The Graph (GraphQL Subgraph) Pusher (Real-time WebSocket)

Architecture Overview

A modular monolith backend orchestrating a multi-phase escrow state machine, with on-chain settlement via a custom Solidity contract managing USDC payments and ERC-721 Title Escrow tokens for transferable document ownership, indexed by The Graph for historical queries.

The Challenges

Transaction Sequencing / Race Conditions

Problem

Sequential blockchain operations (attach document → deploy Title Escrow → nominate buyer) would fail if the first transaction wasn't mined before the second was submitted, causing the dependent call to reference non-existent on-chain state.

Solution

Implemented configurable confirmation blocking using `tx.wait(confirmationBlocks)` after every state-changing contract call. Each operation validates `receipt.status` before proceeding, with exponential backoff retry for transient RPC failures. Database state is only committed after on-chain confirmation.

trustamp-backend-backup/src/transaction/transaction.service.ts (lines 420-470) and TRANSACTION_SEQUENCING.md

Reentrancy / Fund Security

Problem

The escrow contract handles USDC deposits, releases, and refunds, prime targets for reentrancy attacks during fund disbursement that could drain the contract.

Solution

Applied OpenZeppelin ReentrancyGuard modifier to all fund-handling functions (`depositFunds`, `confirmDelivery`, `refundExpiredTransaction`). Combined with SafeERC20 wrapper for all token transfers and strict Checks-Effects-Interactions pattern.

trustamp-contract-backup/contracts/TruStampEscrow.sol (lines 6, 44, 373, 403, 490)

Atomic Ownership Transfer

Problem

Funds must only release to seller if the buyer simultaneously receives legal title (NFT) to the trade document, a two-party atomic swap across separate contract calls (ERC-20 transfer + ERC-721 ownership transfer).

Solution

Two-step Title Escrow nomination pattern: escrow contract holds document NFT as `holder`, seller remains `beneficiary`. Before `confirmDelivery()`, seller must call `nominate(buyer)` on TitleEscrow. On confirmation, contract verifies nomination then atomically executes `transferOwners()` and `safeTransfer()` in a single transaction, reverting both if either fails.

trustamp-contract-backup/contracts/TruStampEscrow.sol (lines 395-455)

Document Authenticity / Tamper-Proofing

Problem

Proving a digital trade document (Bill of Lading, Invoice) hasn't been tampered with and was issued by a legitimate authority, without relying on a centralized trust anchor.

Solution

Integrated OpenAttestation SDK to wrap documents with Merkle tree proofs, generating a unique `merkleRoot` hash. The root is issued on-chain to a DocumentStore contract. Verification re-computes the merkle proof client-side and validates against the immutable on-chain record.

trustamp-backend-backup/src/open-attestation/open-attestation.service.ts (lines 174-230)

Complex Relational Queries

Problem

Fetching document ownership required joining 5+ MongoDB collections (documents, transactions, organizations, wallets, templates) with conditional logic based on transaction state to determine current owner.

Solution

Built multi-stage MongoDB aggregation pipelines with `$lookup` joins, `$unwind` for nested arrays, and `$addFields` with conditional expressions (`$cond`) to dynamically resolve ownership based on whether transaction status is 'completed'. Single query returns fully denormalized view.

trustamp-backend-backup/src/documents/documents.service.ts (lines 97-236)

Private Key Security

Problem

Organization wallets require private keys for signing blockchain transactions, but storing plaintext keys creates critical security exposure.

Solution

AES-256 symmetric encryption of private keys at rest using a server-side master key. Decryption occurs in-memory only at transaction signing time via `decryptData()`, with plaintext never persisted, logged, or returned in API responses.

trustamp-backend-backup/src/common/helpers/cryptography.ts and transaction.service.ts (line 240)