Skip to content

Commit 28eea9a

Browse files
author
Edward (subagent)
committed
docs: reframe asset-leasing as on-chain securities lending
The program's lessee role is mechanically a short seller — borrow fungibles, sell now, rebuy cheaper, return equivalent. Physical- asset framing (leasing, gold bars) misled readers about what the product actually is. README now opens with "on-chain securities lending used primarily for short selling" and uses lender/borrower terminology alongside the lessor/lessee identifiers. Code unchanged.
1 parent 10a6caa commit 28eea9a

1 file changed

Lines changed: 93 additions & 89 deletions

File tree

defi/asset-leasing/anchor/README.md

Lines changed: 93 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
11
# Asset Leasing
22

3-
A fixed-term token lease on Solana, with a second-by-second lease fee
4-
stream, a separate collateral deposit, and a Pyth-oracle-triggered
5-
seizure path when the collateral is no longer worth enough.
3+
**On-chain securities lending.** Long holders rent out fungible token
4+
inventory to short sellers. Borrowers post collateral, pay a
5+
second-by-second lending fee, and return equivalent tokens before
6+
expiry. If the borrowed asset rallies past the maintenance margin,
7+
keepers liquidate the position; if it falls, the borrower profits and
8+
returns equivalent tokens cheaply.
9+
10+
This is the same primitive that underpins traditional securities
11+
lending: long inventory holders (exchange-traded funds and pension
12+
funds in traditional finance; passive holders on-chain) earn yield on
13+
assets they would hold anyway, and short sellers and arbitrageurs get
14+
the borrow they need. The program is written in Anchor; a parallel
15+
[Quasar port](#7-quasar-port) implements the same on-chain behaviour.
16+
17+
The code uses `lessor` / `lessee` identifiers throughout — those names
18+
predate the framing change and stay as-is so the source is grep-able.
19+
The README freely uses **lender** for the lessor and **borrower** (or
20+
**short seller**) for the lessee; they refer to the same on-chain
21+
roles.
622

723
Every instruction handler is walked through with the exact token
824
movements it causes. If you already know what collateral, a
@@ -31,84 +47,72 @@ appear.
3147

3248
## 1. What does this program do?
3349

34-
Two users, a **lessor** and a **lessee**, want to swap tokens
35-
temporarily:
36-
37-
- The lessor has some number of tokens of mint **A** (call it the
38-
"leased mint") they would like to hand over for a fixed period of
39-
time.
40-
- The lessee has tokens of a different mint **B** (the "collateral
41-
mint") they can lock up as a security deposit.
50+
A **lessor (lender)** offers some quantity of one fungible token —
51+
mint **A**, the "leased mint" — for a fixed term. A **lessee
52+
(borrower / short seller)** posts collateral in a different mint
53+
**B** — the "collateral mint" — to take delivery. The borrower will
54+
typically sell the A tokens immediately on a market like Jupiter, then
55+
re-acquire equivalent A tokens later to close out. Because mint A is
56+
fungible, the borrower only has to return the same *quantity*, not the
57+
exact units they received.
4258

4359
The program acts as a non-custodial escrow. It:
4460

45-
1. Takes the lessor's A tokens and locks them in a program-owned vault
46-
until a lessee shows up.
47-
2. When a lessee calls `take_lease`, the program locks the lessee's B
48-
tokens as collateral and hands the A tokens to the lessee.
49-
3. While the lease is live, a second-by-second **lease fee stream**
50-
pays the lessor out of the collateral vault.
51-
4. If the price of A (measured in B) moves against the lessee far enough
52-
that the locked collateral is no longer enough to cover the cost of
53-
re-acquiring the leased tokens, anyone can call `liquidate` — the
54-
collateral is seized, most of it goes to the lessor, and a small
55-
percentage (the **liquidation bounty**) goes to whoever called it.
56-
Such a caller is known as a **keeper** — a bot or anyone else who
57-
watches the chain for positions that have gone underwater and earns
58-
the bounty by cleaning them up.
59-
5. If the lessee returns the full A amount before the deadline, they get
60-
back whatever collateral is left after lease fees.
61-
6. If the lessee ghosts past the deadline without returning anything,
62-
the lessor calls `close_expired` and sweeps the collateral as
63-
compensation.
61+
1. Takes the lender's A tokens and locks them in a program-owned vault
62+
until a borrower shows up.
63+
2. When a borrower calls `take_lease`, the program locks the
64+
borrower's B tokens as collateral and hands the A tokens to the
65+
borrower.
66+
3. While the loan is live, a second-by-second **lending fee stream**
67+
pays the lender out of the collateral vault.
68+
4. If the price of A (measured in B) rises far enough that the locked
69+
collateral is no longer enough to cover the cost of re-acquiring
70+
the borrowed tokens, anyone can call `liquidate` — the collateral
71+
is seized, most of it goes to the lender, and a small percentage
72+
(the **liquidation bounty**) goes to whoever called it. Such a
73+
caller is known as a **keeper** — a bot or anyone else who watches
74+
the chain for positions that have gone underwater and earns the
75+
bounty by cleaning them up.
76+
5. If the borrower returns the full A amount before the deadline, they
77+
get back whatever collateral is left after lending fees.
78+
6. If the borrower ghosts past the deadline without returning
79+
anything, the lender calls `close_expired` and sweeps the
80+
collateral as compensation.
6481

6582
The trigger for step 4 is the **maintenance margin**: a ratio,
66-
expressed in basis points (1 bp = 1/100 of a percent), of required
67-
collateral value to debt value. `maintenance_margin_basis_points = 12_000` is
68-
120%, meaning the collateral must stay worth at least 1.2× the leased
69-
tokens. Drop below and the position becomes liquidatable.
83+
expressed in basis points (1 basis point = 1/100 of a percent), of
84+
required collateral value to debt value.
85+
`maintenance_margin_basis_points = 12_000` is 120%, meaning the
86+
collateral must stay worth at least 1.2× the borrowed tokens. Drop
87+
below and the position becomes liquidatable.
7088

7189
The program is a pair of vaults, a small piece of state that tracks
72-
how much has been paid, and an oracle check. It is written in Anchor.
73-
74-
### The tradfi picture, briefly
75-
76-
Two analogies from finance for the uninitiated; the on-chain mechanics
77-
above are the canonical description.
78-
79-
- **Leasing gold bars from a bullion dealer.** The dealer hands over a
80-
fixed amount of physical gold for a fixed period; the counterparty
81-
pays a per-day leasing fee and posts cash collateral worth more than
82-
the gold. If the gold price rises enough that the posted cash no
83-
longer covers the value of the bars, the dealer can seize the cash
84-
before the position goes further underwater. The leased tokens here
85-
play the role of the gold; the collateral plays the role of the cash;
86-
the oracle plays the role of a live gold price feed.
90+
how much has been paid, and an oracle check.
8791

88-
- **Securities lending — borrowing stock to short.** A broker lends
89-
shares (say, NVIDIA) to a short seller for a fee. The short seller
90-
posts cash collateral worth more than the shares. If NVIDIA rallies,
91-
the collateral ratio falls; if it falls far enough, the broker issues
92-
a margin call and, if unmet, liquidates the position by buying back
93-
the shares from the collateral. This program's `liquidate`
94-
instruction handler is the on-chain equivalent of that forced
95-
buy-back.
92+
### Roles
9693

97-
Neither analogy is exact — real bullion leases and real securities
98-
lending add features the program doesn't model (recall rights, rebate
99-
rates, haircuts).
94+
- **Lessor / lender.** Long the asset, willing to part with it
95+
temporarily to earn the lending fee. The economic match for this
96+
role is a passive holder — someone who would hold the asset anyway
97+
and is happy to earn yield on idle inventory.
98+
- **Lessee / borrower / short seller.** Pays the lending fee for the
99+
right to sell the borrowed tokens now and buy them back later. The
100+
payoff shape is the same as a short: profit if the borrowed asset
101+
falls, loss (and possible liquidation) if it rises.
102+
- **Keeper / liquidator.** Standard role — watches for
103+
undercollateralised positions and takes the bounty for closing them.
100104

101-
### Worked example: leasing xNVDA against USDC
105+
### Worked example: shorting xNVDA via the lending market
102106

103107
Concrete numbers using assets that already trade on Solana —
104108
[xNVDA](https://www.backed.fi/) (a Backed Finance / xStocks tokenised
105109
NVIDIA share) and USDC. xNVDA has its own Pyth feed; the program
106110
takes the feed id verbatim at `create_lease`.
107111

108112
Alice holds 100 xNVDA at ~$180 / share, ~$18 000 notional. She wants
109-
yield without selling the underlying.
113+
yield on inventory she would hold anyway.
110114

111-
Bob wants short exposure to NVIDIA without using a perp.
115+
Bob wants short exposure to NVIDIA without using a perpetual future.
112116

113117
Alice lists the lease (assume USDC is 6-decimal, xNVDA is also
114118
6-decimal for round numbers):
@@ -151,11 +155,11 @@ sells them on Jupiter for ~18 000 USDC at the spot price.
151155
accrued lease fee. The remaining ~22 000 USDC (minus fees paid)
152156
refunds to Bob.
153157
- Bob's profit ≈ `$18 000 − $16 000 − fees − trading costs ≈ $2 000`
154-
minus carry — the same payoff shape as a 30-day short on NVIDIA.
158+
minus carry. This is a 30-day short on NVIDIA, expressed on-chain.
155159

156-
The asymmetry: liquidation only ever fires when the *leased* asset
157-
rallies against the collateral. A drop in the leased asset price is
158-
purely beneficial to the lessee. The streaming lease fee is the
160+
The asymmetry: liquidation only ever fires when the *borrowed* asset
161+
rallies against the collateral. A drop in the borrowed asset price is
162+
purely beneficial to the borrower. The streaming lending fee is the
159163
position's only ongoing cost in either direction.
160164

161165
§4 walks the on-chain token flows for each path with abstract numbers
@@ -680,11 +684,14 @@ closed; all three rent-exempt lamport refunds go to the lessor.
680684

681685
## 4. Full-lifecycle worked examples
682686

683-
All three use the same starting numbers so the arithmetic is easy to
684-
follow. Both mints are 6-decimal tokens, so 1 token = 1 000 000 base
685-
units. Throughout this section, "leased units" means base units of
686-
the leased mint and "collateral units" means base units of the
687-
collateral mint — they are descriptive labels, not real tickers.
687+
These are abstract walkthroughs of the same machinery the §1 xNVDA
688+
example uses, with round numbers chosen to make the arithmetic easy
689+
to follow and to match the LiteSVM tests one-to-one. All paths share
690+
the same starting parameters. Both mints are 6-decimal tokens, so
691+
1 token = 1 000 000 base units. Throughout this section, "leased
692+
units" means base units of the leased mint and "collateral units"
693+
means base units of the collateral mint — they are descriptive
694+
labels, not real tickers.
688695
The diagrams use the same convention: `[<number> leased]` and
689696
`[<number> collateral]`.
690697

@@ -802,14 +809,13 @@ Same setup. Steps 1 and 2 run identically.
802809
tokens. The collateral pays the lessor for the lost asset. The lessee
803810
has effectively bought the leased tokens at the forfeit price.)
804811
805-
### 4.3 Falling-price path — lessee benefits
812+
### 4.3 Falling-price path — borrower profits
806813
807814
Liquidation is a one-sided risk: it only ever fires when the leased
808815
asset *appreciates* against the collateral. If the leased asset
809-
depreciates, the collateral ratio rises and the lessee's position
810-
gets safer. Mechanically the position behaves like a short on the
811-
leased asset — gains accrue to the lessee, the only ongoing cost is
812-
the streaming lease fee.
816+
depreciates, the collateral ratio rises and the borrower's position
817+
gets safer. The streaming lending fee is the position's only ongoing
818+
cost.
813819
814820
Same setup. Steps 1 and 2 run identically.
815821
@@ -844,18 +850,16 @@ Same setup. Steps 1 and 2 run identically.
844850
845851
- Lessor: 1 000 000 000 leased units (full return), 6 000 collateral units in lease
846852
fees.
847-
- Lessee: 100 000 000 leased units received → bought 100 leased tokens
848-
back at the lower price → returned them. Their net cost is the
849-
lease fee (6 000 collateral units) plus whatever
850-
they paid on the open market for the replacement leased tokens;
851-
their gain is the difference between what they originally received
852-
the leased tokens at versus what they paid to re-acquire them.
853-
854-
This is the same payoff shape as a short on the leased asset: the
855-
lessee profits from price drops and pays a small carry (the lease
856-
fee) for the duration. Only adverse moves trigger liquidation, and
857-
the lessee can defend a borderline position with `top_up_collateral`
858-
or close it early via `return_lease`.
853+
- Lessee: received 100 000 000 leased units, sold them at the
854+
original price, bought 100 leased tokens back at the lower price,
855+
returned them. Net cost is the lending fee (6 000 collateral units)
856+
plus whatever they paid on the open market for the replacement
857+
tokens; gain is the difference between the original sale price and
858+
the buy-back price. The standard short payoff.
859+
860+
The borrower can defend a borderline position with
861+
`top_up_collateral` or close it early via `return_lease`. Only
862+
adverse price moves trigger liquidation.
859863
860864
### 4.4 Default / expiry path — `close_expired` on an `Active` lease
861865

0 commit comments

Comments
 (0)