Thurman Protocol

Automated secondary loan sales with onchain USDC settlement and trustless execution

Thurman Protocol

Created At

ETHGlobal New York 2026

Winner of

Arc

Arc - Arc Continuity Track: Extend the Arc Ecosystem 1st place

Chainlink Labs

Chainlink - Best Chainlink-Powered Upgrade

Project Description

This project extends an existing POC for secondary loan sales onchain. Initially, we allowed users to create loan packages and list them onchain via an atomic escrow mechanism, where buyers can deposit USDC to purchase loans. Now, using Chainlink CRE and Docusign API webhooks the settlement happens trustlessly and automatically once both parties completely sign the agreement. The mechanism is designed around delivery-vs-payment, meaning in a single transaction the packages/loans and USDC swap hands between Sellers and Buyers. Sellers can also opt-in to have their funds forwarded to an external account and chain via Circle Forwarder, all configured via the smart contract. Onchain details are fully abstracted away from the user.

How it's Made

IMPORTANT REPO NOTES

  • This project is a continuation of an existing product, that could not be forked, due to the existing CI/CD pipeline on Google Cloud Platform. The first commit from the hackathon was done on Friday, June 12th @ 8:54pm after Kartik's announcement speech.
  • All work was done on STAGING branch exclusively, https://github.com/thurmanlabs/thurman-monorepo/commits/staging

Background: The stack is a Turborepo monorepo with a Next.js web app, Hono API, background worker, and CRE workflow package. Infra is Google Cloud Run with Neon Postgres. Smart contracts are written in Solidity with Foundry and deployed on Arc testnet. User accounts are created via Circle developer-controlled wallets (smart contract accounts).

The core settlement contract is DvPEscrow.sol, a delivery-versus-payment escrow that holds package (ERC-721) and loan (ERC-1155) tokens from the seller and USDC (ERC-20) from buyers. When settlement fires it atomically deducts a platform fee, pays the seller, and distributes loan tokens to buyers pro-rata. The seller payout has two paths: (1) if the seller configured a CCTP destination inside of the PackageNFT.sol, settlement calls ITokenMessengerV2.depositForBurnWithHook() which routes proceeds through Circle's Forwarding Service to the destination chain. Otherwise it transfers USDC directly on Arc to the sellers SCA wallet. Same contract, same settlement function, conditional on whether a destination address is set.

The real-world settlement trigger is Docusign. When an escrowed package is fully funded, a document is generated and sent to Seller and all Buyers (there can be N buyers but always 1 seller). Then when all parties sign a purchase agreement, a Docusign webhook posts to our API, which verifies the payload with HMAC-SHA256 timing-safe comparison, commits the envelope status as COMPLETED to Postgres, then fires an HTTP trigger to the Chainlink CRE workflow.

The CRE workflow is TypeScript simulated on my staging environment, see bottom notes for the exact hacky solution to get this running on a deployed staging environment. It runs five steps: (1) verify the Docusign envelope status via our internal API, (2) call canSettlePackage() on-chain to confirm escrow conditions are met, (3) build a report payload of the package ID, and chain ID where the chain ID is checked in our ThurmanReceiver.sol (based on Chainlink's ReceiverTemplate.sol) to prevent cross-chain replay, (4) write the report through the Chainlink CRE simulation mode to DvPEscrow.onReport() which triggers the atomic settlement, and (5) finally POST back to our API to mark the package settled in Postgres and send Mailgun confirmation emails to the seller and all buyers resolved from on-chain addresses. All in a single CRE workflow.

Notably hacky, CRE runtime and workflow aren't super friendly for programatic usage. Using the "/trigger" endpoint workaround, I still had to hardcode values such as a pure-JS base64 encoder, all ABI-encoding was done manually and pasted into the main CRE workflow file.

Another hacky achievement was deploying the CRE workflow as a "listener" port-forwarded via ngrok, this permanent ngrok URL is served to our API as an environment variable, enabling us to use the experimental CRE workflow programatically in a staging environment!

HOW TO TEST

  1. Sign up for a seller account, complete step 1 of onboarding (step 2 is technically disabled and reserved for prod, not staging)
  2. Sign up for a buyer account, complete step 1 of onboarding
  3. Use the arc faucet to fund the buyer account (bypassing step 2 of onboarding since Bridge onramp is only available on mainnets)
  4. Login as seller again
  5. Create a package selling for $1, and a loan under that package
  6. Publish both onchain from the package detail screen
  7. Escrow the package (loans get automatically escrowed)
  8. Login as buyer
  9. Deposit the $1 into the escrow contract
  10. Sign the generated docusign agreement as buyer and seller
  11. Settlement automatically happens after this, watch for confirmation emails!

Gotchas: Docusign sometimes doesn't send the contract to buyers after seller signs, you can simply login as seller and click "Resend" on the package detail screen to void the last document and generate a new one.

background image mobile

Join the mailing list

Get the latest news and updates

Thurman Protocol | ETHGlobal