Skip to content

feat(stablecoin): add collateralization-check helper - #336

Open
gravityblast wants to merge 1 commit into
mainfrom
feat/stablecoin-collateralization-check
Open

feat(stablecoin): add collateralization-check helper#336
gravityblast wants to merge 1 commit into
mainfrom
feat/stablecoin-collateralization-check

Conversation

@gravityblast

Copy link
Copy Markdown
Collaborator

Adds stablecoin_program::checks::assert_position_is_collateralized, the shared
spec §6.2 invariant used by withdraw_collateral (post-decrement) and
generate_debt (post-mint).

Pure function over scalars — the callers project the accumulator and redemption
price forward to now (§5.3) and pass them in, so the projection isn't computed
twice per instruction. Uses the cross-multiplied form the spec prescribes, in
U256, so no intermediate rounding enters the comparison. Zero-debt positions
short-circuit to pass.

8 unit tests: zero debt with and without collateral, comfortable surplus, the
exact boundary and one unit below it, exactly 1.5x and one unit below it, and
accumulator growth flipping a passing position to failing.

First of eight issues in Plan 3 (#173). No Instruction variant and no guest
change, so the IDL is untouched.

closes #174

@gravityblast
gravityblast marked this pull request as draft August 27, 2026 14:32
@gravityblast
gravityblast marked this pull request as ready for review August 27, 2026 14:34
@gravityblast
gravityblast requested review from 0x-r4bbit and a lite review from Copilot August 27, 2026 14:35

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.

Pull request overview

Adds a reusable, spec-aligned collateralization invariant check to stablecoin_program so upcoming position-lifecycle instructions can share one canonical implementation and test suite.

Changes:

  • Introduces stablecoin_program::checks::assert_position_is_collateralized, implementing the §6.2 invariant using U256 intermediates and a zero-debt fast-path.
  • Adds focused unit tests covering boundary, near-boundary, and accumulator-growth scenarios.
  • Wires the new module into the crate exports and adds the required direct dependency.

Reviewed changes

Copilot reviewed 3 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
programs/stablecoin/src/lib.rs Exposes the new checks module from stablecoin_program.
programs/stablecoin/src/checks.rs Implements assert_position_is_collateralized and adds unit tests for key invariant edges.
programs/stablecoin/Cargo.toml Adds alloy-primitives as a direct dependency for U256 use in stablecoin_program.
Cargo.lock Records the new stablecoin_program -> alloy-primitives dependency in the workspace lockfile.
programs/stablecoin/methods/guest/Cargo.lock Updates the guest lockfile to reflect the new dependency in guest builds.

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

.checked_div(one)
.expect("collateralization check: FIXED_POINT_ONE is non-zero");

let collateral_value = multiply(multiply(U256::from(position.collateral_amount), one), one);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

U256 is not wide enough for these cross-products over the function's valid u128 input domain. Since FIXED_POINT_ONE^2 == 10^54, the left side already overflows when collateral_amount reaches
115792089237316195423571. With that collateral, debt 1, accumulator and redemption price FIXED_POINT_ONE, and ratio 1.1 * FIXED_POINT_ONE, the position is comfortably collateralized but this multiplication panics before the comparison. Token supply, holding balance, and position collateral have no
smaller bound. Please use a width that holds the complete products (for example U512) or an overflow-free exact comparison, and add a regression at this boundary.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Concrete trigger:

position.collateral_amount       = 115792089237316195423571
position.normalized_debt_amount  = 1
current_accumulator              = 1000000000000000000000000000
current_redemption_price         = 1000000000000000000000000000
minimum_collateralization_ratio  = 1100000000000000000000000000

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 · 01] Collateralization-check helper

3 participants