emj
shrx

Lesson 2 · ~12 min · Lesson 1

How offer terms survive on-chain

Lesson 1 was the economic story. This lesson is the machinery: tokens and factories that carry terms and roles across multiple covenant transactions.

The problem

Creating a lending offer is not one transaction — it is a chain of covenant spends: mint tokens → lock collateral → accept → repay or liquidate. Each step must know the same terms (amounts, rate, expiry) and which party is acting.

Off-chain servers can lie or go offline. So the protocol embeds data in the chain itself — inside assets and transaction metadata.

Two ways to carry terms

ApproachWhere terms liveSource
Parameter tokens Bit-packed into the amount field of 1-unit NFT UTXOs Official docs
OP_RETURN metadata Fixed-length blob in offer-creation tx (rate, expiry, principal asset, amounts) simplicity-lending

Both solve the same problem: immutable offer parameters across covenant spends. When reviewing code, check which pattern it implements — the indexer verification rules differ. Details: Parameter encoding reference.

Parameter tokens (official docs)

Liquid limits how much data fits in a UTXO amount (51 bits). The docs split parameters across two NFTs:

  • FIRST_PARAMETERS_NFT — interest rate, loan expiration block, decimal exponents
  • SECOND_PARAMETERS_NFT — base collateral amount, base principal amount

An indexer can extract these amounts, recompile the Pre-lock covenant, and compare its CMR (script hash) to output 0 — proving the tx is a genuine offer initialization.

Utility NFTs: terms + roles

Beyond parameters, the protocol mints role tokens — each a 1-unit Liquid asset glued to covenant logic:

NFTPurpose
Borrower NFTProves the borrower is spending; required to repay; burned on cancel/full repay
Lender NFTIdentifies the lender; unlocked when accepting; burned on liquidation
Protocol fee keeperAuthorizes withdrawals from the protocol-fee vault on repayment

These are not collectibles — they are capabilities. Holding a borrower NFT means you can act as borrower in covenant spends. The indexer tracks NFT UTXOs to know who participates in each offer.

Secondary markets Docs note that one-time role assets enable selling or transferring loan positions. The covenant enforces who can act; the NFT UTXO shows which address currently holds that role.

IssuanceFactory

In the reference implementation, each borrower sets up a personal IssuanceFactory covenant once. It mints the utility NFTs needed for each new offer.

Borrower wallet IssuanceFactory + auth NFT (1 unit) IssueAssets | RemoveFactory Borrower NFT Lender NFT Protocol NFT Lending offer create once IssueAssets create offer
Reference-impl flow: factory mints role NFTs per offer; those feed into the LendingOffer covenant.

The factory covenant has two witness paths (from issuance_factory.simf):

  • IssueAssets — spends auth NFT + factory UTXO; issues new assets via Liquid issuance inputs; outputs role NFTs for one offer
  • RemoveFactory — burns factory and auth NFTs when the borrower is done

Factory creation also writes OP_RETURN metadata: program id, issuing UTXO count, reissuance flags bitmask.

Covenant chain (tying it together)

Official docs order the first implementation as:

  1. Create utility tokens — parameter data + role NFTs (via factory in reference impl)
  2. Lock collateral — borrower builds lock / pending-offer covenant
  3. Set up lending — lender accepts, funds principal
  4. Settle lending — repay or liquidate

Lesson 1 reminder: collateral locks at step 2 (propose). Role NFTs are already minted at step 1 so the covenant knows who may spend which branch later.

Check your understanding

1. What do parameter tokens carry across covenant spends?

2. Who typically creates an IssuanceFactory covenant first?

3. What must a borrower NFT prove during repayment?

Ask your teacher
Try: “how does IssueAssets relate to create offer?” or “what’s the difference between parameter tokens and OP_RETURN metadata?”