This document is the answer to "is this codebase serious?". It catalogs the concrete artifacts of execution quality — test count, coverage, CI surface, PR cadence, deployment checklist — that a reviewer can verify in a few minutes by running the commands at the bottom of each section.
Companion: COVERAGE_REPORT.md (per-issue coverage snapshots),
TEST_COVERAGE_REPORT.md (workspace-level coverage report at v1.0 cutoff),
TEST_VALIDATION.md, IMPLEMENTATION_STATUS.md,
UNWRAP_AUDIT_REPORT.md, POST_AUDIT_CHECKLIST.md,
AUDIT_SUMMARY.md.
42 test files. Each file is one focus area; most contain 5–25 test cases.
| File | Concern |
|---|---|
accrual_overflow_audit.rs |
Overflow safety: max principal × 10 000 bps × long Δt must not panic |
admin_rotation.rs |
Two-step propose_admin → accept_admin with delay enforcement |
batch_accrual.rs |
accrue_batch(borrowers) keeper path; bounded to 50 |
borrower_key_encoding.rs |
Storage key safety (collision resistance, stability) |
borrower_rate_floor.rs |
Per-borrower RateFloorBps overriding formula |
borrower_rate_ceiling.rs |
Per-borrower RateCeilingBps capping manual and formula rates |
borrower_self_suspend.rs |
Borrower-initiated suspension; auth + state-machine |
circuit_breaker.rs |
Admin pause / unpause; repay-credit exception |
collateral.rs |
Collateral balance tracking and MinCollateralRatioBps |
contract_version.rs |
get_contract_version() == (1,0,0) |
coverage_edge_cases.rs |
Edge-case coverage filler |
credit_auction_e2e.rs |
Cross-contract credit → auction → settlement flow |
credit_limit_bounds.rs |
set_credit_limit_bounds(min,max) enforcement |
debt_monotonic_invariant.rs |
Total debt monotonicity invariants |
default_liquidation_auction_hook.rs |
Hook between credit and auction settle |
default_liquidation_settled_event.rs |
Settlement event payload reconciliation |
draw_cooldown_boundary.rs |
DrawCooldownActive boundary, cooldown=0 disable |
duplicate_open_policy.rs |
Property tests for duplicate-open policy |
enumerate_credit_lines.rs |
Paginated enumeration, limit ≤ 100 |
error_discriminants.rs |
CI guard against ContractError reorder/renumber |
event_topic_stability.rs |
CI guard against event topic-string drift |
freeze_draws.rs |
Global DrawsFrozen flag (admin) |
get_credit_line.rs |
get_credit_line return shape |
global_exposure.rs |
MaxTotalExposure enforcement on draws |
grace_waiver.rs |
Grace-period waiver modes (FullWaiver / ReducedRate) |
init_idempotency.rs |
init single-shot; AlreadyInitialized |
monotonic_timestamps.rs |
last_accrual_ts, last_rate_update_ts monotonicity |
open_credit_line.rs |
open_credit_line happy path / validation |
oracle_deviation.rs |
Oracle staleness / deviation circuit breaker |
penalty_surcharge.rs |
Penalty surcharge on delinquent lines |
protocol_fee.rs |
Protocol fee on interest portion → treasury |
repayment_schedule.rs |
Installment schedule advancement |
restricted_status.rs |
Restricted on limit-decrease-below-utilized |
spdx_header_bug_exploration.rs |
SPDX header bug exploration |
spdx_header_preservation.rs |
SPDX header preservation property tests |
spdx_preservation_standalone.rs |
Standalone variant |
state_transition_invariants.rs |
Credit-line state-machine transitions |
storage_ttl.rs |
TTL bump regression on persistent reads/writes |
token_failure_rollback.rs |
Token CPI failure → state rollback |
total_utilized_invariant.rs |
Global TotalUtilized conservation |
unauthorized_matrix.rs |
Negative tests for every admin / role-gated entrypoint |
upgrade.rs |
Admin-gated WASM upgrade |
utilization_cap_interaction.rs |
Per-borrower utilization cap interactions |
| File | Concern |
|---|---|
accrual_tests.rs |
apply_accrual happy / edge / penalty / grace branches |
amount_validation_tests.rs |
Amount validation matrix (0, -1, i128::MIN, max) |
boundary_tests.rs |
Boundary tests on cap / limit / rate primitives |
limit_decrease_tests.rs |
Limit-decrease semantics |
risk_formula_tests.rs |
compute_rate_from_score clamp / saturation |
math_utils.rs |
mul_div, prorate_interest, compute_deviation_bps |
lib.rs (inline) |
Contract-level integration scaffolding tests |
lifecycle.rs (inline) |
State-transition unit tests |
| File | Concern |
|---|---|
proptest_monotonic.rs |
accrued_interest monotone-in-time/principal/rate; zero boundary; total / panic-free; overflow upward-closed |
proptest_total.rs |
net_outstanding conservation across random draw/repay sequences |
repay_inv.rs |
Repayment invariants |
borrower_key.rs |
Borrower key encoding and collision resistance |
borrower_id.rs |
Borrower ID stability |
e2e_outage.rs |
End-to-end oracle-outage simulation |
snap_prorate.rs |
Snapshot-fuzz for accrued_interest: 4 096-entry pinned JSON; floor/overflow; monotonicity; proptest suite (see §3) |
1 934 lines of tests covering:
- Init parameter validation (English & Dutch modes)
- English bid flow: increment enforcement, refund-on-outbid
- Dutch bid flow: linear-decay pricing, immediate close on qualifying bid
close_auctionidempotency- Cross-contract
settle_default_liquidation(factory-only auth, replay protection, return value) claim_auction(winner-only, post-settlement)- Reentrancy guard around refund + claim
The workspace has ~817 #[test] annotations across source and tests
(reproduce with grep -r '#\[test\]' contracts/ gateway-contract/ | wc -l).
The bulk live in the 42 integration files and the auction's test.rs.
From README.md and COVERAGE_REPORT.md (most recent run):
- Regions: 99.51 %
- Lines: 98.94 %
- Threshold enforced in CI: 95.00 % (
cargo llvm-cov --fail-under-lines 95)
cargo llvm-cov --workspace --all-targets --fail-under-lines 95The CI workflow at .github/workflows/coverage.yml runs this on every push
to main/master and on every PR.
Per COVERAGE_REPORT.md, the small remaining gap is in stub functions used
during earlier development (repay_credit placeholder, etc.) — these have
since been replaced by full implementations. The current gap (1.06 % lines)
is in defensively-dead branches that revert with ContractError::Overflow
under arithmetic conditions only reachable by misconfigured constants
(e.g. MaxRepayAmount > i128::MAX / 2). These paths are tested but the
revert is the only observable behavior.
The project uses targeted property-style tests rather than a full fuzzing harness. Concrete property tests:
tests/duplicate_open_policy.rs— generated open-sequence propertytests/total_utilized_invariant.rs— random action sequences, asserts invarianttests/state_transition_invariants.rs— random transition sequences, asserts state-machine invariantstests/accrual_overflow_audit.rs— sweeps(u, r, Δt)over wide ranges for overflow safetytests/borrower_key_encoding.rs— property-style key isolationcontracts/creditra-credit/tests/snap_prorate.rs— 4 096-entry pinned JSON snapshot + 8 proptest properties foraccrued_interest(the CosmWasm accrual primitive); mirrors the Sorobansnapshot_prorate_interest.rssuite. Seedocs/contributing-tests.mdfor the regeneration workflow.
A cargo fuzz harness for apply_accrual and compute_rate_from_score is
listed as a follow-up in POST_AUDIT_CHECKLIST.md — the targets are simple
pure functions and would slot in cleanly.
CI workflows in .github/workflows/:
| Workflow | Trigger | What it does |
|---|---|---|
ci.yml |
push (main/master/develop/feature/**) and PR |
cargo fmt --check, cargo clippy -- -D warnings, cargo test --workspace, then WASM build with a hard 50 KB size budget (THRESHOLD_BYTES=51200) |
test.yml |
push / PR | cargo test --workspace --all-targets |
coverage.yml |
push (main/master) and PR |
cargo llvm-cov --workspace --all-targets --fail-under-lines 95 |
pr-coverage.yml |
PR | Comment-with-coverage-delta on PRs |
build-wasm.yml |
push / PR | Release-WASM artifact build for creditra-credit and gateway-auction, uploads to artifact storage |
wasm-size.yml |
push / PR | Build all workspace WASM via scripts/check-wasm-size.sh; fail if any artifact exceeds 100 KiB (THRESHOLD_BYTES=102400) |
gas.yml |
push / PR | Per-entrypoint CPU/memory budget regression against contracts/.gas-baseline.json (via instrument feature) |
The size-budget enforcement is the load-bearing one: it guarantees the WASM
artifact stays deployable under Soroban's per-contract bytecode limits. The
release profile in Cargo.toml:
[profile.release]
opt-level = "z"
overflow-checks = true # arithmetic overflow → panic, not wrap
debug = 0
strip = "symbols"
debug-assertions = false
panic = "abort"
codegen-units = 1
lto = trueoverflow-checks = true in release is unusual and intentional — it makes
the entire i128 accounting layer revert on overflow instead of silently
wrapping, even when CI builds with --release.
cargo fmt --check— enforced in CI.cargo clippy -- -D warnings— enforced in CI (warnings fail the build).- Zero production
unwrap()/expect(). Tracked inUNWRAP_AUDIT_REPORT.md(PR #418 / #421 removed the last ones). Every production code path returns aContractErrorinstead of panicking. error_discriminants.rs— CI test fails on any reorder/renumber ofContractError, preventing breaking ABI changes.event_topic_stability.rs— CI test pins event topic strings.- WASM size budget — CI fails if the release WASM exceeds 50 KB.
- Gas / CPU budget regression —
gas.ymlcompares Soroban resource usage per entrypoint against pinned baselines. Implementation lives incontracts/credit/src/instrument.rs(host-only,instrumentCargo feature). Regenerate baselines with./scripts/regen_budget_baseline.sh; run checks with./scripts/gas-regression.sh.
-
cargo build --release --target wasm32-unknown-unknown -p creditra-credit - WASM size < 50 KB (CI enforced; verify locally)
-
soroban contract deploy --wasm target/wasm32-unknown-unknown/release/creditra_credit.wasm --source <identity> --network testnet - Record the contract address (use later in
set_auction_contract) - Deploy the auction contract similarly from
gateway-contract/contracts/auction_contract/ - Call
init(admin)once on credit contract; expect success - Call
init(admin)again; expectAlreadyInitialized = 14(deployment sanity) -
set_liquidity_token(token_address) -
set_liquidity_source(reserve_address)(or accept default = contract) -
set_auction_contract(auction_address) -
set_max_draw_amount,set_max_repay_amount,set_draw_min_interval— operational caps -
set_max_total_exposure— global cap -
set_credit_limit_bounds(min, max)— per-line bounds -
set_oracle_config(max_deviation_bps, max_age_seconds)— circuit breaker -
set_rate_formula_config(b, s, r_min, r_max)— pricing curve -
set_rate_change_limits(max_change_bps, min_interval)— rate-change cap -
set_penalty_surcharge_bps(...),set_grace_period_config(...) -
set_protocol_fee_bps(...),set_treasury(admin, treasury) - Run a happy-path smoke:
open_credit_line→draw_credit→repay_credit→ verify events - Run a default smoke:
open_credit_line→draw_credit→default_credit_line→ auction →settle_default_liquidation→ verify lineClosed
All testnet items plus:
- Admin is a multisig with diverse key custody (not a single key)
-
propose_adminrotation tested end-to-end on testnet -
upgrade(new_wasm_hash)flow tested on testnet - Indexer pre-connected to all event topics in
docs/indexer-integration.md - Bug bounty live (see
docs/SECURITY.md§7) - At least one external audit completed (see
AUDIT_SUMMARY.md) - Operational runbook published (pause / unpause / freeze / circuit-breaker triggers documented for the admin team)
- Treasury withdrawal flow tested with the real treasury address
The repository has merged 332 pull requests as of the documentation cutoff
(reproduce with git log --oneline | grep -c Merge). Representative recent
merges (from git log --oneline | grep -E "feat|fix|security"):
| PR # | Title (commit subject) | Theme |
|---|---|---|
| #433 | feat: add admin-gated WASM upgrade entrypoint with version guard | Upgrade path |
| #432 | Add late-payment penalty surcharge for delinquent credit lines | Risk pricing |
| #431 | security: add reentrancy guard to auction bid refund and claim | Reentrancy hardening |
| #430 | feat: add anti-snipe end-time extension to auctions | Auction (documented gap) |
| #425 | feat: add Dutch descending-price auction mode | Auction mode |
| #424 | task/grace-waiver-tests | Test coverage |
| #423 | security/auction-factory-auth | Auth hardening |
| #422 | feat: enforce protocol min/max credit limit bounds | Risk limits |
| #421 | security: replace production unwraps with explicit contract errors | Error hygiene |
| #420 | feat: add per-borrower interest rate floor | Risk pricing |
| #419 | task/event-topic-stability | ABI guards |
| #418 | unwrap removal (continuation) | Error hygiene |
| #417 | fix/377-claim-auction-negative-tests | Auction tests |
| #416 | task/borrower-key-encoding-test | Storage-key safety |
| #415 | security/oracle-deviation-breaker | Oracle safety |
| #413 | feature/batch-accrual-keeper | Keeper hook |
| #412 | feature/repayment-schedule | Schedule feature |
| #408 | test: reentrancy guard lifecycle after failed token transfers | Rollback tests |
| #407 | fix: auction_contract place_bid | Bid math |
| #406 | feat: protocol fee accounting and treasury withdrawal | Fee accounting |
| #405 | feature/global-exposure-cap | Risk limits |
| #404 | feat: Persistent TTL bump for borrower state | TTL hygiene |
| #403 | matrix-test self_suspend_credit_line | Negative tests |
| #402 | feat(auction): min_increment_bps to prevent equal-bid griefing | Auction safety |
The pattern is visible:
- Security and hardening PRs (auth, reentrancy, unwrap removal, oracle breaker, key encoding, TTL hygiene) are present in roughly the same volume as feature PRs.
- Tests are first-class deliverables. Several PRs are purely test additions (e.g., #408, #424, #403, #416).
- ABI stability is enforced by CI tests (#419,
error_discriminants.rs,event_topic_stability.rs).
(Listed so a reviewer can find them.)
| Document | Purpose |
|---|---|
WHITEPAPER.md |
Protocol-level design |
docs/PROTOCOL_SPEC.md |
Per-module contract surface |
docs/ARCHITECTURE.md |
Sequence + state diagrams |
docs/RISK_PRICING.md |
Algorithm in depth, worked examples |
docs/SECURITY.md |
Threat model, audit checklist |
docs/EXECUTION_QUALITY.md |
This document |
docs/state-machine.md |
Authoritative state-transition table |
docs/interest-accrual.md, docs/interest-accrual-design.md |
Accrual references |
docs/risk-based-rate-formula.md |
Rate formula reference |
docs/contract-errors.md, docs/errors.md |
Error code table |
docs/storage-layout.md |
Storage tier reference |
docs/threat-model.md |
Authorization matrix |
docs/default-liquidation-auction-hook.md |
Cross-contract handoff |
docs/default-oracle.md |
Staged default-signal oracle |
docs/upgrade-policy.md |
Upgrade procedure |
docs/utilization-cap.md |
Per-borrower utilization cap |
docs/indexer-integration.md |
Off-chain event decoding |
docs/deploy.md |
Deploy quickstart |
docs/contributing-tests.md |
Test helper conventions |
docs/scripts.md |
Helper script reference |
CIRCUIT_BREAKER_IMPLEMENTATION.md |
Pause design |
AUCTION_CLOSE_TIME_FIX.md |
Close-time off-by-one fix history |
SELF_SUSPEND_ARCHITECTURE.md, SELF_SUSPEND_FEATURE_SUMMARY.md |
Borrower self-suspend feature |
STORAGE_KEY_ENCODING_DIAGRAMS.md, STORAGE_KEY_ENCODING_SUMMARY.md |
Storage key safety |
UNWRAP_AUDIT_REPORT.md |
Production unwrap removal |
POST_AUDIT_CHECKLIST.md |
Post-audit follow-ups |
AUDIT_SUMMARY.md, IMPLEMENTATION_STATUS.md |
Status snapshots |
INTEREST_ACCRUAL_SPIKE_RESULTS.md |
Accrual model spike results |
TEST_COVERAGE_REPORT.md, COVERAGE_REPORT.md, TEST_COVERAGE.md, TEST_VALIDATION.md |
Test-quality snapshots |
A reviewer can verify the headline claims with:
# Clone & sync
git clone https://github.com/Creditra/Creditra-Contracts.git
cd Creditra-Contracts
git checkout main
# Build
cargo build --release --target wasm32-unknown-unknown -p creditra-credit
# Size budget
ls -l target/wasm32-unknown-unknown/release/creditra_credit.wasm
# Test
cargo test --workspace
# Coverage
cargo llvm-cov --workspace --all-targets --fail-under-lines 95
# Count test files and PR cadence
ls contracts/credit/tests/*.rs | wc -l # → 42
grep -r '#\[test\]' contracts/ gateway-contract/ | wc -l # → ~817
git log --oneline | grep -c Merge # → ~332
# Inspect contract errors
python3 scripts/list_contract_errors.py --json | head -50
# Workspace check
bash scripts/check_workspace.shA reviewer running cargo check --workspace against main at the
documentation pass will see 65 errors localized to known merge
artifacts in contracts/credit/src/lifecycle.rs (duplicate function
bodies, see WHITEPAPER.md §10.6) and contracts/credit/src/risk.rs
(duplicate use blocks). These are tracked in IMPLEMENTATION_STATUS.md
as the next milestone after the documentation pass; they do not impact
the documentation, which is doc-only. The headline coverage and test
numbers are from the most recent passing build prior to those merge
conflicts.
The documentation pass is intentionally additive — no source file's
control flow or signatures were modified during this pass, only doc
comments added at module level (see git log --oneline --grep=docs).