CRX
What is the core contract?
CRX.sol — a UUPS singleton that is the factory, registry, fund vault, role system, and oracle registry at once. It deploys a beacon-proxy NDF clone per bilateral relationship and holds all collateral in its own vault, keyed by relationship. It trades one instrument: the non-deliverable forward.
The contract is split by deployed bytecode into CRX.sol (hot paths) and CRXCascade.sol (rare paths) to fit the 24 KB EIP-170 limit. Both inherit one CRXStorage layout; the rare paths forward to the engine by delegatecall and run in the core's storage.
What does it hold?
| State | Holds |
|---|---|
_generalBalance[party][token] | a party's free, global margin — the shared backstop across all its agreements; variation margin lands here |
_sca[maId][party][token] | one party's segregated collateral inside one agreement; initial margin only, never accumulated P&L |
_imAggregate[maId][party] | running sum of required IM, for O(1) free-margin checks |
_mas[maId] | the registry entry per Master Agreement, including its CSA address |
oracleOf[pair] | the per-pair FX oracle the core marks against |
collateralOracle[token] | the per-token USD price oracle — one price per token, global |
| roles | OZ AccessControl: DAO (operator), MAKER, TAKER, VALIDATION, DEFAULT |
What are the collateral entry points?
| Function | What it does |
|---|---|
deposit(token, amount) | fund your general balance |
withdraw(token, amount) | pull from your general balance |
allocate(maId, token, amount) | move general balance → your SCA in one agreement |
computeDeallocation(...) → deallocate(maId, token, amount) | move SCA → general, two-phase, O(1) free-margin check |
What are the lifecycle entry points?
| Function | What it does |
|---|---|
openMasterAgreement(party1, party2, number, csa, deadline, sig1, sig2) | both parties sign; pairs one MAKER with one TAKER; selects the CSA; deploys the clone; sets maId |
openAndBind(...) | open an agreement and bind its first position in one call |
bind(terms, sig1, sig2) | open a position inside an agreement; both parties sign the Terms; adds IM to each side's aggregate |
settle(id, vwap) | settle a position at/after its settlement date from the oracle rate |
closeOnChain(...) | both parties close a position cooperatively, no operator involved |
withdrawClaim(...) | claim collateral owed after a wind-down |
multicall(bytes[]) | batch calls via delegatecall into self |
What are the margin and default entry points?
These live on the cascade engine and are reached through the core.
| Function | What it does |
|---|---|
callVM(maId, positionIds[]) | permissionless crank — settle variation margin on proof |
computeVM(...) → applyVM(...) | the two-phase daily cycle; applyVM also re-trues each SCA toward its IM target, at most once a day |
fill(maId, positionIds[]) | top up an SCA from the party's general balance |
assertLiquidation(party, maDefaulted, bond) | open a default proof window against a party, posting a bond |
| the cascade | force-VM the party's whole book, test global solvency, run the waterfall, burn the agreements, terminate the party |
forceClose(maId, positionIds[], instruction) | operator-only, on a legal order — close at a validated fair price and route collateral |
What are the registry setters?
Operator-only (DAO role): setOracle(pair, oracle), setCollateralOracle(token, oracle), setGlobalCSA(csa), setCascadeEngine(...), approveMaker(a) / approveTaker(a), ban(party) / terminateParty(party, reason). Onboarding starts permissionless with register(), which grants VALIDATION.
How does margin clear?
Continuously. Variation margin moves the mark-to-market between the two parties each cycle; the loser pays from its SCA, the winner receives into its general balance. There is no margin call. See Margin (VM) (~3 min).
Next: Audits (~3 min) — the security review status and the test coverage.