create account

代理升级模式 / 学习智能合约#61 by lemooljiang

View this thread on: hive.blogpeakd.comecency.com
· @lemooljiang ·
$0.58
代理升级模式 / 学习智能合约#61
前不久研究了下重入攻击的玩法,里面有个重要的特性:**合约的fallback()函数。** fallback是合约的底层函数,在没有其它函数匹配的情况下会执行。这个特性导致了重入的风险性,但在另一方面,合约的升级性也会用到这一特性。这充分体现了一物的两面性:是好是坏取决于你!

由于区块链不可篡改性,合约如果有漏洞就很难更改!那么,怎么才能安全地升级合约呢?这里要用到一种解藕的想法。把一个合约分成:代理、数据和逻辑三部分,通常要升级的也就是逻辑部分,其它不受影响,如下图所示:

![proxy.jpg](https://ipfs.ilark.io/ipfs/QmevMvGBShbhVJaF8x9AkNErLywfzhnZKpVuH3afZmdWMn)

我们来看下具体实现:

```js
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

//定义数据合约
contract storageStructure {
    //记录球员和分数
    address public implementation;//逻辑合约地址
    mapping(address=>uint256) public points;
    address public owner;
}

//定义逻辑合约
contract implementationV1 is storageStructure {
    modifier onlyowner()  {
        require(msg.sender == owner, "only owner can do");
        _;
    }
    //增加球员和分数
    function addPlayer(address player, uint256 point) public onlyowner {
        require(points[player] == 0, "player already exists");
        points[player] = point;
    }
    //修改球员和分数
    function setPlayer(address player, uint256 point) public onlyowner {
        require(points[player] != 0, "player must already exists");
        points[player] = point;
    }
}

//代理合约 代理合约调用逻辑合约的逻辑去修改本身(代理合约)的数据
contract proxy is storageStructure {
    modifier onlyowner()  {
        require(msg.sender == owner, "only owner can call");
        _;
    }
    
    constructor()  {
        owner = msg.sender;
    }
    
    //更新逻辑合约的地址
    function setImpl(address _impl) public onlyowner {
        implementation = _impl;
    }
    
    //fallback函数 调用逻辑合约中的函数,在本地(代理合约)执行
    fallback() external {
        address impl = implementation; //逻辑合约的地址
        require(impl != address(0), "implementation must exists");
        
        //底层调用
        assembly {
            //调用delegateccall
            let ptr := mload(0x40)
            calldatacopy(ptr, 0, calldatasize())
            //delegatecall(g, a, in, insize, out, outsize)
            let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0)
            let size := returndatasize()
            
            //returndatacopy(t, f, s)
            returndatacopy(ptr, 0, size)
            
            switch result 
                case 0 { revert(ptr, size) }
                default { return(ptr, size) }
        }
    }  
}
```

可以看出,里面最核心的就是`assembly中调用delegateccall`。`assembly`属于汇编的写法,是比较底层的语法(yul),不太好理解。我们大概可以理解整个地调用过程:用户调用代理合约,代理合约调用逻辑合约修改本身的数据。**如果需要升级,代理合约调用逻辑合约时就可以指向新的逻辑合约即可!**

![proxy2.jpg](https://ipfs.ilark.io/ipfs/QmengeoafwcJhZQrZYQ9riVqYFffkoYwbGf42mnYoV9jBY)

```js
//逻辑合约升级
contract implementationV2 is implementationV1 {
    function addPlayer(address player, uint256 point) override public onlyowner virtual {
        require(points[player] == 0, "player already exists");
        points[player] = point;
        totalPlayers ++;
    }
}
```

升级合约差不多就是个解藕的思路,分成三个部分,把需要升级的部分单独更改升级就可以啰!
👍  , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
properties (23)
authorlemooljiang
permlinktnza9jgp
categoryhive-105017
json_metadata{"tags":["smartcontract","cn","eth","implementation","assembly","proxy","solidity"],"dapp":"larkBlog","format":"markdown"}
created2022-10-30 09:46:27
last_update2022-10-30 09:46:27
depth0
children1
last_payout2022-11-06 09:46:27
cashout_time1969-12-31 23:59:59
total_payout_value0.290 HBD
curator_payout_value0.285 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length2,819
author_reputation378,459,582,201,132
root_title"代理升级模式 / 学习智能合约#61"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id117,904,149
net_rshares902,162,845,784
author_curate_reward""
vote details (30)
@marygong77777 · (edited)
👍👍
properties (22)
authormarygong77777
permlinkre-lemooljiang-20221030t185458522z
categoryhive-105017
json_metadata{"tags":["hive-105017","smartcontract","cn","eth","implementation","assembly","proxy","solidity"],"app":"ecency/3.0.34-mobile","format":"markdown+html"}
created2022-10-30 10:55:03
last_update2022-10-30 10:55:18
depth1
children0
last_payout2022-11-06 10:55:03
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length2
author_reputation205,730,515,670,751
root_title"代理升级模式 / 学习智能合约#61"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id117,905,074
net_rshares0