全面掌握Solidity智能合约开发

2024年09月25日更新 796 人订阅
原价: ¥ 46 限时优惠
专栏简介 跟我学 Solidity :开发环境 跟我学 Solidity:关于变量 跟我学 Solidity : 变量的存储 跟我学 Solidity :引用变量 跟我学 Solidity :函数 跟我学 Solidity :合约的创建和继承 跟我学 Solidity :工厂模式 用Web3.js构建第一个Dapp 跟我学Solidity:事件 Solidity 中 immutable (不可变量)与constant(常量) [译] Solidity 0.6.x更新:继承 解析 Solidity 0.6 新引入的 try/catch 特性 探究新的 Solidity 0.8 版本 探索以太坊合约委托调用(DelegateCall) 停止使用Solidity的transfer() 使用工厂提高智能合约安全性 Solidity 怎样写出最节省Gas的智能合约[译] Solidity 优化 - 编写 O(1) 复杂度的可迭代映射 Solidity 优化 - 控制 gas 成本 Solidity 优化 - 减少智能合约的 gas 消耗的8种方法 Solidity 优化 - 如何维护排序列表 Solidity 优化:打包变量优化 gas 使用 Solidity 瞬态存储操作码 在 Solidity中使用值数组以降低 gas 消耗 Gas 优化:Solidity 中的使用动态值数组 计算Solidity 函数的Gas 消耗 Solidity 技巧:如何减少字节码大小及节省 gas 一些简单的 Gas 优化基础 "Stack Too Deep(堆栈太深)" 解决方案 智能合约Gas 优化的几个技术 合约实践:避免区块Gas限制导致问题 如何缩减合约以规避合约大小限制 Solidity 类特性 无需gas代币和ERC20-Permit还任重而道远 智能合约实现白名单的3个机制 Solidity智能合约安全:防止重入攻击的4种方法 Solidity 十大常见安全问题 [译]更好Solidity合约调试工具: console.log 智能合约开发的最佳实践 - 强烈推荐 全面理解智能合约升级 Solidity可升级代理模式: 透明代理与UUPS代理 使用OpenZeppelin编写可升级的智能合约 实战:调整NFT智能合约,减少70%的铸币Gas成本 Solidity 优化 - 隐藏的 Gas 成本 Gas 技巧:Solidity 中利用位图大幅节省Gas费 Solidity Gas 优化 - 理解不同变量 Gas 差异 关于Solidity 事件,我希望早一点了解到这些 Solidity 编码规范推荐标准 深入了解 Solidity bytes OpenZeppelin Contracts 5.0 版本发布 Solidity Gas优化:高效的智能合约策略 智能合约安全的新最低测试标准:Fuzz / Invariant Test 智能合约的白名单技术 模糊测试利器 - Echidna 简介 智能合约设计模式:代理 离线授权 NFT EIP-4494:ERC721 -Permit

跟我学 Solidity :工厂模式

如何在智能合约中使用clone工厂模式减少合约部署 gas。

欢迎来到学习 Solidity 系列的另一部分。在上一篇文章,我们讨论了如何从智能合约中创建另一个智能合约。今天,我们将研究这种情况下的典型用例。

什么是工厂模式?

工厂模式的想法是拥有一个合约(工厂),该合约将承担创建其他合约的任务。在基于类的编程中,此模式的主要动机来自单一职责原则(一个类不需要知道如何创建其他类的实例),并且该模式为构造函数提供了一种抽象。

UML diagram for factory method

图片来自Wikipedia.

为什么要在 Solidity 中使用工厂模式?

在Solidity中,出于以下原因之一,你可能要使用工厂模式:

  • 如果要创建同一合约的多个实例,并且正在寻找一种跟踪它们并简化管理的方法。

    contract Factory {
        Child[] children;
        function createChild(uint data){
           Child child = new Child(data);
           children.push(child);
        }
    }
    contract Child{
       uint data;
       constructor(uint _data){
          data = _data;
       }
    }
  • 节省部署成本:你可以先部署工厂,之后在使用时再来部署其他合约。

  • 提高合约安全性(请参阅).

如何与已部署的智能合约进行交互

在深入探讨如何实现工厂模式的细节之前,我想澄清一下我们与已部署的智能合约进行交互的方式。工厂模式是用来创建子合约的,并且我们可能希望调用它们的某些函数以更好地管理这些合约。

调用部署的智能合约,需要做两件事:

  1. 合约的ABI(提供有关函数签名的信息)。如果合约在同一个项目中。你可以使用import关键字将其导入。
  2. 部署合约的地址。

举个例子:

contract A {
    address bAddress;
    constructor(address b){
       bAddress = b;
    }

    function callHello() external view returns(string memory){
       B b = B(bAddress); // 转换地址为合约类型
       return b.sayHello();
    }
}

contract B {
     string greeting = "hello world";
     function sayHello() external view returns(string memory){
         return greeting;
     }
}

在Remix中,首先部署合约B,然后复制其地址,并在部署时将其提供给A的构造函数。现在你可以调用callHello()函数,你将获得合约B的sayHello()函数的结果。

普通工厂模式

在此模式下,我们创建具有创建子合约函数的工厂合约,并且可能还会添加其他函数来有效管理这些合约(例如,查找特定合约或禁用合约)。在create函数中,我们使用new关键字来部署子合约。


contract Factory{
     Child[] public children;
     uint disabledCount;

    event ChildCreated(address childAddress, uint data);

     function createChild(uint data) external{
       Child child = new Child(data, children.length);
       children.push(child);
       emit ChildCreated(address(child), data);
     }

     function getChildren() external view returns(Child[] memory _children){
       _children = new Child[](children.length- disabledCount);
       uint count;
       for(uint i=0;i<children.length; i++){
          if(children[i].isEnabled()){
             _children[count] = children[i];
             count++;
          }
        }
     }  

     function disable(Child child) external {
        children[child.index()].disable();
        disabledCount++;
     }

}
contract Child{
    uint data;
    bool public isEnabled;
    uint public index;
    constructor(uint _data,uint _index){
       data = _data;
       isEnabled = true;...

剩余50%的内容订阅专栏后可查看

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

3 条评论

请先 登录 后评论