Register, Deposit and Withdrawal


The function registerUser can be called to add a user to StarkEx. It creates a mapping between the user's starkKey and the user's ethereumAddress .

The registered user does not have to be the sender of the transaction.

The registration is accepted if the following holds:

  1. The starkKey provided is not zero and has not been registered in the past under any other ethereumAddress.

  2. The key provided represents a valid point on the Stark-friendly elliptic curve.

  3. The provided signature is a valid signature on keccak256("UserRegistration:", ethereumAddress, starkKey) by the userAdmin (i.e. the application).

If the requirements above hold, the starkKey is registered in the contract and is mapped to the ethereumAddress. Note that the contract allows registering many different starkKey's to one ethereumAddress.

This mapping is later used to ensure that withdrawal requests are valid. StarkEx checks that a withdrawal from an account that corresponds to a starkKey can only be performed by a user authenticated with its associated ethereumAddress (see Withdrawal).

A userAdmin may be instantly appointed or removed by the contract Governor (see Governance).


Depositing ETH is done by calling the payable function deposit, which takes the amount through msg.value.

Depositing ETH is also possible by calling the payable function deposit, which takes the amount through msg.value.

To perform an ERC20 deposit to StarkEx, two calls are needed:

  1. approval on the ERC20 contract, authorizing StarkEx to transfer funds on behalf of the user.

  2. ​deposit on StarkEx contract, with the following parameters:quantizedAmount, user's starkKey, assetType and user's vaultId to which to send the deposit.

The result of the operation, assuming all requirements are met, is that the amount of ETH/ERC20 tokens, specified in the deposit call and multiplied by the quantization factor, is transferred on behalf of the user to the contract.

In addition, the contract adds the funds to an accumulator of pending deposits for the provided starkKey, assetType and vaultId. The starkKey may belong to the user that called deposit or to a different user. When this happens, the event LogDeposit is emitted.

The funds in the Pending Deposits area may be inspected by calling getDepositBalance and getQuantizedDepositBalance. Both functions get starkKey, assetId and vaultId and return the pending amount of funds that correspond to the input parameters. These funds are pending to enter the vault vaultId belonging to the user that owns the specified starkKey. Note that if there are several pending deposits with the same parameters, these functions will return the accumulated value.

To remove funds from the Pending Deposits area, the application needs to include it in a proof, which will result in the addition of the amount(s) deposited to the specified vaultId. When the contract receives such valid proof, it deducts the transferred funds from the pending deposits for the specified starkKey, assetType and vaultId.

Until that point, the user may cancel the deposit by performing a time-locked cancel-deposit operation that consists of two calls:

  1. A call to depositCancel that sets a timer. Once the timer expires, it enables the reclaim of the deposit. Until this timer expires, the user cannot reclaim funds as the application may still be processing the deposit for inclusion in the off-chain vault. Only the recipient of the funds may call depositCancel. Once this call is done, the event LogDepositCancel is emitted.

  2. A call to depositReclaim to perform the actual transfer of funds from the contract back to the on-chain user account. This will only succeed if the timer set in the previous call has expired. This operation results in a transfer of all pending funds (i.e. funds not accounted for in proofs for off-chain inclusion) back to the user account (on the ERC20 contract or on their ETH balance). Once this call is done, the event LogDepositCancelReclaimed is emitted.

If according to the off-chain state, the vaultId and starkKey specified in the deposit request do not match each other, this deposit is not valid and cannot be included in a proof. In this case, the money remains in the deposit area. However, it can still be reclaimed to the ethereumAddress that deposited it by using depositCancel and depositReclaim. This call must be performed by the user that the starkKey in the original deposit call belongs to.


In this section, we describe how to withdraw funds from the StarkEx contract, once they are in the on-chain contract. There are three types of withdrawals related to different asset types in the system: withdrawal of ETH/ERC20 token, withdrawal of ERC721 token and withdrawal of an asset that was minted off-chain. The three flows are very similar with small variations that we highlight in the text.

Funds become available for an on-chain withdrawal

When a new state update is submitted on-chain, it may contain off-chain withdrawal transactions (see Withdrawal ). This transaction results in an addition of the withdrawn amount to the on-chain pending withdrawals area, specifically under the vault owner's starkKey and the appropriate assetType. At the same time, this amount is also deducted from the off-chain vault.

When this happens, an event is emitted, with the following parameters: starkKey, assetType and the (non-accumulative)quantizedAmount and unquantized amount as parameters. The event is of type LogWithdrawalAllowed or LogWithdrawalAllowed or LogNftWithdrawalAllowed for ERC20/ETH, ERC721 and off-chain minted asset respectively.

After this step, the funds can be viewed with the function getWithdrawalBalance that gets the starkKey and assetId as input. Note that the funds are still at the StarkEx contract.

The On-Chain call(s) to Extract Assets from the StarkEx Contract

Only an ethereumAddress corresponding to the starkKey of a pending withdrawal account may perform this operation, which can be done by either one of the options below:

  1. Withdraw to self: by calling the on-chain withdrawal function, withdraw for ERC20/ETH and NftWithdraw for ERC721, to perform the actual withdrawal of the asset, transferring it to the user's on-chain account. Withdrawal of an off-chain minted asset is done by calling the on-chain withdrawAndMint to mint the asset on the fly and transfer them to the user account.

  2. Withdraw to another: by calling the on-chain function, withdrawTo for ERC20/ETH and NftWithdrawTofor ERC721, providing the recipient parameter: the ethereumAddress that should receive the withdrawn funds. This option is not available for off-chain minted assets

After the second step, one of the following events is emitted to inform of the withdrawal:

  • For ERC20/ETH withdrawal, the event LogWithdrawalPerformed is emitted, with the parameters of the relevant starkKey, the recipient Ethereum address, the assetType, quantizedAmount and unquantized amounts.

  • For ERC721 withdrawal, the event LogNftWithdrawalPerformed is emitted, with the parameters of the relevant starkKey, the recipient Ethereum address, the assetId.

  • For off-chain minted assets, the event LogMintWithdrawalPerformed is emitted, with the parameters of the relevant starkKey, the recipient Ethereum address, the assetType, quantizedAmount , unquantized amounts and assetId

The result of the operation, assuming all requirements are met, is that an amount of assets in the pending withdrawal account, (times the quantization factor for ERC20/ETH) , is transferred to the corresponding account of the recipient.

It is possible to perform multiple withdrawals from off-chain vaults, and withdraw the entire amount using only one withdraw call to the on-chain contract, as long as the withdrawals are of the same assetId/mintingBlob and starkKey.

A withdrawal request cannot be canceled. Once funds reach the pending withdrawals account on-chain, they cannot be moved back into an off-chain vault before completion of the withdrawal to the corresponding account of the user.

Assets that are already on-chain can still be reclaimed even when the contract is Frozen by calling the relevant withdraw function from the following: withdraw ,withdrawTo , withdrawNft ,NftWithdrawTo and withdrawAndMint.