摘要:本文首发于深入浅出区块链社区原文链接如何编写一个可升级的智能合约原文已更新,请读者前往原文阅读区块链信任基础的数据不可修改的特性,让它传统应用程序有一个很大的不同的地方是一经发布于区块链上就无法修改不能直接在原有的合约上直接修改再重新发布。
本文首发于深入浅出区块链社区
原文链接:如何编写一个可升级的智能合约原文已更新,请读者前往原文阅读
区块链信任基础的数据不可修改的特性,让它传统应用程序有一个很大的不同的地方是一经发布于区块链上就无法修改(不能直接在原有的合约上直接修改再重新发布)。
写在前面阅读本文前,你应该对以太坊、智能合约及Solidity语言有所了解,如果你还不了解,建议你先看以太坊是什么
当智能合约出现bug一方面正式由于智能合约的不可修改的特性,因为只要规则确定之后,没人能够修改它,大家才能够信任它。但另一方面,如果规则的实现有Bug, 可能会造成代币被盗,或是调用消耗大量的gas。这时就需要我们去修复错误。
我们知道一个智能合约包含两部分: 代码逻辑和数据,而代码逻辑又是最容易出问题的部分, 如在实现如下合约时,由于手抖在写addTen()时,10写成了11。
pragma solidity ^0.4.18; contract MyContract { mapping (address => uint256) public balanceOf; function setBlance(address _address,uint256 v) public { balanceOf[_address] = v; } function addTen(address addr) public returns (uint){ return balanceOf[addr] + 11; } }
假如我们在部署之后发现了这个问题,想要修复这个bug的话,只好重新部署合约,可是这时会有一个尴尬的问题,原来的合约已经有很多人使用,如果部署新的合约,老合约的数据将会丢失。
数据合约及控制合约那么如何解决上面的问题了,一个解决方案是分离合约中的数据,使用一个多带带的合约来存储数据(下文称数据合约),使用一个多带带的合约写业务逻辑(下文称控制合约)。
我们来看看代码如何实现。
pragma solidity ^0.4.18; contract DataContract { mapping (address => uint256) public balanceOf; function setBlance(address _address,uint256 v) public { balanceOf[_address] = v; } } contract ControlContract { DataContract dataContract; function ControlContract(address _dataContractAddr) public { dataContract = DataContract(_dataContractAddr); } function addTen(address addr) public returns (uint){ return dataContract.balanceOf(addr) + 11; } }
现在我们有两个合约DataContract 专门用来存数据,ControlContract用来处理逻辑,并利用DataContract来读写数据。通过这样的设计,可以在更新控制合约后保持数据合约不变,这样就不会丢失数据,也不用迁移数据。
读写控制通过DataContract我们可以多带带更新合约逻辑,不过你也许发现了一个新的问题,DataContract的数据不仅仅可以被ControlContract读写,还可以被其他的合约读写,因此需要对DataContract添加读写控制。我们给DataContract添加一个mapping, 用来控制哪些地址可以访问数据,同时添加了修饰器及设置访问的方法,代码如下:
pragma solidity ^0.4.18; contract DataContract { mapping (address => uint256) public balanceOf; mapping (address => bool) accessAllowed; function DataContract() public { accessAllowed[msg.sender] = true; } function setBlance(address _address,uint256 v) public { balanceOf[_address] = v; } modifier platform() { require(accessAllowed[msg.sender] == true); _; } function allowAccess(address _addr) platform public { accessAllowed[_addr] = true; } function denyAccess(address _addr) platform public { accessAllowed[_addr] = false; } } ...
订阅我的小专栏可参看合约的完整代码。
部署方法如下:
先部署DataContract合约
使用DataContract合约地址作为部署ControlContract合约的参数
用ControlContract合约地址作为参数调用DataContract合约的allowAccess方法。
如果需要更新控制合约(如修复了addTen)则重新执行第2-3步,同时对老的控制合约执行denyAccess()。
更多当我们在实现数据合约时,它包含的逻辑应该越少越好,并且应该是严格测试过的,因为一旦数据合约部署之后,就没法更改。
大多数情况下,和用户交互的是DApp, 因此当控制合约升级之后,需要升级DApp,使之关联新的控制合约。
尽管合约可以通过本文的方式升级,但我们依然要谨慎升级,因为升级表示你可以重写逻辑,会降低用户对你的信任度。
本文介绍升级方法更多的是一种思路,实际项目中可能会对应多个控制合约及数据合约。
☛ 深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。
☛ 我的知识星球为各位解答区块链技术问题,欢迎加入讨论。
☛ 关注公众号“深入浅出区块链技术”第一时间获取区块链技术信息。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/24108.html
摘要:接上篇合约升级模式介绍笔者改写了一个可用于实践生产的升级框架,需要自取。在介绍合约升级模式中提到了一个可以解决这个问题的方法。深度理解注意为中的低阶方法下文中出现的方法,是我在智能合约中写的一个方法名称,不要混淆。 接上篇:合约升级模式介绍笔者改写了一个可用于实践生产的升级框架,需要自取。https://github.com/hammewang/... 同时欢迎讨论,微信xiuxiu1...
摘要:以后的逻辑合约可以升级现有的方法或者创造新的方法,但是不能引入新的状态变量。使用非结构化存储升级非结构化存储模式和继承存储类似,但是不要求逻辑合约继承任何和升级相关的状态变量。 以太坊最大的优势就是,每一笔用来转账、部署合约或者和合约交互的交易(事务)都被存在一个叫做区块链的公共账本上。一旦交易发生,就再也无法隐藏或者改变。这带来一个巨大的好处,就是在以太坊中的每一个节点都可以去验证任...
摘要:今天我们来一步一步从搭建以太坊智能合约开发环境开始,讲解智能合约的如何编写。开发环境搭建安装强烈建议新手使用来进行开发。第行修改部署账户为新账户索引,即使用新账户来部署合约。 本文首发于深入浅出区块链社区原文链接:智能合约开发环境搭建及Hello World合约原文已更新,请读者前往原文阅读 如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇。就先...
阅读 1630·2021-10-27 14:13
阅读 1867·2021-10-11 10:59
阅读 3366·2021-09-24 10:26
阅读 1925·2019-08-30 12:48
阅读 3040·2019-08-30 12:46
阅读 2032·2019-08-30 11:16
阅读 1414·2019-08-30 10:48
阅读 2740·2019-08-29 16:54