Розробка мультичейн-токена
Мультичейн-токен — це не просто деплой однаково ERC-20 на кілька мереж. Це архітектурне рішення з серйозними наслідками для управління supply, безпеки та UX. Неправильно спроектований мультичейн-токен створює ілюзію єдиного активу при реально розпорошеному supply, відкриває поверхню для bridge-атак та ускладнює governance. Давайте розберемось, як це робити правильно.
Моделі мультичейн-токена
Перед тим як писати код, потрібно вибрати архітектурну модель. Їх три, та вони фундаментально різні.
Lock & Mint (канонічна модель)
Токен існує нативно на одному чейні (home chain, зазвичай Ethereum). На всіх інших чейнах існують wrapped версії. Bridge блокує токени на home chain та мінтить wrapped на destination chain. При бриджингу назад — burning wrapped, unlock оригіналу.
Плюси: єдиний canonical supply, проста ментальна модель для користувачів.
Мінуси: якщо bridge зламаний — зловмисник може мінтити wrapped токени без забезпечення. Так був зламаний Wormhole ($320M в 2022) та Ronin Bridge ($625M).
Burn & Mint (omnichain модель)
При трансфері токен спалюється на source chain та мінтиться на destination chain. Total supply глобально постійний. Цей підхід використовують LayerZero OFT (Omnichain Fungible Token) та Axelar ITS.
Плюси: немає locked liquidity на одному чейні, рівнозначність токенів на всіх мережах.
Мінуси: транзакція не атомарна — токен знищений на source, але може не домінтитись на destination при сбої. Потрібен механізм recovery.
Liquidity Pool модель
Незалежні токени на кожному чейні сполучені через AMM-пулы в bridge-протоколах (Stargate, Synapse). Bridge нативного свопу, не wrapped tokens.
Плюси: миттєвість (атомарний своп з пулу), нема wrapped токенів.
Мінуси: вимагає bootstrap liquidity на кожному чейні, slippage при незбалансованих пулах.
Реалізація через LayerZero OFT
LayerZero став де-факто стандартом для нових мультичейн-токенів. OFT (Omnichain Fungible Token) — burn & mint модель з messaging через LayerZero Endpoint.
Базова реалізація OFT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import { OFT } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFT.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is OFT {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint, // LayerZero Endpoint адреса для поточної мережі
address _delegate
) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {}
// Мінтинг лише при деплое або через governance
function mint(address _to, uint256 _amount) external onlyOwner {
_mint(_to, _amount);
}
}
На home chain деплоїм цей контракт та мінтимо весь supply. На інших чейнах деплоїм той же контракт, але без початкового мінтингу — токени туди приходять через bridge.
Конфігурація OFT після деплою
Після деплою на всіх чейнах потрібно пов'язати контракти через setPeer:
// На кожному чейні для кожної іншої мережі
function configurePeers() external onlyOwner {
// eid = endpoint ID в системі LayerZero
// Ethereum mainnet: 30101, Arbitrum: 30110, Base: 30184, BSC: 30102
// Якщо ми на Ethereum, реєструємо Arbitrum peer
oft.setPeer(30110, bytes32(uint256(uint160(ARBITRUM_OFT_ADDRESS))));
// Реєструємо Base peer
oft.setPeer(30184, bytes32(uint256(uint160(BASE_OFT_ADDRESS))));
}
Відправка токенів між чейнами
// Підготовка параметрів для cross-chain transfer
function bridgeTokens(
uint32 _dstEid, // destination endpoint ID
address _recipient,
uint256 _amount
) external payable {
SendParam memory sendParam = SendParam({
dstEid: _dstEid,
to: bytes32(uint256(uint160(_recipient))),
amountLD: _amount,
minAmountLD: (_amount * 995) / 1000, // 0.5% slippage tolerance
extraOptions: OptionsBuilder.newOptions()
.addExecutorLzReceiveOption(200000, 0), // gas на destination
composeMsg: "",
oftCmd: ""
});
// Отримуємо quote на native fee для оплати LayerZero messaging
MessagingFee memory fee = oft.quoteSend(sendParam, false);
oft.send{ value: fee.nativeFee }(sendParam, fee, payable(msg.sender));
}
Управління supply між чейнами
Це найскладніший аспект. Потрібен моніторинг:
| Метрика | Як відстежувати |
|---|---|
| Supply per chain | Вызов totalSupply() на кожному деплое |
| Circulating supply | Сума всіх totalSupply() мінус locked в bridge контрактах |
| Bridge flow | OFTSent / OFTReceived события |
| Pending messages | LayerZero Scan API |
Для Lock & Mint моделі (якщо використовуєте кастомний bridge) потрібен invariant check: sum(wrapped supplies) <= locked_on_home_chain. Моніторинг через Tenderly або власний скрипт з PagerDuty алертингом.
Безпека мультичейн-токена
DVN (Decentralized Verifier Network) конфігурація
LayerZero V2 дозволяє налаштовувати, які верифікатори повинні підтвердити повідомлення перед виконанням. Мінімальна безпечна конфігурація — 2 з N верифікаторів:
// Налаштування ULN (Ultra Light Node) конфігурації
UlnConfig memory ulnConfig = UlnConfig({
confirmations: 15, // блоків для finality
requiredDVNCount: 2, // мінімум 2 DVN повинні підтвердити
optionalDVNCount: 0,
optionalDVNThreshold: 0,
requiredDVNs: [LAYERZERO_DVN, GOOGLE_CLOUD_DVN],
optionalDVNs: new address[](0)
});
Для production рекомендується використовувати LayerZero DVN + один незалежний DVN (Google Cloud, Nethermind, p2p.org).
Rate limiting
Навіть з надійним bridge — додайте rate limiting на рівні токен-контракту як останню лінію захисту:
// Обмеження на максимальний transfer за період
mapping(uint256 => uint256) public dailyBridgeVolume; // day => volume
uint256 public constant MAX_DAILY_BRIDGE = 1_000_000e18; // 1M токенів/день
modifier withRateLimit(uint256 amount) {
uint256 today = block.timestamp / 1 days;
require(
dailyBridgeVolume[today] + amount <= MAX_DAILY_BRIDGE,
"Daily bridge limit exceeded"
);
dailyBridgeVolume[today] += amount;
_;
}
Якщо bridge зламаний — rate limit дасть час на реакцію, ограничивая урон.
Pause механізм
Контракт повинен мати pause функцію, керовану мультисигом з коротким timelock (або без нього — для екстрених випадків). При виявленні аномальної bridge активності — миттева зупинка передач.
Деплой та інфраструктура
Послідовність деплою
- Деплой на home chain, мінтинг supply
- Деплой на всі destination chains
- Вызов
setPeerна кожному чейні для кожної пари - Верифікація: тестовий bridge transfer невеликої суми
- Моніторинг: налаштування алертів на bridge events
Мережі та LayerZero Endpoint IDs (актуальні)
| Мережа | Endpoint ID | Chain ID |
|---|---|---|
| Ethereum | 30101 | 1 |
| Arbitrum One | 30110 | 42161 |
| Base | 30184 | 8453 |
| Optimism | 30111 | 10 |
| BSC | 30102 | 56 |
| Polygon | 30109 | 137 |
| Avalanche | 30106 | 43114 |
Скрипт деплоя через Hardhat
// scripts/deploy-oft.ts
import { ethers } from "hardhat";
import { EndpointId } from "@layerzerolabs/lz-definitions";
async function main() {
const [deployer] = await ethers.getSigners();
const lzEndpoint = getEndpointForNetwork(network.name);
const OFT = await ethers.getContractFactory("MyToken");
const oft = await OFT.deploy(
"My Token",
"MYT",
lzEndpoint,
deployer.address
);
await oft.waitForDeployment();
console.log(`OFT deployed to: ${await oft.getAddress()}`);
// Мінтинг лише на home chain
if (network.name === "ethereum") {
await oft.mint(deployer.address, ethers.parseEther("100000000"));
}
}
Governance та мультичейн-токен
Якщо токен використовується для governance — виникає проблема: як рахувати voting power при розподіленому supply? Три підходи:
Hub-and-spoke: голосування лише на home chain. Користувачі з інших чейнів повинні bridge токени назад. Просто, але UX поганий.
Cross-chain voting: off-chain snapshot голосів на всіх чейнах, агрегація через LayerZero або Axelar. Використовує Snapshot + XCHAIN voting.
Dedicated governance token: окремий non-transferable governance token на одному чейні, distribution token — мультичейн. Складніше, але архітектурно чистіше.
Мультичейн-токен — це не feature, це commitment. Кожен новий чейн додає операційну нагрузку, аудит поверхню та ризики. Додавайте мережі лише там, де реально є ліквідність та користувачі.







