Off-chain state

Balances tree

The first element in the off-chain state of StarkEx is the Balances tree. The Balances tree is a Merkle Tree, whose leaves are StarkEx Vaults. Each vault contains a single Stark key, which identifies the user in the off-chain state. Other elements in the vault are defined according to the business logic.

Vault structure

The vault contains the following fields:

  • starkKey - the public Stark key of the vault’s owner. Transfers and trades from this vault must be signed with this key.

  • collateralAmount - the amount of collateral in the vault.

  • A list of synthetic assets. For each asset:

An empty vault has a balance of 0.

An empty vault has no owner, that is, no public Stark key is assigned to the vault. So you can assign it an owner whether it has not yet been used, or it was in use and is now empty.

Orders tree

The Orders tree prevents the operator from replaying transactions in the system. To prevent this attack, the Orders tree has the following properties:

  1. A leaf in the Orders tree represents an order that StarkEx executed.

  2. Each leaf has an ID and a value. The ID is a hash of a signed transaction request. The value is the amount of an order that has already been fulfilled. For example, if Alice signed a transfer request for 1000 USDC, with a hash value 0xdeadbeef, StarkEx stores 1000 quantized USDC in leaf index 0xdeadbeef in the Orders tree.

  3. If the operator tries to resubmit Alice’s order, then when validating a transfer, StarkEx checks that this transfer was not previously executed by checking that the value in leaf number 0xdeadbeef is zero. Because the value is not zero, the on-chain Cairo Verifier cannot accept this order.

  4. StarkEx uses the Orders tree to keep track of assets that were previously minted.

The Orders tree is a Merkle tree.

Enforcing consistency in the on-chain state

The StarkEx smart contract stores the root of the Balances tree and the root of the Orders tree, which are a commitment to the off-chain state. The off-chain state is the tuple of roots. The state is updated when the contract receives a new proof that there exists a valid sequence of transactions that, when executed, changes the current state to a new state.

Additional Elements in the State

Global funding indices

When the application sends a funding tick, it updates an index called the global funding index for each synthetic asset in the system. The global funding index updates a position’s collateral balance before every transaction execution, according to the funding logic. In order to optimize system performance, this update only applies to a given position when the position’s owner executes a transaction. After the update, StarkEx caches the index for each synthetic asset for each position.

Although StarkEx only applies the global funding index when a user executes a transaction, and not simply upon querying a position, you should consider that your application should show a user their current position after a funding tick is applied, even if they only query their position without executing a transaction.

The on-chain state for StarkEx includes the most recent global funding index, according to the most recent funding tick.

The global funding index is a 64-bit fixed-point signed number, with 32 bits after the decimal point.

To calculate the value of the index that you send to the StarkEx gateway when sending a transaction, multiply this value by 232 and round the product down to the nearest integer. 232 in the calculation accounts for the 32 bits to the right of the decimal point in the 64-bit number.

Example: Calculating the global funding index to send to the StarkEx gateway

Consider that the global funding index for synthetic ETH is 0.009. The following calculation determines the value of the global funding index to send to the StarkEx gateway in a FundingTick transaction:

  1. 0.009 * 232 = 38654705.664

  2. Round the product down to the nearest integer. The result, 38654705, is the value you send for the global funding index to the StarkEx gateway.

Example: FundingTick transaction

This FundingTick transaction includes global funding indices for two synthetic assets, indicated by 0x0 and 0x1:

{
    "global_funding_indices": {
        "indices": {
            "0x0": "-431710025170174585",
            "0x1": "6084712057446794809"
        },
        "timestamp": "1676361600"
    },
    "type": "FUNDING_TICK"
}

Current system time

The current time of the system advances whenever a funding tick or an oracle price tick arrives. When closing a batch for submission, the system time must be a date within the last week.

Current prices

The current prices of all the assets in the system, as received from different Oracle price tick transactions.

Additional resources