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
| Concept | Example | Description |
|---|---|---|
| Asset | AAPL, USD, BTC | A single tradeable or settlement unit |
| Instrument | AAPL-USD, AAPL-BTC | A trading pair composed of a base asset and a quote asset |
| Asset token | AAPLo, USDo, BTCo | The 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:
| Instrument | Base token | Quote token |
|---|---|---|
| AAPL-USD | AAPLo | USDo |
| AAPL-BTC | AAPLo | BTCo |
| TSLA-USD | TSLAo | USDo |
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.