【以太坊 Solidity】管理员读写权限/访问控制/角色控制
摘要
在 Solidity 语言的多继承中,若多个合约
共同继承一个父合约
,则这多个合约
共享 父合约
中的变量和函数。
1.测试的智能合约
合约继承路线如下:
#mermaid-svg-DtimeTjOch5CJh50 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-DtimeTjOch5CJh50 .error-icon{fill:#552222;}#mermaid-svg-DtimeTjOch5CJh50 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DtimeTjOch5CJh50 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-DtimeTjOch5CJh50 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DtimeTjOch5CJh50 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DtimeTjOch5CJh50 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DtimeTjOch5CJh50 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DtimeTjOch5CJh50 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DtimeTjOch5CJh50 .marker.cross{stroke:#333333;}#mermaid-svg-DtimeTjOch5CJh50 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DtimeTjOch5CJh50 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DtimeTjOch5CJh50 .cluster-label text{fill:#333;}#mermaid-svg-DtimeTjOch5CJh50 .cluster-label span{color:#333;}#mermaid-svg-DtimeTjOch5CJh50 .label text,#mermaid-svg-DtimeTjOch5CJh50 span{fill:#333;color:#333;}#mermaid-svg-DtimeTjOch5CJh50 .node rect,#mermaid-svg-DtimeTjOch5CJh50 .node circle,#mermaid-svg-DtimeTjOch5CJh50 .node ellipse,#mermaid-svg-DtimeTjOch5CJh50 .node polygon,#mermaid-svg-DtimeTjOch5CJh50 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DtimeTjOch5CJh50 .node .label{text-align:center;}#mermaid-svg-DtimeTjOch5CJh50 .node.clickable{cursor:pointer;}#mermaid-svg-DtimeTjOch5CJh50 .arrowheadPath{fill:#333333;}#mermaid-svg-DtimeTjOch5CJh50 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DtimeTjOch5CJh50 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DtimeTjOch5CJh50 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-DtimeTjOch5CJh50 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-DtimeTjOch5CJh50 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DtimeTjOch5CJh50 .cluster text{fill:#333;}#mermaid-svg-DtimeTjOch5CJh50 .cluster span{color:#333;}#mermaid-svg-DtimeTjOch5CJh50 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DtimeTjOch5CJh50 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
1.1 权限管理合约
// SPDX-License-Identifier: GPL-3.0
// filename: authority.sol
pragma solidity ^0.8.18;
contract Authority {
address private OWNER;
mapping(address => bool) private ADMIN;
constructor() {
OWNER = msg.sender;
ADMIN[OWNER] = true; // !注意,此处意为授予合约拥有者管理员权限
}
modifier isOwner() {
require(msg.sender == OWNER, unicode"非合约拥有者");
_;
}
// 修饰函数,被修饰的函数仅管理员才可调用
modifier isAdmin() {
require(ADMIN[msg.sender] == true, unicode"无管理员权限");
_;
}
function addAdmin(address addrs) public isOwner {
ADMIN[addrs] = true;
}
function removeAdmin(address addrs) public isOwner {
ADMIN[addrs] = false;
}
}
1.2 继承权限管理合约的基类合约
// SPDX-License-Identifier: GPL-3.0
// filename: base.sol
pragma solidity ^0.8.18;
import { Authority } from "./authority.sol";
// 继承 Authority 合约,继而使用 isAdmin() 修饰函数
contract A is Authority {
string a = "aaa";
// 仅管理员才可调用 getAstring()
function getAstring() isAdmin public view returns (string memory) {
return a;
}
}
contract B is Authority {
string b = "bbb";
function getBstring() isAdmin public view returns (string memory) {
return b;
}
}
1.3 待测试的合约
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;
import { A, B } from "./base.sol";
contract Test is A, B {
// 合约 Test 继承了 A 中的 a, getAstring() 以及
// B 中的 b, getBstring()
}
2.权限管理合约测试
2.1 正向测试:合约拥有者OWNER具有管理员权限
此时 合约 Authority
中的 构造函数 constructor()
中的 ADMIN[OWNER] = true
,意为 OWNER 具有管理员权限。
经 Remix 中测试,Test 合约的部署者具有管理员权限,能正常调用继承的函数,如下:
2.2 反向测试:合约拥有者OWNER没有管理员权限
此步测试中将 合约 Authority
中的 构造函数 constructor()
中改为 ADMIN[OWNER] = false
,意为 用户 OWNER 没有了管理员权限,测试测试结果如下:
3.总结
合约继承图:
#mermaid-svg-KFCYHbbZi97v6Stp {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-KFCYHbbZi97v6Stp .error-icon{fill:#552222;}#mermaid-svg-KFCYHbbZi97v6Stp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KFCYHbbZi97v6Stp .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-KFCYHbbZi97v6Stp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KFCYHbbZi97v6Stp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KFCYHbbZi97v6Stp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KFCYHbbZi97v6Stp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KFCYHbbZi97v6Stp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KFCYHbbZi97v6Stp .marker.cross{stroke:#333333;}#mermaid-svg-KFCYHbbZi97v6Stp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KFCYHbbZi97v6Stp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KFCYHbbZi97v6Stp .cluster-label text{fill:#333;}#mermaid-svg-KFCYHbbZi97v6Stp .cluster-label span{color:#333;}#mermaid-svg-KFCYHbbZi97v6Stp .label text,#mermaid-svg-KFCYHbbZi97v6Stp span{fill:#333;color:#333;}#mermaid-svg-KFCYHbbZi97v6Stp .node rect,#mermaid-svg-KFCYHbbZi97v6Stp .node circle,#mermaid-svg-KFCYHbbZi97v6Stp .node ellipse,#mermaid-svg-KFCYHbbZi97v6Stp .node polygon,#mermaid-svg-KFCYHbbZi97v6Stp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KFCYHbbZi97v6Stp .node .label{text-align:center;}#mermaid-svg-KFCYHbbZi97v6Stp .node.clickable{cursor:pointer;}#mermaid-svg-KFCYHbbZi97v6Stp .arrowheadPath{fill:#333333;}#mermaid-svg-KFCYHbbZi97v6Stp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KFCYHbbZi97v6Stp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KFCYHbbZi97v6Stp .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-KFCYHbbZi97v6Stp .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-KFCYHbbZi97v6Stp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KFCYHbbZi97v6Stp .cluster text{fill:#333;}#mermaid-svg-KFCYHbbZi97v6Stp .cluster span{color:#333;}#mermaid-svg-KFCYHbbZi97v6Stp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KFCYHbbZi97v6Stp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
虽然 合约 A,B,Test 都直接或间接继承了 合约 Authority,但是 合约 A,B,Test 都 “ 共享 ” 了 合约 Authority 中的 变量 ADMIN
,函数 isAdmin()
等。