Skip to main content

Command Palette

Search for a command to run...

智能合约工厂:如何用Solidity合约创建另一个合约?

Published
3 min read
智能合约工厂:如何用Solidity合约创建另一个合约?

智能合约工程师, 业余Youtuber, 投机套利爱好者.

介绍

solidity 中的 new 关键字允许使用模板创建和部署新的合约实例。“XxxContractFactory”是一种命名约定和用于创建“XxxContract”合约的模式。

本文的目的是了解制作简单合约工厂的过程,同时了解它的工作原理并想象一些潜在的用例。让我们直接开始。

合约工厂是一种基于模板创建合约的设计模式。用户可以在字段中引入值,作为输入来初始化新部署的合约的状态变量。为什么这很有用?根据一些用例,你可以做一些很酷的事情,例如:

  • 允许用户创建流动资金池:Uniswap

  • 利用每个地址的 Adidas 2 NFT 铸币限制:交易

  • 无代码平台以帮助用户创建自己的代币:ThirdWeb

  • 其他例子:业务流程管理和医疗保健

实现原理

对于这个例子,我将使用我编写的 Bank 合约(模板)和 BankFactory 合约(工厂)。目的是部署一次工厂Factory合约,并根据需要创建多个银行Bank合约,而无需自己部署每个合约。

image.png

1、首先是银行 Bank(模板):

构造函数初始化由 BankFactory 传递的状态变量。在这里,我们传递Bank拥有的资金数量,谁是Bank的所有者以及谁创建了Bank合约。

//  这是一个模板合约, 拥有初始化 Bank 及其变量 

contract Bank {
  uint256 public bank_funds;
  address public owner;
  address public deployer;

  constructor(address _owner, uint256 _funds) {
    bank_funds = _funds;
    owner = _owner;
    deployer = msg.sender;
  }
}

2、第二个 BankFactory(工厂):

在这里,我们实例化银行合约 Bank,创建一个类型为银行的列表 Bank[] public list_of_banks 来跟踪新创建的合约,最后是createBank()一个将银行的构造函数参数作为参数的函数。

这是创建新合约的行:

bank = new Bank(_owner, _funds)

数组中索引 0 处的值list_of_banks成为创建合约的地址!

contract BankFactory {
  // instantiate Bank contract
  Bank bank;
  //keep track of created Bank addresses in array 
  Bank[] public list_of_banks;

  // function arguments are passed to the constructor of the new created contract 
  function createBank(address _owner, uint256 _funds) external {
    bank = new Bank(_owner, _funds);
    list_of_banks.push(bank);
  }
}

这就是全部。现在,当 Factory 已部署后,createBank(.., ..) 使用所需值作为参数调用函数将导致新Bank合约保存这些值!

想看看如何用 HardHat 做到这一点?

使用 HardHat 进行测试

1、创建一个新目录并安装安全帽:

npm install --save-dev hardhat

2、创建一个新项目并安装依赖项:

npx hardhat

3、使用你选择的文本编辑器打开文件夹。我喜欢 Visual Studio 代码:

4、创建一个新的 Solidity 文件并将代码复制到其中:

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

import "hardhat/console.sol";

// Template used to initialize state variables 
contract Bank {

  uint256 public bank_funds;
  address public owner;
  address public deployer;

  constructor(address _owner, uint256 _funds) {
    bank_funds = _funds;
    owner = _owner;
    deployer = msg.sender;
  }
}


contract BankFactory {

  // instantiate Bank contract
  Bank bank;

  //keep track of created Bank addresses in array 
  Bank[] public list_of_banks;


  // function arguments are passed to the constructor of the new created contract 
  function createBank(address _owner, uint256 _funds) external {
    bank = new Bank(_owner, _funds);
    list_of_banks.push(bank);
  }
}

5、编译合约:

npx hardhat compile

6、测试它!注意测试脚本。将代码复制粘贴到其中并运行它!

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Deploying a BankFactory and creating Bank instances ", function () {

  it("Should instantiate the created Bank and call its functions", async () => {

    // ContractFactory in ethers.js is an abstraction used to deploy new smart contracts, so Token here is a factory for instances of our token contract.
    const BF = await ethers.getContractFactory('BankFactory');
    const Bank = await ethers.getContractFactory('Bank');

    // deploy bank factory
    const bf = await BF.deploy();
    await bf.deployed();

    const owner = "0x0d8D32B83aaBBB675333468E4794eE0cDE666666"
    // call function with (address owner, uint256 number) parameters
    const tx1_receipt = await bf.createBank(owner, 69420);
    const tx2_receipt = await bf.createBank(owner, 00100);
    const tx3_receipt = await bf.createBank(owner, 113377);

    console.log("BankFactory address at: ", tx1_receipt.to);
    console.log("\n")


    // Get the addresses of the deployed bank contracts 
    const bank1_address = await bf.list_of_banks(0);
    const bank2_address = await bf.list_of_banks(1);
    const bank3_address = await bf.list_of_banks(2);
    console.log("BankFactory array of banks, address at (index 0): ", bank1_address);
    console.log("BankFactory array of banks, address at (index 1): ", bank2_address);
    console.log("BankFactory array of banks, address at (index 2): ", bank3_address);
    console.log("\n")


    // Attach the created Bank instance to the address it's located at. Call functions.
    const bank1 = await Bank.attach(bank1_address);
    const bank2 = await Bank.attach(bank2_address);
    const bank3 = await Bank.attach(bank3_address);


    // Get Bank 1 variables
    const bank1_owner = await bank1.owner();
    const bank1_bank_funds = await bank1.bank_funds();
    const bank1_deployer = await bank1.deployer()
    console.log(`Bank 1 \nowner: ${bank1_owner}\nbank_funds: ${bank1_bank_funds}\ndeployer: ${bank1_deployer}`)
    console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")


    // Get Bank 2 variables
    const bank2_owner = await bank2.owner();
    const bank2_bank_funds = await bank2.bank_funds();
    const bank2_deployer = await bank2.deployer()
    console.log(`Bank 2 \nowner: ${bank2_owner}\nbank_funds: ${bank2_bank_funds}\ndeployer: ${bank2_deployer}`)
    console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

    // Get Bank 3 variables
    const bank3_owner = await bank3.owner();
    const bank3_bank_funds = await bank3.bank_funds();
    const bank3_deployer = await bank3.deployer()
    console.log(`Bank 3 \nowner: ${bank3_owner}\nbank_funds: ${bank3_bank_funds}\ndeployer: ${bank3_deployer}`)
    console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
  })

});

希望你和我一样完成的这个挑战!

参考链接:

https://docs.uniswap.org/protocol/V2/reference/smart-contracts/factory

https://research.csiro.au/blockchainpatterns/general-patterns/contract-structural-patterns/factory-contract/

https://arxiv.org/abs/1706.03700

https://www.researchgate.net/publication/303996559_Untrusted_Business_Process_Monitoring_and_Execution_Using_Blockchain

https://docs.openzeppelin.com/learn/developing-smart-contracts

关注我们, 获得更多优质内容

1.2K views

More from this blog

现在谁继续赚取数百万美元?正确答案:鲸鱼和内幕钱包。

现在谁继续赚取数百万美元?正确答案:鲸鱼和内幕钱包。 因为市场完全依赖于他们的操纵, 他们在任何游戏中,拥有绝对优势。 因为Axiom等工具具备监控功能,所以他们也会经常替换钱包: 💰钱包实时监控:https://axiom.trade/@0xcii 📱钱包监控:https://debot.ai?inviteCode=174709 分享一批上周的链上顶级内幕钱包🧵👇 我花了很多时间在链上筛选这些钱包! 请关注我 @AntCaveClub,点赞并转发——确保不再...

Apr 18, 20251 min read34

这个钱包昨天一笔交易用 0.9 Eth 赚了 8.4 Eth

几乎是交易市场的一条定律: 不管新闻是真假, 它带来的影响是真的就行。 昨天,我们知道 特朗普团队发币这一消息后, 第一时间关注市场上的新币。 发现了 ETH 链上的 $DJT 代币, 当时市值仅 $450K , 而现在达到了 $ 3.3 M 。 由于信息较少, 小入了一手, 然后发公告了,估计都跌麻木了没人上车,结果今天获利 8 倍。 另一个值得 关注的信息是特朗普最大主题代币 $TRUMP 今日突然下跌 -40% 我们通过链上数据观察, 这部分游资进入了 $DJT 而这个...

Jun 18, 20241 min read355

Ton 会成为真正的独角兽,因为它拥有

TON 才是独角兽。 正确使用TON 工具能给你带来财富。 SOL / ETH 的 memcoins 交易良好,但 TON 正在超越它。 以下 5 个基本工具可帮助你获得 10-100 倍收益 1⃣️ TON 的土壤 显然,TON 上的 memcoin 越来越受欢迎,TON 市值已超过 160 亿美元。 $NOT 上线币安,其涨幅众所周知。其他大量 TON memcoin 会增值 10-100 倍。让我们学习一下用于搜寻早期 TON 山寨币的主要工具…… 2⃣️ Defilla...

Jun 5, 20241 min read109

昨晚用 1 Eth 赚了 10 Eth ! 没想到睡觉起来就这样了。

昨天睡觉前搞了 $DEW 建仓时市值 500K 附近, 现在 6M 左右了, 一晚上 10 倍。 最近确实以太坊链上出金狗,千万市值天天都有。 也主要因为我睡着了, 睡之前和朋友讲了下,建议他上车,他说他在打球🏀 推荐 $DEW 的主要原因是, 我前几天不是推了 $PEW ,推的时候市值 $2 M 附近,结果 3天一路干到了 $94 M , 大概快有 50 倍... 当时跟朋友讲让他上点车, 他在追剧,忘上车了, 我说下次一定。 他推荐我看《庆余年》,说这个好看。 昨晚看到出...

Jun 1, 20241 min read324

专注 Web3 网络赚钱模式, 区块链实践教程与交流分享

127 posts

专注 Web3 网络赚钱模式, 实践教程与交流分享 !

加入社群 | 订阅Youtube