Olympus

Asset Tokens

Per-asset ERC-20 tokens, the "o" suffix convention, shared tokens across instruments, and on-chain queries

Asset Tokens

Olympus deploys one ERC-20 token per asset, not per instrument. This means the token for AAPL exists independently of any particular trading pair. Instruments like "AAPL-USD" and "AAPL-BTC" both use the same AAPLo token for their base asset side.

Asset vs. Instrument

ConceptExampleDescription
AssetAAPL, USD, BTCA single tradeable or settlement unit
InstrumentAAPL-USD, AAPL-BTCA trading pair composed of a base asset and a quote asset
Asset tokenAAPLo, USDo, BTCoThe ERC-20 representation of an asset on the EVM

An instrument like "AAPL-USD" involves two assets: AAPL (base) and USD (quote). Each asset has its own ERC-20 token. When a user locks AAPL on the core layer, the bridge mints AAPLo on the EVM -- regardless of which instrument the AAPL was associated with.

Sharing across instruments

Multiple instruments can share the same asset tokens:

InstrumentBase tokenQuote token
AAPL-USDAAPLoUSDo
AAPL-BTCAAPLoBTCo
TSLA-USDTSLAoUSDo

Adding "AAPL-BTC" to the exchange does not deploy a new AAPLo token -- it reuses the existing one. Only assets that don't already have a token trigger a new deployment.

The "o" Suffix Convention

All Olympus asset tokens follow a consistent naming scheme:

  • Token name: "Olympus {ticker}" -- e.g. "Olympus AAPL", "Olympus USD"
  • Token symbol: "{ticker}o" -- e.g. "AAPLo", "USDo", "BTCo"

The o suffix stands for "Olympus" and distinguishes these wrapped tokens from the underlying assets. This convention applies to all asset types -- equities, currencies, and crypto.

Token Deployment

Tokens are deployed via the OlympusTokenFactory genesis contract at 0x0D00 using CREATE2:

salt = keccak256(symbol)    // e.g. keccak256("AAPLo")

This gives deterministic, restart-stable addresses. The same symbol always produces the same token address regardless of deployment order or timing.

When a new instrument is added via AdminAddInstrument, the core engine checks which assets need tokens and emits a DeployToken instruction for each new asset:

BridgeInstruction::DeployToken {
    asset: "AAPL",
    token_name: "Olympus AAPL",
    token_symbol: "AAPLo",
}

The factory call is:

factory.createToken("Olympus AAPL", "AAPLo")

Querying Token Addresses On-Chain

Token addresses are queryable via the factory's on-chain registry. The lookup key is the token symbol (with the o suffix):

// Get the AAPLo token address
address aaplToken = OlympusTokenFactory(0x0D00).getToken("AAPLo");

// Get the USDo token address
address usdToken = OlympusTokenFactory(0x0D00).getToken("USDo");

The getToken function returns address(0) if the token has not been deployed.

Token Registry

The bridge maintains an in-memory TokenRegistry mapping asset names (e.g. "AAPL") to their deterministic CREATE2 token addresses. This registry is populated at startup (for existing instruments) and updated when new instruments add new assets. The registry is keyed by asset, not by instrument or symbol.

Constructor Args for Blockscout Verification

When BLOCKSCOUT_API is set, the node automatically verifies deployed asset tokens on Blockscout. The constructor arguments submitted for verification are ABI-encoded as:

abi.encode(string name, string symbol, address operator)

For example, the AAPLo token's constructor args would be:

abi.encode("Olympus AAPL", "AAPLo", 0x0D00)

where 0x0D00 is the factory address (which serves as the token operator). This matches the OlympusToken constructor signature:

constructor(string memory _name, string memory _symbol, address _operator)

Verification runs as a background task and never blocks the engine. Tokens that are already verified are skipped.

On this page