Skip to content

[BUG BOUNTY] CreditDelegation Negative Debt Erasure, Zero Repayment Line Termination, and Self-Delegation #956

Description

@teddyvj

Summary

Multiple critical business logic flaws, input validation omissions, and state-corruption bugs were identified in the stellarlend-credit-delegation smart contract (contracts/credit-delegation/src/lib.rs):

  1. Arbitrary Debt Erasure via Negative draw():

    • draw() takes amount: i128 without verifying amount > 0.
    • If a borrower calls draw() with a negative amount (e.g. amount = -1_000_000), new_drawn = credit_line.drawn_amount + amount computes to credit_line.drawn_amount - 1_000_000.
    • A delinquent borrower can arbitrarily reduce or completely erase their recorded debt without repaying any funds.
  2. Immediate Line Termination on Zero Repayment (repay(id, 0)):

    • repay() takes amount: i128 without verifying amount > 0 or checking whether any debt has actually been drawn (credit_line.drawn_amount == 0).
    • If repay(id, delegate, 0) is called on a freshly created active credit line (drawn_amount == 0):
      new_repaid = 0 + 0 = 0.
      new_repaid >= credit_line.drawn_amount evaluates to 0 >= 0 (True!).
      credit_line.status = CreditStatus::Repaid.
    • The credit line is permanently killed and can never be drawn, causing an immediate denial of service.
  3. Missing Lifecycle and Entity Validations in create_credit_line():

    • Allows self-delegation: delegator == delegate.
    • Allows creating expired credit lines: maturity <= ledger.sequence().
    • Allows negative collateral: collateral < 0.
  4. Missing Authority Checks on Inactive Lines:

    • adjust_limit() allowed adjusting new_max on defaulted/repaid lines or setting new_max <= 0.
    • transfer() allowed delegators to transfer debt ownership to the borrower (new_delegator == delegate) or transfer defaulted/repaid lines.
  5. Unrecorded Audit History:

    • Defined DrawRecord and RepaymentRecord data types were never saved to storage, eliminating on-chain audit trails for debt movements.

Root Cause & Impact

  • Severity: Critical / High (under SECURITY.md rules: arbitrary debt balance erasure, credit line denial of service, invalid state transitions).
  • Vulnerable Code: contracts/credit-delegation/src/lib.rs:
    • draw(): missing amount > 0 guard.
    • repay(): missing amount > 0 and drawn_amount > 0 guard.
    • create_credit_line(): missing delegator != delegate, maturity > current_ledger, and collateral >= 0.

Proposed Remediation

  1. Enforce Strict Positive Amounts:

    • Require amount > 0 in both draw() and repay().
    • Reject repay() when drawn_amount == 0.
  2. Enforce Creation & Transfer Constraints:

    • Reject delegator == delegate, maturity <= ledger.sequence(), and negative collateral in create_credit_line().
    • Reject transfers to delegate or transfers of inactive lines.
  3. Record Audit History:

    • Save DrawRecord and RepaymentRecord in storage on each operation and expose view functions get_draw_record() and get_repayment_record().

Bounty Payout Addresses

In accordance with SECURITY.md:

  • USDC / USDT (EVM / Arbitrum / Ethereum / Polygon): 0xf5fcb1f90f8a2e658f38f72f0156ecbec7aa964d
  • SOL / USDC (Solana): ECYrMmKpVNyvWMuLNkBuWxqkk2TNRC3qVPDgonBwamKP
  • BTC (Bitcoin): bc1qjg5lug59rn9rz2j2f9ut798g99mn2asw9jfv0s
  • Security Contact: teddy.vj@gmail.com

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions