文章目录

  • 1 介绍
  • 2 主要功能
  • 3 代码示例
  • 4 部署测试
    • 4.1 部署Factory工厂合约
    • 4.2 利用工厂合约生成新的合约
    • 4.3 导入新创建的合约并验证

猛戳订阅学习专栏solidity系列合约源码+解析

1 介绍

何为工厂合约呢?相信有过编程经验的小伙伴都听说过工厂模式,此处的工厂合约其实和他的概念相似,该合约将承担创建其他合约的任务。在基于类的编程中,此模式的主要动机来自单一职责原则(一个类不需要知道如何创建其他类的实例),并且该模式为构造函数提供了一种抽象。

2 主要功能

为什么要用到工厂合约呢?

  1. 我们可以通过部署一个工厂合约来为供用户去创建N个功能相同的智能合约
  2. 可以节约一定的Gas费用,简化部署流程
  3. 提高合约的安全性

3 代码示例

// SPDX-License-Identifier:MIT;pragma solidity ^0.8;import "@openzeppelin/contracts/token/ERC721/ERC721.sol";import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";import "@openzeppelin/contracts/utils/Counters.sol";contract TestNFT is ERC721,ERC721Enumerable, ERC721URIStorage {using Counters for Counters.Counter;Counters.Counter private _tokenId;constructor(string memory _contract_name,string memory _contract_symbol) ERC721(_contract_name,_contract_symbol){}function mint(address _recipient, string memory _tokenUrl) public returns(uint _mintTokenId){require(bytes(_tokenUrl).length > 0,"The _tokenUrl must be have");_tokenId.increment();uint newTokenId = _tokenId.current();_mint(_recipient, newTokenId);_setTokenURI(newTokenId, _tokenUrl);return newTokenId;}function _beforeTokenTransfer(address from, address to, uint256 tokenId)internaloverride(ERC721, ERC721Enumerable){super._beforeTokenTransfer(from, to, tokenId);}function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {super._burn(tokenId);}function tokenURI(uint256 tokenId)publicviewoverride(ERC721, ERC721URIStorage)returns (string memory){return super.tokenURI(tokenId);}function supportsInterface(bytes4 interfaceId)publicviewoverride(ERC721, ERC721Enumerable)returns (bool){return super.supportsInterface(interfaceId);}}contract Factory{// TestNFT[] public addr;uint nowNum = 0;mapping(address => string) public ERC_project;mapping(string => address) public name_addr;mapping(uint => address) public addr;function createContract(string memory _name,string memory _symbol) public returns(address){address t_address; TestNFT t= new TestNFT(_name,_symbol); t_address = address(t); addr[nowNum] = t_address; ERC_project[t_address] = _name; name_addr[_name] = t_address;nowNum++;return t_address;}function getAddress(string memory _name) public view returns(address){return name_addr[_name];}}

4 部署测试

4.1 部署Factory工厂合约

首先我们先部署要测试的工厂合约:

4.2 利用工厂合约生成新的合约

利用我们工厂合约定义的createContract方法来创建一个新的ERC721合约:

可以在返回值中查看到我们新创建的合约地址:0xb7b6b4aA81A6b0Dd20500cd19a485a95Fa206687,

其次我们也可以通过新创建的合约的名称来查询到我们新创建的合约的地址,可以看到两次查询到的地址是一致的。

4.3 导入新创建的合约并验证

接下来我们把通过工厂合约创建的ERC721合约通过地址导入到remix中进行进一步的验证:

可以查看其名称和我们定义的是一致的:

到此我们几句实现了一个简单的Factory工厂合约,也实现了通过Factory工厂合约成功创建了一个ERC721合约。
当然你也可以去尝试调用新生成合约中的其他方法来进行验证,文章中就不再一一测试了。