当前位置: 首页 > news >正文

如何编写一个可升级的智能合约

    想学习更多的区块链知识,请百度【链客区块链技术问答社区】
    

区块链信任基础的数据不可修改的特性,让它传统应用程序有一个很大的不同的地方是一经发布于区块链上就无法修改(不能直接在原有的合约上直接修改再重新发布)。
写在前面
阅读本文前,你应该对以太坊、智能合约及Solidity语言有所了解,如果你还不了解,建议你先看以太坊是什么
当智能合约出现bug
一方面正式由于智能合约的不可修改的特性,因为只要规则确定之后,没人能够修改它,大家才能够信任它。但另一方面,如果规则的实现有Bug, 可能会造成代币被盗,或是调用消耗大量的gas。这时就需要我们去修复错误。
我们知道一个智能合约包含两部分: 代码逻辑和数据,而代码逻辑又是最容易出问题的部分, 如在实现如下合约时,由于手抖在写addTe1n()时,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;
}

}

...
部署方法如下:
1.先部署DataContract合约
2.使用DataContract合约地址作为部署ControlContract合约的参数
3.用ControlContract合约地址作为参数调用DataContract合约的allowAccess方法。
如果需要更新控制合约(如修复了addTen)则重新执行第2-3步,同时对老的控制合约执行denyAccess()。
更多
当我们在实现数据合约时,它包含的逻辑应该越少越好,并且应该是严格测试过的,因为一旦数据合约部署之后,就没法更改。
大多数情况下,和用户交互的是DApp, 因此当控制合约升级之后,需要升级DApp,使之关联新的控制合约。
尽管合约可以通过本文的方式升级,但我们依然要谨慎升级,因为升级表示你可以重写逻辑,会降低用户对你的信任度。
本文介绍升级方法更多的是一种思路,实际项目中可能会对应多个控制合约及数据合约。

相关文章:

  • disruptor 核心概念 二
  • 线程池-线程池源码详解
  • Java总结 - String - 这篇请使劲喷我
  • 星舆科技:打造下一代定位技术 以高精度位置感知构筑AI+时代基础力量
  • Spring配置报错- 元素 'beans' 必须不含字符 [子级]
  • tomcat如何修改发布目录
  • bootstrap网站后台从设计到开发
  • 企业分布式微服务云SpringCloud SpringBoot mybatis (十二)断路器监控(Hystrix Dashboard)...
  • XML已死 ?
  • 如何查看Oracle官方文档
  • 开发常用的小软件
  • 香港股市大涨 创逾1个月新高
  • 程序员工作法
  • 三分钟了解实时流式大数据分析
  • 韩国企业入驻沈阳跨境电商产业园区
  • [Vue CLI 3] 配置解析之 css.extract
  • 【comparator, comparable】小总结
  • const let
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • ESLint简单操作
  • IP路由与转发
  • JavaScript DOM 10 - 滚动
  • js
  • js 实现textarea输入字数提示
  • k8s 面向应用开发者的基础命令
  • leetcode98. Validate Binary Search Tree
  • Mybatis初体验
  • Objective-C 中关联引用的概念
  • SpiderData 2019年2月25日 DApp数据排行榜
  • vuex 笔记整理
  • webpack4 一点通
  • 高性能JavaScript阅读简记(三)
  • 观察者模式实现非直接耦合
  • 聊聊directory traversal attack
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 深度解析利用ES6进行Promise封装总结
  • 微服务入门【系列视频课程】
  • 微信小程序填坑清单
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • ionic入门之数据绑定显示-1
  • 阿里云服务器购买完整流程
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • #HarmonyOS:Web组件的使用
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (0)Nginx 功能特性
  • (搬运以学习)flask 上下文的实现
  • (二)丶RabbitMQ的六大核心
  • (分布式缓存)Redis持久化
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (原創) 物件導向與老子思想 (OO)
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法