Rollup Bridge 介绍(五):Hop Protocol 第二部
来源:    发布时间: 2023-12-28 16:54   46 次浏览   大小:  16px  14px  12px
本篇是 Rollup Bridge 介绍的第五篇,主要用来补充第二篇 Hop Prot​ocol 第一部分的运作细节,建议先从第二篇看起:

本篇是 Rollup Bridge 介绍的第五篇,主要用来补充第二篇 Hop Protocol 第一部分的运作细节,建议先从第二篇看起:

  • 以下所称的 L2 皆指 Rollup 而非 Plasma 或侧链

  • 以下所称「资产」和「代币」两个词指的是一样的东西

  • 以下所称「七天」和「Rollup 挑战期」两个词指的是一样的东西

  • 以下示意图中 Arbitrum 会是 Rollup A,Optimism 会是 Rollup B,使用者要将资产从 Rollup A 跨到 Rollup B

  • Hop Protocol 第一部分中用 fast transfer 代指跨 Rollup 的 transfer,来和第一篇 Maker Bridge 的 fast withdraw(回 L1)做区隔,不过本文会用 transfer/withdraw 代指一样的事情

Recap: Relay transfer 资料

为什么要 relay transfer 资料?

因为 transfer 资料是客观的资料,Hop 合约不能随便相信流动性提供者(Bonder) 说他替谁先垫付了某笔 transfer 就拨款给 Bonder,Hop 合约只会认 transfer 资料来确认实际上 transfer 是否发生,所以 Hop 合约只有等到 transfer 资料真的抵达 Rollup B 时才会拨款给 Bonder。

对使用者来说,如果 Bonder 帮他垫付了,则他完全不需担心 transfer 资料的 relay 过程(毕竟他已经在 Rollup B 收到代币了)。但如果 Bonder 下线了,使用者就要自己把 transfer 资料 relay 到 Rollup B 来向 Hop 合约证明并取回自己应得的代币。

注:Hop 把 transfer 资料从 Rollup 送到 L1 的过程叫做 commit。

Recap: Batch Transfer(批量处理)

Hop Protocol 第一部分有提到为了节省 Bonder 的成本,Hop 设计让 transfer 可以以 batch 的方式一次 commit 回 L1,不需每一笔都 commit 一次。而 batch 的条件分别是 (1) 累积 512 笔 transfer 或 (2) 离上一次该 Bonder commit 的时间已经过了一天。

注 1:条件 (2) 是为了在不打扰 Bonder 前提下让使用者能够自己完成 relay 的条件:当 Bonder 下线太久时,使用者可以自己把 transfer 资料 commit 到 L1,再 relay 到 Rollup B。

注 2: Bonder 自己来 commit 时可以不受 (1) 限制,不管累积几笔 transfer,随时都可以 commit。

而 batch transfer 也不会真的把 batch 里面所有 transfer 资料都 commit 进去,而是把 transfer 资料组成一个 Merkle Tree,然后只 commit Merkle Root。当要使用到 transfer 资料时,再提供 Merkle Proof 来证明 transfer 存在于该 Merkle Tree 里。

注:实际上 commit 的函式名称为 commitTransferRoot 。这里看到 Hop 用的是 transfer 的字眼,而待会可以看到在 Rollup B 上的操作 Hop 会用 withdraw,但其实两个指的是一样的。

接下来会搭配图示介绍使用者和 Bonder 的操作流程及 challenge 机制。

使用者视角的运作流程

对使用者来说,使用 Hop 会有两种结果:(一) Bonder 为你在 Rollup B 上垫付,或是 (二) Bonder 没有垫付,导致使用者必须自己完成把 transfer 资料从 Rollup A relay 到 Rollup B 的旅程。

结果一:Bonder 有垫付

Happy case:Bonder 完成垫付

1st Tx

使用者发起 withdraw,他有两个选择:如果使用者有 hUSDT,则他直接触发 L2_Bridge 合约的 send 函式(Opt 2);如果他没有 hUSDT,则触发 AMM_Wrapper 合约的 swapAndSend 函式,先用 USDT 去换成 hUSDT(Opt 1)。L2_Bridge 合约会销毁 hToken(也就是 hUSDT),表示资产从 Rollup A 离开,并 emit(发出)event,让 Bonder 知道。

2nd Tx

接着 Bonder 执行垫付,如果使用者要收 hUSDT,则合约会直接铸造 hUSDT 给使用者,如果使用者要收 USDT,则会多一步,把铸造的 hUSDT 去换成 USDT 再给使用者。

结果二:Bonder 没有垫付

Unhappy case: 使用者要自己 relay transfer(i.e., withdraw)资料到 Rollup B 来领取资产

这边的步骤是接续在使用者已经透过 L2_Bridge 合约申请 withdraw 并销毁 hToken 之后。

1st Tx

如果使用者的 withdraw 刚好是第 512 笔 withdraw,则会直接触发 commitTransferRoot 函式,将 TransferRoot 送到 L1(那就不需要 1st Tx)。

如果不是的话,则他需要等到离 Bonder 上次 commit 时间的一天后才能自己去执行 commitTransfer,commitTransfer 会去触发 commitTransferRoot 函式,将 TransferRoot 送到 L1。

2nd Tx

接着就要等到 Rollup A 的挑战期过后,才能完成 TransferRoot 到 L1 的写入。假设今天该 TransferRoot 已经经过了七天挑战期,则任何人都可以去把 TransferRoot 的跨链讯息 relay 到 L1_Bridge 合约,这笔交易会同时把 TransferRoot relay 到 Rollup B。

3rd Tx

通常等个五到十分钟,TransferRoot 就会被 relay 到 Rollup B 上的 L2_Bridge 合约。等到 TransferRoot 被写进 L2_Bridge 合约后,使用者就可以触发合约的 withdraw 函式,提供 Merkle Proof 去证明自己的 withdraw 存在在这个 Merkle Tree 里,这时合约就会直接铸造 hUSDT 给使用者,完成 withdraw。

Bonder 视角的运作流程

第一步:流动性提供者先垫付

第一步是 Bonder 发现使用者在 Rollup A 上申请 withdraw (1st Tx)后,他在 Rollup B 去触发 bondWithdrawalAndDistribute 函式(2nd Tx),垫付给使用者(看使用者是要收 USDT 或 hUSDT)。

你可能会以为垫付是 Bonder 将自己的 hToken 转给使用者。但实际上的过程是:合约会铸造新的 hToken 给使用者,然后在合约的帐本上记录下该 Bonder 因为这笔垫付所新增的负债。

第二步:等待 TransferRoot 被 commit

Bonder 可以等待凑满 512 个 withdraw 再开始 relay withdraw 资料。或是提前去 Rollup A 的L2_Bridge 合约触发 commitTransfer,开始 relay withdraw 资料。当 Bonder 在 Rollup B 的负债多到他没办法再垫付后,他就可能会提前去触发 commitTransfer。

第三步:在 TransferRoot 被写进 L1_Bridge 合约前,先为该 TransferRoot 做担保

因为等待 Rollup A 挑战期结束才能 relay TransferRoot 的时间可能太久了,会影响 Bonder 的资本效率(Bonder 在 Rollup B 上的负债要等到 TransferRoot 抵达才能抵销),所以 Hop 做了一个 trade-off:引入一个 challenge 机制。

Bonder 可以为自己的 TransferRoot 担保:不需要等到 Rollup A 挑战期结束并把 TransferRoot 写入 L1_Bridge 合约,就可以直接去触发 bondTransferRoot(1st Tx),把 TransferRoot relay 到 L2 的合约。等待五到十分钟 TransferRoot 写进 L2_Bridge 合约后,Bonder 就可以触发 settleBondedWithdrawal(2nd Tx),将之前垫付所累积的负债抵销。

Bonder 在执行 bondTransferRoot时要顺便抵押 TransferRoot总金额的 110%(10% 是当作 challenge 的奖金)。因此当一个 Bonder 担保一个假的 TransferRoot,意图在 Rollup B 抵销负债被抓到时,他在 L1 会被没收的金额会是他在 Rollup B 抵销负债金额的 110%(也就是会赔 10%),所以想要造假是有风险在的。

注:TransferRoot 总金额指的是这一批 withdraw 金额的加总。

但如同其他 challenge 机制,challenge 也是有时效性的。目前如果 Bonder 触发 bondTransferRoot 后,经过一小时都没有人 challenge 的话,则该 TransferRoot 就会被视为合法,不能再被 challenge。

第四步(optional):Bonder 完成 TransferRoot 的 relay,将 TransferRoot 写进 L1_Bridge 合约

等到 Rollup A 挑战期过后,Bonder 就可以将 TransferRoot 的跨链讯息 relay 到 L1_Bridge 合约。但如果 Bonder 没有被 challenge 的话,其实他没有动机要完成 relay。不过只要 Bonder 担保的是正确的 TransferRoot 或是 Bonder 造假 TransferRoot 都有被抓到的话,没有完成 TransferRoot relay 不会影响系统的安全性。

当 TransferRoot 被 challenge

第一步:bondTransferRoot

首先,从 Bonder bondTransferRoot 开始。

第二步:challenger 抵押 TransferRoot 总金额 10% 来挑战 TransferRoot

如果 challenger 发现 Bonder 产生的 TransferRoot 不合法,例如里面偷偷夹带了不存在的 withdraw,则 challenger 可以透过抵押 TransferRoot 总金额的 10% 来进行 challenge(要在 bondTransferRoot 的一小时内进行 challenge)。

Challenge 被申请后,L1_Bridge 合约会把 Bonder 担保的金额(TransferRoot 总金额的 110%)新增到 Bonder 的负债。

注:如果没有被 challenge,系统就会放行,不以增加 Bonder 负债的方式来扣住 Bonder 资产。

如果 challenge 成功,则负债会保留,表示 Bonder 的钱被系统没收;如果 challenge 失败,系统会从 Bonder 负债中减去原本担保的金额,表示系统将钱还给 Bonder。

第三步:等待 Rollup A 挑战期结束,将真正的 TransferRoot 写进 L1_Bridge 合约

等到 Rollup A 挑战期过后,Bonder 或 Challenger 就可以将 TransferRoot relay 到 L1_Bridge 合约。但还不能 resolve challenge,Hop 有设定一个 challengeResolutionPeriod 来确保 challenge 可以 resolve 时,Rollup 挑战期已经结束,意即确保 TransferRoot 已经被写入 L1_Bridge 合约里了。

注:目前 challengeResolutionPeriod 是十天(要大于挑战期)。

第四步:等待 challengeResolutionPeriod 结束

真正的 TransferRoot 讯息抵达后就可以验证 Bonder 当初担保的 TransferRoot 是不是对的,决定 challenge 是否成立。

如果 challenge 不成立,系统会从 Bonder 负债中减去原本担保的金额,表示系统将钱还给 Bonder。而 Challenger 的抵押则会被没收。

如果 challenge 成立,则 Bonder 的负债会保留,表示 Bonder 的钱被系统没收。Challenger 除了拿回自己的押金,还会获得 Bonder 担保金额当作 challenge 奖金的那 10%。

注:奖金其中有一半会被销毁,目的是避免 Bonder 自己 challenge 自己,同时拿回完整的押金和奖金。

风险评估

使用者风险

如果 Bonder 有垫付给使用者,则使用者成功完成 withdraw,皆大欢喜。

如果 Bonder 没有垫付给使用者,则使用者必须要自行完成 TransferRoot 的 relay,这会需要讯息能够正确地从 Rollup A -> L1 -> Rollup B 传递。

不过只要 Hop 合约和 Rollup L1<->L2 messege bridge 都有顺利接上,且 Rollup 都正常运作,就能够达成,这是一个相对可靠的安全假设。所以对使用者来说,风险是相对小很多的。

Bonder 风险

因为 Bonder 们的钱都锁在同一个合约,所以假设有 challenge 没被抓到,则代表攻击者可以凭空降低自己的负债、提走不该提走的钱,这对所有 Bonder 都会造成损失(但使用者不会被影响)。

而目前一小时的 challenge window 其实是相对短暂的,再加上一个 withdraw 可以是从任意  Rollup 转任意资产到任意其他 Rollup,要假设整个系统内所有的 withdraw 都能被监控会是一个具有挑战性的要求(例如某些 Bonder 可能只会在某些 Rollup 上提供流动性,所以他们可能只会监控那些 Rollup 之间的 withdraw)。