以太坊智能合约部署到链上就无法在修改,这样就导致链上合约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,频繁的更新合约会导致用户的不信任。
网友评论