编译器
0.8.17+commit.8df45f5f
文件 1 的 6:Auth.sol
pragma solidity 0.8.17;
import {Authority} from "./Authority.sol";
abstract contract Auth {
event OwnershipTransferred(address indexed user, address indexed newOwner);
event AuthorityUpdated(address indexed user, Authority indexed newAuthority);
address public owner;
Authority public authority;
constructor(address _owner, Authority _authority) {
owner = _owner;
authority = _authority;
emit OwnershipTransferred(msg.sender, _owner);
emit AuthorityUpdated(msg.sender, _authority);
}
modifier requiresAuth() virtual {
require(isAuthorized(msg.sender, msg.sig), "Auth: UNAUTHORIZED");
_;
}
function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) {
Authority auth = authority;
return
(address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) ||
user == owner;
}
function setAuthority(Authority newAuthority) public virtual {
require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig));
authority = newAuthority;
emit AuthorityUpdated(msg.sender, newAuthority);
}
function transferOwnership(address newOwner) public virtual requiresAuth {
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}
文件 2 的 6:Authority.sol
pragma solidity 0.8.17;
interface Authority {
function canCall(address user, address target, bytes4 functionSig) external view returns (bool);
}
文件 3 的 6:EnumerableSet.sol
pragma solidity 0.8.17;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 4 的 6:Governor.sol
pragma solidity 0.8.17;
import {EnumerableSet} from "./Dependencies/EnumerableSet.sol";
import {Authority} from "./Dependencies/Auth.sol";
import {RolesAuthority} from "./Dependencies/RolesAuthority.sol";
contract Governor is RolesAuthority {
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableSet for EnumerableSet.AddressSet;
bytes32 NO_ROLES = bytes32(0);
struct Role {
uint8 roleId;
string roleName;
}
struct Capability {
address target;
bytes4 functionSig;
uint8[] roles;
}
mapping(uint8 => string) internal roleNames;
event RoleNameSet(uint8 indexed role, string indexed name);
constructor(address _owner) RolesAuthority(_owner, Authority(address(this))) {}
function getUsersByRole(uint8 role) external view returns (address[] memory usersWithRole) {
uint256 count;
for (uint256 i = 0; i < users.length(); i++) {
address user = users.at(i);
bool _canCall = doesUserHaveRole(user, role);
if (_canCall) {
count += 1;
}
}
if (count > 0) {
uint256 j = 0;
usersWithRole = new address[](count);
address[] memory _usrs = users.values();
for (uint256 i = 0; i < _usrs.length; i++) {
address user = _usrs[i];
bool _canCall = doesUserHaveRole(user, role);
if (_canCall) {
usersWithRole[j] = user;
j++;
}
}
}
}
function getRolesForUser(address user) external view returns (uint8[] memory rolesForUser) {
uint256 count;
for (uint8 i = 0; i <= type(uint8).max; ) {
if (doesUserHaveRole(user, i)) {
count += 1;
}
if (i < type(uint8).max) {
i = i + 1;
} else {
break;
}
}
if (count > 0) {
uint256 j = 0;
rolesForUser = new uint8[](count);
for (uint8 i = 0; i <= type(uint8).max; ) {
if (doesUserHaveRole(user, i)) {
rolesForUser[j] = i;
j++;
}
if (i < type(uint8).max) {
i = i + 1;
} else {
break;
}
}
}
}
function getRolesFromByteMap(bytes32 byteMap) public pure returns (uint8[] memory roleIds) {
uint256 count;
for (uint8 i = 0; i <= type(uint8).max; ) {
bool roleEnabled = (uint256(byteMap >> i) & 1) != 0;
if (roleEnabled) {
count += 1;
}
if (i < type(uint8).max) {
i = i + 1;
} else {
break;
}
}
if (count > 0) {
uint256 j = 0;
roleIds = new uint8[](count);
for (uint8 i = 0; i <= type(uint8).max; ) {
bool roleEnabled = (uint256(byteMap >> i) & 1) != 0;
if (roleEnabled) {
roleIds[j] = i;
j++;
}
if (i < type(uint8).max) {
i = i + 1;
} else {
break;
}
}
}
}
function getByteMapFromRoles(uint8[] memory roleIds) public pure returns (bytes32) {
bytes32 _data;
for (uint256 i = 0; i < roleIds.length; i++) {
_data |= bytes32(1 << uint256(roleIds[i]));
}
return _data;
}
function getEnabledFunctionsInTarget(
address _target
) public view returns (bytes4[] memory _funcs) {
bytes32[] memory _sigs = enabledFunctionSigsByTarget[_target].values();
if (_sigs.length > 0) {
_funcs = new bytes4[](_sigs.length);
for (uint256 i = 0; i < _sigs.length; ++i) {
_funcs[i] = bytes4(_sigs[i]);
}
}
}
function getRoleName(uint8 role) external view returns (string memory roleName) {
return roleNames[role];
}
function setRoleName(uint8 role, string memory roleName) external requiresAuth {
roleNames[role] = roleName;
emit RoleNameSet(role, roleName);
}
}
文件 5 的 6:IRolesAuthority.sol
pragma solidity 0.8.17;
import "./EnumerableSet.sol";
interface IRolesAuthority {
event UserRoleUpdated(address indexed user, uint8 indexed role, bool enabled);
event PublicCapabilityUpdated(address indexed target, bytes4 indexed functionSig, bool enabled);
event CapabilityBurned(address indexed target, bytes4 indexed functionSig);
event RoleCapabilityUpdated(
uint8 indexed role,
address indexed target,
bytes4 indexed functionSig,
bool enabled
);
enum CapabilityFlag {
None,
Public,
Burned
}
}
文件 6 的 6:RolesAuthority.sol
pragma solidity 0.8.17;
import {IRolesAuthority} from "./IRolesAuthority.sol";
import {Auth, Authority} from "./Auth.sol";
import "./EnumerableSet.sol";
contract RolesAuthority is IRolesAuthority, Auth, Authority {
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableSet for EnumerableSet.AddressSet;
constructor(address _owner, Authority _authority) Auth(_owner, _authority) {}
EnumerableSet.AddressSet internal users;
EnumerableSet.AddressSet internal targets;
mapping(address => EnumerableSet.Bytes32Set) internal enabledFunctionSigsByTarget;
EnumerableSet.Bytes32Set internal enabledFunctionSigsPublic;
mapping(address => bytes32) public getUserRoles;
mapping(address => mapping(bytes4 => CapabilityFlag)) public capabilityFlag;
mapping(address => mapping(bytes4 => bytes32)) public getRolesWithCapability;
function doesUserHaveRole(address user, uint8 role) public view virtual returns (bool) {
return (uint256(getUserRoles[user]) >> role) & 1 != 0;
}
function doesRoleHaveCapability(
uint8 role,
address target,
bytes4 functionSig
) public view virtual returns (bool) {
return (uint256(getRolesWithCapability[target][functionSig]) >> role) & 1 != 0;
}
function isPublicCapability(address target, bytes4 functionSig) public view returns (bool) {
return capabilityFlag[target][functionSig] == CapabilityFlag.Public;
}
function canCall(
address user,
address target,
bytes4 functionSig
) public view virtual override returns (bool) {
CapabilityFlag flag = capabilityFlag[target][functionSig];
if (flag == CapabilityFlag.Burned) {
return false;
} else if (flag == CapabilityFlag.Public) {
return true;
} else {
return bytes32(0) != getUserRoles[user] & getRolesWithCapability[target][functionSig];
}
}
function setPublicCapability(
address target,
bytes4 functionSig,
bool enabled
) public virtual requiresAuth {
require(
capabilityFlag[target][functionSig] != CapabilityFlag.Burned,
"RolesAuthority: Capability Burned"
);
if (enabled) {
capabilityFlag[target][functionSig] = CapabilityFlag.Public;
} else {
capabilityFlag[target][functionSig] = CapabilityFlag.None;
}
emit PublicCapabilityUpdated(target, functionSig, enabled);
}
function setRoleCapability(
uint8 role,
address target,
bytes4 functionSig,
bool enabled
) public virtual requiresAuth {
if (enabled) {
getRolesWithCapability[target][functionSig] |= bytes32(1 << role);
enabledFunctionSigsByTarget[target].add(bytes32(functionSig));
if (!targets.contains(target)) {
targets.add(target);
}
} else {
getRolesWithCapability[target][functionSig] &= ~bytes32(1 << role);
if (getRolesWithCapability[target][functionSig] == bytes32(0)) {
enabledFunctionSigsByTarget[target].remove(bytes32(functionSig));
}
if (enabledFunctionSigsByTarget[target].length() == 0) {
targets.remove(target);
}
}
emit RoleCapabilityUpdated(role, target, functionSig, enabled);
}
function burnCapability(address target, bytes4 functionSig) public virtual requiresAuth {
require(
capabilityFlag[target][functionSig] != CapabilityFlag.Burned,
"RolesAuthority: Capability Burned"
);
capabilityFlag[target][functionSig] = CapabilityFlag.Burned;
emit CapabilityBurned(target, functionSig);
}
function setUserRole(address user, uint8 role, bool enabled) public virtual requiresAuth {
if (enabled) {
getUserRoles[user] |= bytes32(1 << role);
if (!users.contains(user)) {
users.add(user);
}
} else {
getUserRoles[user] &= ~bytes32(1 << role);
if (getUserRoles[user] == bytes32(0)) {
users.remove(user);
}
}
emit UserRoleUpdated(user, role, enabled);
}
}
{
"compilationTarget": {
"contracts/Governor.sol": "Governor"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":true,"internalType":"bytes4","name":"functionSig","type":"bytes4"}],"name":"CapabilityBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":true,"internalType":"bytes4","name":"functionSig","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"PublicCapabilityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"role","type":"uint8"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":true,"internalType":"bytes4","name":"functionSig","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"RoleCapabilityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"role","type":"uint8"},{"indexed":true,"internalType":"string","name":"name","type":"string"}],"name":"RoleNameSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint8","name":"role","type":"uint8"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"UserRoleUpdated","type":"event"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"functionSig","type":"bytes4"}],"name":"burnCapability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"functionSig","type":"bytes4"}],"name":"canCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"capabilityFlag","outputs":[{"internalType":"enum IRolesAuthority.CapabilityFlag","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"role","type":"uint8"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"functionSig","type":"bytes4"}],"name":"doesRoleHaveCapability","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint8","name":"role","type":"uint8"}],"name":"doesUserHaveRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"roleIds","type":"uint8[]"}],"name":"getByteMapFromRoles","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"getEnabledFunctionsInTarget","outputs":[{"internalType":"bytes4[]","name":"_funcs","type":"bytes4[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"role","type":"uint8"}],"name":"getRoleName","outputs":[{"internalType":"string","name":"roleName","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getRolesForUser","outputs":[{"internalType":"uint8[]","name":"rolesForUser","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"byteMap","type":"bytes32"}],"name":"getRolesFromByteMap","outputs":[{"internalType":"uint8[]","name":"roleIds","type":"uint8[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"getRolesWithCapability","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getUserRoles","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"role","type":"uint8"}],"name":"getUsersByRole","outputs":[{"internalType":"address[]","name":"usersWithRole","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"functionSig","type":"bytes4"}],"name":"isPublicCapability","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"functionSig","type":"bytes4"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setPublicCapability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"role","type":"uint8"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"functionSig","type":"bytes4"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setRoleCapability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"role","type":"uint8"},{"internalType":"string","name":"roleName","type":"string"}],"name":"setRoleName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint8","name":"role","type":"uint8"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setUserRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]