# StarkEx Specific Concepts

## Quantization and Resolution

In the Ethereum blockchain, token quantities are represented by a 256-bit number. However, to be efficient, all quantities in StarkEx are represented by a 64-bit number.

Since the inputs to all the off-chain transactions and some on-chain requests are given in StarkEx representation, it is crucial that the code that generates the transaction signature uses the correct quantization/resolution. Therefore, the quantization/resolution is reflected in the `assetId`, i.e. a unique StarkEx asset representation, as we explain in detail below.

In this section, we explain how to convert between one representation to the other.

### Quantization

The quantization factor (sometimes referred to as quantum) represents the multiplier of a StarkEx amount of tokens to get the blockchain amount. Namely, if the quantization of an asset is $q$ it means that $v$ tokens in StarkEx represent $q*v$ tokens in blockchain representation.

 For example, say that the quantization of ETH in StarkEx is 10,000,000. (Note: In blockchain, ETH amount is represented by WEI, 1 ETH = $10^{-18}$WEI). This means that '1' in our system represents 10,000,000 WEI or $10^{-11}$ETH on blockchain.
 The quantization factor is necessary for every asset that can be represented on-chain. This is clear when looking at the deposit flow. The on-chain deposit transaction gets an unquantized amount of tokens from the user, yet the parameter to the on-chain call is a quantized amount.

### Resolution

The resolution factor represents the reverse direction from quantization. That is, instead of asking "how many WEI are represented by writing '1' in the system" we ask: "what is the number in the system that represents 1 ETH" .

 As an example, say that the resolution of ETH is 10,000,000. This means that 10,000,000 tokens in our system represent 1ETH, therefore 1 in the system is $10^{-7}$ETH.

In perpetual trading, we use resolution, rather than quantization, for all the synthetic assets. Notice that since these assets are not represented on-chain, quantization is not needed. However, resolution provides the following benefits:

• Since signed external Oracle prices are given in round units, for example, BTC/ETH and not Satoshi/WEI, it makes the translation to the price used in the system valid.

• Since users usually refer to buying/selling in round units, for example, BTC and not satoshi, it makes the system easier to understand.

## AssetInfo, AssetType and AssetId

All asset types have the same APIs. These asset types are:

• ETH

• ERC-20

• ERC-721

• ERC-1155

• Synthetics

In the off-chain application, the `assetId` uniquely identifies the asset for all off-chain flows (transfer/conditional transfer/limit order/withdrawal)

 In perpetual trading, the synthetic assets are not represented on-chain and thus the off-chain`assetId`representation is enough for them. The `assetId` of a synthetic asset is a 120-bit number that represents their identity and resolution. For example, "ETH-8".encode('ascii') represents Ethereum with a resolution of $10^8$.

For on-chain assets (non-synthetic assets), the off-chain `assetId` is cryptographically bound to the identity of the token as represented on-chain (external ERC-20/ERC-721/ERC-1155 for deposit/withdraw goes through, correct quantization, etc), and therefore the calculation of `assetId` is as follows:

1. We call `assetInfo`, the string concatenation of `selector` *(explained below) and `address` *(if relevant). It enables StarkEx to redeem assets according to their initial standard.

2. We call `assetType`, the 250-bit hash of `assetInfo` and `quantum`. It enables StarkEx to convert an off-chain balance to an on-chain balance

3. We call `assetId`, a 250-bit number which definition depends on the asset standard. `assetId` is the only asset identifier off-chain.

To compute `assetInfo` , `assetType` and `assetId`, we need:

1. `Selector`, the 4-byte constant specifying the asset standard. Either ETH, ERC-20, ERC-721, or ERC-1155.

2. `Address` (if relevant), the asset contract address.

3. `Quantum` (if relevant), the multiplicative factor from the on-chain 256-bits integer balance to the 63-bits integer used as balance in StarkEx. Only amounts divisible by the quantum can be deposited in the system.

4. `TokenId` (if relevant), the asset serial number in the context of ERC-721 or ERC-1155.

#### Computing `assetInfo`, `assetType` and `assetId`

Below you can find a pseudo-code of the computation. Full implementation in JS can be found here.

#### ETH

``````def getEthAssetInfo():
ETH_SELECTOR = '0x8322fff2' # '0x8322fff2' = bytes4(keccak256(“ETH()”))
asset_info = ETH_SELECTOR
return asset_info

def getEthAssetType(quantum):
asset_info = getEthAssetInfo()
asset_type = keccak256(asset_info, quantum)
& 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return asset_type

def getEthAssetId(quantum):
asset_id = getEthAssetType(quantum)
return asset_id``````

#### ERC-20

``````def getErc20AssetInfo(address):
ERC20_SELECTOR = '0xf47261b0'
# '0xf47261b0' = bytes4(keccak256('ERC20Token(address)'))
asset_info = ERC20_SELECTOR + bytes.fromhex(address[2:]).rjust(32, b'\0')
# For ERC20, asset_info is 36 bytes long
return asset_info

asset_type = keccak256(asset_info, quantum)
& 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return asset_type

asset_id = getErc20AssetType(quantum, address)
return asset_id``````

#### ERC-721

``````def getErc721AssetInfo(address):
ERC721_SELECTOR = '0x02571792'
# 0x02571792 = bytes4(keccak256('ERC721Token(address,uint256)'))
asset_info = ERC721_SELECTOR + bytes.fromhex(address[2:]).rjust(32, b'\0')
# For ERC721, asset_info is 36 bytes long.
return asset_info

asset_type = keccak256(asset_info, 1)
& 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return asset_type

asset_id = keccak256('NFT:', asset_type, token_id)
& 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return asset_id``````

#### ERC-1155

``````def getErc1155AssetInfo(address):
ERC1155_SELECTOR = `0x3348691d`
# 0x3348691d = bytes4(keccak256('ERC1155Token(address,uint256)'))
asset_info = ERC1155_SELECTOR + bytes.fromhex(address[2:]).rjust(32, b'\0')
return asset_info

quantum = 1
asset_type = keccak256(asset_info, quantum)
& 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return asset_type

asset_id = keccak256("NON_MINTABLE:", asset_type, token_id)
& 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return asset_id``````

#### Mintable ERC-721

``````def getErcMintable721AssetInfo(address):
MINTABLE_ERC721_SELECTOR = '0xb8b86672'
# 0xb8b86672 = bytes4(keccak256('MintableERC721Token(address,uint256)'))
asset_info = MINTABLE_ERC721_SELECTOR + bytes.fromhex(address[2:]).rjust(32, b'\0')
# For Mintable ERC721, asset_info is 36 bytes long.
return asset_info

asset_type = keccak256(asset_info, 1)
& 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
return asset_type

blob_hash = keccak256(minting_blob)
asset_id = keccak256('MINTABLE:', asset_type, blob_hash)
& 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
asset_id = asset_id
| 0x400000000000000000000000000000000000000000000000000000000000000
return asset_id``````

#### Mintable ERC-20

``````def getErcMintable20AssetInfo(address):
MINTABLE_ERC20_SELECTOR = '0x68646e2d'
# 0xb8b86672 = bytes4(keccak256('MintableERC20Token(address)'))
asset_info = MINTABLE_ERC20_SELECTOR + bytes.fromhex(address[2:]).rjust(32, b'\0')
# For Mintable ERC20, asset_info is 36 bytes long.
return asset_info