StarkEx applications

StarkEx applications are a family of applications powering scalable and self-custodial exchanges. StarkWare currently supports two engines:

  • The StarkEx scalability engine, facilitating scalable spot trading.

  • The StarkPerpetual scalability engine, facilitating leveraged trading.

High-level architecture

exchange app highlevel arch

At a high level, these applications provide traders with an experience similar to centralized exchanges (i.e., high-speed trading and low fees) while preserving self-custody (i.e., ensuring that malicious exchange operators can not "steal" user funds).

Components

Two components make up the Exchange Application:

  • StarkWare Exchange smart contract

  • StarkWare Exchange backend

StarkEx smart contract

The StarkWare Exchange smart contract manages the commitment to the Exchange state, which is usually a Merkle hash of the state, for succinctness. For more information, see Commitment scheme in Wikipedia.

The StarkEx smart contract allows only valid state transitions.

Note, the concept of "valid" is application dependent, as defined by the customer’s business logic. The transition rules, as defined by the Exchange itself, are unknown to the application’s smart contract. The smart contract is aware only of a succinct commitment to the state. Any specific state transition is dependent on the executed transactions (which are not transmitted on-chain to enhance scalability).

The Exchange Application’s smart contract ensures the validity of a state transition (an update to the state commitment) using succinct proofs of computational integrity.

The Exchange Application’s smart contract allows the state commitment to transform from C_0 to C_1 if there is knowledge of:

  • Explicit state S_0 such that C_0 is its commitment.

  • Explicit state S_1 such that C_1 is its commitment.

  • A list of transactions t_0, t_1, ..., t_k executable (one after the other) on S_0(implying valid state transitions — as defined by the application rules), such that the resulting state is S_1.

The StarkEx smart contract does not verify the integrity proofs itself but instead relies on the Verifier contract exposing a Fact Registry API. The Verifier contract stores the hash of any statement it verified a proof for (aka a fact registration). The StarkEx smart contract allows a state transition only if a fact attesting to the state transition was registered beforehand.

In addition to managing the Exchange state, the StarkEx smart contract also manages the liquidity of the Exchange (all the tokens of the Exchange belong to the smart contract, which ensures traders' self custody) and supports direct interactions with traders for flows such as deposits, withdrawals, and the anti-censorship mechanism.

StarkEx backend

The StarkEx backend interacts with the customer’s Exchange. It receives transactions from the customers' Exchanges, creates batches of transactions, and executes them on an internal copy of the (explicit) customer’s Exchange state. The backend is responsible for translating the state transitions (implied by the batches) to provable statements, and ensures that a fact of the state transition validity is registered in the on-chain Verifier Fact Registry, using SHARP. Finally, the backend is responsible for applying the state transition implied by each batch on the StarkEx smart contract.

See more on the StarkEx backend architecture.

See more on the Fact Registry.

Standard flows

  1. Users send orders to the customer’s Exchange (via API or UI)

    • Not all orders need to be signed.

    • Not all transactions need to be sent directly to the Exchange.

      • deposits and withdrawals might be achieved through direct interaction with the StarkEx smart contract.

      • anti-censorship flows typically require direct interaction of the user with the StarkEx smart contract

  2. The customer’s Exchange executes logic similar to centralized exchanges. It defines the order of transaction execution, it can ignore invalid requests, and matches user orders when applicable.

    The customer Exchange transmits their transaction stream to the StarkWare application backend.

    Each transaction in the stream is assigned a unique transaction ID, defining its location in the stream (if there is a gap in the transaction id’s sequence, the transactions following the gap are not executed until the gap is filled).

  3. The backend submits a state-transition statement as a job to SHARP.

    The request contains a Cairo program (which is committed on the StarkEx smart contract and a private input to it (the statement is the program output, e.g., two state Merkle roots of the current state and new state). The shared proving service (SHARP) is responsible for generating the proof for the statement and submitting it on-chain to the Verifier contract.

  4. After the integrity proof is submitted on-chain and the expected fact is registered on the Verifier contract, the StarkEx backend executes the state transition on the StarkEx smart contract (this might require one or more Ethereum transactions).

  5. The StarkEx smart contract ensures the validity of the state transition by checking it applies to a set of predefined rules.

    One of the rules requires a valid proof for this transition to be verified on-chain. It ensures this is the case by requiring a compatible fact to be registered on the Verifier Fact Registry contract.

    The fact includes the hash of the Cairo program enforcing the application rules and the hash of the program’s output (the input is unknown to any smart contract).

Anti-censorship flows

By design, most standard flows require interactions of the user with the customer Exchange. In particular, a malicious exchange could censor a user. The StarkEx applications do not aim to prevent all possible censorship, but only such which might harm the traders' self-custody. Therefore, flows are enforced to ensure that traders can withdraw their funds from the Exchange even if this might be more expensive or require more time than the standard flow (as long the cost is reasonable).

At a high level, there are three flows to ensure self custody:

  • Withdrawing assets explicitly known to the StarkEx smart contract

  • Forcing the exchange to withdraw assets

  • Withdrawing from a frozen exchange

Withdrawing assets explicitly known to the StarkEx smart contract

There are cases where a user’s interaction with a contract results in funds being locked on the smart contract, although the contract knows whom those funds belong to. One example of this is the deposit flow, where traders move funds to the StarkEx smart contract, which writes a record (on-chain) describing whom those funds belong to. In the standard flow, a state transition is expected to erase this on-chain record and instead add the appropriate amount to an off-chain record — but there is no enforcement on the Exchange actually to do that. In order to prevent race condition issues, the Exchange should prevent immediate withdrawal requests. On the other hand, to ensure self custody, the trader should be able to withdraw in such situations. This is currently solved by allowing traders to withdraw such assets after a timelock.

Timelock: a call initiates a withdrawal by starting a timer, and another call (that can be invoked only after enough time has passed) withdraws the funds.

Forcing the exchange to withdraw assets

In the case the trader asset records are not explicitly known to the StarkEx smart contract, such as when the contract stores only the commitment, a trader can try to force an operation.

Forcing an operation requires submitting it directly to the StarkEx smart contract. If, during a time period known as the grace period, the Exchange fails to execute the requested operation or show it is illegal, the trader can ask the StarkEx smart contract to enter a frozen state. Freezing prevents any new state updates, and can be recovered from, only after a long time period such as a year.

Withdrawing from a frozen exchange

In the case that the exchange is frozen, all traders can withdraw their assets by presenting proof of ownership, that is, a Merkle authentication path.