理解 通用可升级代理(UUPS) 模式

理解 UUPS 模式:以太坊智能合约的可升级方案

什么是 UUPS 模式?

UUPS(Universal Upgradeable Proxy Standard)是以太坊上用于实现智能合约可升级性的一种模式。它依赖于代理合约和逻辑合约的分离。

由于UUPS模式将升级函数放在了逻辑合约中,避免了潜在的,升级函数与代理合约中函数的函数选择器冲突。

UUPS 模式的核心概念

  1. 代理合约(Proxy Contract):负责接收和转发所有调用,并将调用委托给逻辑合约。
  2. 逻辑合约(Logic Contract):包含实际的业务逻辑代码,可以随时更换新的逻辑合约以实现升级。
  3. 升级函数:逻辑合约内包含一个专门的函数,用于处理升级过程。

DEMO

代理合约

contract UUPSProxy {
    address public implementation; // 逻辑合约地址
    address public admin; // admin地址
    string public words; // 字符串,可以通过逻辑合约的函数改变

    // 构造函数,初始化admin和逻辑合约地址
    constructor(address _implementation){
        admin = msg.sender;
        implementation = _implementation;
    }

    // fallback函数,将调用委托给逻辑合约
    fallback() external payable {
        (bool success, bytes memory data) = implementation.delegatecall(msg.data);
    }
}

实现合约

// UUPS逻辑合约(升级函数写在逻辑合约内)
contract UUPS1{
    // 状态变量和proxy合约一致,防止插槽冲突
    address public implementation; 
    address public admin; 
    string public words; // 字符串,可以通过逻辑合约的函数改变

    // 改变proxy中状态变量,选择器: 0xc2985578
    function foo() public{
        words = "old";
    }

    // 升级函数,改变逻辑合约地址,只能由admin调用。选择器:0x0900f010
    // UUPS中,逻辑合约中必须包含升级函数,不然就不能再升级了。
    function upgrade(address newImplementation) external {
        require(msg.sender == admin);
        implementation = newImplementation;
    }
}

// 新的UUPS逻辑合约
contract UUPS2{
    // 状态变量和proxy合约一致,防止插槽冲突
    address public implementation; 
    address public admin; 
    string public words; // 字符串,可以通过逻辑合约的函数改变

    // 改变proxy中状态变量,选择器: 0xc2985578
    function foo() public{
        words = "new";
    }

    // 升级函数,改变逻辑合约地址,只能由admin调用。选择器:0x0900f010
    // UUPS中,逻辑合约中必须包含升级函数,不然就不能再升级了。
    function upgrade(address newImplementation) external {
        require(msg.sender == admin);
        implementation = newImplementation;
    }
}
posted @ 2021-06-01 14:53  sorachannel  阅读(544)  评论(0)    收藏  举报