Skip to main content
This guide covers the technical steps for deploying a MetaToken hub contract on your canonical token chain. The hub manages the canonical token supply and coordinates transfers to spoke chains. The MetaToken standard is open and permissionless, allowing anyone to deploy hub contracts using the proxy pattern for upgradeability. Deployment involves multi-chain coordination, domain configuration, and ongoing operational overhead including message monitoring, upgrades, and gas management. We strongly recommend contacting Caldera for end-to-end production deployments. See Next Steps below for more information.

Source Code

All MetaToken contracts are open source and available in the metatoken-contracts repository. The contracts include comprehensive inline documentation. The hub implementation is located at MetaERC20Hub.sol.

Deployment Architecture

MetaToken hubs use the OpenZeppelin TransparentUpgradeableProxy pattern for upgradeability. The deployment consists of:
  1. TransparentUpgradeableProxy: The proxy contract that users interact with
  2. ProxyAdmin: Controls proxy upgrades, owned by your admin address
  3. MetaERC20Hub: The implementation contract with hub logic
The proxy pattern allows you to upgrade the implementation logic while maintaining the same contract address and escrowed token balances.

Configuration Parameters

You will need to provide the following initialization parameters for the MetaERC20Hub contract:
ParameterTypeDescription
metalayerDomainuint32The Metalayer domain ID for the chain where the hub is deployed. This is typically the chain where your canonical token exists (e.g., 1 for Ethereum mainnet). See contract deployments for domain IDs.
metaERC20Versionuint8MetaToken protocol version. Currently 1. Must match across all spokes to ensure message compatibility.
metalayerRouteraddressThe MetalayerRouter contract address on this chain. See contract deployments.
canonicalTokenaddressThe address of the canonical ERC20 token that will be locked in the hub. This is the native token that users deposit to mint on spoke chains.
tokenDecimalsuint8Token decimals of the canonical token. Must match the canonical token’s decimals exactly. All spokes must also use this same decimal value.
ttlWindowuint256Time-to-live window for transfer records in seconds. Must coordinate with spoke TTL settings. Typical values range from 1-7 days (86400-604800 seconds).
owneraddressAdmin address that receives DEFAULT_ADMIN_ROLE, ADMIN_ROLE, and VALIDATOR_ROLE. Should be a multisig or secure EOA.

Deployment Steps

1. Deploy the Proxy

Deploy a TransparentUpgradeableProxy contract. The proxy will be the permanent address that manages the canonical token escrow.
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

// Deploy proxy with empty implementation initially
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
    address(0),           // initial implementation (can be address(0))
    proxyAdminAddress,    // ProxyAdmin contract address
    ""                    // empty initialization data
);
You’ll also need a ProxyAdmin contract to manage upgrades:
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";

ProxyAdmin proxyAdmin = new ProxyAdmin(ownerAddress);

2. Deploy the Implementation

Deploy the MetaERC20Hub implementation contract.
import {MetaERC20Hub} from "src/token/MetaERC20Hub.sol";

MetaERC20Hub implementation = new MetaERC20Hub();
You will need all dependencies installed:
  • OpenZeppelin Contracts (Upgradeable)
  • Hyperlane Core Contracts

3. Point Proxy to Implementation

Use the ProxyAdmin to upgrade the proxy to point to your MetaERC20Hub implementation and initialize it with the configuration parameters listed above.
// Upgrade and initialize the proxy
proxyAdmin.upgradeAndCall(
    ITransparentUpgradeableProxy(address(proxy)),
    address(implementation),
    initializationData
);
The hub is now deployed and initialized at the proxy address.

4. Configure the Hub

After deploying your hub, you’ll need to register spoke contracts as they are deployed. Register spokes on hub: Call setDomainAddressBatch on your MetaERC20Hub to register each spoke’s address.
hub.setDomainAddressBatch(
    [spokeChain1Domain, spokeChain2Domain],
    [spoke1Address.addressToBytes32(), spoke2Address.addressToBytes32()]
);
You can add spokes incrementally as you deploy them to additional chains.

5. Test the Deployment

Approve the hub to spend your canonical tokens, then initiate a small test transfer from hub to a spoke:
// Approve hub to lock canonical tokens
IERC20(canonicalToken).approve(address(hub), amount);

// Transfer to spoke
hub.transferRemote{value: gasFee}(
    spokeDomain,
    recipientAddress.addressToBytes32(),
    smallAmount
);
Monitor the Hyperlane message delivery and verify the spoke mints the correct amount to the recipient.

Next Steps

After deploying your hub, you’ll need to deploy spoke contracts on each chain where you want your token available. Self-deploying MetaToken hubs involves significant ongoing operational complexity. Caldera’s managed MetaToken deployments provide:
  • Deterministic Addressing: Automated deployment tooling ensures consistent contract addresses across all chains
  • Ongoing Operations: Message monitoring, implementation upgrade coordination across all chains, and 24/7 incident response
  • Gas & State Management: Interchain Gas Paymaster funding, TTL pruning, and storage optimization
  • Production Support: Direct access to Caldera’s infrastructure and protocol teams