Skip to content

Lending locks shares too: a supplier can raise a reserve's size by borrowing from it - #168

Merged
mikemaccana merged 1 commit into
mainfrom
claude/laughing-noether-ox587k
Sep 23, 2026
Merged

mikemaccana merged 1 commit into
mainfrom
claude/laughing-noether-ox587k

Conversation

@mikemaccana

Copy link
Copy Markdown
Collaborator

Merge after quicknode/solana-program-examples#155. This PR names MINIMUM_SHARES, inflating_shares_through_own_borrow_does_not_pay and sole_supplier_leaves_the_minimum_behind, which exist only on that PR's branch until it merges.

What was untrue

  • lending.md, failure modes: "The donation attack fails because available_liquidity, not the vault balance, is the source of truth." The donation does fail, but the sentence implied the reserve was safe from share inflation, and it wasn't. A reserve's size also counts the interest its borrowers owe, and a supplier may borrow from their own reserve.
  • The Adversary chapter: listed ignoring donations as the lending market's only defence.
  • lending.md, first deposit: "The first deposit into a reserve mints shares one-to-one." After Refine prose for clarity and consistency across chapters #155 it withholds 1,000 shares.
  • lending.md, wall-clock leftovers: three statements Reorganize reader guidance by audience and skill level #151 made untrue:
    • "interest that compounds by the slot"
    • "a single slot's interest"
    • "slot-warping" in the testing section

Changes

  • Lending and Borrowing:
    • Maria makes each reserve's first deposit, 1,001 minor units, so she holds one share and 1,000 are withheld. That keeps every later number in the chapter and its figures exact.
    • The share formula counts the withheld 1,000.
    • The solvency invariant now says the shares, plus the withheld 1,000, are a claim on total liquidity.
    • The failure mode is rewritten around the borrow route, with the test's numbers: 4,000 → 4,155.20 USDC without the lock; with it, the attacker ends 1,065 minor units down.
    • The three wall-clock statements are corrected.
  • The Adversary:
    • The lending reserve is the second example, after perpetual futures, of a recorded pool size that the pool's own users can raise.
    • The summary now says the lending market uses both defences: it ignores donations and it locks shares.
  • WRITING-PLAN: Maria's opening deposits, and her three share accounts in the account map, join the list of steps waiting for a figure.

Checks

  • Lint: npm run lint is clean.
  • Figures: node scripts/check-figure-geometry.mjs is clean across 99 figures.
  • Build: npm run build-pdf writes the PDF.
  • Identifiers: I searched for every identifier the new prose names; each one is defined on the Refine prose for clarity and consistency across chapters #155 branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_013vsKb7K4wGqggas2vtABoF


Generated by Claude Code

…rrowing from it

The Lending and Borrowing chapter said the donation attack fails because
available_liquidity is the source of truth, and the Adversary chapter
listed ignoring donations as the lending market's only defense. Both
held only against a donation. A reserve's size also counts the interest
its borrowers owe, and a supplier may borrow from their own reserve: one
minor unit of rounded-up interest lifts a lone share above one unit,
and the rounding on the attacker's own deposits and redemptions does
the rest. The companion repository now withholds MINIMUM_SHARES from
each reserve's first deposit and counts them in every conversion
(quicknode/solana-program-examples#155), and the chapters follow.

- Lending and Borrowing: Maria makes each reserve's first deposit, the
  share formula counts the withheld 1,000, the solvency invariant says
  what the shares are a claim on, and the failure mode is rewritten
  around inflating_shares_through_own_borrow_does_not_pay and its
  numbers. Three leftovers from the wall-clock accrual change are
  corrected: interest compounds on every refresh rather than by the
  slot, the scale keeps a second's interest from truncating, and the
  tests move the clock rather than warping slots.
- The Adversary: the lending reserve is the second example of a
  recorded size its own users can raise, and the lending market does
  both defenses, as the perpetual futures pool does.
- WRITING-PLAN: Maria's opening deposits join the list of steps
  awaiting a figure.

Claude-Session: https://claude.ai/code/session_013vsKb7K4wGqggas2vtABoF
@mikemaccana
mikemaccana merged commit 23c639f into main Sep 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant