Skip to content

Latest commit

 

History

History
106 lines (78 loc) · 3.64 KB

File metadata and controls

106 lines (78 loc) · 3.64 KB

Contributing to Flash Risk Engine

Code Standards

Precision Handling

All intermediate arithmetic must use BN (arbitrary-precision integers). Floating-point is permitted only for final display formatting (e.g., formatUsd, formatLeverage). Intermediate computations must never convert to number or use JavaScript arithmetic operators on financial values.

No implicit scaling. Every multiplication or division that involves a precision constant must explicitly reference the constant by name:

// Correct
const leverage = sizeUsd.mul(BPS_POWER).div(marginUsd);

// Incorrect
const leverage = sizeUsd.mul(new BN(10000)).div(marginUsd);

Unit Documentation

Every function that performs a computation must document:

  1. Input units -- What precision each parameter uses (e.g., USD_DECIMALS, ORACLE_PRICE_SCALE, BPS_DECIMALS)
  2. Output units -- What precision the return value uses
  3. Rust source -- File path and function name in the reference implementation
  4. Assumptions -- What must be true for the computation to be valid
  5. Production divergence -- Known or suspected differences from the closed-source production program

Example:

/**
 * Compute current leverage in BPS (10^4 precision).
 *
 * Rust source: flash-perpetuals/programs/perpetuals/src/state/pool.rs
 *              -> fn get_leverage (lines ~438-468)
 *
 * Formula:
 *   current_leverage = size_usd * BPS_POWER / current_margin_usd
 *
 * Precision:
 *   Input:  size_usd and margin_usd in USD_DECIMALS (10^6)
 *   Output: leverage in BPS_DECIMALS (10^4). E.g., 10x = 100,000 BPS.
 *
 * Assumptions:
 *   - margin_usd >= 0 (pre-clamped by computeMargin).
 *
 * PRODUCTION DIVERGENCE: None expected.
 */

Formula References

All mathematical formulas must reference their Rust source. If a formula is derived (not directly implemented in Rust), document the derivation steps explicitly in the JSDoc header. Use the format:

Rust source: <file_path> -> fn <function_name>

If the formula is derived rather than direct:

Rust source: Derived from the liquidation condition in <file_path> -> fn <function_name>

Guard Assertions

Runtime guards (src/guards.ts) must:

  • Be pure functions (no side effects beyond throwing)
  • Include the context parameter in error messages for debugging
  • Document what invariant they protect
  • Never fire under normal operation -- they catch impossible states

Commit Conventions

Commits should be logically grouped by subsystem:

  • risk-engine: -- Core computation changes
  • oracle: -- Oracle/pricing logic
  • metrics: -- Aggregation and display metrics
  • cli: -- CLI, audit mode, presentation
  • guards: -- Runtime validation
  • docs: -- Documentation only
  • infra: -- Build, config, dependencies

Type Safety

  • Use the interfaces defined in src/types.ts for all on-chain account data
  • Do not use any except at the Anchor deserialization boundary in decoder.ts
  • All BN values must be typed as BN, not number

What Not to Change

  • src/constants.ts -- These are verified against multiple sources. Changes require re-verification.
  • src/types.ts -- These match the IDL account layouts. Changes require IDL version update.
  • scripts/setup.sh -- Downloads the canonical IDL. Changes require verification of the new source URL.

Submitting Changes

  1. Fork the repository
  2. Create a feature branch from main
  3. Ensure npm run lint passes with no errors
  4. Ensure all existing sanity checks pass when running npm start
  5. If adding new computations, include the Rust source reference and unit documentation
  6. Submit a pull request with a description of what changed and why