Ethereal Docs
  • Introduction
    • What is Ethereal?
  • Public Testnet
  • Trading
    • Perpetual Futures
      • Margining
      • Order Types
      • Positions
      • Funding Rates
      • Market Specifications
      • Liquidations
      • Auto Deleveraging
      • Subaccounts
      • Price Oracles
  • Points
    • Staking sENA
    • Season Zero
  • developer-guides
    • Trading API
      • Quick Start
      • Message Signing
      • Accounts & Signers
      • Order Placement
      • System Limits
      • Products
      • Token Transfers
      • Supported Tokens
      • Websocket Gateway
    • Python SDK
  • Protocol Reference
    • API Hosts
    • Contracts
    • Audits
Powered by GitBook
On this page
  • Overview
  • Why Virtual Tokens?
  • Configuration
  • Retrieving Configured Tokens
  • Unit Precision
  1. developer-guides
  2. Trading API

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.

Ethereal will only support USDe concrete tokens on launch with BTC and ETH support in a subsequent release for portfolio margin.

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 modifiers

  • The 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
    }
}

Concrete tokens will always have an ERC20 address

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.

PreviousToken TransfersNextWebsocket Gateway

Last updated 3 days ago

Page cover image