LayerZero Messaging (Hedera)
OFT pattern: deploy paired Omnichain Fungible Tokens — a standard OFT on the EVM side and an HTS connector OFT on Hedera — then setPeer both ways and send with LayerZero V2 fees.
OFT (EVM) ←setPeer→ HTSConnectorOFT (Hedera)
│ send / quoteSend │ _debit burn / _credit mint (HTS 0x167)
└──────── Endpoint V2 + ULN + DVN + Executor ────────┘
This skill focuses on LayerZero V2 OApp/OFT + Hedera HTS. Educational templates may use simple workers and a manual/UI lzReceive relay — not the same as production LayerZero Labs verification.
Quick Reference
| Concept | Rule |
|---|---|
| Endpoint | ILayerZeroEndpointV2 per chain |
| Peer | setPeer(remoteEid, bytes32(uint256(uint160(remoteOApp)))) on both sides |
| Send | quoteSend(SendParam, payInLzToken) → send{value: nativeFee}(SendParam, fee, refund) |
| Receiver | to in SendParam is bytes32 (padded address) |
| Hedera OFT | HTS-backed connector — create HTS token, burn on send, mint on receive |
| HTS fee | Deploy connector with native value to pay createFungibleToken |
| Approval | User must approve(connector, amount) on the HTS token before Hedera → EVM send |
| IDs | Use LayerZero EIDs in peers/dstEid — not EVM chain IDs |
See references/hedera-endpoints.md for where to source Endpoint/ULN/DVN addresses. See references/examples.md for wire and send sketches.
Critical: Wire Both Directions
Incomplete peer config bricks the pathway. For each local OApp:
setPeer(remoteEid, remoteOAppAsBytes32)setSendLibrary/setReceiveLibrary(ULN302)setConfig— ExecutorConfig (type1) on send lib; UlnConfig (type2) on send + receive libssetEnforcedOptions— e.g.lzReceivegas for msgType1(token send)
Verify with peers(remoteEid) on both chains before sending.
Critical: Hedera HTS Connector Semantics
On Hedera, do not use a plain ERC-20 OFT as the primary path. Use an HTS-backed connector:
- Constructor creates fungible HTS via precompile
0x167(supply key = connector) _debit: transfer HTS in → burn_credit: mint → transfer HTS out- Amounts must fit
int64for HTS mint/burn/transfer - Associate the receiver account with the HTS token before EVM → Hedera receives
// Deploy with value so createFungibleToken fee is paid
new HTSConnectorOFT{ value: htsCreateValue }(name, symbol, lzEndpoint, owner);
Send Flow
SendParam memory sendParam = SendParam({
dstEid: remoteEid,
to: bytes32(uint256(uint160(receiver))),
amountLD: amountLD,
minAmountLD: (amountLD * 9) / 10,
extraOptions: OptionsBuilder.newOptions().addExecutorLzReceiveOption(lzReceiveGas, 0),
composeMsg: "",
oftCmd: ""
});
MessagingFee memory fee = IOFT(localOFT).quoteSend(sendParam, false);
IOFT(localOFT).send{ value: fee.nativeFee }(sendParam, fee, payable(refundTo));
Hedera → EVM note: forge fee simulation can disagree with Hedera JSON-RPC wei/tinybar scaling — often quote via cast + scaled native fee for that direction.
Deploy Checklist (generic)
- Deploy EVM
OFT(optional premint) - Deploy Hedera HTS connector OFT with HTS create value
- Deploy workers (Labs DVN/executor or educational simple workers)
- Wire both OApps (
setPeer+ libraries + config + enforced options) - Associate Hedera account with
htsTokenAddress() - Sync frontend config if applicable; fund relay key if using UI auto-relay
- Send small amount; track on LayerZero Scan (testnet/mainnet as appropriate)
Educational Relay
Some templates use simple DVN/executor mocks and an explicit lzReceive relay step. Treat that as a learning aid — production apps rely on LayerZero’s verification network, not a custom relayer key in the app server.
Checklist
- Peers set both ways with correct EIDs (not EVM chain IDs)
- Send/receive libraries + ULN/executor config applied
- Hedera side is HTS connector; create fee paid; supply key is connector
- Receiver associated with HTS token before inbound transfers
-
quoteSendnative fee attached tosend - Receiver address encoded as
bytes32 - Educational disclaimer: not audited / not for mainnet funds
References
- references/examples.md — OFT, HTS connector, wire, send
- references/hedera-endpoints.md — EIDs vs chain IDs, where to source addresses
- LayerZero V2 docs
- LayerZero deployments metadata