Skip to content

Latest commit

 

History

History
183 lines (151 loc) · 13.6 KB

File metadata and controls

183 lines (151 loc) · 13.6 KB

ContractError Reference

Version: 2026-04-24
Source of truth: contracts/credit/src/types.rs

This document is the canonical reference for all ContractError discriminants in the Creditra Credit contract. Integrators (TypeScript SDK, Rust SDK, indexers) must use these integer codes to identify failure reasons.


Stability Guarantee

Discriminants are permanent and immutable once assigned. The contract is deployed on Stellar Soroban and cannot be upgraded without a migration. Changing or reordering a discriminant would silently break all SDK clients that match on integer codes.

Rules enforced by CI (tests/error_discriminants.rs):

  • Every variant has an explicit = N assignment in types.rs.
  • No two variants share the same integer.
  • New variants are always appended at the end with the next available integer.
  • The assertion test file must be updated alongside any enum change.

Error Code Table

Code Variant When it occurs Resolution
1 Unauthorized Caller is not the authorized party for this operation (e.g., non-borrower calling draw_credit). Ensure the correct signer is authorizing the transaction.
2 NotAdmin Caller does not hold the admin role stored in instance storage. Use the admin keypair or rotate admin via propose_admin / accept_admin.
3 CreditLineNotFound No credit line exists in persistent storage for the given borrower address. Verify the borrower address and that open_credit_line was called successfully.
4 CreditLineClosed The credit line status is Closed; draws and repayments are both blocked. A closed line cannot be reopened. Open a new credit line for the borrower.
5 InvalidAmount The supplied amount is zero, negative, or otherwise outside the valid range. Pass a strictly positive i128 value.
6 OverLimit The requested draw would push utilized_amount above credit_limit. Reduce the draw amount or request a limit increase via update_risk_parameters.
7 NegativeLimit A credit limit of zero or below was supplied to update_risk_parameters. Supply a positive i128 credit limit.
8 RateTooHigh interest_rate_bps exceeds 10 000 (100 %) or the configured max_rate_change_bps delta. Use a rate in the range 0–10 000 bps.
9 ScoreTooHigh risk_score exceeds 100. Supply a score in the range 0–100.
10 UtilizationNotZero An operation that requires zero utilization was attempted while the borrower still has an outstanding balance. Repay the full balance before retrying.
11 Reentrancy A reentrant call was detected via the reentrancy guard on draw_credit or repay_credit. This should not occur with standard Stellar Asset Contracts. Investigate the token contract for unexpected callbacks.
12 Overflow An arithmetic operation (e.g., checked_add on utilized_amount) would overflow i128. Amounts near i128::MAX are not supported. Reduce the draw or limit value.
13 LimitDecreaseRequiresRepayment A limit decrease was requested that would push credit_limit below utilized_amount. The line transitions to Restricted status. Borrower must repay the excess (utilized_amount - new_limit) before the limit can be lowered further.
14 AlreadyInitialized init was called on a contract that already has an admin stored. init is a one-time operation. Do not call it again after deployment.
15 AdminAcceptTooEarly accept_admin was called before the delay_seconds window set in propose_admin has elapsed. Wait until env.ledger().timestamp() >= accept_after and retry.
16 BorrowerBlocked The borrower address is on the admin-managed block list; draws are disabled. Contact the protocol admin to remove the block, or use a different borrower address.
17 DrawExceedsMaxAmount The requested draw amount exceeds the per-transaction cap set via set_max_draw_amount. Split the draw into smaller transactions or request a cap increase from the admin.
18 Paused The protocol is paused via the emergency circuit breaker; operation is blocked. Wait for the admin to unpause the protocol via set_protocol_paused(false). repay_credit remains active during a pause.
19 DrawsFrozen Draws are globally frozen during liquidity reserve operations. Wait for the admin to call unfreeze_draws. Repayments remain available.
20 CreditLineSuspended A draw was attempted while the credit line status is Suspended. Reinstate the line or resolve the suspension before drawing.
21 CreditLineDefaulted A draw was attempted while the credit line status is Defaulted. Defaulted lines cannot draw; use repayment or liquidation workflows.
22 MissingLiquidityToken draw_credit or repay_credit requires a liquidity token, but none is configured. Admin must call set_liquidity_token before liquidity-moving operations.
23 MissingLiquiditySource draw_credit or repay_credit requires a liquidity source, but none is configured. Admin must call set_liquidity_source or run the configured initialization path.
24 InsufficientLiquidityReserve The reserve token balance is below the requested draw amount. Fund the liquidity source or reduce the draw amount.
25 LiquidityTokenCallFailed A liquidity token interaction failed where the contract can expose a canonical token-call failure. Inspect the configured token contract and retry only after the token issue is resolved.
26 InsufficientRepaymentAllowance The borrower has not approved enough liquidity token allowance for repay_credit. Approve at least the effective repayment amount for the credit contract.
27 InsufficientRepaymentBalance The borrower's liquidity token balance is below the effective repayment amount. Transfer or mint enough tokens to the borrower before retrying repayment.
28 RepayExceedsMaxAmount The requested repay exceeds the per-transaction cap. Split into smaller transactions.
29 DrawCooldownActive Borrower attempted to draw before cooldown elapsed. Wait for the cooldown interval.
30 TreasuryNotSet Treasury address is not configured. Admin must call set_treasury.
31 ExposureCapExceeded Draw would exceed the global protocol exposure cap. Reduce draw amount or wait for repayments.
32 AdminNotInitialized Admin address has not been initialized. Deployer must call init() first.
33 TimestampRegression Timestamp regression detected. Re-sync ledger view and retry.
34 LimitOutOfBounds Credit limit outside configured min/max bounds. Adjust limit to [min, max] range.
35 CollateralRatioBelowMinimum Collateral ratio is below the minimum required. Reduce withdrawal or add collateral.
36 OraclePriceInvalid Oracle price is zero, negative, or malformed. Ensure oracle returns a valid positive price.
37 OraclePriceStale Oracle price exceeds max_age_seconds. Wait for oracle price update.
38 OraclePriceDeviation Oracle price deviation exceeds configured maximum. Do not retry with same price; await new price.
39 InsufficientCollateralBalance Borrower's collateral balance is below the withdrawal amount. Reduce withdrawal amount.
40 BorrowerFrozen Borrower's draws are temporarily frozen until expiry. Wait for freeze expiry or contact admin.
41 BountyNotSet Bounty pool address is not configured. Admin must call set_bounty.
42 NoPendingTreasuryWithdrawal No pending treasury withdrawal proposal exists. Create a proposal first via propose_treasury_withdrawal.
43 TreasuryTimelockActive The 24-hour treasury timelock has not elapsed. Wait for timelock.
44 TreasuryProposalExists A treasury withdrawal proposal already exists. Execute or cancel the existing proposal.
45 CloseFactorAboveMax The supplied close_factor_bps exceeds the protocol maximum. Reduce close_factor_bps.
46 CreditLineFrozen Credit line draws are frozen by admin (compliance hold). Wait for admin unfreeze_credit_line.
47 DrawReversalWindowExpired Draw reversal attempted after the allowed window expired. Reversal no longer possible.
48 OriginalDrawNotFound Original draw record not found for reversal. No matching draw record.
49 AttestationBatchNotFound No attestation batch has been committed. Admin must commit a batch first.
50 OracleQuorumNotMet Oracle quorum condition not satisfied. Submit prices from more feeds.
51 AlreadySettled Liquidation for this (borrower, id) already processed. No action needed — already settled.
52 InvalidRiskWeight Collateral risk weight exceeds 10 000 bps. Ensure risk weight is in 0..=10_000.
53 InvalidAttestation Attestation proof is invalid or no batch committed. Commit a valid batch and retry.
54 AdminCollateralCooldownActive Critical collateral admin action before cool-off elapsed. Wait for admin_collateral_cooldown_seconds or set interval to 0.

SDK Usage Examples

Rust

use creditra_credit::types::ContractError;

match result {
    Err(e) if e == ContractError::OverLimit as u32 => {
        // handle over-limit
    }
    Err(e) if e == ContractError::CreditLineNotFound as u32 => {
        // handle not found
    }
    _ => {}
}

TypeScript (Soroban SDK)

import { ContractError } from "@creditra/credit-sdk";

try {
  await client.drawCredit({ borrower, amount });
} catch (err) {
  if (err.code === 6 /* OverLimit */) {
    console.error("Draw exceeds credit limit");
  } else if (err.code === 3 /* CreditLineNotFound */) {
    console.error("No credit line found for borrower");
  }
}

Security Notes

Failure Modes and Trust Boundaries

Reentrancy (code 11)
The reentrancy guard on draw_credit and repay_credit is defense-in-depth. Standard Stellar Asset Contracts do not invoke callbacks into the caller, so this error should never appear in production. If it does, the token contract being used is non-standard and must be audited before use.

Overflow (code 12)
All arithmetic on utilized_amount uses checked_add; overflow reverts the transaction with no state change. Amounts near i128::MAX (~1.7 × 10³⁸) are outside the intended operating range of the protocol.

AlreadyInitialized (code 14)
The init guard prevents admin takeover via re-initialization. The check reads instance storage before writing; a rejected second call leaves storage unchanged.

AdminAcceptTooEarly (code 15)
The two-step admin rotation (propose_adminaccept_admin) includes an optional time-lock. The delay is enforced against env.ledger().timestamp(), which is network-provided and monotonic enough for coarse governance windows. It is not suitable for sub-second precision.

BorrowerBlocked (code 16)
The block list is admin-controlled. Blocking a borrower prevents draws but does not affect repayments — a blocked borrower can still repay outstanding debt.

DrawExceedsMaxAmount (code 17)
The per-transaction draw cap is a risk-management control, not a security boundary. It limits the blast radius of a compromised borrower key or a buggy integration.

Paused (code 18)
The protocol pause is an emergency circuit breaker controlled by the admin. When activated, all state-mutating operations are blocked except repay_credit, which remains active to allow users to reduce their debt exposure even during an incident. The pause state is stored in instance storage and checked at the entry of every guarded function. Read-only operations (get_credit_line, is_protocol_paused, etc.) are never blocked.

Liquidity errors (codes 22-27) Liquidity-moving operations use stable ContractError codes instead of ad-hoc panic strings. draw_credit requires both LiquidityToken and LiquiditySource, then checks the source balance before transferring. repay_credit requires the same configuration and checks allowance and borrower balance before transfer_from. Soroban token calls that trap internally are not catchable by this contract; the canonical token-call variants cover failures observable before state mutation.

General Trust Model

Actor Trusted for
Admin Lifecycle operations, risk parameters, block list, liquidity config
Borrower Drawing and repaying their own credit line only
Liquidity token Standard Stellar Asset Contract behavior (no callbacks)
Ledger timestamp Coarse monotonic ordering (governance delays, accrual intervals)

Errors in the 1–2 range (Unauthorized, NotAdmin) indicate an access-control violation and should be treated as security-relevant events by monitoring systems.