AAVE跨链治理的技术细节

缘由

AAVE 最近通过了一项更新利率的治理，结果却把 Polygon 上 BTC ETH USDT MATIC 的池子给冻结了，影响 1.1 亿美元的资金，详情可见：BlockSec 推文 ，技术分析，官方声明

官方宣称只能通过治理投票的方式进行修复，必须等待至少 7 天，也不打算使用 emergencyAdmin 权限

所以自然地就好奇 AAVE 的跨链治理是怎么做的？技术上又是如何实现的？真的必须等待 7 天嘛？

提案从提出到执行的全流程

以本次出问题的这次提案 224 为例，看看这个提案的整个时间线

1. 2023/4/22 论坛讨论

https://governance.aave.com/t/arfc-aave-v2-interest-rate-curve-recommendations-from-gauntlet-2023-04-21/

2. 2023/4/29~2023/5/6 Snapshot 链下投票

2023/4/29 开始，2023/5/6 结束

共计 15854 人参与投票，574K AAVE 赞同 (99.93%)

https://snapshot.org/#/aave.eth/proposal/0x65b77de92c88a6046a9179abe8e67d5c0e9e4203eace4425aac215dbb7d5a885

3. 2023/5/10 Payload 合约部署

本次提案同时修改了 ETH 链和 Polygon 链的利率模型

2023/5/10 部署 ETH 上 Payload 合约 0x24bdacf6bbebaf567123da16cdb79a266597e92b 其中涉及的新的利率合约 例如USDT 的利率合约 在 2023/5/8 部署

2023/5/10 部署 Polygon 上 Payload 合约0xF22c8255eA615b3Da6CA5CF5aeCc8956bfF07Aa8 其中涉及的新的利率合约 例如USDT 的利率合约 在 2023/5/7 部署

4. 2023/5/11 链上提案提出

本次链上提案由多签钱包提出
https://etherscan.io/tx/0x05152e33582d861b7047254680588b249783be8d680936423f91bb90a74717cf#eventlog

提案提出的区块高度为 17240283，投票开始高度 17247483 （相距 7200 个 block），结束高度 17266683（投票期间 19200 个 block）

Executor 为0xEE56e2B3D491590B5b31738cC34d5232F378a8D5 这个 Executor 实际上就是 AAVE 全局的 admin 合约

提案要执行的事情就两个：

使用 delegatecall 执行 ETH 上的 Payload 合约 0x24db...e92b 的execute()

使用 delegatecall 执行 ETH 上的 CrosschainForwarderPolygon 合约 0x158a...d45b 的execute(0xF22C8255EA615B3DA6CA5CF5AECC8956BFF07AA8) 可以看到 Polygon 需要执行的 Payload 合约地址作为参数传入

5. 2023/5/11 ~ 2023/5/15 链上投票

https://app.aave.com/governance/proposal/?proposalId=224

投票通过需要满足的条件们：

Quorum 320K

Differential 80K

一共 11 个地址完成投票，例如aavechan.eth 的投票交易

6. 2023/5/15 ETH 链上等待执行

投票结束后需要调用queue(224) 将提案从投票成功状态转为 Queued 状态：

https://etherscan.io/tx/0x7dbfef2616f1efa17328d4bfe97b7bfd7e72f05d9f413c64a3c934278f54d242

这个交易是 ChainLink Keeper 触发的，然后等待时间到 1684280195 之后可以链上执行

注意到还有一个 grace period 的概念，如果提案可执行但超过 grace period（432000 秒 = 5 天）仍然没有执行则进入 expired 状态，提案就过期不可再执行

7. 2023/5/17 ETH 链上执行

提案执行的交易： https://etherscan.io/tx/0xe0e0ab8f7524f0165e6cb1182db18cf3ffe1c4f7cb57f335b40a322d8026de3f 时间戳 1684284539

也是由 ChainLink Keeper 触发的，由 EthRobotKeeper 负责调用 Goverance 合约的execute(224)

然后交给 Executor.executeTransaction 使用 delegatecall 去调用 payload 合约

还记得 Executor 合约就是全局 admin 嘛？所以通过这种方式就能执行任意操作了

ETH 上的执行的消息怎么传递到 Polygon 上来执行呢？这就要用到 Polygon 官方桥了

CrosschainForwarderPolygon 会被 Executor 以 delegatecall 的方式调用，来调用 Polygon 官方桥 FX_ROOT_ADDRESS = 0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2 ，将消息传递给 Polygon 目标合约 POLYGON_BRIDGE_EXECUTOR = 0xdc9A35B16DB4e126cFeDC41322b3a36454B1F772

所以在 Polygon 官方桥看来消息的发送者还是 Executor 的地址 0xee56...a8d5 这个 admin 地址

Polygon 官方桥合约在收到这个调用之后就会发出StateSynced(counter, receiver, data)事件，其中 counter 是全局递增计数器，receiver 是固定的 fxChild，data 是(msg.sender, _receiver, _data)的 abi 编码，这里的实例是：

对其中的 data 进行 abi 解码可以得到：

Copy
msg.sender = 0xee56e2b3d491590b5b31738cc34d5232f378a8d5
receiver = 0xdc9a35b16db4e126cfedc41322b3a36454b1f772
data = 00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f22c8255ea615b3da6ca5cf5aecc8956bff07aa800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000009657865637574652829000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001

这么长的 data 是干啥的呢

8. 2023/5/17 Polygon 链上接收消息

Polygon 官方桥会以0x0000000000000000000000000000000000001001 地址的身份调用 FxChild 合约 0x8397259c983751DAf40400790063935a11afa28a，进而调用到 receiver 的processMessageFromRoot(stateId, rootMessageSender, data)函数

https://polygonscan.com/tx/0x52ed6243fc44b0b3999685020ca4b7b42c2629582194789a25792c044743dd59

这个交易是 Polygon 系统交易 所以 sender 和 to 都是 0 地址 而且同时包含其他不相关的跨链交易

时间戳 1684285952 可以看到这个跨链消息传递用了 23 分钟 还是挺快的

收到消息后就进入了 receiver PolygonBridgeExecutor 0xdc9a...f772 的 processMessageFromRoot 函数了，这个函数会校验 msg.sender 必须是跨链桥 FxChild，消息的来源必须是_fxRootSender 也就是 ETH 上的 admin 合约

可以看到 data 实际上是 targets, values, signatures, alldatas, withDelegates 这五个数组的 abi 编码，所以我们解码一下就能得到：

Copy
targets: (('0xf22c8255ea615b3da6ca5cf5aecc8956bff07aa8',)
values: (0,)
signatures: ('execute()',)
calldatas: (b'',)
withDelegatecalls: (True,)

这里的 targets 也就是 Payload 合约咯

收到消息后并不会立刻执行 还有一个 Delay 等待期 172800=2 天，同样地也有一个 3 天的 GracePeriod

9. 2023/5/19 Polygon 链上执行

https://polygonscan.com/tx/0x6172ae452fb2c6abab7aef013e33cf899e3de09e4933433eeeae5fa41be46457

也是由 ChainLink Keepr 负责触发，使得 PolygonBridgeExecutor 以 delegatecall 的方式执行 payload 合约 完成参数变更

所以可见整个流程确实需要 7 天：

Considering governance times, if approved, the fix will be applied in approximately 7 days from now:

1 day of delay to start voting,

3 days of voting,

1 day of timelock on Ethereum

and 2 extra days of timelock on Polygon.