Invalid transactions and alternative transactions

When you integrate with the StarkEx system, your application should maintain its own state, in parallel with the StarkEx state, including the following:

  • vault balances

  • unfulfilled or partially-fulfilled user orders

Your application’s state should provide your end users with a smooth experience, with little or no latency, which StarkEx, with its required L1 state updates, cannot provide. So your application should ensure that transactions that it submits to the StarkEx gateway are accepted before updating its own state, thus ensuring that both states are synchronized.

However, there are rare occurrences where despite a transaction being approved by the StarkEx gateway, it is subsequently rejected, often for reasons beyond your control. In such a case, the StarkEx state might diverge from the operator’s state.

In order to synchronize the two states when a transaction that was accepted by the gateway is rejected further down the pipeline, causing a state divergence, StarkEx requests that you send an alternative transaction to replace the failed transaction.

What happens when StarkEx receives an invalid transaction?

StarkEx validates a transaction against its current state + the transactions that are currently in the batch

The StarkEx gateway performs syntactic checks and validates each received transaction against its current state and the other transactions that are currently in the batch. The gateway returns an error code if the transaction is not valid. In general, StarkEx detects errors as early as possible in the pipeline, but some errors are detected later, when StarkEx performs system checks that depend on the current state.

Whenever an invalid transaction occurs in a batch, it prevents StarkEx from processing the batch, resulting in a request for an alternative transaction. Additionally, any subsequent transactions that depend upon the first become invalid as well.

Receiving an error for a transaction when it is already in a batch is very severe. Avoid these types of errors as much as possible.

For example, an invalid deposit to a vault might invalidate a subsequent withdrawal that depends upon the funds in that vault.

Other possible causes of invalid transactions are:

  • Bugs

  • Reorganization of the blockchain

  • An order ID is not registered on-chain

  • A fact is not registered on-chain for a conditional transfer

  • The expiration time of a transaction does not allow enough time for the proof to be submitted on-chain

Take special care to understand and properly respond to a request for an alternative transaction, because it might be a dependency for other transactions in the batch. Responding with an improper alternative transaction might cause a cascade of subsequent alternative transaction requests.

Invalid transactions generally indicate a severe bug in your system, so you should handle each one manually to identify the cause, mitigate the impact on any subsequent transactions, and prevent any issues in the synchronization of your application’s state and StarkEx’s state.

Synchronization problems can be very difficult to solve, and can result in a complete system freeze if not handled in a timely manner.

Validate the following to prevent invalid transactions:

  • On-Chain state, for any transactions that rely on L1 predicates, such as deposits, conditional transfers, and settlements which use an L1 order. Wait for 6-10 block confirmations before relying on a given on-chain state to reduce the chances of issues arising from a reorg.

  • Balances, currencies and vault ownership.

  • Signatures and their consistency with vault ownership.

  • Expiration timestamps should be at least seven days in the future.

  • Allowed value ranges.

Alternative transactions

When StarkEx identifies an invalid transaction, StarkEx marks the transaction as invalid and sends a request to the application’s endpoint for a list of alternative transactions.

Once you respond to the request by submitting a list of alternative transactions, the batcher reconstructs and processes the batch accordingly. The invalid transaction is removed, and the alternative transactions within the list are processed in order.

There is no impact on StarkEx transaction ids.

Example: Invalid transaction and an alternative transaction list

The following example shows an error message for an invalid transaction. In response to this error, you need to send an list of one or more alternative transactions.

In this example the balance is known to be valid, but it does not yet appear on-chain.

{
    "reason_code": "INSUFFICIENT_ONCHAIN_BALANCE",
    "tx_id": 7,
    "reason_msg": "Not enough onchain balance to complete deposit. balance_used:10 onchain_balance:0 deposit: DepositRequest(vault_id=1, stark_key=2, token_id=3, amount=10)",
    "tx": {
        "stark_key": "0x2",
        "token_id": "0x3",
        "amount": "10",
        "vault_id": 1,
        "type": "DepositRequest"
    }
}

The following example shows a response with a list of one alternative transaction. In this case, it is the same transaction sent initially, assuming that the on-chain balance has been updated since receiving the error message:

{
    "alt_txs": [
        {
            "stark_key": "0x2",
            "token_id": "0x3",
            "amount": "10",
            "vault_id": 1,
            "type": "DepositRequest"
        }
    ]
}

Built-in safety: REPLACED_BEFORE

StarkEx might restart processing a batch either because it encountered an invalid transaction in the list of alternative transactions that you sent, or for some other reason.

StarkEx includes a safety mechanism to maintain synchronization between your application’s state and StarkEx’s state, as follows:

  1. After you send a list of alternative transactions, StarkEx restarts batch processing.

  2. The batcher processes the ID of the transaction that was previously marked as invalid, and automatically identifies that transaction as invalid.

  3. StarkExand sends a REPLACED_BEFORE message, even if the transaction is now valid.

This sequence can potentially occur multiple times.

When you receive a REPLACED_BEFORE message, you must investigate the actual cause of the error.

A REPLACED_BEFORE message doesn’t necessarily indicate a new error. Rather, it might indicate that after you sent the alternative transaction list, StarkEx was unable to create a batch for an unrelated reason. Even so, after restarting the batch, StarkEx again encountered the transaction that you replaced and automatically identified that transaction as invalid.

In such a case, after you ensure there are no errors, you can resend the same list of alternative transactions.

It is recommended that after replacing a transaction manually, you automate the response to all future REPLACED_BEFORE messages, that is, requests for an alternative transaction for that same transaction. The response should be the exact same replacement. Doing so ensures that the systems remain synchronized.

However, if the original replacement becomes invalid, you need to manually send a new alternative transaction.