Skip to content

test: strengthen core issuance, reserve, and DepegGuard coverage - #72

Closed
Pattermesh wants to merge 1 commit into
mainfrom
pattermesh/stablecoin-toolkit-tests
Closed

Pattermesh wants to merge 1 commit into
mainfrom
pattermesh/stablecoin-toolkit-tests

Conversation

@Pattermesh

Copy link
Copy Markdown
Contributor

Summary

Strengthens the test suite on the three core areas of the toolkit with three new Foundry suites (39 new tests). All are additive — existing tests are untouched and the full suite stays green: 145 passed, 0 failed, 0 skipped (up from 106).

forge-test/MinterIssuance.t.sol — issuance (mint/burn against reserves), 12 tests

  • Reserve-ratio gate reverts when a mint would push tracked supply past what reserves back (ReserveRatioTooLow), and confirms no tokens were minted.
  • Mint at the exact reserve ceiling succeeds (ratio == 100%).
  • Successful mint propagates new supply into ReserveManager.totalSupplyTracked.
  • Raised minimum ratio (105%) gate trips at the 100% boundary and passes within headroom (self-contained strict stack).
  • authorizeMinter -> revokeMinter lifecycle blocks a previously-authorized minter; owner is an implicit authorized minter.
  • Compliance enforced through the minter: non-KYC recipient reverts; daily-limit bookkeeping via recordSpend trips ExceedsDailyLimit.
  • Full-fee mint routes everything to the collector; setFeeCollector reroutes future fees.
  • Redeem burns against supply (reduces totalSupply and tracked supply, queues redemption); redeem without approval reverts.

forge-test/ReserveManagerPoR.t.sol — reserve management / PoR, 16 tests

  • setPorAdapter set/emit, zero-address reject, onlyOwner.
  • pullPorReserve: 8->6 decimal conversion + storage under canonical id, idempotent reserve ids on repeated pulls, coexistence with a manual reserve, and PorAdapterNotSet revert when unset.
  • pullPorReserveAndCheck: reverts when ratio too low, passes when sufficient, reverts when adapter unset.
  • updateReserve on an inactive asset reverts; re-adding an asset id overwrites without duplicating the id.
  • Emitted events (ReserveUpdated, SupplyUpdated, MinimumRatioUpdated, PorReservePulled, PorAdapterSet) and onlyOwner gating on mutators.

forge-test/DepegGuardStateMachine.t.sol — DepegGuard state machine, 11 tests

  • Direct Normal -> Hard escalation (skips Caution) after one observation window.
  • Hard pins to Hard while price only recovers into the caution band.
  • Hysteresis band holds Caution (between recoveryCeilingBps and cautionBps).
  • Real Minter authorize/revoke side-effects observed under guard ownership: revoked in Caution, re-authorized on recovery to Normal; emergency-escalate/reset toggles pause + authorization.
  • emergencyEscalate to the same state is a no-op (no pause, no stateEnteredAt bump).
  • poke clears the pending observation when price snaps back to peg.
  • Remaining tuning setters: setDurations, setStaleness, setPegTarget (valid + invalid), including peg-target driving currentDeviationBps recomputation.

Also gitignores forge-out/ build output and package-lock.json.

Test output

Ran 13 test suites in 31.59s: 145 tests passed, 0 failed, 0 skipped (145 total tests)

forge build succeeds (lint warnings only). CI (.github/workflows/forge.yml) already installs forge-std + npm deps and runs forge test -vvv; no CI changes needed since the new suites use the same forge-std/Test.sol import and OpenZeppelin.

🤖 Generated with Claude Code

Adds three focused Foundry suites on the toolkit core. All complement the
existing tests rather than replace them; the full suite stays green
(145 passed, 0 failed).

- MinterIssuance.t.sol (12): mint/burn against reserves — reserve-ratio
  gate reverts on under-collateralization, exact-ceiling mint, tracked-supply
  propagation, raised-minimum-ratio gate, authorize/revoke lifecycle,
  owner-implicit authorization, compliance enforced through the minter
  (non-KYC + daily-limit), fee/collector routing, and redeem burn accounting.
- ReserveManagerPoR.t.sol (16): Chainlink PoR pull path (setPorAdapter,
  pullPorReserve decimal conversion + idempotent ids + manual coexistence,
  pullPorReserveAndCheck pass/fail/unset), inactive-asset guard, re-add
  overwrite without duplicate id, emitted events, and onlyOwner gating.
- DepegGuardStateMachine.t.sol (11): direct Normal->Hard escalation, Hard
  pin in the caution band, hysteresis hold, real Minter authorize/revoke
  side-effects under guard ownership, emergency-escalate no-op, pending-clear
  on snap-back to peg, and the remaining tuning setters (durations/staleness/
  pegTarget incl. deviation recomputation).

Also gitignores forge-out/ build output and package-lock.json.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@abhicris

Copy link
Copy Markdown
Contributor

Welcome to kcolbchain, @Pattermesh — glad you're here. 🌱

Here's what happens from this PR:

  1. Our automated review looks for obvious issues (tests, secrets, size) within a couple of hours.
  2. If it's clean and CI passes, we merge without back-and-forth.
  3. If we need changes, we'll leave a specific comment — not a generic nit. Push another commit and we re-review.

While you wait:

  • Run the repo's tests locally (see the repo README.md).
  • Keep the PR scoped to one concern — bigger PRs land slower.
  • Don't commit tokens or .env contents.

What happens after your first merge

Thanks for writing the code. We're building this to last.

@abhicris

Copy link
Copy Markdown
Contributor

This issue/PR has had no activity for 21 days and is being closed automatically by the kcolbchain PR pipeline.

If it's still relevant, reopen or leave a comment and we'll re-triage. For the full policy see pipeline docs.

@abhicris abhicris closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants