# [教程] Gnosis Safe多签钱包生成靓号地址

By [pan](https://paragraph.com/@pan-3) · 2022-09-14

---

介绍
--

[Gnosis Safe](https://gnosis-safe.io/) 是一款运行在 EVM 兼容链的智能合约钱包 ，它已经支持以下公链：Ethereum、Gnosis Chain、Polygon、BNB Smart Chain、Energy Web Chain、Arbitrum、Aurora、Avalanche、Optimism、Goerli、Rinkeby、Valta。目前大多数用户正在使用单一密钥钱包，如果私钥以任何方式泄露，资金就可能会被盗。而使用 Gnosis Safe 钱包发送交易需要得到最少数量的授权人批准交易，单个私钥的泄露并不会直接威胁到钱包的安全。

使用 Gnosis Safe [官方 APP](https://gnosis-safe.io/app/welcome) 我们可以轻松地创建一个随机地址的多签钱包。多签钱包的用户群体多为团队、公司、项目方等，我认为看起来很酷(比如有大量的连号)钱包地址能够给客户留下的一个深刻的印象，本教程的目的就是教会大家创建一个看起来很酷的多签钱包地址。以太坊的靓号钱包地址我们可以写程序生成大量地址进行碰撞获得，而 Gnosis Safe 多签钱包地址也是使用类似的方法，不同的是 Gnosis Safe 多签钱包是一个智能合约，而智能合约地址有一个确定性的生成规则：`contractAddress = Keccak256(rlp(address, nonce))[12:]` 。

根据这个规则我们可以编写程序生成大量的以太坊账户，然后计算每个账户部署第一个合约（从成本考虑）的地址是否为靓号，如果是靓号就用此账户部署 Gnosis Safe 多签钱包合约。下面我们就从碰撞靓号合约地址开始，一步一步地演示如何生成和部署多签钱包。

碰撞靓号
----

首先我们需要一个拥有靓号合约地址的以太坊账户，我已经使用 golang 语言编写了一个程序用于批量生成以太坊账户以及计算它们的第一个合约地址，项目仓库位于：[fachebot/batch-safe-wallet: 批量生成以太坊多签合约地址 (github.com)](https://github.com/fachebot/batch-safe-wallet)。大家可以拿来直接使用。

首先参考官方文档 [https://go.dev/doc/install](https://go.dev/doc/install) 安装 golang 环境，这里不做过多讲解。然后将仓库 clone 到本地并编译源代码：

    git clone https://github.com/fachebot/batch-safe-wallet.git
    cd batch-safe-wallet
    go build
    

编译完成之后会生成可执行文件 `batch-safe-wallet`，然后执行 `batch-safe-wallet batch` 命令批量生成以太坊账户和合约地址，下面的命令表示生成 100 个 6 个连续相同字符的账户。

    ./batch-safe-wallet batch 1000 6 0
    

当我们生成了足够多的账户时，再执行 `batch-safe-wallet filter` 命令筛选符号条件的账户并打印出来，下面的命令表示筛选合约地址是 6个连续相同字符的账户。

    ./batch-safe-wallet filter contract 6 0
    

控制台将输出所有符合条件的账户地址以及它们部署第一个合约时产生的合约地址和账户私钥：

![](https://storage.googleapis.com/papyrus_images/442b5ab4f7b1df36b75732676c747b4ec986535f6622b272c5366a8baf2de1f3.png)

部署合约
----

如果我们已经获得了一个拥有靓号合约地址的以太坊账户，接下来就可以使用此账户部署 Gnosis Safe 多签钱包合约了。手动部署 Gnosis Safe 多签钱包会涉及到两个合约：[GnosisSafeProxy.sol](https://github.com/safe-global/safe-contracts/blob/main/contracts/proxies/GnosisSafeProxy.sol) 和 [GnosisSafeL2.sol](https://github.com/safe-global/safe-contracts/blob/main/contracts/GnosisSafeL2.sol)。GnosisSafeL2 合约是多签钱包的核心实现，它已经被官方团队提前部署到多条 EVM 兼容链，以下是部署在各个公链的 GnosisSafeL2 合约地址：

    | Network          | Contract                                   |
    | ---------------- | :----------------------------------------- |
    | Ethereum         | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Rinkeby Testnet  | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Goerli Testnet   | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Kovan Testnet    | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Gnosis Chain     | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Energy Web Chain | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Valta            | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Polygon          | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Arbitrum         | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | BNB Smart Chain  | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    | Avalanche        | 0xfb1bffC9d739B8D520DaF37dF666da4C687191EA |
    | Optimism         | 0xfb1bffC9d739B8D520DaF37dF666da4C687191EA |
    | Aurora           | 0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
    

> 参考文档：[safe-transaction-service/setup\_service.py at master · safe-global/safe-transaction-service (github.com)](https://github.com/safe-global/safe-transaction-service/blob/master/safe_transaction_service/history/management/commands/setup_service.py)

GnosisSafeProxy 是一个代理合约，用于存储多签钱包的状态数据，用户通过它以 [delegatecall](https://solidity-by-example.org/delegatecall/) 的方式去执行 GnosisSafeL2 合约的所有函数，GnosisSafeL2 合约负责实现多签钱包的业务逻辑。所以用户部署的 GnosisSafeProxy 合约地址就是 Gnosis Safe 多签钱包的地址，马上我们将会部署一个 GnosisSafeProxy 合约。

### 1\. 导入私钥

在本教程我将用以太坊账户地址 `0x2b8b69eb411847d55e5Af23D55482f469E05c2A9` 作为示例，它部署第一个智能合约地址是 `0x1000000604603803FFa91F16d1dA0dD038a9D7a3`。

![](https://storage.googleapis.com/papyrus_images/b3fbdf3570064dbc8fcc2ad3736b773aaa177236212838fd1ba002c741901161.png)

大家在操作的过程中请将教程中使用的以太坊账户替换为自己的账户，在教程正式开始之前大家还需要依次完成以下事情：

1.  导入账户 `0x2b8b69eb411847d55e5Af23D55482f469E05c2A9` 到 MetaMask钱包；
    
2.  将 MetaMask 钱包网络切换到 Goerli 测试网络；
    
3.  往 `0x2b8b69eb411847d55e5Af23D55482f469E05c2A9` 地址转入一些代币作为部署合约的 GAS 费用。
    

### 2\. 部署多签钱包

首先打开 [http://remix.ethereum.org/](http://remix.ethereum.org/) 网站，这是一款在线的以太坊 Solidity IDE，我们将使用它编译和部署 GnosisSafeProxy.sol 合约。

创建一个新文件，命名为 **GnosisSafeProxy.sol**，然后将 [safe-contracts/GnosisSafeProxy.sol at main · safe-global/safe-contracts (github.com)](https://github.com/safe-global/safe-contracts/blob/main/contracts/proxies/GnosisSafeProxy.sol) 里面的内容拷贝至 **GnosisSafeProxy.sol** 文件。

![](https://storage.googleapis.com/papyrus_images/514c55c572af3ef611274e3b4db36ed4522a2219e2ceddd532ccf00a80101de9.png)

然后点击左边导航栏 **Solidity Compiler** 按钮切换到编译界面，再点击 **Compile GnosisSafeProxy.sol** 按钮编译合约代码。

![](https://storage.googleapis.com/papyrus_images/3f785cb81b3901c0d17a21dc02bbae12ec0e87fe0fc5ed1359464ab06f54c6dc.png)

然后点击左边导航栏 **Deploy & run transactions** 按钮切换到部署界面。点击 **ENVIRNMENT** 下拉选项框选择 **Injected Provider - Metamask**，之后会唤醒 MetaMask 钱包进行确认。

![](https://storage.googleapis.com/papyrus_images/0230208b73c91ba1c5c4a7bade694175ef4f462cfd606fa1a4e884f09acd7b64.png)

接下来在 **Deploy** 按钮旁边的输入框输入 **GnosisSafeL2** 合约的地址（参考前面的表格）：`0x3E5c63644E683549055b9Be8653de26E0B4CD36E`。

![](https://storage.googleapis.com/papyrus_images/dff41b63385ff66fa45742956889d46a92db410a8ee258173a0945895617e68c.png)

最后点击 **Deploy** 按钮部署合约并通过 MetaMask 钱包发送交易。

![](https://storage.googleapis.com/papyrus_images/8d1966e6c51c73b5a79a142ddd3ddb9abbdbfbb46885c1e4e7f46eb53bf8ea61.png)

等待部署合约的交易确认，然后点击左下方的 **Copy** 按钮将刚才部署的合约地址复制到剪贴板查看，和我们预期的一样，合约地址是 `0x1000000604603803FFa91F16d1dA0dD038a9D7a3`。

![](https://storage.googleapis.com/papyrus_images/4a5e768087f9176703182efdc647b48647ce13d7fadd9de8d002c6355eb38823.png)

现在我们已经成功部署了 **GnosisSafeProxy** 合约，并且合约地址和我们预期的一样。接下来还需要初始化合约状态，目的是为了设置多签钱包的 `owners` 账户地址以及发送交易所需的最少授权数量。

### 3\. 初始多签钱包

我们需要通过 **GnosisSafeProxy** 合约以 delegatecall 的方式调用 **GnosisSafeL2** 合约的 `setup` 函数来初始化多签钱包。**GnosisSafeProxy** 合约已经实现了 `fallback()` 函数，它会转发所有交易数据给 **GnosisSafeL2** 合约并返回所有收到的数据。所有我们只需要生成 `setup` 函数的输入参数并发送给 **GnosisSafeProxy** 合约即可。

#### 3.1 生成调用参数

打开 [https://ethtools.github.io/ethtools/#/metamask/contract](https://ethtools.github.io/ethtools/#/metamask/contract) 网站，这是一个在线的以太坊合约测试工具，你只需要提供合约地址和ABI文件，它就可以通过 MetaMask 钱包发起函数的调用。我们先点击右上角红色的 **连接MetaMask** 按钮，然后在合约地址入框输入 **GnosisSafeL2** 合约的地址（参考前面的表格）：`0x3E5c63644E683549055b9Be8653de26E0B4CD36E`。下载 **GnosisSafeL2** 合约的 ABI 文件([batch-safe-wallet/GnosisSafeL2.json at main · fachebot/batch-safe-wallet (github.com)](https://github.com/fachebot/batch-safe-wallet/blob/main/abi/GnosisSafeL2.json)到本地，点击 **打开文件** 按钮选择刚才下载的 ABI 文件。

![](https://storage.googleapis.com/papyrus_images/37a29b38ca7d5e80cd14f92abc1bb5743d3fa86236bce933adcc901b52774a86.png)

然后在函数列表中找到 `setup` 函数，函数签名如下：

        function setup(
            address[] calldata _owners,
            uint256 _threshold,
            address to,
            bytes calldata data,
            address fallbackHandler,
            address paymentToken,
            uint256 payment,
            address payable paymentReceiver
        )
    

*   `_owners` 表示多签钱包的 owner 列表，应当填写自己控制私钥的钱包地址。
    
*   `_threshold` 表示发送交易所需的最少 owner 授权数量，比如设置了 3 个 owners 并且 threshold 为 2，发送交易就需要 2 个 owner 进行授权。
    
*   `to` 忽略，填写 0 地址。
    
*   `data` 忽略，填写 `0x` 空数据。
    
*   `fallbackHandler` 表示处理 fallback 的合约地址。像 ERC721 和 ERC1155 这样的标准要求合约在接收代币时立即做出响应，这里统一填写 Gnosis Safe 官方部署的 [safe-contracts/DefaultCallbackHandler.sol at main · safe-global/safe-contracts (github.com)](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/DefaultCallbackHandler.sol) 合约地址 `0x1AC114C2099aFAf5261731655Dc6c306bFcd4Dbd` 即可。
    
*   `paymentToken` 忽略，填写 0 地址。
    
*   `payment` 忽略，填写 0。
    
*   `paymentReceiver` 忽略，填写 0 地址。
    

![](https://storage.googleapis.com/papyrus_images/0f5ade185a94f5d0101ad619f6323ad6326502a50ef1c5c23610bf54e8be5cef.png)

填写完毕之后点击 **transact** 按钮，它会唤醒 MetaMask 钱包发送交易。这时候我们**不要**发送交易，在 **transact** 按钮旁边会出现一个 **copy** 按钮，点击它复制调用 `setup` 函数的输入参数然后妥善保存，复制的内容格式如下(每个人的内容不一样，请不要复制下面的内容)：

#### 3.1 发送调用合约交易

现在回到之前的部署 **GnosisSafeProxy** 合约的界面，点击左下角 **GNOSISSAFEPROXY AT 0X100..9** 展开界面，在 **CALLDATA** 输入框内输入上面生成的调用数据，然后点击 **Transact** 按钮唤醒 MetaMask 钱包发送交易。

![](https://storage.googleapis.com/papyrus_images/c34c44ac28c36366e6f9b781e4e720a306634c44151463c39000fd549f2c1f0f.png)

之后交易确认后将会初始化多签钱包，我们就可以在任意 Gnosis Safe 的 APP 上导入我们部署的多签钱包了。

加载多签钱包
------

我们已经完成部署和初始化多签钱包合约，合约地址为：`0x1000000604603803FFa91F16d1dA0dD038a9D7a3`，它设有一个 `owner` 并且发送交易只需要一个 `owner` 授权。接下来我们通过 Gnosis Safe 官方 APP 验证是否成功，浏览器打开 [网页端 APP](https://gnosis-safe.io/app/welcome) ，然后将 `owner` 账户的私钥导入到 MetaMask 钱包，点击网页右上方 **Connect Wallet** 按钮连接到 MetaMask 钱包。

![](https://storage.googleapis.com/papyrus_images/6feeabbc19c9103a9d8212cd2d22522fc38d688fa97638d4611b080f9c39375e.png)

然后点击 **Add existing Safe** 按钮导入多签钱包，只需要填写多签钱包的名字和合约地址，名字可以随便填写，地址填写之前部署的 **GnosisSafeProxy** 合约地址。

![](https://storage.googleapis.com/papyrus_images/50b064af1af471b6ecc1ede277dae5472ce18558655ab4c6f94aad1d2ef2830e.png)

后面的步骤中会让你确认多签钱包的信息，我们依次点击 **Next** 、**Add** 和 **Continue** 按钮即可。

![](https://storage.googleapis.com/papyrus_images/55721a64be9101964daa3d4d0459b8116a4f13eeaef4b2a4474576209f6a5093.png)

![](https://storage.googleapis.com/papyrus_images/bb486e69cc0a50e87fb308552569becf4ea5e722a4dbadeb6f41ac060ec00391.png)

![](https://storage.googleapis.com/papyrus_images/443bbda565c8863d9f5be73be02e459d9e3d7073df6981131819bd49649c7bb8.png)

导入成功后进入多签钱包仪表盘，可以看到多签钱包地址是 `0x1000000604603803FFa91F16d1dA0dD038a9D7a3`，和我们预期的一样。在 Safe APP 里面我们不仅可以查看多签钱包的资产、发起交易，还可以重新设置 `owners` 账户列表和最少授权数量。本教程到此结束了， Safe APP 的更多功能留着大家慢慢去探索。

---

*Originally published on [pan](https://paragraph.com/@pan-3/gnosis-safe)*
