前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式:智能合约的经典设计模式及解析

设计模式:智能合约的经典设计模式及解析

作者头像
苏泽
发布2024-03-28 09:38:28
910
发布2024-03-28 09:38:28
举报
总而言之,智能合约实现上要达到的目标是:完备的业务功能、精悍的代码逻辑、良好的模块抽象、清晰的合约结构、合理的安全检查、完备的升级方案

经典的5种设计模式

1、自毁合约

1、自毁合约: 合约自毁模式用于终止一个合约,从区块链中永久删除该合约,无法调用合约功能或记录交易。常见用例包括定时合约或必须在达到里程碑时终止的合约。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

contract SelfDesctructionContract { public address owner; public string someValue; modifier ownerRestricted { require(owner == msg.sender); _; } // constructor function SelfDesctructionContract() { owner = msg.sender; } // a simple setter function function setSomeValue(string value){ someValue = value; } // you can call it anything you want function destroyContract() ownerRestricted { suicide(owner); } }

正如你所看到的, destroyContract()方法负责销毁合约。

请注意,我们使用自定义的ownerRestricted修饰符来显示该方法的调用者,即仅允许合约的拥有者 销毁合约。

2、工厂合约

工厂合约用于创建和部署子合约(资产),存储子合约地址以确保安全性和防止数据丢失。常用于销售资产并跟踪资产所有者。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

contract CarShop { address[] carAssets; function createChildContract(string brand, string model) public payable { // insert check if the sent ether is enough to cover the car asset ... address newCarAsset = new CarAsset(brand, model, msg.sender); carAssets.push(newCarAsset); } function getDeployedChildContracts() public view returns (address[]) { return carAssets; } } contract CarAsset { string public brand; string public model; address public owner; function CarAsset(string _brand, string _model, address _owner) public { brand = _brand; model = _model; owner = _owner; } }

代码address newCarAsset = new CarAsset(...)将触发一个交易来部署子合约并返回该合约的地址。 由于工厂合约和资产合约之间唯一的联系是变量address[] carAssets,所以一定要正确保存子合约的地址。

3、名称注册表

名称注册表模式通过合约名称到地址的映射表,简化了依赖多个合约的DApp的开发。通过固定一个合约地址,可以轻松查找合约地址,更新合约时不影响DApp的代码。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

contract NameRegistry { struct ContractDetails { address owner; address contractAddress; uint16 version; } mapping(string => ContractDetails) registry; function registerName(string name, address addr, uint16 ver) returns (bool) { // versions should start from 1 require(ver >= 1); ContractDetails memory info = registry[name]; require(info.owner == msg.sender); // create info if it doesn't exist in the registry if (info.contractAddress == address(0)) { info = ContractDetails({ owner: msg.sender, contractAddress: addr, version: ver }); } else { info.version = ver; info.contractAddress = addr; } // update record in the registry registry[name] = info; return true; } function getContractDetails(string name) constant returns(address, uint16) { return (registry[name].contractAddress, registry[name].version); } }

你的DApp将使用getContractDetails(name)来获取指定合约的地址和版本。

4、映射表迭代器

映射表迭代器模式解决了Solidity中映射表无法迭代的问题,通过将键值对存储在数组中实现迭代操作。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

contract MappingIterator { mapping(string => address) elements; string[] keys; function put(string key, address addr) returns (bool) { bool exists = elements[key] == address(0) if (!exists) { keys.push(key); } elements[key] = addr; return true; } function getKeyCount() constant returns (uint) { return keys.length; } function getElementAtIndex(uint index) returns (address) { return elements[keys[index]]; } function getElement(string name) returns (address) { return elements[name]; } }

实现put()函数的一个常见错误,是通过遍历来检查指定的键是否存在。正确的做法是 elements[key] == address(0)。虽然遍历检查的做法不完全是一个错误,但它并不可取, 因为随着keys数组的增长,迭代成本越来越高,因此应该尽可能避免迭代。

5、提款模式

提款模式用于退款操作,避免在退款过程中出现异常导致整个交易被回滚。建议使用withdrawFunds()方法单独按需退款给调用者,而不是一次性退款给所有买家。

1 2 3 4 5 6 7 8 9 10 11 12 13

contract WithdrawalContract { mapping(address => uint) buyers; function buy() payable { require(msg.value > 0); buyers[msg.sender] = msg.value; } function withdraw() { uint amount = buyers[msg.sender]; require(amount > 0); buyers[msg.sender] = 0; require(msg.sender.send(amount)); } }

五种模式优劣性解析:

  1. 自毁合约:自毁合约模式用于终止一个合约并从区块链中永久删除。这种模式常用于一次性合约或需要在特定条件下终止的合约。通过调用自毁函数(selfdestruct)并指定一个地址,合约的余额将被转移到该地址,并且合约的代码和存储将被删除。
  2. 工厂合约:工厂合约模式用于创建和部署子合约。工厂合约负责管理子合约的创建过程,并存储子合约的地址以确保安全性和方便访问。这种模式常用于创建多个相似的合约实例,例如创建代币合约或其他可复制的资产。
  3. 名称注册表:名称注册表模式通过将合约名称映射到地址的表来简化依赖多个合约的去中心化应用(DApp)的开发。通过使用注册表合约,可以通过固定的合约地址轻松查找和更新合约,而不需要在DApp的代码中硬编码合约地址,从而提高了灵活性和可维护性。
  4. 映射表迭代器:Solidity中的映射表无法直接迭代,但通过映射表迭代器模式可以解决这个问题。该模式通过将键值对存储在数组中,以特定的顺序记录映射表中的键,并提供函数来遍历数组并返回键值对的详细信息,从而实现对映射表的迭代操作。
  5. 提款模式:提款模式用于在合约中进行退款操作,以防止在退款过程中出现异常导致整个交易被回滚。通常建议使用提款模式时,将退款金额存储在合约中,然后通过调用合约的withdrawFunds()方法,单独按需退款给调用者,而不是一次性退款给所有的买家。这样可以确保退款操作的可靠性,并避免因异常而导致整个退款过程失败。
本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 经典的5种设计模式
    • 1、自毁合约
      • 2、工厂合约
        • 3、名称注册表
          • 4、映射表迭代器
            • 5、提款模式
            • 五种模式优劣性解析:
            相关产品与服务
            对象存储
            对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
            http://www.vxiaotou.com