CortexRails Protocol

Liquidations shouldn't be a guess.

CortexRails is the deterministic policy layer that decides whether a borrow, withdrawal, transfer, or liquidation is actually safe -- before it executes. Live on Robinhood Chain against real TSLA stock tokens and real USDG, with every liquidation threshold checked against 14 years of real price history, not assumptions.

1policy surface
4consumer adapters
2Stylus engines
  1. Agent / Protocolproposes an action
  2. Intent{ asset, positionId, action, amount }
  3. CortexRailscanExecute() · onchain policy
  4. DecisionALLOW / LIMIT / REVIEW / BLOCK
  5. Executionconsuming adapter enforces, then moves value

Proven, not asserted

This isn't a hypothetical.

CortexRails' live risk formulas were run against 14 years of real TSLA price history (2010-2024) -- not a synthetic backtest, not a cherry-picked window.

The result is a provable, closed-form finding: at the testnet's live parameters, a full-capacity borrower becomes liquidatable the instant the asset falls exactly 20% below the price they borrowed at -- no more, no less. Full methodology and data in docs/ANALYSIS.md.

Worked example — the November 2021 all-time high
Entry · 2021-11-04$409.97
Liquidation trigger (80% risk adjustment)$327.98
Crossed · 2021-12-13$322.14 — 26 trading days later
70%of historical entry days eventually crossed the trigger
72median trading days to liquidation
1fastest trading day to trigger

Autonomous agents

Agents propose. CortexRails decides.

Autonomous agents can determine what they want to do. Financial protocols still need a deterministic boundary that decides what they are actually allowed to do.

CortexRails evaluates the requested action against the current asset, position, lifecycle, and policy state before execution.

01 · OffchainAgent intentStructured request: asset, position, action, amount
→
02 · Onchain readCortexRails policy evaluationPolicy.canExecute()
→
03 · ResultALLOW / LIMIT / BLOCKdecision · permittedAmount · reason
→
04 · Onchain writeAdapter executionThe adapter re-checks policy in the same transaction

No model sits in the decision path. The agent layer only translates units and enum names, and the authoritative answer is the onchain canExecute() result. Every adapter calls canExecute() again at execution time, so a stale or skipped evaluation can't bypass policy.

The policy primitive

One call before value moves.

Every consumer asks the same question through the same function. The same policy surface is called before different financial actions.

canExecute() is a view function. It never moves funds or enforces anything itself; the calling contract does both.

ILedgerLinePolicy

function canExecute(
    uint256 assetId,
    uint256 positionId,
    Action  action,     // BORROW | WITHDRAW | TRANSFER | ...
    uint256 amount      // 18-decimal internal units
) external view returns (PolicyResponse memory);

struct PolicyResponse {
    Decision decision;        // ALLOW | LIMIT | REVIEW | BLOCK
    uint256  permittedAmount; // the maximum permitted, never the request
    bytes32  reason;          // "OK", "EXCEEDS_CAPACITY", "RESTRICTED", ...
}

A consumer enforcing it · LendingAdapter.borrow()

PolicyResponse memory response =
    policy.canExecute(assetId, positionId, Action.BORROW, amount);

if (response.decision == Decision.BLOCK) revert PolicyBlocked(response.reason);

uint256 wouldOweTotal = debt[msg.sender] + amount;
if (wouldOweTotal > response.permittedAmount)
    revert ExceedsPermittedAmount(wouldOweTotal, response.permittedAmount);

Reuse

One policy surface. Multiple financial consumers.

Three independent adapter contracts call the same, unmodified Registry, Stylus engines, and Policy. Adding WITHDRAW and then TRANSFER needed no change to the Registry or either engine, just one new Policy branch each.

BORROW

Action.BORROW

CortexRails evaluates borrowing capacity and risk before a lending action executes: position value × collateral factor × risk adjustment, computed by the Stylus engines.

Policy
Lifecycle must be ACTIVE · request compared to capacity
Adapter
Adapter enforces existing debt + request ≤ permitted amount

LedgerLineLendingAdapter

WITHDRAW

Action.WITHDRAW

CortexRails evaluates lifecycle conditions before collateral leaves the vault. The adapter then applies debt safety: remaining capacity must still cover outstanding debt.

Policy
Lifecycle must be ACTIVE · permitted up to the full position
Adapter
Adapter blocks a withdrawal that would under-collateralize debt

LedgerLineVaultAdapter

TRANSFER

Action.TRANSFER

CortexRails evaluates lifecycle conditions before collateral changes owner. Ownership is reassigned in custody; no tokens move.

Policy
Lifecycle must be ACTIVE · permitted up to the full position
Adapter
Adapter blocks the transfer while any debt is outstanding

LedgerLineTransferAdapter

LIQUIDATE

Action.LIQUIDATE

CortexRails evaluates whether a position's real, live debt has crossed the Stylus RiskEngine's maintenance threshold. Policy stays debt-agnostic by design -- the adapter supplies the borrower's actual debt from LendingAdapter as the request amount.

Policy
Debt supplied by the adapter must exceed value × collateral factor
Adapter
Permissionless: any caller repays part of the debt and receives seized collateral in return

LedgerLineLiquidationAdapter

Decision model

Deterministic decisions.

The same state and the same request always produce the same response. LIMIT returns the maximum permitted amount, and CortexRails never quietly reduces the request. The caller decides whether to resubmit.

ALLOW

The action satisfies policy.

LIMIT

The requested amount exceeds the permitted amount. The response carries the maximum permitted.

REVIEWReserved

Reserved in the Decision enum for a manual-review path. No policy branch returns it today.

BLOCK

The action violates policy, for example a non-ACTIVE lifecycle or zero capacity.

Policy simulation · Action.BORROWRuns in your browser · no chain call
Position value$200,000
× Collateral factor70%
× Risk adjustment80%
Borrowing capacity$112,000
canExecute(1, positionId, BORROW, 120,000)
lifecycle: ACTIVE
LIMIT
PolicyResponse {
decision: LIMIT
permittedAmount: 112,000
reason: "EXCEEDS_CAPACITY"
}

Same rules and reason codes as LedgerLinePolicy.canExecute() for BORROW, applied to an illustrative $200,000 position. The policy engine at /app reads the deployed contract live.

Policy inputs

Policy is state-aware.

A balance and a price are not the whole story. Tokenized assets carry lifecycle state that can change whether an action should execute at all.

ASSET
Price and multiplier from the Registry, the single state store.
POSITION
Raw collateral balance per (assetId, positionId).
RISK
Collateral factor and risk adjustment, each bounded to ≤ 100%.
LIFECYCLE
ACTIVE · RESTRICTED · CORPORATE_ACTION · SUSPENDED · MATURING · REDEEMABLE · REDEEMED. Any state other than ACTIVE blocks every action with a state-specific reason.
ACTION
BORROW, WITHDRAW, TRANSFER and LIQUIDATE all have real consumers. LedgerLineLiquidationAdapter derives a borrower's live debt from LendingAdapter, asks canExecute() with Action.LIQUIDATE, and on ALLOW calls LendingAdapter's liquidate() to move tokens -- permissionless, like every reference lending protocol's liquidation path. INCREASE_LEVERAGE remains reserved in the enum only.
STATE + POSITION + RISK + LIFECYCLE + ACTION → POLICY DECISION

Agent intent / policy evaluation

An agent asks. CortexRails answers.

An illustrative $200,000 TSLA position under the testnet configuration (70% collateral factor, 80% risk adjustment) has $112,000 of borrowing capacity.

This walkthrough is illustrative. The policy engine at /app runs the same flow against the deployed contract with your connected wallet's real position.

Agent

“Borrow 120,000 USDG against TSLA.”

CortexRails
LIMIT
Requested
$120,000
Permitted
$112,000
Reason
EXCEEDS_CAPACITY
Agent adjusts

“Borrow 112,000 USDG.”

CortexRails
ALLOW
Requested
$112,000
Permitted
$112,000
Reason
OK
Execution

LendingAdapter.borrow() re-evaluates policy, checks existing debt, then transfers USDG.

Live deployment

Deployed on Robinhood Chain testnet.

Chain ID 46630. The current testnet deployment demonstrates CortexRails against the real TSLA Stock Token and USDG contracts, while policy state and reference pricing remain operator-configured in the test environment.

Real / deployed
  • Robinhood Chain testnet
  • Real TSLA Stock Token collateral
  • Real USDG borrow asset (6-decimal scaling)
  • Stylus PositionEngine and RiskEngine
  • Registry, Policy, four consumer adapters (Lending, Vault, Transfer, Liquidation)
  • canExecute() computed live on every call
Operator-configured
  • Policy reference price ($364.27)
  • Lifecycle state
  • Collateral factor and risk adjustment
  • No oracle pushes into the Registry automatically
Not claimed
  • Mainnet or production readiness
  • Decentralized live equity pricing
  • Automatic oracle-to-policy sync
  • Support for every tokenized asset
  • Third-party audit
ContractRoleAddress
LedgerLineRegistryState store0x8850…907c ↗
LedgerLinePolicycanExecute()0xD6EC…5460 ↗
PositionEngineStylus (Rust/WASM)0xde83…Ff0F ↗
RiskEngineStylus (Rust/WASM) · isLiquidatable()0x1024…C2bc ↗
LedgerLineLendingAdapterBORROW/repay()/liquidate() consumer0x5e55…560d ↗
LedgerLineVaultAdapterWITHDRAW consumer0x4E94…9C43 ↗
LedgerLineTransferAdapterTRANSFER consumer0x32D4…D4f1 ↗
LedgerLineLiquidationAdapterLIQUIDATE consumer0xB24A…a97d ↗
RobinhoodStockTokenAdapterAsset adapter · not wired into Registry0x3A1B…dfb9 ↗
TSLA Stock TokenCollateral · 18 decimals0xC9f9…Bd4E ↗
USDGBorrow asset · 6 decimals0x7E95…802F ↗

Every address above has live bytecode on Robinhood Chain testnet. Block numbers, deploy transactions, and the VaultAdapter redeploy history are in DEPLOYMENTS.md.

Architecture

Deciding is separate from executing.

The Registry holds state. Two stateless Stylus contracts compute position value and capacity. Policy turns that into a decision. Adapters custody funds and enforce the decision. The agent layer sits outside this deterministic core.

  1. 01Asset adapterRobinhoodStockTokenAdapter · deployed, not yet wired to Registry
  2. 02Registry / stateLedgerLineRegistry
  3. 03Position engineStylus · position value
  4. 04Risk engineStylus · borrowing capacity + isLiquidatable()
  5. 05PolicycanExecute()
  6. 06Financial adapterLending · Vault · Transfer · Liquidation

Developers

Integrate the decision surface.

Applications and autonomous agents can submit structured action intents to CortexRails and receive the authoritative policy result before execution.

Intent → SDK → CortexRails Policy → Decision

Solidity consumers call canExecute() directly. Offchain code uses @ledgerline/core, a typed viem client in this repo's sdk/ directory. It is not yet published to npm.

TypeScript · sdk/src/agent.ts

import { LedgerLineClient, evaluateAgentIntent, suggestRetryIntent } from "@ledgerline/core";

const client = new LedgerLineClient({ rpcUrl }); // defaults to the testnet deployment

const intent = {
  asset: "TSLA",
  positionId: agentWallet,   // address or raw positionId
  action: "BORROW",          // "BORROW" | "WITHDRAW" | "TRANSFER"
  amount: "120000",          // human units; the SDK scales to 18 decimals
};

const result = await evaluateAgentIntent(client, intent);
// e.g. { decision: "LIMIT", permittedAmount: "112000", reason: "EXCEEDS_CAPACITY", raw, ... }

const retry = suggestRetryIntent(intent, result); // amount = permittedAmount, only on LIMIT

Agents propose. CortexRails decides. Adapters execute.

Evaluate a real position against the deployed policy.