Solidity智能合约专题

Solidity合约代理模式的简单示例

2022-11-08  本文已影响0人  梁帆

一、概述

这个合约示例中,我们有以下几个文件:

Types.sol
IProcessor.sol
Processor.sol
Proxy.sol
Client.sol

分别论述下文件的作用:
Types.sol定义了一些基本类型,与业务逻辑无关;
IProcessor.sol:关键合约,定义了Processor的接口;
Processor.sol:关键合约,定义了实际对数据的逻辑操作;
Proxy.sol:关键合约,定义了数据以及逻辑操作合约Processor的地址;
Client.sol定义了用户操作Proxy合约的方法,免去手动将IProcessor赋予Proxy的过程。

1.Types.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

enum Gender {
    Male,
    Female
}

struct Student {
    string name;
    Gender gender;
    uint256 age;
}

2.IProcessor.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import {Gender} from "./Types.sol";

interface IProcessor {
    function setStudentName(string memory) external;
    function setStudentGender(Gender) external;
    function setStudentAge(uint256) external;
}

3.Processor.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "./IProcessor.sol";
import {Gender, Student} from "./Types.sol";

contract Processor is IProcessor {
    Student public student;
    address public processor;

    function setStudentName(string calldata _name) override external {
        student.name = _name;
    }

    function setStudentGender(Gender _gender) override external {
        student.gender = _gender;
    }

    function setStudentAge(uint256 _age) override external {
        student.age = _age;
    }
}

4.Proxy.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "./IProcessor.sol";
import {Student} from "./Types.sol";

contract Proxy {
    Student public student;
    address public processor;

    function setProcessor(address _processor) external {
        processor = _processor;
    }

    fallback() external payable  {
        (bool success, bytes memory data) = processor.delegatecall(msg.data);
        require(
            success,
            "error"
        );
    }
}

5.Client.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "./IProcessor.sol";
import {Gender, Student} from "./Types.sol";

contract Client {
    IProcessor ip;

    constructor(address _proxy) {
        ip = IProcessor(_proxy);
    }

    function setName(string calldata _name) external {
        ip.setStudentName(_name);
    } 

    function setGender(Gender _gender) external {
        ip.setStudentGender(_gender);
    }

    function setAge(uint256 _age) external {
        ip.setStudentAge(_age);
    }
}

我们用Client进行操作,比如说,执行setName函数,输入的参数为字符串Tom,接下来,就是触发IProcessor类型的代理合约Proxy去执行setStudentName,但事实上,代理合约中并没有setStudentName,因此会去执行fallback函数,fallback函数中有关键的delegatecall函数,它会委托Processor合约去执行setStudentName的函数逻辑,但是改变的是Proxy合约上的student值。这样就实现了数据逻辑的分离。下次如果我们需要升级逻辑处理合约就非常简单了——在Proxy中,使用setProcessor函数将旧的Processor合约替换成新的Processor合约即可。

二、缺陷

这个实现主要有两个缺陷。

这两个问题其实都有解决方案,请看下一篇:《Solidity合约代理模式的几个技术技巧》

上一篇下一篇

猜你喜欢

热点阅读