Skip to content

fix(lp): validate fund_loan recipients and cap outflows & merchant exposure - #110

Closed
KingFRANKHOOD wants to merge 1 commit into
StepFi-app:mainfrom
KingFRANKHOOD:fix/106-lp-fund-loan-recipient-validation-caps
Closed

fix(lp): validate fund_loan recipients and cap outflows & merchant exposure#110
KingFRANKHOOD wants to merge 1 commit into
StepFi-app:mainfrom
KingFRANKHOOD:fix/106-lp-fund-loan-recipient-validation-caps

Conversation

@KingFRANKHOOD

Copy link
Copy Markdown
Contributor

Closes #106

Summary

liquidity_pool::fund_loan previously paid any merchant address the registered creditline supplied, with no independent recipient verification and no bound on how fast a misbehaving or compromised creditline could drain pool liquidity. This PR layers defense-in-depth guards on top of the existing require_creditline caller restriction (kept):

  1. Per-ledger outflow cap — admin configurable set_outflow_cap_bps (1..=10_000 bps of available liquidity; 0 = disabled). Cumulative fund_loan outflows within a ledger are bounded, with a rolling window keyed to the ledger sequence that resets automatically on ledger change.
  2. Single-recipient concentration cap — admin configurable set_merchant_exposure_cap (token units; 0 = disabled) bounds cumulative funding to any one merchant. Cumulative exposure is tracked regardless (persistent with TTL) so admins can monitor get_merchant_funded before enabling a ceiling.
  3. Optional vendor cross-checkinitialize() accepts an optional vendor_registry address (also settable post-init via admin-only set_vendor_registry). When set, fund_loan requires the recipient to be an active (approved) vendor via the registry's is_active(), fail-closed (invocation errors block funding). Unset = backward-compatible legacy behavior.

Changes

  • contracts/liquidity-pool-contract/src/lib.rs — guards, admin setters, getters, internal vendor_is_active cross-check
  • contracts/liquidity-pool-contract/src/storage.rs — outflow window, exposure, vendor-registry storage + TTL
  • contracts/liquidity-pool-contract/src/types.rs — default cap constants (targeted, zero, default-disabled)
  • contracts/liquidity-pool-contract/src/errors.rsOutflowCapExceeded, MerchantExposureCapExceeded, VendorNotActive, InvalidCap
  • contracts/liquidity-pool-contract/src/events.rsLOAN_FUNDED now carries (merchant, amount, outflow_remaining, merchant_remaining); new CAPSUPD / VREGUPD events
  • contracts/liquidity-pool-contract/src/tests.rs — 16 new tests: cap enforcement under repeated calls, rolling window reset, guarded/validated admin setters, per-recipient independence, enabled/disabled vendor modes, legacy-restore, event payload
  • contracts/creditline-contract/src/tests.rs — updated for new initialize signature
  • scripts/deploy-testnet.sh — passes --vendor_registry, opt-in OUTFLOW_CAP_BPS / MERCHANT_EXPOSURE_CAP env-gated caps
  • context/progress-tracker.md — documented entry

Acceptance criteria

  • Outflow and concentration caps enforced on-chain with tests
  • Optional vendor validation wired and tested in both enabled/disabled modes
  • Honest flows unchanged (regression tests)
  • Suite green — cargo test --locked: 401 passing (125 liquidity-pool, 143 creditline, 20 parameters, 60 reputation, 26 vendor-registry, 27 vouching)

@EmeditWeb

Copy link
Copy Markdown
Member

⚠️ @KingFRANKHOOD this PR now has merge conflicts with the base branch (likely because another PR was merged first).

Please rebase/merge the base branch into your branch and resolve the conflicts — a fresh audit will run automatically once new commits land.

@EmeditWeb EmeditWeb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

✅ Automated Audit: solves

@KingFRANKHOOD Excellent work, thank you! 🎉

The PR GENUINELY addresses issue #106 by implementing all required defense-in-depth guards: (1) per-ledger outflow cap with rolling window reset keyed to ledger sequence, (2) single-recipient concentration cap with cumulative tracking and TTL, and (3) optional vendor cross-check via vendor-registry is_active() that's backward-compatible when unset. All 16 new tests pass, covering cap enforcement, window resets, guarded admin setters, per-recipient independence, both vendor modes, and legacy behavior. The 401 CI tests pass. The code changes directly implement the issue's requirements without replacing the existing require_creditline restriction. The PR title and description are substantive and match the implementation.


CI checks: ✅ PASSED: Build and Test Contracts
Merge conflicts: ⚠️ YES — this PR has conflicts with the base branch and cannot be merged. Please resolve the conflicts before this PR can be approved.

Audited by stepfi-audit-bot 🤖

@Emeka-12

Copy link
Copy Markdown
Contributor

Superseded by PR from Emeka-12 fork (same branch/commit, correct authorship).

@KingFRANKHOOD

Copy link
Copy Markdown
Contributor Author

Superseded by PR from the Emeka-12 fork (same branch, correct authorship).

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.

Critical: liquidity pool blindly pays any merchant address the creditline names — no recipient validation or exposure cap

3 participants