Supported Tokens
Overview
Tokens represent the assets used within the exchange ecosystem. Their configuration is managed exclusively by the exchange, with careful controls for both virtual and concrete assets.
The exchange supports two primary types of tokens:
Concrete tokens: These correspond to actual ERC20 assets on the blockchain, such as USDe. Concrete tokens have an associated onchain address and can be deposited to and withdrawn from the exchange.
Virtual tokens: These tokens exist only within the exchange ecosystem and serve as the base asset for specific markets without being directly tradable. For example, in the SOLUSD perpetual market, SOL would be configured as a virtual token without an onchain address.
Token promotion: Virtual tokens can be promoted to concrete tokens as the exchange evolves. For example, BTC and ETH will initially be configured as virtual tokens at launch since they cannot be traded directly (i.e., cannot be a quote asset and cannot be spot traded). When the exchange is upgraded to support spot trading and portfolio margin, the ETH virtual token can be promoted to a concrete token, enabling direct trading, deposits, and withdrawals.
Why Virtual Tokens?
This design allows contracts and downstream offchain services reconcile tokens without branching deeply supporting non-tokens and tokens. Everything is simply a “token”. When necessary, a token can be promoted to a concrete token by providing an address.
Configuration
Token management is handled through privileged contract functions:
All token configuration functions are protected by
onlyOwner
modifiersThe same configuration management processes control which tokens are acceptable for deposits
Token management functions emit
TokenXXX
events (e.g.,TokenAdded
,TokenUpdated
) that are indexed and propagated to offchain systems
Each token can have various settings that are managed independently:
Status flags: deposit enabled/disabled, withdrawal enabled/disabled
Risk controls: deposit caps (maximum amount that can be deposited), withdrawal limits
Fee structure: Deposit/withdrawal fees
Retrieving Configured Tokens
Once configured and indexed, you can query against the trading API to retrieve configured tokens:
curl -X 'GET' \
'https://api.etherealtest.net/v1/token?order=asc' \
-H 'accept: application/json'
{
"hasNext": false,
"data": [
{
"id": "ff761c8b-6248-4673-b63d-d1f980551959",
"address": "0xa1623E0AA40B142Cf755938b325321fB2c61Cf05",
"name": "USD",
"erc20Name": "USDe",
"erc20Symbol": "USDe",
"erc20Decimals": 18,
"depositEnabled": true,
"withdrawEnabled": true,
"depositFee": "0",
"withdrawFee": "1",
"minDeposit": "10",
"createdAt": 1743745409966
},
{
"id": "d800d607-2c0d-43f6-af5e-19b7f8dd4caa",
"address": "0x0000000000000000000000000000000000000000",
"name": "BTC",
"depositEnabled": false,
"withdrawEnabled": false,
"depositFee": "0",
"withdrawFee": "0",
"minDeposit": "0",
"createdAt": 1743745409966
},
{
"id": "cda05e1e-fd10-433c-8cbd-36b7545307b0",
"address": "0x0000000000000000000000000000000000000000",
"name": "ETH",
"depositEnabled": false,
"withdrawEnabled": false,
"depositFee": "0",
"withdrawFee": "0",
"minDeposit": "0",
"createdAt": 1743745409966
},
{
"id": "790b743e-1a19-4bd6-8cd4-1bcff9bb0b86",
"address": "0x0000000000000000000000000000000000000000",
"name": "ENA",
"depositEnabled": false,
"withdrawEnabled": false,
"depositFee": "0",
"withdrawFee": "0",
"minDeposit": "0",
"createdAt": 1743745409966
}
}
Tokens are also accessible onchain:
/// @notice Returns an array of token names.
function getExchangeTokens() external view returns (bytes32[] memory);
/// @notice Returns the token deatils, that was at one point supported by the exchange.
/// @param tokenName Name of the token to retrieve the details for
function getToken(bytes32 tokenName) external returns (Token.Data memory);
library Token {
struct Data {
/// Address of token (can be zero when virtual);
address tokenAddress;
/// Maximum balance an account can hold after a deposit.
uint256 depositCapacity;
/// Minimum deposits amount, in the token, in the native units.
uint256 minDeposit;
/// Withdraw fee, in the token, in the native units.
uint128 withdrawFee;
/// Deposit fee, in the token, in the native units.
uint128 depositFee;
/// Deposit restriction.
bool depositEnabled;
/// Withdraw restriction.
bool withdrawEnabled;
/// If the token is used by a product (as either a quote or base asset), it cannot never be removed.
bool removeProtected;
}
}
Tokens are not particularly useful on their own but they referenced throughout the trading API in areas such as transfers, products, and subaccount balances.
Unit Precision
Ethereal implements a standardized precision approach for all supported tokens, maintaining consistent gwei precision (1e9 or 9 decimal places) throughout the exchange. This standardization ensures that tokens with more than 9 decimals (like USDe with 18 decimals) are downscaled, while tokens with fewer decimals are upscaled to match the uniform 9-decimal precision used internally.
When making deposits, users must specify amounts in the token's native precision relative to its original decimal places. For example, depositing 1000 USDe requires specifying 1000000000000 (1e18). However, once these tokens enter the exchange, they're automatically normalized to the standard 9-decimal precision used across all internal systems and calculations.
This normalized precision is consistently reflected throughout the platform, with API responses expressing token amounts as string decimals and message signing representing amounts as integers with 1e9 precision. This approach eliminates potential calculation errors that could arise from varying decimal places across different tokens and ensures reliable, consistent handling of all supported assets.
Last updated