> ## Documentation Index
> Fetch the complete documentation index at: https://docs.caldera.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploying MetaToken Hub

> Guide for self-service MetaToken hub deployment

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](#next-steps) below for more information.

## Source Code

All MetaToken contracts are open source and available in the [metatoken-contracts](https://github.com/ConstellationCrypto/metatoken-contracts) repository. The contracts include comprehensive inline documentation.

The hub implementation is located at [MetaERC20Hub.sol](https://github.com/ConstellationCrypto/metatoken-contracts/blob/main/src/token/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:

| Parameter          | Type      | Description                                                                                                                                                                                                                                          |
| ------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `metalayerDomain`  | `uint32`  | The 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](/metalayer/resources/contract-deployments) for domain IDs. |
| `metaERC20Version` | `uint8`   | MetaToken protocol version. Currently `1`. Must match across all spokes to ensure message compatibility.                                                                                                                                             |
| `metalayerRouter`  | `address` | The MetalayerRouter contract address on this chain. See [contract deployments](/metalayer/resources/contract-deployments).                                                                                                                           |
| `canonicalToken`   | `address` | The 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.                                                                                                        |
| `tokenDecimals`    | `uint8`   | Token decimals of the canonical token. Must match the canonical token's decimals exactly. All spokes must also use this same decimal value.                                                                                                          |
| `ttlWindow`        | `uint256` | Time-to-live window for transfer records in seconds. Must coordinate with spoke TTL settings. Typical values range from 1-7 days (86400-604800 seconds).                                                                                             |
| `owner`            | `address` | Admin 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.

```solidity theme={null}
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:

```solidity theme={null}
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";

ProxyAdmin proxyAdmin = new ProxyAdmin(ownerAddress);
```

### 2. Deploy the Implementation

Deploy the [MetaERC20Hub](https://github.com/ConstellationCrypto/metatoken-contracts/blob/main/src/token/MetaERC20Hub.sol) implementation contract.

```solidity theme={null}
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.

```solidity theme={null}
// 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.

```solidity theme={null}
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:

```solidity theme={null}
// 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

<CardGroup cols={2}>
  <Card title="Contact Team" icon="message" href="https://t.me/james_caldera">
    Contact for production MetaToken deployments
  </Card>

  <Card title="Deploy Spoke" icon="arrow-right" href="/metalayer/protocol/deploying-metatoken-spoke">
    Deploy spoke contracts on target chains
  </Card>
</CardGroup>
