reinstate_credit_line from Defaulted#213
Merged
greatest0fallt1me merged 6 commits intoCreditra:mainfrom Mar 31, 2026
Merged
Conversation
Implement reinstate_credit_line as a public contract function that
transitions a Defaulted credit line to either Active or Suspended,
per the documented state machine.
Changes:
- lifecycle.rs: update reinstate_credit_line to accept target_status
parameter (Active or Suspended); validate invalid targets panic with
'target_status must be Active or Suspended'
- lib.rs: expose reinstate_credit_line as a public #[contractimpl] fn;
inline config:: and query:: calls that were referencing undeclared
modules; add missing ContractError import; fix CreditLineData init
to include accrued_interest and last_accrual_ts fields
- test.rs: update all existing call sites to pass target_status; add
12 new explicit transition tests covering:
- Defaulted → Active (draws re-enabled)
- Defaulted → Suspended (draws still blocked)
- utilized_amount preserved on both paths
- invalid target_status (Closed, Defaulted) reverts
- event emission with correct status for both targets
- state machine round-trips (reinstate → suspend, reinstate → close)
- unauthorized caller reverts
Invariants documented:
- utilized_amount, credit_limit, interest_rate_bps, risk_score
are all preserved unchanged after reinstatement
- Only admin can reinstate; only from Defaulted status
Closes Creditra#115
- Add missing SPDX-License-Identifier: MIT header to lib.rs - Import ContractError from types in lib.rs (was undeclared) - Inline config:: calls (set_liquidity_token, set_liquidity_source) - Inline query::get_credit_line (module was never declared) - Inline risk::set/get_rate_change_limits (module was never declared) - Add missing accrued_interest and last_accrual_ts fields to CreditLineData init - Add missing setup() and approve() helpers to test module - Add TryFromVal/TryIntoVal imports to test module - Fix test_suspend_nonexistent_credit_line: was opening with invalid rate instead of suspending nonexistent borrower - Fix suspend_defaulted_line_reverts: body was testing draw/balance, not the suspend transition - Fix test_draw_credit_updates_utilized: risk_score 101 exceeds max, changed to 70 - Fix test_multiple_borrowers: was calling suspend after default (invalid transition), rewrote to actually test multiple borrowers - Fix duplicate_open_policy.rs: add Restricted arm to non-exhaustive match on CreditStatus - Delete stale test snapshots that caused false failures
|
@Phantomcall Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
- cargo fmt: fix all formatting issues flagged by CI - Add test_events_coverage module covering all uncovered events.rs functions: publish_credit_line_event_v2, publish_repayment_event_v2, publish_drawn_event_v2, publish_interest_accrued_event - Fix test_reinstate_to_suspended_blocks_draws: expected panic message was 'draws are not allowed', actual is 'credit line is suspended' - Add SPDX header to lib.rs (fixes spdx_header_bug_exploration tests) Coverage: events.rs was at 40.68% dragging total to 85.71%. New tests cover all 4 previously-dead publish functions, pushing events.rs coverage up and total line coverage above 95% threshold.
- Remove unused Ledger import from test_smoke_coverage module - Remove dead-code helpers from mod test (setup_contract_with_credit_line, setup_test, call_contract, get_credit_data) — none were called - Fix unused variable: borrower shadowed in test_event_reinstate_credit_line - Fix unused variable: token_id in draw_credit_overflow test (prefix _) - Add #[allow(dead_code)] to events.rs v2 publish functions and publish_interest_accrued_event — these are public API for indexers, intentionally not called from contract logic
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.
feat(credit): reinstate_credit_line — Defaulted → Active / Suspended
Summary
Implements
reinstate_credit_lineas a public contract entry point, allowing an admin to transition a credit line out of theDefaultedstate back to eitherActiveorSuspended, per the documented state machine. Also resolves a set of pre-existing compilation and test errors that were blocking the build.What Changed
Core Feature —
reinstate_credit_linecontracts/credit/src/lifecycle.rsUpdated the existing
reinstate_credit_linefunction to accept atarget_status: CreditStatusparameter instead of hardcodingActive. The function now:"Credit line not found"otherwise)Defaulted(panics with"credit line is not defaulted"otherwise)target_statusis eitherActiveorSuspended(panics with"target_status must be Active or Suspended"for any other value)("credit", "reinstate")CreditLineEventwith the new statuscontracts/credit/src/lib.rsExposed
reinstate_credit_lineas a public#[contractimpl]function on theCreditstruct, with full doc comments covering parameters, panics, events, and post-reinstatement invariants.State Machine
Invariants After Reinstatement
utilized_amountis preserved unchanged (outstanding debt is not forgiven)credit_limit,interest_rate_bps, andrisk_scoreare unchangedActive; remain disabled when target isSuspendedTests Added (
contracts/credit/src/test.rs)12 new explicit transition tests:
test_reinstate_to_active_enables_drawstest_reinstate_to_suspended_statustest_reinstate_to_suspended_blocks_drawstest_reinstate_preserves_utilized_amounttest_reinstate_to_suspended_preserves_utilized_amounttest_reinstate_invalid_target_status_closed_revertstest_reinstate_invalid_target_status_defaulted_revertstest_reinstate_to_active_emits_event_with_active_statustest_reinstate_to_suspended_emits_event_with_suspended_statustest_reinstate_to_active_then_suspend_againtest_reinstate_to_suspended_then_admin_closetest_reinstate_to_suspended_unauthorizedAll existing reinstate call sites updated to pass
&CreditStatus::Activeas the target.Pre-existing Errors Fixed
The codebase had 97 compilation errors and several failing tests before this PR. The following were resolved as part of this work:
Compilation Errors (lib.rs)
ContractErrorundeclareduse types::{}was missingContractErrorconfig::set_liquidity_token/set_liquidity_sourcemod configwas never declared in lib.rsquery::get_credit_linemod querywas never declared in lib.rsenv.storage().persistent().get(&borrower)risk::set_rate_change_limits/get_rate_change_limitsmod riskwas never declared in lib.rsCreditLineDatamissing fieldsaccrued_interestandlast_accrual_tsadded totypes.rsbut not to the struct literal inopen_credit_line0lib.rsfirst line was#![no_std]// SPDX-License-Identifier: MITas line 1Test Errors (lib.rs test modules)
mod testsetup()andapprove()helpers called but not defined in that modulemod testmod testTryFromVal/TryIntoValnot in scopeusestatementtest_suspend_nonexistent_credit_linesuspend_credit_lineon an address with no linesuspend_defaulted_line_revertsdefault_credit_lineorsuspend_credit_linetest_draw_credit_updates_utilizedupdate_risk_parameterswithrisk_score = 101(exceeds max of 100)70test_multiple_borrowers(smoke)suspend_credit_lineafterdefault_credit_line— invalid transition that panicstest_event_reinstate_credit_line(coverage gaps)setup_contract_with_credit_linewhich is not in scope in that modulebase_setupwhich is defined in the same moduleIntegration Test Error (
tests/duplicate_open_policy.rs)matchonCreditStatusRestrictedvariant added to enum but not covered in matchCreditStatus::Restricted => {}armTest Results
Security Notes
reinstate_credit_lineis admin-only. No borrower-initiated reinstatement path exists.utilized_amountis intentionally preserved on reinstatement — the debt does not disappear. Reinstating toActivere-enables draws, so the admin should verify the borrower's repayment capacity before reinstating.Suspendedis a safer intermediate step: it clears theDefaultedflag (e.g. for accounting) while keeping draws locked until a subsequentActivetransition.Closes #115