Frequently asked questions

Why are alternative transactions necessary?

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 is an alternative transaction?

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.

For more information, see Alternative transactions

How do I handle a request for an alternative transaction?

Send a list of zero or more alternative transactions in .json format.

I received a REPLACED_BEFORE message. What should I do?

What is the difference between assetId and tokenId?

Layer 2: The StarkEx API and SDK

The StarkEx API and SDK only apply to L2.

The SDK and API use two different terms to refer to a unique asset on L2:

  • The StarkEx SDK uses the term assetId.

  • The StarkEx API uses the term token_id.

The StarkEx API does not include the keyword asset_id. Use the keyword token_id in API calls to refer to a unique offchain asset.

Layer 1: StarkEx Contracts

Be aware that in the ERC-721 and ERC-1155 L1 StarkEx contracts, the terms assetId and tokenId have slightly different meanings from those in the contracts for ERC-20, ETH, and mintable ERC-721 assets.

The value of assetInfo is the address of the L1 contract for a given asset type. For example, for ERC-20 tokens, the value of assetInfo is the address of the L1 ERC-20 contract.

Table 1. Meaning of assetId and tokenId for each asset type
Asset type Description


There is no identifier for any one specific coin, unlike with ERC-721 or ERC-1155, because one unit of ETH or of an ERC-20 token has the same value as any other of the same type of token. StarkEx does not track individual assets of these types.

The StarkEx system calculates the value for assetId as follows:

  1. assetId = assetType

  2. assetType = hash(assetInfo, quantum)

  3. assetInfo = L1_contract_address + erc_type (selector)

ERC-721, ERC-1155

An NFT has two identifiers:


Identifies the NFT within its L1 ERC-721 or ERC-1155 contract scope, but another contract can have another asset with the same value for tokenId.


Uniquely identifies the NFT on the entire Ethereum blockchain.

For example, consider two NFTs within two separate contracts:

  • Mitzy is a digital kitten within contract A. Mitzy’s unique identifier within contract A is tokenId, which has a value of 0x1234.

  • Spot is a digital puppy within contract B. Spot’s unique identifier within contract B is tokenId, which also has a value of 0x1234.

So the value of tokenId is the same for both Mitzy and Spot.

However, both Mitzy and Spot each have their own unique value for assetId within the entire scope of Ethereum.

The value for assetId is calculated as follows:

  1. assetId = hash (NONMINTABLE_PREFIX, assetType, tokenId)

  2. assetType = hash(assetInfo, quantum) (For ERC-721, quantum = 1)

  3. tokenId is a unique identifier within the scope of the contract.

  4. assetInfo = L1_contract_address + erc_type (selector)

Mintable ERC-721

This type of NFT is minted on L2. It does not exist on L1 until your user withdraws it from L2 to L1.

When your user withdraws the NFT from L2 to L1, you need to provide them with the mintingBlob and the assetType and use those values to generate a value for assetId on your L1 contract.

The value for assetId is calculated as follows:

assetId = hash(MINTABLE_PREFIX, assetType, blob_hash)

Why can’t I query the balance of a certain vault on StarkEx?

There is no API for this query because it normally is not reliable for synchronization between the StarkEx state and your applications’s state, for the following reasons:

  • StarkEx’s state is updated when a batch finishes processing. As a result, any transaction that is already accepted by StarkEx but not included in a batch is not reflected in this state.

  • In the event of an onchain reorg, a batch for which a vault state is known might actually never become accepted on L1. So the only query we can answer is “What was the state of a vault at the end of a batch with ID batch_id?”

Where and when is a particular vault assigned a public Stark key?

The StarkEx service generates an ID for a vault the first time that you specify a public Stark key in any of the following types of transactions:

  • deposit to the vault

  • transfer to the vault

  • minting an asset within the vault

  • settlement

The vault ID is paired with the public Stark key.

If, when a vault receives a transaction, the vault is not empty, you cannot assign it a new public Stark key.

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.

How do I use the testing environment for both developing and QA testing?

To work in parallel on the same environment, allocate one range of vaults for development, and another range for testing.

How do I know that a transaction was accepted by the StarkEx gateway?

The StarkEx gateway returns a response to every request that it receives, including transactions. When it receives a transaction, it returns TRANSACTION_RECEIVED.

When you receive this message, the gateway has accepted the transaction.

If you don’t receive this confirmation message, resend the transaction.

If you receive any other message, the transaction was not accepted.

What should I do when the transaction is not accepted by the StarkEx gateway?

Review the error message that you received and act accordingly.

What should I do when a transaction was not included in the StarkEx L1 state update?

If a transaction is accepted by the StarkEx gateway, but does not appear in the L1 state update, the following are possible reasons:

  • The batch has not finished processing.

  • The transaction failed during the batch processing. In this case, the StarkEx system sends a request for an alternative transaction.

If you don’t see a state update for a significant amount of time, check your logs for a message requesting an alternative transaction.

Can I use the same type of asset, such as BTC, for both collateral and synthetic? (StarkEx Perpetual Trading)

It is not recommended to have your collateral asset also be a synthetic asset in the system.