Prop account model
A prop account is an evaluation contract over real signed trades. The platform never holds the trader’s trading funds — traders sign their own trades — while collateral and payouts settle on your firm’s on-chain treasury.
Each firm is one prop tenant with its own PropInstance contract, deployed by
a shared factory. Your multisig owns the instance and its treasury. The
platform’s risk engine acts as the contract’s observer: it marks
pass, breach, and expiry, and sets payout caps. The trader deposits, quits, and
requests payouts directly from their own wallet.
Two program kinds share one engine: challenge (tier ladder, profit or points
target) and flash (collateral-to-funding ratio, time as currency).
Lifecycle
Section titled “Lifecycle”Two paths reach active, and they don’t overlap. An account the trader buys
goes pending_payment → active when the deposit lands on-chain. A child
account created by a tier-ladder or next-step promotion starts in
pending_agreement and goes → active when the trader agrees. From there:
active → passed → paid_out, with breached, expired, and cancelled
as terminal branches.
| Phase | What happens |
|---|---|
| Catalog → buy | The trader browses active templates and creates an account in pending_payment (POST /api/v1/prop-accounts). |
| Deposit | The trader’s wallet calls the instance’s deposit function. The entry fee is skimmed, the remainder becomes collateral, and the account activates on-chain. The platform composes the calldata via POST /api/prop/deposit-calldata; the wallet broadcasts. |
| Deposit observed → active | The claim watcher sees the on-chain ChallengeDeposited event and flips the account pending_payment → active. No API call is involved — this is the only path that activates a bought account. |
| Evaluation | The engine re-evaluates every rule on each trade, position, and funding change, plus a UTC-midnight roll. |
| Breach | Any rule returning breach is terminal. The on-chain forfeiture split applies and positions are flattened. |
| Pass | Pass conditions met. No money moves — the observer records the on-chain payout ceiling. |
| Promotion → agree | If the passed account’s template carries a tier ladder or a next-step template, the engine creates a child account in pending_agreement. The trader accepts it with POST /api/v1/prop-accounts/{id}/agree, which moves that child to active. Called against any other status, /agree returns 409 invalid_state. |
| Funded | A passed account keeps trading. The trader requests payouts; your multisig approves. |
| Quit | The trader voluntarily closes an active account; the quit forfeiture split applies and the remainder is refunded. Terminal. |
| Expiry | The observer marks expiry; the expiry split applies and collateral remainder is refunded. Terminal. |
Hard enforcement is live and default-on
Section titled “Hard enforcement is live and default-on”This is the core enforcement primitive, and it is not advisory.
On every order, the platform evaluates a hypothetical fill against each
active prop account on the trading account the order is placed from, and
rejects a breaching intent with prop_breach_would_occur (HTTP 409) —
before the venue ever sees the order.
PATCH /api/v1/firms/{id}/hard-enforcement writes a per-firm override, but
program rules are enforced by design: with the platform’s default settings
the override is not consulted at all. Do not treat it as a way to run a firm in
observe-only mode.
The practical consequence: a trader cannot breach by racing the evaluator. The order simply doesn’t reach the market.
Rule catalog
Section titled “Rule catalog”Rules are snapshot-frozen at account creation, so editing a template never retroactively passes or fails an in-flight account.
Rule types include daily_loss_cap_usd · max_drawdown_usd ·
min_trading_days · profit_target_usd · max_concentration_pct ·
consistency_pct · allowed_venues · forbidden_symbols · points_target ·
inactivity_timer_s · collateral_drawdown_pct. The registry is larger than
this list.
Each rule evaluates to
{ type, status, detail, metric?, threshold? }, where status is one of
ok, breach, pass, pending, na, or missing_evaluator.
breach is terminal. pass satisfies a pass condition. pending means a goal
is defined but not reached yet (min_trading_days at 3 of 5) — it does not
breach the account, but it is not inert: a single pending rule holds the
pass back, and it blocks a payout the same way a breach does. na (the rule
doesn’t apply yet) and missing_evaluator (a rule type with no registered
evaluator) never block anything.
Render pending as in-progress, not as a failure — most in-flight challenges
carry at least one. GET /api/v1/prop-accounts/{id} returns these objects
verbatim as results.
A client consuming the catalog also gets parsed headline thresholds
(maxDdUsd, dailyLossUsd, profitTargetUsd) as first-class fields, so you
can render a challenge card without interpreting the rule objects.
Manage them with prop:manage: /api/v1/prop-templates/* for templates,
/api/v1/risk-profiles/* for reusable rule sets, /api/v1/trading-groups/*
for fee, leverage, and venue scoping.
The funded-account payout model
Section titled “The funded-account payout model”A passed account is a funded account that keeps trading. Four properties define the mechanic:
- The ceiling is profit × split. At pass, the observer records a per-account payout ceiling equal to the trader’s split-adjusted profit. A trader can never withdraw more than they earned.
- Two independent caps. Every payout is gated by both the profit entitlement and treasury solvency.
- Multiple withdrawals, no close on payout. Approving accumulates the payout total and leaves the account passed — the funded trader keeps trading. It only leaves that state via breach, quit, or expiry.
- Lazy ceiling raise. When a funded trader requests a payout, their current entitlement is recomputed and the on-chain ceiling raised if they’ve earned more since passing. Raise-only.
Settlement is two-step: the trader’s request creates a pending on-chain
request, and your multisig settles it. POST /api/prop/payout-calldata
pre-checks the live ceiling, account, and treasury, returning
exceeds_profit_entitlement (400) or treasury_underfunded (409) — though the
contract enforces both regardless of what the API says.
Blocking vs suspending
Section titled “Blocking vs suspending”Two operator controls that read alike and are not alike. Both need the
prop:manage scope and are hard-scoped to your own tenant.
| Call | What it does |
|---|---|
PATCH /api/v1/accounts/{id}/suspension |
Sets or clears the suspension. Positions are untouched. New opens are refused; the trader keeps what they hold. |
POST /api/v1/accounts/{id}/block |
Suspends and flattens every open position, then writes an account.block audit row. |
POST /api/v1/accounts/{id}/unblock |
Clears the suspension. It does not restore anything. |
block accepts an optional reason, which lands in the audit row alongside
how many positions were flattened and any that failed to close. Read those
errors — a flatten that partially failed leaves the account suspended with
positions still open, which is the one state neither name describes.
Both resolve the account by UUID or public account number.
Diagnosing an evaluation
Section titled “Diagnosing an evaluation”GET /api/v1/analytics/prop-diagnosis/{propAccountId} answers “where does this
challenge stand?” in one call, so you can build a trader-facing status screen
without re-deriving the rules yourself.
curl -s https://api.troncharts.xyz/api/v1/analytics/prop-diagnosis/$PROP_ACCOUNT_ID \ -H "authorization: Bearer $TOKEN" \ -H "x-tenant-slug: $TC_TENANT_SLUG"Returns the account’s status, its template (templateId, templateName,
programKind), the lifecycle timestamps (startedAt, expiresAt, closedAt,
closedReason), payoutOwedUsd, up to 50 recentTrades scoped to this
account’s own fills within the challenge window, and a recommendation.
recommendation is one of continue, pause, closed, claim_ready.
Scoped to the calling session’s account: another account’s prop record answers
404.
Reading account state
Section titled “Reading account state”| Endpoint | Returns |
|---|---|
GET /api/v1/prop-accounts |
Accounts you can see. |
GET /api/v1/prop-accounts/{id} |
One account with its frozen rule set and live metrics. |
GET /api/v1/prop-accounts/{id}/events |
The full state-transition history. |
Live progress is also pushed as Prop-Account-Update on
/ws/risk.