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

一、概述

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

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合约即可。

二、缺陷

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

  • 其一是Proxy中的fallback函数执行delegatecall后,有两个返回值,一个是bool类型的success,一个是bytes类型的data。这个示例中我们的Processor合约中的函数没有返回值,倒无所谓,如果有返回值的话,我们其实是需要返回给调用者的。
  • 其二是为了使得delegatecall的顺利执行,ProxyProcessor两个合约保持了相同的变量存储结构,但实际执行时Processor中的变量却仅仅是摆设,这样的设计就显得累赘,不够优雅。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容