技术|手动构造 Gnosis 多签交易

如何手动构造Gnosis 多签交易

<img src="https://i.loli.net/2021/11/01/aD2SxfHTKmeYgNl.png" alt="image-20211101153746205" style="zoom:80%;" />

出品:DODO Research

作者:Owen Liu

编辑:Mark Wang

背景

DODO 当前在以太坊主网以及 BSC 使用了Gnosis Safe 智能合约钱包当做平台主要合约的 owner。Gnosis Safe 的多重签名功能允许我们方便的定义合约管理员列表,以及设定交易需要的管理员确认阈值。一旦一笔交易收集了超过阈值数量的确认,即可执行多签交易。

DODO 之所以使用该服务,是为了避免单一EOA(externally owned accounts:使用传统密钥对的以太坊外部账户)因丢失私钥控制,而导致账户资金损失以及平台合约权限被滥用的单点故障。

Gnosis Safe 提供了网页界面,我们可以方便的进行多签操作。但与此同时,该网页界面背后有着后端服务,用于索引与追踪多签账户下所有交易的事件以及待上链交易的链下签署信息。对于依赖 Gnosis 的项目方来说,当后端服务不可用时,这无疑也会阻塞多签交易的执行,进而影响正常业务进展。所以为了规避这个问题,我们尝试不依赖任何服务,采用最原始底层的方式,即手动构造多签交易,以保证 DODO 平台多签交易安全执行,无任何单点服务的故障。

多签交易长什么样子?

首先,我们需要知道一个可上链执行的多签交易长什么样子,明确需要手动构造哪些内容。通过区块链浏览器,我们可以很容易的拿到多签交易的 Input Data。如下为样例:

image-20211101153837961

以上 Input Data 按照 ABI (Application Binary Interface)编码方式进行了拆解,阅读起来会更友好一些。而有关ABI的定义,是了解多签交易构造需要掌握的。ABI 作为任何执行合约交易采用的标准编码方式,基本的组成包括Input Data中前四字节的函数选择器的哈希值,之后的编码将会以32字节为单位,进行划分。主要是执行合约函数涉及到的参数编码,参数按照函数的定义有序排列。同时根据参数类型,需要区分静态和动态类型。静态类型会被直接编码,动态类型则会被单独分配位置进行编码。具体的细节可以参考链接: https://docs.soliditylang.org/en/develop/abi-spec.html

因为ABI 的编码方式与交互的合约函数有关,因此查看 Gnosis Safe的合约函数定义,我们可以标记出 Input Data 各个位置的数值代表的意义。正如上 Input Data 注释中标注出来的结论,我们需要的信息包括如下:

  • 多签交易调用的合约地址
  • 多签交易的value值 (转ETH or 向合约充入ETH 非零,其他情况为零)
  • 多签交易的Input Data
  • 链下收集足够的管理员signatures

根据具体的多签交易,我们可以很容易的确定前三个信息,而如何链下收集管理员signatures,需要继续摸索。

如何链下签署多签交易?

实施签名需要两部分,待签名的数据以及实施签名的账户。而如何确定待签名的数据,我们可以通过查看Gnosis Safe的合约源码中对签名数据验证的部分作为突破口。通过区块链浏览器查看多签账户的合约代码,发现其是一个Proxy合约,这是一种智能合约常用的设计模式,在这个模式下,实现了Storage 与 Logic的分离,Proxy 合约保存全部的合约状态,而合约的业务逻辑全部被代理至逻辑合约。

这种模式可以降低部署代码的成本,仅部署短小的 Proxy 合约即可;同时降低了代码重复率,因为所有 Gnosis Safe 下的多签合约逻辑均是相同的,可以共用。具体的细节可以参考链接:https://blog.openzeppelin.com/proxy-patterns/

image-20211101153924190

了解了 Proxy 的模式后,我们需要找到背后的 Logic 合约地址来查看业务源码,通过 Proxy 代理合约的构造函数,可以看到 Logic 合约地址是构造函数的唯一参数,因此可以通过创建 Proxy 的交易 Input Data 中拿到 Logic 的地址。通过验证签名的代码逻辑,我们可以追溯到 getTransactionHash 函数,这个函数通过输入多签交易的原始内容后,会返回 messageHash,这正是我们需要的待签名数据。

调用合约的只读函数,可以到区块链浏览器的 Read Contract 下找到具体的函数,直接输入参数调用,但是因为多签合约是 Proxy 合约,目前除了 Etherscan提供了 Read as Proxy 的功能外,Bscscan 上的多签合约还没有办法直接调用 Logic 合约的函数。因此我们可以到 myetherwallet 中,通过多签 Proxy 地址以及 Logic 合约的 abi,去实例化合约,即可看到 getTransactionHash 方法。

<img src="https://i.loli.net/2021/11/01/eAahRtuZI1OmJv9.png" alt="image-20211101154004833" style="zoom:67%;" />

传入的参数与文章开头解析多签交易 ABI 的字段一一对应, 最后的 _nonce,是多签合约发起交易的数量累加值,可以通过调用多签合约的 nonce 方法直接读取到。

image-20211101154041575

当拿到待签名的数据后,我们需要多签合约的管理员列表中的账户去实施签名,签署 messageHash 可以尝试 web3.js 中 web3.eth.accounts.sign。

image-20211101154056334

或者直接使用 myetherwallet 的可视化功能,这样不需要编写脚本,可以直接在界面操作。

<img src="https://i.loli.net/2021/11/01/5iq8kXF1YM6U7Kw.png" alt="image-20211101154119863" style="zoom:57%;" />

签名采用的是 ECDSA 签名算法,返回值 signature 可以分为三个部分:r + s + v。其中前 0~32 个字节为 r, 32-64之间的字节为 s, 65 字节为 v,v 的值是 27(16进制 1b)或者 28(16进制 1c)。但需要注意的是,我们通过以上两种方式签出来的内容,带有 "\x19Ethereum Signed Message:\n32" (32 是 messageHash 的长度)前缀信息。而 Gnosis 的合约,在这种情况下,通过对 v 值做了额外逻辑的判断,即我们需要将 v 值手动加 4,这样就变为了 31 (16进制 1f )或者 32 ( 16 进制 20) 来修改 signature。这个手动修改仅仅是为了进入判断分支内,在合约验证的时候会将 v 值增加的 4 减掉。

image-20211101154146998

简单来说,通过多签合约管理员列表的账户对 getTransactionHash 函数返回的 messageHash 进行签署,合约会根据签署后的 signature 以及 messageHash,计算出签名的公钥地址是否与实施签名的账户一致,来完成签名验证。

最后的组装拼接

最后,我们需要收集足够的链下签名,若多签合约设置的阈值为 3,则需要收集 2 个链下签名,另外一个由发起多签交易的账户在链上执行过程即可被验证确认。因为涉及到多个独立的 signature 以及执行账户的确认信息,如何将这些信息汇总拼接,将是手动构造 Gnosis Safe 的最后一个步骤。因此回溯到合约代码,可以看到如下的逻辑:

image-20211101154227384

按照多签合约管理员列表的公钥地址从小到大排序,signature 对应的是 65 字节,而发起多签账户的确认信息同样是 65 字节,组成方式是 0-32 字节为公钥地址(需要0补齐),32-64 为全零,最后一个字节为 01,01 代表确认。最后列举阈值为2,收集 1 个链下签名所拼接的 signatures 样例:

image-20211101154246280

如上我们手动构造了达到阈值数量的 signatures,结合文章开头 ABI 前半部分的多签交易具体请求与配置信息、前四个字节的函数哈希值组装拼接,即完成了整个手动构造的过程。

以上是我们日常工作中遇到问题的简单记录,为了规避因为多签服务阻塞造成业务的"单点故障",手动构造交易的办法是应急方案。当然这不是唯一办法,开发者也可以自己本地搭建 Gnosis 后端服务等。

参考资料

免责声明

本研究报告内的信息均来自公开披露资料,且本文中的观点仅作为研究目的,并不代表任何投资意见。报告中出具的观点和预测仅为出具日的分析和判断,不具备永久有效性。

版权声明

未经 DODO 研究院授权,任何人不得擅自使用(包括但不限于复制、传播、展示、镜像、上载、下载、转载、摘编等)或许可他人使用上述知识产权的。已经授权使用作品的,应在授权范围内使用,并注明作者来源。否则,将依法追究其法律责任。

关于我们

「DODO 研究院」由一群「DODO 研究员」提供靠谱、深度的研究。以鲜明观点和数据洞察,解码加密世界,发现未来价值。「DODO 」是一个由主动做市商(PMM)算法驱动的去中心化交易平台,旨在为流动性消费者提供最好的交易体验,为流动性创造者提供最好的生产工具。

更多信息

Official Website: https://dodoex.io/

FAQhttps://dodoex.github.io/docs/docs/

GitHub: https://github.com/DODOEX

Telegram: [t.me/dodoex_official]()

Twitter: https://twitter.com/BreederDodo

Reddit: https://www.reddit.com/r/DodoEx/

Discordhttps://discord.gg/tyKReUK

本文首发于:https://mp.weixin.qq.com/s/qgbTnchCHup24ANprGXH5Q

<img src="https://i.loli.net/2021/11/01/aflv3ogsWNS94MH.png" alt="image-20211101154457509" style="zoom:67%;" />

点赞 1
收藏 6
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

1 条评论

请先 登录 后评论
DODO研究院
DODO研究院
江湖只有他的大名,没有他的介绍。