Base Conversion Relayer
The Base conversion relayer (base-conversion-relayer) watches for TokensConverted events on the Base chain and mints corresponding GhostERC20 tokens (g-tokens) on the Specter chain via the GhostMinter contract. This enables a one-way conversion flow from Base-native tokens to privacy-wrapped tokens on Specter.
Conversion Flow
Base Chain Relayer Specter Chain
│ │ │
│ User calls │ │
│ ConversionContract │ │
│ .convert(token, amount) │ │
│ │ │
│ Tokens transferred to │ │
│ conversion contract │ │
│ │ │
│ emit TokensConverted( │ │
│ user, token, amount, │ │
│ specterRecipient) │ │
│────── Event detected ──────────▶│ │
│ │ │
│ │ Validate event │
│ │ Determine g-token mapping │
│ │ │
│ │── GhostMinter.mint( │
│ │ gToken, recipient, ──────▶│
│ │ amount) │
│ │ │
│ │ g-tokens minted to │
│ │ specterRecipient │
How It Works
1. Event Detection
The relayer maintains a WebSocket or polling connection to a Base chain RPC endpoint. It listens for TokensConverted events emitted by the Specter conversion contract deployed on Base:
event TokensConverted(
address indexed user,
address indexed token,
uint256 amount,
address specterRecipient
);
The event contains:
- user: The Base address that initiated the conversion.
- token: The ERC20 token address on Base that was converted.
- amount: The quantity of tokens converted.
- specterRecipient: The Specter chain address that should receive the minted g-tokens.
2. Token Mapping
The relayer maintains a mapping from Base token addresses to their corresponding GhostERC20 addresses on Specter. For example:
| Base Token | Base Address | Specter g-Token | Specter Address |
|---|---|---|---|
| USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | gUSDC | 0x... |
| WETH | 0x4200000000000000000000000000000000000006 | gWETH | 0x... |
If a TokensConverted event references an unmapped token, the relayer logs a warning and skips the event.
3. Minting on Specter
After validating the event, the relayer submits a mint() transaction on the Specter chain:
GhostMinter.mint(gTokenAddress, specterRecipient, amount);
The GhostMinter contract is a permissioned minting authority for GhostERC20 tokens. Only authorized minters (such as the conversion relayer's operator address) can call mint(). This ensures that g-tokens are only created in response to legitimate conversion events on Base.
4. Confirmation and Logging
After the mint transaction is confirmed on Specter, the relayer logs the completed conversion:
{
"event": "conversion_complete",
"baseToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"gToken": "0x...",
"amount": "1000000000000000000",
"baseUser": "0x...",
"specterRecipient": "0x...",
"baseTxHash": "0x...",
"specterTxHash": "0x...",
"blockNumber": 12345678
}
One-Way Design
The Base conversion relayer is intentionally one-way: tokens flow from Base to Specter, but not back. This design choice reflects the privacy model — once tokens are on Specter, they enter the Ghost Protocol's commit/reveal system. Exiting back to Base is handled by the Hyperlane bridge relayers (see Bridge Relayers), which provide a more general cross-chain messaging path.
The one-way design also simplifies the security model. The relayer only needs minting authority on Specter; it does not need the ability to unlock or transfer tokens on Base. The tokens deposited into the Base conversion contract are held in custody by that contract.
Duplicate Prevention
The relayer tracks processed events by their Base transaction hash and log index to prevent double-minting:
- Before processing an event, check if the
(txHash, logIndex)pair has already been processed. - If already processed, skip the event.
- After successful minting, record the
(txHash, logIndex)pair in the processed events store.
The processed events store is persisted to disk and loaded at startup. This ensures that a relayer restart does not re-process events that were already minted.
Block Confirmations
To mitigate the risk of processing events from reorged blocks, the relayer waits for a configurable number of block confirmations on Base before processing a TokensConverted event:
| Setting | Default |
|---|---|
| Confirmations required | 12 blocks (~24 seconds on Base) |
This provides a reasonable balance between latency and safety. A reorg deeper than 12 blocks on Base is extremely unlikely under normal conditions.
Error Handling
- Base RPC failure: Exponential backoff reconnection. Events are not lost because the relayer resumes from the last processed block on reconnection.
- Mint transaction failure: Retry with increased gas. If the
GhostMintercontract reverts (e.g., due to an invalid token address), the event is logged as failed for manual investigation. - Unmapped token: Logged as a warning and skipped. No mint is attempted.
- Insufficient operator balance: If the Specter operator wallet lacks gas, the relayer pauses and logs a critical alert.
Configuration
| Parameter | Description |
|---|---|
BASE_RPC_URL | Base chain RPC endpoint |
SPECTER_RPC_URL | Specter chain RPC endpoint |
CONVERSION_CONTRACT_ADDRESS | Address of the conversion contract on Base |
GHOST_MINTER_ADDRESS | Address of GhostMinter on Specter |
OPERATOR_PRIVATE_KEY | Relayer operator key (authorized minter on Specter) |
TOKEN_MAPPING | JSON mapping of Base token addresses to Specter g-token addresses |
CONFIRMATIONS | Block confirmations to wait on Base |
START_BLOCK | Base block to begin historical sync from |