Elysium
Bridging a HyperEVM-native ERC-20 to Elysium and back through the canonical bridge, permissionlessly and with zero issuer action.
Last updated
A developer guide for bridging a HyperEVM-native ERC-20 to Elysium and back through the canonical bridge — the stock token bridge of the Arbitrum Orbit rollup stack Elysium runs on, unchanged: lock on HyperEVM, mint a 1:1 representation on Elysium.
Bridging is permissionless with zero issuer action: any ERC-20 works, and the representation contract on Elysium is auto-deployed by the first-ever deposit at a deterministic address. See Token bridging on Elysium for how this leg fits the full lifecycle.
Elysium is pre-launch: the address constants in the samples (ROUTER, TOKEN, …) are deliberately left undefined, so substitute the values published at launch. Details may be refined before mainnet.
1. Overview
- HyperEVM → Elysium (deposit): approve the bridge escrow, then call
outboundTransferon the router with a small amount of native HYPE (msg.value) to fund delivery. The token locks in escrow on HyperEVM and the representation is minted to the recipient on Elysium, typically within a minute. - Elysium → HyperEVM (withdraw): call
outboundTransferon the Elysium router. The representation burns immediately, and the escrowed original is claimable on HyperEVM after the challenge period.
At a glance
Value | |
|---|---|
Router (HyperEVM) |
|
Standard gateway / escrow (HyperEVM) |
|
Router (Elysium) |
|
Elysium chain ID |
|
Fee asset (both directions) | native HYPE via |
The representation on Elysium is a standard bridge token: same decimals as the original, minted and burned only by the bridge, supply always equal to the escrow locked on HyperEVM.2. Finding the representation
The router maps every HyperEVM token to its gateway and its deterministic Elysium address, before or after the first deposit:
// The same router surface exists on both chains: deposits enter on HyperEVM,
// withdrawals enter on Elysium.
interface IGatewayRouter {
function outboundTransfer(address token, address to, uint256 amount,
uint256 maxGas, uint256 gasPriceBid, bytes calldata data)
external payable returns (bytes memory);
function getGateway(address token) external view returns (address);
function calculateL2TokenAddress(address token) external view returns (address);
}// ROUTER: published at launch. TOKEN: the HyperEVM-native ERC-20 you're bridging.
address rep = IGatewayRouter(ROUTER).calculateL2TokenAddress(TOKEN);
// -> the representation's Elysium address (same before and after first deposit)
address gateway = IGatewayRouter(ROUTER).getGateway(TOKEN);
// -> the escrow contract your approval must targetgetGateway(token) returns the escrow contract your approval must target. For an unregistered token it returns the standard gateway, the default every plain ERC-20 uses.
3. HyperEVM → Elysium (deposit)
Two transactions on HyperEVM: approve the gateway, then deposit through the router. The first-ever deposit of a token also auto-deploys its representation on Elysium. No additional step is required, though that one transaction costs slightly more gas.
Step 1: Approve on the token
Approve the gateway (from getGateway), not the router:
// GATEWAY = IGatewayRouter(ROUTER).getGateway(TOKEN)
IERC20(TOKEN).approve(GATEWAY, 100e18); // 100 tokens at 18 dpStep 2: Deposit on the router
msg.value funds delivery on Elysium: maxSubmissionCost + maxGas × gasPriceBid, all in native HYPE. Over-provisioning is safe, since the excess refunds to the recipient on Elysium.
uint256 maxGas = 300_000;
uint256 gasPriceBid = 0.1 gwei; // Elysium gas price bid
uint256 maxSubmissionCost = 4e14; // headroom; excess refunds on Elysium
uint256 fee = maxSubmissionCost + maxGas * gasPriceBid;
// data = abi.encode(maxSubmissionCost, ""), the standard 2-tuple
IGatewayRouter(ROUTER).outboundTransfer{value: fee}(
TOKEN, RECIPIENT, 100e18, maxGas, gasPriceBid, abi.encode(maxSubmissionCost, bytes(""))
);What happens: the gateway pulls amount into escrow on HyperEVM and sends a delivery message to Elysium. The representation is minted to to when it executes, normally automatically within about a minute.
Common reverts: ERC-20 allowance/balance (approve the gateway first), NO_VALUE class errors when msg.value doesn't cover maxSubmissionCost + maxGas × gasPriceBid, and non-standard tokens. Fee-on-transfer tokens are not currently supported (the bridge mints against the requested amount, not the received amount).
4. Elysium → HyperEVM (withdraw)
One transaction on Elysium, no approval needed. The bridge burns the representation directly:
// ELYSIUM_ROUTER: published at launch.
// TOKEN = the ORIGINAL HyperEVM address. The router keys on it, not the representation.
// maxGas/gasPriceBid/data are unused on withdrawals: pass 0, 0, "".
IGatewayRouter(ELYSIUM_ROUTER).outboundTransfer(TOKEN, RECIPIENT, 100e18, 0, 0, "");Then:
- The representation burns immediately on Elysium.
- The withdrawal message finalizes after the challenge period.
- Claim the escrowed original on HyperEVM (the bridge UI surfaces claimable withdrawals; programmatic claiming executes the message against the bridge's outbox).
Note the token argument is always the HyperEVM address of the original, in both directions. The bridge keys every route on the parent-chain address.Common reverts: representation balance too low; EXTRA_DATA_DISABLED if you pass non-empty data on a withdrawal.
5. If a deposit doesn't arrive
Deposit delivery on Elysium is a retryable message. If the delivery leg fails to auto-execute (for example, gasPriceBid was set below the live Elysium gas price), the funds are not lost: the message stays claimable and anyone can re-execute it. The bridge UI surfaces stuck deposits, and re-executing mints the representation as if delivery had succeeded the first time. Messages left unredeemed for an extended period (measured in days) can expire, so re-execute promptly.
6. Reference
// router (deposit entrypoint on HyperEVM, withdrawal entrypoint on Elysium)
function outboundTransfer(address token, address to, uint256 amount,
uint256 maxGas, uint256 gasPriceBid, bytes calldata data) external payable returns (bytes memory);
// views (both routers)
function getGateway(address token) external view returns (address);
function calculateL2TokenAddress(address token) external view returns (address);- Deposits: approve the gateway, call the router, fund with
msg.valueHYPE. - Withdrawals: call the router on Elysium with
0, 0, "". No approval, no value. - The representation address is deterministic and identical before/after deployment.
For the architecture deep dive (sequence diagrams, derivation mechanics, trust model), see Token bridging architecture.
Contract addresses and example transactions will be added at launch.