Layerzero:OFT-adapter
OFT-adapter
命令:
npx hardhat lz:oft:send \
--src-eid 40231 \
--dst-eid 40245 \
--amount 1.5 \
--to 0x3ab12b9ff37c21c8c2d92f8f0209d1e04d6b57ee
Src(Arbitrum)
RayERC20(本地 ERC20 资产)
0x7bC68465b92b82dDd89097E1BFABA2F9348404c5
OFTAdapter(把 RayERC20 封装成 OFT的适配器,也就是src)
0x1137ef9869DEc71FCa947cd9D8d7606bF05690d6
Dst(Base)
OFT(OApp_dst)
0x790E5667A1bC449803E68e827b60919859d75546
①:Src(Arbitrum):OFTAdapter 发 message + assignJob + 付款
1. 跨链转账
OFTAdapter.sendFrom里面:RayERC20余额:- 用户的
RayERC20从msg.sender转到OFTAdapter(lock 模式)
- 用户的
- message 并调用
Endpoint:
2. EndpointV2.send / _send:对这笔 OFT 转账生成 Packet
EndpointV2.send:_sender是OFTAdapter:_outbound(OFTAdapter, 40245, receiver=OFT_on_base):- 给
OFTAdapter → Base(OFT)这条路径分配一个新的 nonce;
- 给
- encode Packet:
- message 里其实就是这次跨链转账的业务数据:
(to, amount); guid是这笔跨链转账的“全局 ID”,后面 dst 链执行时要用;
- message 里其实就是这次跨链转账的业务数据:
- 找到
SendLib(SendUln302),调用:ISendLib(sendLib).send(packet, options, payInLzToken);
3. SendUln302.send:给 Executor/DVN assign“这笔 OFT 转账” + 计算gas fee
_payWorkers:- 针对这笔 OFT 跨链转账:
- 按
calldata长度 + dst 链 gas 情况,给Executor算 fee; - 按
confirmations+quorum,给DVN算 fee; - 这里 message 只是包含
to+amount的 payload。
_payTreasury:- 额外抽一部分协议费(LayerZero fee)。
在干嘛:
“给 Base 链上 OFT 合约的一笔跨链转账”。
- 额外抽一部分协议费(LayerZero fee)。
4. EndpointV2.send:检查用户本次 OFT 桥转账付的钱够不够
_assertMessagingFee确认这笔 OFT 跨链操作提供的native/lzToken足够覆盖:Executor的 gasDVN的 gasTreasury的协议费
_payNative/_payToken真正把钱存进SendLib的 fee 账本
至此,在 src 链的工作完成:- 用户已经被扣了
RayERC20(lock); - 对应的一条 LayerZero message 已经生成、assignjob、payworkers、并 emit
PacketSent。
②:Off-chain:DVN / Executor 监听这笔 OFT 跨链转账
这一条跨链消息,代表一笔 OFT 转账。
DVN Network:
- 监听这条
PacketSent,确认:- 源链交易已经上链、达到
confirmations; packetHeader+payload确实编码了正确的(to, amount);
Executor Network:
- 源链交易已经上链、达到
- 记录这条 OFT 转账消息要在 Base 上执行:
- 它后面会在 Base 调
Endpoint.lzReceive(origin, receiver=OFT, guid, message)
→ message 里就是(to, amount)。
- 它后面会在 Base 调
③:Dst(Base):DVN 验证 + commit → Base Endpoint.verify → _inbound
这一段链路的逻辑不变,只是:
receiver= 在 Base 上部署的OFT合约
0x790E5667A1bC449803E68e827b60919859d75546payloadHash对应的是:abi.encodePacked(guid, abi.encode(to, amount))最后:
Base 链上的Endpoint把这条 OFT 转账消息的payloadHash写进:inboundPayloadHash[OFT][ArbitrumEid][OFTAdapter][nonce] = payloadHash;也就是:
“从 Arbitrum 上OFTAdapter来的 OFT 跨链转账”已经进到 Base 上的 message channel,等待 Executor 执行。
④:Dst(Base):Executor.lzReceive → _clearPayload → OFT.lzReceive / _credit
4. Executor 在 Base 调 Endpoint.lzReceive
- Executor 拿到 src 侧的
encodedPacket,解出:origin = { srcEid = 40231, sender = OFTAdapter, nonce }guidmessage = abi.encode(to, amount)extraData = executorOptions编出来的执行配置
- 在 Base 上调用:
endpoint.lzReceive(origin, OFT, guid, message, extraData);
5. Endpoint.lzReceive / _clearPayload
- 验证这条消息的
(guid, message)的哈希 ==inboundPayloadHash[OFT][ArbEid][OFTAdapter][nonce] - 更新
lazyInboundNonce - 删除
payloadHash,防止这笔 OFT 转账被执行两次
6. OFT 合约的 lzReceive / _lzReceive:在 Base 上 mint OFT
OFT._mint(to, amount)
表示:“在src已经锁住了 RayERC20,现在在 Base 链上给对应地址发放同额度的 OFT。”
版权声明
本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。
区块链技术网
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。