Интеграция с LayerZero
LayerZero — omnichain messaging протокол, который позволяет смарт-контрактам в разных блокчейнах общаться напрямую. Не просто bridge для токенов — обобщённый протокол передачи сообщений. На его базе строятся OFT (Omnichain Fungible Token), ONFT (Omnichain NFT), cross-chain governance, cross-chain liquidity протоколы.
Ключевое отличие от классических bridge-ей: нет централизованного custodian-а, который держит средства. Есть DVN (Decentralized Verifier Networks) — независимые верификаторы, которые подтверждают доставку сообщений. Безопасность — через независимость верификаторов.
Архитектура V2
LayerZero V2 (актуальная версия) упростила архитектуру по сравнению с V1. Ключевые компоненты:
Endpoint — singleton контракт в каждой сети. Все взаимодействия идут через него. Адрес одинаковый во всех поддерживаемых сетях: 0x1a44076050125825900e736c501f859c50fE728c.
DVN (Decentralized Verifier Network) — набор верификаторов, которые читают события source chain и подтверждают их на destination. Разработчик выбирает DVN конфигурацию: минимальное количество верификаторов, required vs optional DVN-ы. Google Cloud, Polyhedra, Axelar — примеры DVN провайдеров.
Executor — агент, который вызывает lzReceive на destination chain после подтверждения DVN-ами. Либо LayerZero executor, либо собственный.
OApp: базовый паттерн интеграции
OApp (Omnichain Application) — базовый контракт для любой LayerZero интеграции:
import { OApp, Origin, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
contract CrossChainMessenger is OApp {
event MessageReceived(uint32 srcEid, bytes32 sender, string message);
constructor(address _endpoint, address _owner)
OApp(_endpoint, _owner) {}
// Отправка сообщения в другую сеть
function sendMessage(
uint32 dstEid, // destination endpoint ID (например, 30101 = Ethereum)
string calldata message,
bytes calldata options // газ лимит на destination
) external payable {
bytes memory payload = abi.encode(message);
MessagingFee memory fee = _quote(dstEid, payload, options, false);
require(msg.value >= fee.nativeFee, "Insufficient fee");
_lzSend(dstEid, payload, options, fee, payable(msg.sender));
}
// Получение сообщения (вызывается Executor-ом)
function _lzReceive(
Origin calldata origin,
bytes32 /*guid*/,
bytes calldata payload,
address /*executor*/,
bytes calldata /*extraData*/
) internal override {
string memory message = abi.decode(payload, (string));
emit MessageReceived(origin.srcEid, origin.sender, message);
}
// Квота на fee перед отправкой
function quoteSend(
uint32 dstEid,
string calldata message,
bytes calldata options
) external view returns (MessagingFee memory) {
return _quote(dstEid, abi.encode(message), options, false);
}
}
options — важный параметр. Кодирует lzReceive gas limit на destination, drop ETH на destination адрес (airdrop), ordered delivery. Используется OptionsBuilder:
bytes memory options = OptionsBuilder.newOptions()
.addExecutorLzReceiveOption(200000, 0); // 200k gas, 0 ETH airdrop
Недостаточный gas limit → транзакция на destination реверсируется. Слишком большой → пользователь переплачивает. Нужно профилировать реальный gas consumption через тесты.
OFT: Omnichain Fungible Token
OFT — главный use case LayerZero. Вместо bridge-а (lock-and-mint) токен существует нативно в каждой сети. При cross-chain transfer: burn на source + mint на destination. Нет custodian-а, нет locked liquidity.
import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol";
contract MyOFT is OFT {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _owner
) OFT(_name, _symbol, _lzEndpoint, _owner) {}
}
Это буквально весь контракт для базового OFT. Логика cross-chain transfer в родительском OFT контракте. Деплоить нужно в каждой целевой сети и связать через setPeer:
// На Ethereum: сообщаем что контрагент на Arbitrum — вот этот адрес
myOFT.setPeer(30110, bytes32(uint256(uint160(arbitrumOFTAddress))));
setPeer — критически важная операция безопасности. Если указать неправильный peer — сообщения будут уходить в неверный контракт или игнорироваться.
OFTAdapter для существующих токенов
Если токен уже существует на одной сети и нужно добавить cross-chain — используется OFTAdapter. Он lock-and-mint: оригинальные токены блокируются в Adapter, в других сетях mintится OFT версия:
import { OFTAdapter } from "@layerzerolabs/oft-evm/contracts/OFTAdapter.sol";
contract MyTokenAdapter is OFTAdapter {
constructor(address _token, address _lzEndpoint, address _owner)
OFTAdapter(_token, _lzEndpoint, _owner) {}
}
На home chain деплоим OFTAdapter, на остальных — обычный OFT. OFTAdapter — единственный custodian.
DVN конфигурация и безопасность
Выбор DVN — ключевое решение безопасности. Конфигурация через ILayerZeroEndpointV2.setConfig:
// Установка required DVN (нужны все) и optional DVN (нужен минимум threshold из них)
const configParams = [{
eid: dstEid,
configType: CONFIG_TYPE_ULN,
config: ethers.AbiCoder.defaultAbiCoder().encode(
['tuple(uint64,uint8,uint8,uint8,address[],address[])'],
[[
0, // confirmations (0 = default)
2, // requiredDVNCount
1, // optionalDVNCount
0, // optionalDVNThreshold
[dvn1, dvn2], // requiredDVNs
[dvn3] // optionalDVNs
]]
)
}]
await endpoint.setConfig(oappAddress, sendLibAddress, configParams)
Минимальная безопасная конфигурация: 2 independent DVN в required. Компромисс одного не ломает систему. Популярный вариант: LayerZero Labs DVN + Google Cloud DVN.
Тестирование и DevTools
Hardhat/Foundry: официальные пакеты @layerzerolabs/devtools-evm-hardhat содержат задачи для wire (setPeer во всех сетях разом), конфигурации DVN, деплоя.
Тестирование в Foundry: TestHelper из @layerzerolabs/test-devtools-evm-foundry позволяет тестировать cross-chain логику локально:
contract OFTTest is TestHelper {
function setUp() public virtual override {
super.setUp();
// Создаёт два endpoint и соединяет их
setUpEndpoints(2, LibraryType.UltraLightNode);
}
}
lzScan — официальный explorer для LayerZero сообщений. При дебаге cross-chain проблем — первый инструмент.
Типичные проблемы интеграции
Insufficient gas on destination — lzReceive реверсируется из-за маленького gas limit в options. Решение: увеличить gas limit в OptionsBuilder, предварительно замерив через тесты.
Unordered delivery — по умолчанию сообщения могут приходить не в порядке отправки. Если важен порядок — использовать ordered delivery опцию (дороже).
Fee estimation — _quote должна вызываться непосредственно перед транзакцией. Fee зависит от gas price на destination и меняется.
Стек и сроки
| Задача | Инструмент |
|---|---|
| Smart contracts | Solidity + OApp/OFT SDK |
| Деплой и wire | Hardhat + lz-devtools |
| DVN конфигурация | LayerZero SDK + Dashboard |
| Тестирование | Foundry + TestHelper |
| Мониторинг | lzScan |
Базовая OFT интеграция (существующий токен + cross-chain transfer): 2-3 недели. Включает контракты, деплой в 2-3 сети, DVN конфигурацию, тесты.
Cross-chain приложение с кастомной messaging логикой, несколькими сетями, UI: 6-8 недель. Аудит рекомендован для OFT с значимой ликвидностью — setPeer конфигурация критична.







