Skip to content

feat(stablecoin): rebuild withdraw_collateral with the collateralization check - #348

Merged
gravityblast merged 5 commits into
mainfrom
feat/stablecoin-withdraw-collateral-rebuild
Sep 24, 2026
Merged

gravityblast merged 5 commits into
mainfrom
feat/stablecoin-withdraw-collateral-rebuild

Conversation

@gravityblast

@gravityblast gravityblast commented Sep 2, 2026 •

Copy link
Copy Markdown
Collaborator

Rebuilds withdraw_collateral to spec §10.6, replacing the scaffold's
normalized_debt_amount == 0 placeholder with the real §6.2 check.

Accounts go 4 → 8, adding the three read-only globals — each pinned to its
canonical PDA — and clock. The check runs after the decrement against debt and
redemption price projected to now (§5.3). Adds the frozen gate the scaffold
lacked.

Guards the check needs:

  • amount == 0 is a no-op (§11) and skips the projections entirely — nothing
    about the position changed, so there is nothing to re-check.
  • Zero-debt positions skip them too. There is nothing to collateralize.
  • A projected redemption price of zero is rejected. Zero would zero the required
    collateral and let an indebted position be drained completely.

The projections and the check itself run in saturating U512. A rate at the
controller's permitted limit projects past u128 about 45 minutes out, which
panicked before the comparison could run. Saturation is the safe direction: the
check's left-hand side tops out near 10^119, so a saturated requirement always
loses.

32 unit tests.

closes #177

@gravityblast
gravityblast requested a lite review from Copilot September 2, 2026 12:04
@gravityblast
gravityblast force-pushed the feat/stablecoin-deposit-collateral branch from 3a92d45 to b13e825 Compare September 2, 2026 12:08
@gravityblast
gravityblast force-pushed the feat/stablecoin-withdraw-collateral-rebuild branch from d6108e0 to 17d1634 Compare September 2, 2026 12:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are still doc/test inconsistencies in the modified areas (outdated panic/docs and a test that claims to assert four echoed globals but only checks one), which should be corrected before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR rebuilds the stablecoin program’s withdraw_collateral instruction to follow the spec’s fee-aware, post-decrement collateralization invariant, expanding the ABI to include additional read-only global/state accounts and updating the guest entrypoint, IDL, unit tests, and the zkVM integration test fixtures accordingly.

Changes:

  • Replaces the scaffolded “no debt allowed” guard with a spec-aligned collateralization check using projected accumulator/redemption-price values and adds the protocol frozen gate.
  • Expands WithdrawCollateral account list from 4 → 8 (adds accumulator, redemption price state, protocol parameters, and clock) and regenerates IDL/guest wiring.
  • Updates stablecoin unit tests and the integration test harness to seed/pass the new global accounts.
File summaries
File Description
programs/stablecoin/src/withdraw_collateral.rs Implements freeze check + post-decrement collateralization enforcement; adds global PDA validation helper; updates destination naming.
programs/stablecoin/src/tests.rs Adds new withdraw-collateral tests and updates existing ones for the 8-account ABI.
programs/stablecoin/methods/guest/src/bin/stablecoin.rs Updates guest instruction signature to accept the four new accounts.
programs/stablecoin/core/src/lib.rs Updates Instruction::WithdrawCollateral docs to reflect the new account list and semantics.
programs/integration_tests/tests/stablecoin.rs Seeds and passes the new global accounts in the e2e test state and call site.
artifacts/stablecoin-idl.json Regenerates IDL to match the new withdraw-collateral ABI (account names/order).
Review details

Suppressed comments (3)

programs/stablecoin/src/withdraw_collateral.rs:37

  • The panic list still claims non-zero debt is rejected, but debt is now allowed as long as the post-withdrawal position remains collateralized. Update this bullet to reflect the actual failure mode.
/// - `Position.normalized_debt_amount` is non-zero.

programs/stablecoin/src/tests.rs:1310

  • Test name still uses the old destination terminology, but the account is now user_collateral_holding. Renaming the test improves clarity and keeps terminology consistent.
        STABLECOIN_PROGRAM_ID,
        100,
    );
}

programs/stablecoin/src/tests.rs:1333

  • Test name still uses the old destination terminology, but the account is now user_collateral_holding. Renaming the test improves clarity and keeps terminology consistent.
        protocol_parameters_account(false),
        clock_account(NOW),
        STABLECOIN_PROGRAM_ID,
        100,
    );
}
  • Files reviewed: 6/6 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread programs/stablecoin/src/tests.rs
Comment thread programs/stablecoin/core/src/lib.rs Outdated
Comment thread programs/stablecoin/src/tests.rs Outdated
Comment thread programs/stablecoin/src/withdraw_collateral.rs
Comment thread programs/stablecoin/src/withdraw_collateral.rs Outdated
Comment thread programs/stablecoin/src/withdraw_collateral.rs Outdated
Comment thread programs/stablecoin/src/withdraw_collateral.rs
@gravityblast
gravityblast force-pushed the feat/stablecoin-deposit-collateral branch from b13e825 to a552497 Compare September 10, 2026 09:32
@gravityblast
gravityblast force-pushed the feat/stablecoin-withdraw-collateral-rebuild branch 2 times, most recently from 9f7cba9 to a2aa9a4 Compare September 16, 2026 12:42
@gravityblast
gravityblast force-pushed the feat/stablecoin-deposit-collateral branch from 3fe6237 to 46885a3 Compare September 18, 2026 07:57
@gravityblast
gravityblast force-pushed the feat/stablecoin-withdraw-collateral-rebuild branch 2 times, most recently from 60317da to 0305cf0 Compare September 18, 2026 10:51
@gravityblast
gravityblast requested a review from 3esmit September 18, 2026 10:51
Comment thread programs/stablecoin/src/withdraw_collateral.rs Outdated
Comment thread programs/stablecoin/src/withdraw_collateral.rs Outdated
@3esmit
3esmit self-requested a review September 21, 2026 17:18
@gravityblast
gravityblast force-pushed the feat/stablecoin-deposit-collateral branch from 858c0b6 to af9a944 Compare September 24, 2026 10:45
@gravityblast
gravityblast force-pushed the feat/stablecoin-withdraw-collateral-rebuild branch from 16d2c8f to de82977 Compare September 24, 2026 10:45
gravityblast added a commit that referenced this pull request Sep 24, 2026
Carries #348's fix to the other §6.2 call site. The accumulator stays
narrow — it divides `amount` to size the debt delta, so a value `u128`
cannot hold is not a mint we can price.
@gravityblast
gravityblast force-pushed the feat/stablecoin-deposit-collateral branch from af9a944 to 5ecc658 Compare September 24, 2026 10:53
…o-op- and overflow-safe

`withdraw_collateral(0)` is a no-op per spec §11, so it now skips both
projections and the §6.2 check — nothing about the position changed. An
indebted position previously still projected, and a decaying rate that
reaches zero failed the call.

The projections and the check move to saturating `U512`. A rate at the
controller's permitted limit projects past `u128` about 45 minutes out,
which panicked before the comparison could run and blocked withdrawals
that were comfortably collateralized. Saturation is the safe direction:
the check's left-hand side tops out near 10^119, so a saturated
requirement always loses.

8 new tests.
Base automatically changed from feat/stablecoin-deposit-collateral to main September 24, 2026 11:28
@gravityblast
gravityblast force-pushed the feat/stablecoin-withdraw-collateral-rebuild branch from de82977 to 426811b Compare September 24, 2026 11:29
@gravityblast
gravityblast merged commit 8db408c into main Sep 24, 2026
7 checks passed
gravityblast added a commit that referenced this pull request Sep 24, 2026
Carries #348's fix to the other §6.2 call site. The accumulator stays
narrow — it divides `amount` to size the debt delta, so a value `u128`
cannot hold is not a mint we can price.
gravityblast added a commit that referenced this pull request Sep 24, 2026
Carries #348's fix to the other §6.2 call site. The accumulator stays
narrow — it divides `amount` to size the debt delta, so a value `u128`
cannot hold is not a mint we can price.
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.

[Plan 3 · 04] withdraw_collateral rebuild

3 participants