工厂模式 - 智能合约如何部署其他合约

本文介绍了智能合约工厂模式,它通过一个智能合约来部署、初始化和跟踪其他合约,实现标准化、可发现性、初始化安全和确定性部署。文章通过一个 Foundry 示例,展示了如何使用工厂合约部署和交互合约,并解释了为什么现代协议几乎都包含工厂模式。

工厂模式——智能合约如何部署其他合约

到目前为止,我们已经了解了合约是如何部署的(CREATE 和 CREATE2),以及如何通过 EIP-1967EIP-1822 等代理进行升级。

但是,大多数实际系统并不会止步于此,它们需要部署多个合约,而不仅仅是一个。

这就是工厂模式的用武之地。

工厂是一个智能合约,它知道如何在链上部署、初始化和跟踪其他合约。 你无需手动部署每个实例,而是调用一次工厂,它会处理所有事情:创建、配置和事件发布以进行索引。

DEX 交易对vault、钱包和 DAO,任何协议都需要可预测的标准化部署,此模式都可以为此提供支持。

在这篇文章中,我们将介绍:

1. 工厂模式如何在底层使用CREATECREATE2

2. 为什么确定性的部署对于可发现性和安全性至关重要

3. 通过工厂部署合约并与之交互的完整 Foundry 示例

最后,你将了解为什么几乎每个现代协议都包含一个工厂,以及如何构建自己的工厂以安全地在 EVM 上扩展部署。

工厂

到目前为止,我们已经了解了合约是如何部署的,以及代理如何帮助进行升级。 但是,你会在生产 EVM 代码中看到另一种模式:工厂

工厂只是一个知道如何部署其他合约的合约。 你无需手动部署每个新合约,而是与单个工厂合约进行交互,该合约:

  • 启动新实例 (CREATECREATE2)
  • 安全地初始化它们
  • 发布事件,以便你可以在链上跟踪它们

可以把它想象成合约的装配线。 你向工厂提供参数,它会返回一个新实例。

为什么使用工厂?

几乎所有主要的协议都使用工厂,因为它们带来了:

  • 标准化: 每个实例都使用相同的代码路径进行部署。
  • 可发现性: 你可以查询工厂事件或映射以查找所有已部署的实例。
  • 初始化安全性: 工厂通常在部署后立即调用初始化程序,因此你不会得到别人可以劫持的半成品合约。
  • 确定性: 通过 CREATE2,工厂甚至可以在实例存在之前预先计算出实例的地址(非常适合“反事实”钱包或确定性的资金池地址)。

例子:

basicfactory.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Counter {
    address public owner;
    uint256 public value;
    constructor(address _owner, uint256 start) {
        owner = _owner;
        value = start;
    }
    function inc() external {
        require(msg.sender == owner, "not owner");
        value += 1;
    }
}

contract CounterFactory {
    event CounterCreated(address indexed counter, address indexed owner, uint256 start);

    function createCounter(address owner_, uint256 start_) external returns (address addr) {
        for (uint256 i = 0; i < 5; i++) {
            Counter c = new Counter(owner_, start_);
            addr = address(c);
            emit CounterCreated(addr, owner_, start_);
        }
    }
}

注意: 这里的 createCounter 不是通过 CREATE2 部署的,但是可以通过获取 Counter 合约的 bytecode 并执行 create2(...) 轻松实现

设置节点:

anvil

部署合约并调用它

// Deploy the factory contract
// 部署工厂合约
forge create src/basicfactory.sol:CounterFactory \
  --rpc-url localhost:8545 \
  --private-key <YOUR-ANVIL-PK>

// Expected output:
// 预期输出:
// [⠊] Compiling...
// [⠒] Compiling 1 files with Solc 0.8.30
// [⠢] Solc 0.8.30 finished in 52.99ms
// Compiler run successful!
// Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
// Deployed to: 0x610178dA211FEF7D417bC0e6FeD39F05609AD788
// Transaction hash: 0x5c25685d15aacde7128a648d48dcd8b975ffc6e20aac9605bce2f582125b6437
// Call the factory
// 调用工厂
cast send 0x610178dA211FEF7D417bC0e6FeD39F05609AD788 \
  "createCounter(address,uint256)(address)" \
  0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 42 \
  --rpc-url localhost:8545 --private-key <YOUR-ANVIL-PK>
// Logs expected in after this call with topics for each emited event
// 在此调用之后,带有每个发布事件的主题的预期日志
// and there you will find the contract addresses
// 在那里你会找到合约地址

总结

工厂将合约创建变成一个可重复的过程。

你无需手动部署每个实例,而是获得一个受信任的入口点,该入口点处理部署、初始化和跟踪,从而使大型链上系统更安全且更易于管理。

它们是 DeFi 中可扩展架构的支柱,从流动性池到 vault 和智能钱包。

一旦你理解了工厂,你就可以开始设计自动部署和管理整个合约生态系统的协议。

最后,你将了解为什么几乎每个现代协议都包含一个工厂,以及如何构建自己的工厂以安全地在 EVM 上扩展部署。

  • 原文链接: medium.com/@andrey_obruc...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Andrey Obruchkov
Andrey Obruchkov
江湖只有他的大名,没有他的介绍。