如何编写可升级合约

以太坊智能合约部署到链上就无法在修改,这样就导致链上合约bug无法修复只能修复bug后重新部署一份合约,替换原来的合约地址。这样也就导致了合约数据的丢失。

解决这样的问题一般有两种解决方案:

1)使用代理合约

使用delegatecall操作码将函数的调用转移到可更新的目标合约中。

2)分离合约逻辑和数据

      将合约拆分成两个合约:

       包含数据的合约(变量、结构、映射等)以及提供getter setter方法修改          数据合约。

       包含逻辑的合约  (业务逻辑+如何更新数据的)

示例:

pragma solidity ^0.4.2;

contract DataContract{

  //访问控制

  maping(address=>bool) accessAllowed;

  mapiing(address => uint256) balances;

function  DataContract(){

    accessAllowed[msg.sender] = true;

  }

  function setAccessAllow(address addr) public allowed {

    accessAllowed[addr ] = true;

  }

  function denyAccessAllow(address addr) public allowed {

    accessAllowed[addr] = false;

  }

  function setBalance(address addr,uint256 value) public {

    balances[addr] +=value;

  }

  function getBalance(address addr) public returns(uint256){

    return  balances[addr];

  }

  modifier allowed{

    require(accessAllowed[msg.sender]==true);

    _;

  }

}

逻辑合约:

pragma solidity ^0.4.2;

interface DataContract{

  function setAccessAllow(address addr) external ;

  function denyAccessAllow(address addr) external ;

  function setBalance(address addr,uint256 value);

  function getBalance(address addr) public returns(uint256);

  }

contract upgradeContract{

// 0xe07294a5432231055eb64ec44917a8cd3b7aa44a

  DataContract dataContract;

  uint256 balaceValue public;

function upgradeContract(address dataAddr){

  dataContract = DataContract(dataAddr);

}

function setBalance(address addr,uint256 value){

    dataContract.setBalance(addr,value);

}

function getBalance(address addr){

    balaceValue = dataContract.getBalance(addr);

}

}

部署方法: 

1. 先部署DataContract合约 

2. 使用DataContract合约地址作为部署ControlContract合约的参数 

3. 用ControlContract合约地址作为参数调用DataContract合约的allowAccess方法。 

如果需要更新控制合约(如修复了addTen)则重新执行第2-3步,同时对老的控制合约执行denyAccess()。

结语

我们在写智能合约的时候最好仔细审计合约,确保无误后在部署到主网上,避免不必要的损失,升级合约必然要升级与之关联的dapp,频繁的更新合约会导致用户的不信任。

你可能感兴趣的:(如何编写可升级合约)