​跨链消息调用:可重试票据



​跨链消息调用:可重试票据插图1Arbitrum 协议拥有在 L1 和 L2 之间传递消息的能力,可以将资产从以太坊无信任地移动到 Arbitrum 链并返回。原则上可以桥接任何资产类型和跨链调用类型,包括以太币、ERC20 代币、ERC-721 代币、跨链消息调用等。本文将主要介绍从 L1 到 L2 跨链调用的秘密武器:可重试票据。

普通消息跨链

L1 合约可以通过调用 EthBridge 来发送 L2 交易。该 L2 交易将在 与 L1 调用时相同的以太坊块和时间戳进行(这并不代表该交易会马上更新进 L2,因为该交易是被放入慢盒之中,慢盒交易将在几个区块后执行并入 L2 状态),通过这种操作虽然可以使交易及时并入慢盒,但 L1 调用者将无法看到 L2 交易的任何结果。

这种方法的优点是简单,延迟相对较低。与我们将很快描述的另一种方法相比,缺点是如果 L1 调用者没有正确获得 L2 gas price 和正确的 gas cost,则 L2 交易很可能被拒绝。由于 L1 调用方无法看到其 L2 事务的结果,因此不能绝对确定其对 L2 的调用会成功。

这将为某些类型的 L1 到 L2 交互引入一个严重的问题。假设有一个交易,其中用户在 L1 上存入一笔资金,以便在 L2 上的某个地址处可用。如果 L1 端成功,但 L2 端被拒绝,则用户向 L1 inbox合约发送的这些代币在 L2 或 L1 上都无法恢复。显然这并不是一个好的方法。

可重试票据交易

不过,我们有另一种用于 L1 到 L2 调用的方法,它使用基于票证的系统,如若发生与gas 相关的故障时该系统会更加稳健。该系统的大体构架为:  L1 合约可以提交一个“预先打包”的交易,并立即收到一个 “ticketID” 来标识该提交。之后,任何人都可以在 L2 调用一个特殊的预编译合约,提供票证 ID,尝试兑换票证并执行交易(即:该票证会写明l2执行对象及传入参数)。

预先打包的交易包括发送方地址、目的地址、调用值(callvalue)和调用数据。所有这些都将被保存,调用值(callvalue)将从发送者的账户中扣除并(逻辑上)附加到预先打包的交易中。

如果兑换成功,则交易完成,并为其开具收据,取消 ticketID,使得其无法再次使用。如果赎回失败,例如因为打包交易失败或目前 gas 过高,则赎回票据失败,但 ticketID 仍可用于以后的赎回。

作为一种选择(以及我们期望的默认设置),原始提交者可以尝试在提交时立即赎回他们提交的交易,并希望这次赎回能够成功。因此,在我们上面的“代币存款”示例中,正常的情况下,只需要用户的单个签名该上述步骤即可完成。如果此此次兑换失败,则其他人可以稍后兑换该票据 ID 。

以这种方式提交交易必须至少带有提交者支付的 ETH (即 submission cost,用于l2储存票据),该价格因交易的数据大小而异。提交后,票据有效期约为一周。如果有人继续支付租金(票据默认保存一周)来维持它的储存,它就会一直有效。如果到期后租金并未继续支付且票据尚未兑换,则其将会被删除。

兑换票证时,它的 msg.sender 将是最初票据生成者的地址,并使用生成者在提交时提供的目的地址、调用值和调用数据来进行 L2 交易。(提交者可以指定一个地址,如果票据过期被销毁,则交易中多余的 callvalue 将退还到该地址。)

这种基于票据的机制比直接从 L1 到 L2 交易要麻烦一些,但它的优点是 submission cost 是可预测的,并且如果一直支付 submission cost,门票将始终可供赎回。只要有一些用户愿意赎回票(并在需要时支付租金),L2 交易最终将能够执行并且不会被丢弃。

如 Function: depositEth 
(uint256 maxSubmissionCost)

其中:maxSubmissionCost:是用户愿意花费的最大 submission cost,该 submission cost 是用于支付 retryable ticket(相当于 L2 的资产赎回票据)储存于 L2 的 retry buffer 中的开销。

​跨链消息调用:可重试票据插图3

创建票据所需参数

该处共有10个参数需要l1来进行传参。

5 of them have to do with allocating ETH/Gas:

其中有5个与 gas 和 eth 分配相关

DepositValue: L1 质押到 L2 的资产数

CallValue: L2 交易的 CallValue,即 msg.value。

GasPrice: L2 的 gas price bid,多余的将会退回 (可通过RPC查询)

MaxGas: L2 的 Gas limit (可通过 _NodeInterface.estimateRetryableTicket 查询)

MaxSubmissionCost: 用于支付票据储存的费用( 该数值可通过 ArbRetryableTx.getSubmissionPrice 查询)

如果用户不需要立即赎回票据,他们只需要支付 CallValue + MaxSubmissionCost,如果需要立即赎回,他们需要支付CallValue + MaxSubmissionCost + (GasPrice x MaxGas)。

其他参数

Destination Address: 目标调用地址

Credit-Back Address(excessFeeRefundAddress): 如果有在执行的过程中,submission cost 和 gas fee 有剩余部分的返还。

Beneficiary(callValueRefundAddress): 如果票据过期未被赎回,且票据中 callvalue > 0,则将对应部分 callvalue 返还。

重载地址

在创建票据的过程中,可能会重载地址,这是因为退款目标地址为合约地址且对应地址没有对应退款函数,则资金将会永久消失,具体可点击查看

可以重试票据的生命周期

当从 L1 发起可重试票据交易时,会发生以下事情:

质押资金(如果有)记入 L2 上的发件人账户。接下来,如果 L2 账户的余额(包括 DepositValue)小于 MaxSubmissionCost + Callvalue,可重试票据将创建失败。

如果 MaxSubmissionCost 小于当前网络中所需的费用费用,则可重试票据创建失败。

  1. Submission fee收取:Submission fee 从发件人的 L2 账户中扣除;如果发送过多,那么多余部分记入 Credit-Back 地址。

  2. 从发送方的 L2 账户中扣除 Callvalue 并成功创建可重试票据。

  3. 如果发送方没有足够的资金来支付 callvalue(即使在存入 DepositValue 之后),Retryable Ticket 也会失败。

  4. 如果 MaxGas 和 MaxPrice 都大于 0,则票据将尝试立即尝试赎回:

  5. MaxGas x MaxPrice 记入 Credit-Back 地址。

  6. 可重试票据是自动执行的——即,tx 中将会用 callvalue 来编码——并且由 Credit-Back Address 来支付 gas。

  7. 如果成功,则发起成功赎回的交易以及票据对应的交易。任何多余的 gas 都会保留在 Credit-Back 地址中。

  8. 如果它被拒绝,则会发出失败的交易,并将可重试票据放在重试缓冲区中,并等待下一次赎回。

任何用户都可以通过调用 ArbRetryableTicket.redeem(RedemptionTxID) 来兑换重试缓冲区中的可重试票据(如果尚未到期),并且用户将以正常 L2 交易的方式提供 gas。

如果可重试票据在赎回之前被取消或到期,Callvalue 将记入Beneficiary。

阅读原文(节选自):L1 to L2 ticket-based transactions and Messaging Between Layers

作  者: Offchain Labs

翻  译: Jason

如何了解更多 Arbtirum 内容

用户或开发者常用链接:

微信公众号:OffchainLabs

Twiiter | Discord | 微  博

使用手册 | 测试币水龙头 | 跨链桥 | 生态版图

Github | 开发者教程 | 英文文档 | 中文文档

聯系郵箱:0xniumao@gmail.com