You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
asset-leasing: merge accounts section into lifecycle
WHAT: Deleted the standalone Accounts and program-derived addresses
section and integrated its content into the Lifecycle handler
walkthroughs. Each account is now introduced at the moment it is
first created or first used:
- Lease, leased_vault, collateral_vault: introduced in create_lease
with seeds and roles in a new program-derived addresses bullet
list, plus the Lease struct definition in a new What's on the
lease account subsection.
- holder, short_seller, payer, keeper user wallets: a one-line
description added on first appearance in their respective
handler's Signers bullet.
- Associated token accounts (holder_leased_account,
holder_collateral_account, short_seller_*, keeper_collateral_account):
one-line associated-token-account description added on first
appearance in each handler's Accounts bullet.
- price_update: introduced in liquidate, where the Pyth oracle
account is first passed in.
- The Closed/Liquidated states paragraph moved to the end of
return_lease (the first close handler), since it covers all three
closing paths.
Table of contents and any cross-references to the deleted section
updated.
WHY: A reader walking the lifecycle no longer has to flip back to a
static account dump to know what each account is - the prose
introduces every account the moment it appears in the narrative.
@@ -24,12 +24,11 @@ need to sell short. The program is written in
24
24
## Table of contents
25
25
26
26
1.[What does this program do?](#what-does-this-program-do)
27
-
2.[Accounts and program-derived addresses](#accounts-and-program-derived-addresses)
28
-
3.[Lifecycle](#lifecycle)
29
-
4.[Safety and edge cases](#safety-and-edge-cases)
30
-
5.[Running the tests](#running-the-tests)
31
-
6.[Quasar port](#quasar-port)
32
-
7.[Extending the program](#extending-the-program)
27
+
2.[Lifecycle](#lifecycle)
28
+
3.[Safety and edge cases](#safety-and-edge-cases)
29
+
4.[Running the tests](#running-the-tests)
30
+
5.[Quasar port](#quasar-port)
31
+
6.[Extending the program](#extending-the-program)
33
32
34
33
---
35
34
@@ -205,80 +204,6 @@ above is the same machinery applied to a real asset pair.
205
204
206
205
---
207
206
208
-
## Accounts and program-derived addresses
209
-
210
-
Every call to the program touches some subset of these accounts. The
211
-
three [program-derived addresses](https://solana.com/docs/terminology)
212
-
are created on `create_lease` and destroyed on `return_lease` /
213
-
`liquidate` / `close_expired`.
214
-
215
-
### State / data accounts
216
-
217
-
-**`Lease`** - program-derived address with seeds `["lease", holder, lease_id]`. Data account owned by the program, holding all the lease parameters and current lifecycle state (see below).
218
-
219
-
### Token vaults
220
-
221
-
-**`leased_vault`** - program-derived address with seeds `["leased_vault", lease]`. Token account whose authority is itself (program-derived-address-signed). Holds `leased_amount` while `Listed`; `0` while `Active` (the short seller has the tokens); full amount again briefly inside `return_lease`.
222
-
-**`collateral_vault`** - program-derived address with seeds `["collateral_vault", lease]`. Token account whose authority is itself (program-derived-address-signed). Holds `0` while `Listed`; `collateral_amount` while `Active`, decreasing as lease fee streams out and increasing on `top_up_collateral`.
223
-
224
-
### User accounts passed in
225
-
226
-
-**`holder` wallet** (user-owned) - `create_lease` signer, receives the lease fee and final recovery.
-**`keeper` wallet** (user-owned) - `liquidate` signer, receives the bounty.
229
-
-**`payer` wallet** (user-owned) - `pay_lease_fee` signer (can be anyone, not just the short seller).
230
-
-**`holder_leased_account`** - holder's [associated token account](https://solana.com/docs/terminology) for the leased mint; source on `create_lease`, destination on `return_lease` / `close_expired`.
231
-
-**`holder_collateral_account`** - holder's associated token account for the collateral mint; destination for the lease fee and liquidation proceeds.
232
-
-**`short_seller_leased_account`** - short seller's associated token account for the leased mint; destination on `take_lease`, source on `return_lease`.
233
-
-**`short_seller_collateral_account`** - short seller's associated token account for the collateral mint; source on `take_lease` / `top_up_collateral`, destination for collateral refund on `return_lease`.
234
-
-**`keeper_collateral_account`** - keeper's associated token account for the collateral mint; receives the liquidation bounty.
235
-
-**`price_update`** - `PriceUpdateV2` account owned by the Pyth Receiver program, for the feed the lease is pinned to.
236
-
237
-
### Fields on `Lease`
238
-
239
-
From [`state/lease.rs`](programs/asset-leasing/src/state/lease.rs):
240
-
241
-
```rust
242
-
pubstructLease {
243
-
publease_id:u64, // caller-supplied id so one holder can run many leases
244
-
pubholder:Pubkey, // who listed it, gets paid the lease fee
245
-
pubshort_seller:Pubkey, // who took the lease; Pubkey::default() while Listed
246
-
247
-
publeased_mint:Pubkey,
248
-
publeased_amount:u64, // locked at creation, unchanging
249
-
250
-
pubcollateral_mint:Pubkey,
251
-
pubcollateral_amount:u64, // increases on top_up, decreases as lease fees pay out
252
-
pubrequired_collateral_amount:u64, // what the short seller must post on take_lease
253
-
254
-
publease_fee_per_second:u64, // denominated in collateral units
255
-
pubduration_seconds:i64,
256
-
pubstart_timestamp:i64, // 0 while Listed
257
-
pubend_timestamp:i64, // 0 while Listed; start_timestamp + duration once Active
258
-
publast_paid_timestamp:i64, // Lease fee accrues from here to min(now, end_timestamp)
259
-
260
-
pubmaintenance_margin_basis_points:u16, // e.g. 12_000 = 120%
261
-
publiquidation_bounty_basis_points:u16, // e.g. 500 = 5%
262
-
263
-
pubfeed_id: [u8; 32], // Pyth feed_id this lease is pinned to
264
-
265
-
pubstatus:LeaseStatus, // Listed | Active | Liquidated | Closed
266
-
267
-
pubbump:u8,
268
-
publeased_vault_bump:u8,
269
-
pubcollateral_vault_bump:u8,
270
-
}
271
-
```
272
-
273
-
The `Closed` and `Liquidated` states are not directly observable
274
-
onchain: all three of `return_lease`, `liquidate` and `close_expired`
275
-
close the `Lease` account in the same transaction (`close = holder`),
276
-
returning the rent-exempt lamports to the holder. The in-memory
277
-
`status` field is set *before* the close so the transaction logs
278
-
record the terminal state, but the account disappears at the end.
279
-
280
-
---
281
-
282
207
## Lifecycle
283
208
284
209
### What the short seller really gets
@@ -308,16 +233,34 @@ The holder calls `create_lease`, naming the leased mint, the
308
233
collateral mint, the amount of leased tokens to offer, the
309
234
collateral the short seller will have to post, the per-second lease
310
235
fee, the duration, the maintenance-margin and liquidation-bounty
311
-
ratios, and the Pyth `feed_id` the lease will be priced against. The
312
-
program creates the `Lease` account, creates two empty token vault
313
-
[program-derived addresses](https://solana.com/docs/terminology) (one for each
314
-
mint), and moves the leased tokens out of the holder's wallet into
315
-
the leased vault. Locking the leased tokens up front means a short
316
-
seller calling `take_lease` later cannot fail because the holder
317
-
spent the inventory in the meantime - the atomicity guarantee
236
+
ratios, and the Pyth `feed_id` the lease will be priced against.
237
+
This is where every account the rest of the lifecycle uses gets
-`holder_collateral_account` (mut, **init_if_needed** - holder's [associated token account](https://solana.com/docs/terminology) for the collateral mint, destination for the lease fee)
-`price_update` (UncheckedAccount, constrained to `owner = PYTH_RECEIVER_PROGRAM_ID`)
529
+
-`keeper_collateral_account` (mut, **init_if_needed** - keeper's [associated token account](https://solana.com/docs/terminology) for the collateral mint, destination for the bounty)
530
+
-`price_update` (UncheckedAccount, constrained to `owner = PYTH_RECEIVER_PROGRAM_ID`) - a `PriceUpdateV2` account owned by the Pyth Receiver program for the feed the lease was pinned to at creation. This is the first handler that requires the oracle account itself; `create_lease` only stores the `feed_id` it expects to see here.
0 commit comments