这篇文章上次修改于 499 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
场景:eth的智能合约规定是发布后不可修改的,但是在实际场景中,由于业务的不断升级,需求不断变化,可能需要去修改合约已满足业务需要。
思路:编写2个合约,一个合约用来保存数据,一份合约用来实现逻辑,当业务变化时,数据合约不用变,只需要用新的逻辑合约替换老的逻辑合约。
下面是我写的一个合约样例:
pragma solidity ^0.4.18;
/**
* 数据合约
*
*/
contract KccData{
mapping ( address => uint256 ) public balances;
mapping (address => bool) accessAllowed;
mapping ( address => uint8 ) public lockAccounts;
uint256 public totalNum;
address owner;
uint8 public decimals = 18;
function KccData( uint256 totalB ) public{
totalNum = totalB * 10 ** uint256(decimals);
owner = msg.sender;
balances[owner] = totalNum;
accessAllowed[owner] = true;
}
/*权限检查修饰符*/
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;
}
/*增加代币*/
function incr(address _addr, uint256 num) platform public returns (bool){
require( num > 0 );
balances[_addr] += num;
}
/*减少代币*/
function decr(address _addr, uint256 num) platform public returns (bool){
require( num > 0 );
require( balances[_addr] >= num );
balances[_addr] -= num;
}
/*冻结账户*/
function freezeAccount(address _addr) platform public returns (bool){
require( _addr != owner );
lockAccounts[_addr] = 1;
return true;
}
/*解冻账户*/
function unfreezeAccount( address _addr ) platform public returns (bool){
lockAccounts[_addr] = 0;
return true;
}
/*增加总数量*/
function incrTotalNum( uint256 num ) platform public returns (bool){
totalNum += num;
return true;
}
}
/**
* 逻辑合约
*
*/
contract Kcc{
address owner;
KccData dataContract;
event SendEvent(address to, uint value, bool result);
event Transfer(address indexed from, address indexed to, uint256 value, uint256 fees);
/**
* KccDataContractAddr 数据合约的合约地址
* 部署完此逻辑合约后,需要调用数据合约的allowAccess 方法,将此逻辑合约的合约地址加入到数据合约的可调用白名单中
*
*/
function Kcc( address KccDataContractAddr ) public{
dataContract = KccData(KccDataContractAddr);
owner = msg.sender;
}
/*向当前合约存款*/
function deposit() payable public {
}
/*发送eth给地址to*/
function sendEther(address to, uint value) public {
require(msg.sender==owner);
bool result = to.send(value);
emit SendEvent(to, value, result);
}
/*增发代币*/
function addTotalNum( uint256 addNum ) public returns (bool){
require( addNum > 0 );
require( msg.sender == owner );
dataContract.incrTotalNum(addNum);
dataContract.incr(owner, addNum);
return true;
}
/*空投代币*/
function issue( address to, uint256 num )public returns (bool){
require( msg.sender == owner );
require( num > 0 );
require( num < dataContract.balances(owner) );
require( dataContract.lockAccounts(to) != 1 );
dataContract.incr(to,num);
dataContract.decr(owner, num);
emit Transfer(owner, to, num, 0);
}
/*转账,gas由个人[消息发送者]支付*/
function transfer( address to, uint256 num )public returns (bool){
_transfer( msg.sender, to, num, 0 );
return true;
}
/*
* 转账,gas由合约创建者支付 即平台支付
* fees 平台收取的手续费
*/
function p2pTrans( address from, address to, uint256 num, uint256 fees ) public returns (bool success) {
require( msg.sender == owner );
require( from != owner );
require( to != owner );
_transfer(from, to, num, fees);
return true;
}
/*内部转账方法*/
function _transfer(address _from, address _to, uint _value, uint _fees ) internal {
require(_to != 0x0);
require(dataContract.balances(_from) >= _value);
require(dataContract.balances(_to) + _value >= dataContract.balances(_to));
require(dataContract.lockAccounts(_from) != 1 );
require(dataContract.lockAccounts(_to) != 1 );
require(_fees >= 0);
require(_value > _fees);
dataContract.decr(_from, _value);
dataContract.incr(_to, _value - _fees);
if( _fees > 0 ){
dataContract.incr(owner,_fees);
}
emit Transfer(_from, _to, _value, _fees);
}
/*获取指定账户代币余额*/
function getBalance(address account) public constant returns (uint256) {
return dataContract.balances(account);
}
/*冻结账户*/
function freezeAccount(address account) public returns (bool){
require( msg.sender == owner );
require( account != owner );
dataContract.freezeAccount( account );
return true;
}
/*解冻账户*/
function unfreezeAccount( address account ) public returns (bool){
require( msg.sender == owner );
dataContract.unfreezeAccount( account );
return true;
}
/*检查某个账户是否被冻结*/
function getAccountIsFreeze( address account ) public constant returns (uint8){
uint8 r ;
if( dataContract.lockAccounts(account) == 1 ){
r = 1;
}
return r;
}
/*获取合约创建者的地址*/
function getOwnerAddr() public constant returns (address) {
return owner;
}
/*获取合约的总发行量*/
function getTotalNum() public constant returns (uint256){
return dataContract.totalNum();
}
/*获取合约剩余可用代币数量*/
function getHasNum() public constant returns (uint256){
return dataContract.balances(owner);
}
}
没有评论