Repository navigation
Close a bond with its final coupon; emit BondMatured - #275
Merged
Merged
Conversation
Add docs/plans/redeem-with-final-coupon/ (intent, design, plan, progress) and ADR 0005 (Proposed): the final payCoupon pays coupon plus principal in wNOK, burns every unit, skips and then burns unsold manager-held units without cash, and emits one BondMatured event with totals; the separate BondManager.redeem, its API route, the unused UI client, and the AllCouponsPaid / BondRedemptionComplete events are removed. Index both in the documentation index and the ADR index. No code changed.
Phase 0 of docs/plans/redeem-with-final-coupon/: the coupon test pins the per-unit coupon at 42 WNOK (1000 nominal at 4.25%, integer-truncated) so the closure change cannot alter interim payouts unnoticed, and the plan's progress file records that ingestion applies a block batch manager-first inside one database transaction, which the order-independent reducer tolerates.
The final payCoupon now pays each holder coupon plus principal in one DvP settlement with the Redeem operation, burns their units, burns any unsold units the manager holds without payment, requires partition supply to reach zero, and emits BondMatured(isin, paymentCount, principalPaid, couponPaid, unsoldBurned) exactly once. Interim periods are unchanged for holders and skip manager-held units, which closes the treasury-held-units coupon deadlock by construction. The separate redeem entry point and the AllCouponsPaid and BondRedemptionComplete events are removed. The holder loop moves into _payHolders/_payHolder with Period and PayoutTotals memory structs; keeping it inline exceeded solc's stack even under via-IR. Tests replace the redeem cases with closure, incomplete holders, underfunded closure, unsold units, and fuzz coverage: forge test 25 suites, 394 passed. Contract docs and the two affected NatSpec pages describe the closure; the nb-bond-api ABI artifact is refreshed (API and UI follow in the next slice). Plan progress in docs/plans/redeem-with-final-coupon/progress.md; decision in ADR 0005.
This was referenced Sep 8, 2026
Greaker
added a commit
that referenced
this pull request
Sep 8, 2026
Move docs/plans/redeem-with-final-coupon/ to docs/plans/archive/ with its status set to Implemented (shipped via #275 and #276), tick its done criteria, close out progress.md, and move the documentation-index entry to the archive list. ADR 0005 moves to Accepted in the ADR index and the documentation index. The contracts versioning note no longer names the removed BondManager.redeem entry point.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
BondManager.payCouponnow closes the bond on the final period: each holder is settled once for coupon plus principal in WNOK throughBondDvP(Redeemoperation) and their units are burned; unsold units the manager holds are burned without payment; partition supply must reach zero; andBondMatured(isin, paymentCount, principalPaid, couponPaid, unsoldBurned)is emitted once. Interim coupons are unchanged for holders and skip manager-held units, which removes the treasury-held-units coupon deadlock by construction.BondManager.redeemand theAllCouponsPaid/BondRedemptionCompleteevents are removed.docs/plans/redeem-with-final-coupon/and ADR 0005 (Proposed), updates the contract docs and two NatSpec pages, and refreshes the nb-bond-apiBondManagerABI artifact.POST /v1/bonds/{isin}/redemptionsagainst a function that no longer exists, and the projection never reaches a terminal status until the API ingestsBondMatured. The follow-up PR (Phases 2–5: API, UI, sandbox evidence, docs) must land before the sandbox is redeployed fromdevelopment.Test plan
cd contracts && forge fmt --check && forge build --sizes && bash ./check-verify-latest-mapping.sh && forge test— 25 suites, 394 tests (closure, incomplete holders, underfunded closure, unsold units, fuzz)cd services/nb-bond-api && npm run lint && npm run format:check && npm test && npm run build— 245 tests (ABI artifact only)python3 scripts/verification/check-public-repo-hygiene.py && python3 scripts/verification/check-markdown-links.py