fix(lp): validate fund_loan recipients and cap outflows & merchant exposure - #110
Conversation
|
Please rebase/merge the base branch into your branch and resolve the conflicts — a fresh audit will run automatically once new commits land. |
EmeditWeb
left a comment
There was a problem hiding this comment.
✅ 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:
Audited by stepfi-audit-bot 🤖
|
Superseded by PR from Emeka-12 fork (same branch/commit, correct authorship). |
|
Superseded by PR from the Emeka-12 fork (same branch, correct authorship). |
Closes #106
Summary
liquidity_pool::fund_loanpreviously paid anymerchantaddress 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 existingrequire_creditlinecaller restriction (kept):set_outflow_cap_bps(1..=10_000 bps of available liquidity;0= disabled). Cumulativefund_loanoutflows within a ledger are bounded, with a rolling window keyed to the ledger sequence that resets automatically on ledger change.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 monitorget_merchant_fundedbefore enabling a ceiling.initialize()accepts an optionalvendor_registryaddress (also settable post-init via admin-onlyset_vendor_registry). When set,fund_loanrequires the recipient to be an active (approved) vendor via the registry'sis_active(), fail-closed (invocation errors block funding). Unset = backward-compatible legacy behavior.Changes
contracts/liquidity-pool-contract/src/lib.rs— guards, admin setters, getters, internalvendor_is_activecross-checkcontracts/liquidity-pool-contract/src/storage.rs— outflow window, exposure, vendor-registry storage + TTLcontracts/liquidity-pool-contract/src/types.rs— default cap constants (targeted, zero, default-disabled)contracts/liquidity-pool-contract/src/errors.rs—OutflowCapExceeded,MerchantExposureCapExceeded,VendorNotActive,InvalidCapcontracts/liquidity-pool-contract/src/events.rs—LOAN_FUNDEDnow carries(merchant, amount, outflow_remaining, merchant_remaining); newCAPSUPD/VREGUPDeventscontracts/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 payloadcontracts/creditline-contract/src/tests.rs— updated for newinitializesignaturescripts/deploy-testnet.sh— passes--vendor_registry, opt-inOUTFLOW_CAP_BPS/MERCHANT_EXPOSURE_CAPenv-gated capscontext/progress-tracker.md— documented entryAcceptance criteria
cargo test --locked: 401 passing (125 liquidity-pool, 143 creditline, 20 parameters, 60 reputation, 26 vendor-registry, 27 vouching)