Skip to main content

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 TokenBase AddressSpecter g-TokenSpecter Address
USDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913gUSDC0x...
WETH0x4200000000000000000000000000000000000006gWETH0x...

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:

  1. Before processing an event, check if the (txHash, logIndex) pair has already been processed.
  2. If already processed, skip the event.
  3. 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:

SettingDefault
Confirmations required12 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 GhostMinter contract 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

ParameterDescription
BASE_RPC_URLBase chain RPC endpoint
SPECTER_RPC_URLSpecter chain RPC endpoint
CONVERSION_CONTRACT_ADDRESSAddress of the conversion contract on Base
GHOST_MINTER_ADDRESSAddress of GhostMinter on Specter
OPERATOR_PRIVATE_KEYRelayer operator key (authorized minter on Specter)
TOKEN_MAPPINGJSON mapping of Base token addresses to Specter g-token addresses
CONFIRMATIONSBlock confirmations to wait on Base
START_BLOCKBase block to begin historical sync from