Skip to content

Commit a92d2fb

Browse files
author
Edward (Edwardbot)
committed
fix(asset-leasing): settle last_rent_paid_ts on close_expired default path
The default branch of `close_expired` (lessee ghosted past end_ts, lessor takes the collateral) previously left `last_rent_paid_ts` at whatever the most recent `pay_rent` wrote, which could be strictly less than `min(now, end_ts)`. The invariant `last_rent_paid_ts <= min(now, end_ts)` held, but the stronger invariant 'timestamp points at the latest settled instant' did not. Bump `last_rent_paid_ts` via `update_last_paid_ts` on the `Active` branch. Behaviour is unchanged (the lease account is closed in the same ix) but future versions that want to split the collateral differently on default — pro-rata rent, partial refund, haircut for unused time — can now trust that everything up to `now` is already settled rather than having to re-derive it. No-op on the `Listed` branch: rent never started accruing there. All 11 tests still pass.
1 parent 29f5e00 commit a92d2fb

1 file changed

Lines changed: 21 additions & 1 deletion

File tree

  • defi/asset-leasing/anchor/programs/asset-leasing/src/instructions

defi/asset-leasing/anchor/programs/asset-leasing/src/instructions/close_expired.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use anchor_spl::{
77
use crate::{
88
constants::{COLLATERAL_VAULT_SEED, LEASED_VAULT_SEED, LEASE_SEED},
99
errors::AssetLeasingError,
10-
instructions::shared::{close_vault, transfer_tokens_from_vault},
10+
instructions::{
11+
pay_rent::update_last_paid_ts,
12+
shared::{close_vault, transfer_tokens_from_vault},
13+
},
1114
state::{Lease, LeaseStatus},
1215
};
1316

@@ -152,6 +155,23 @@ pub fn handle_close_expired(context: Context<CloseExpired>) -> Result<()> {
152155
&[collateral_vault_seeds],
153156
)?;
154157

158+
// Settle rent accounting on the default path.
159+
//
160+
// We are not forwarding any accrued rent to the lessor here — on default
161+
// the lessor takes the whole collateral vault as compensation — but we
162+
// still bump \`last_rent_paid_ts\` so the invariant
163+
// \`last_rent_paid_ts <= now.min(end_ts)\` stays intact. That matters for
164+
// any future version of the program that wants to split the collateral
165+
// differently (pro-rata rent, partial refund on default, haircut to the
166+
// lessee for unused time): such a version can read
167+
// \`last_rent_paid_ts\` and trust that everything up to \`now\` is already
168+
// settled, rather than having to reason about whether this branch ever
169+
// bumped the timestamp.
170+
//
171+
// No-op on the \`Listed\` branch because rent never started accruing.
172+
if status == LeaseStatus::Active {
173+
update_last_paid_ts(&mut context.accounts.lease, now);
174+
}
155175
context.accounts.lease.collateral_amount = 0;
156176
context.accounts.lease.status = LeaseStatus::Closed;
157177

0 commit comments

Comments
 (0)