Skip to content

Instantly share code, notes, and snippets.

@bodrovis
Last active November 14, 2022 15:26
Show Gist options
  • Save bodrovis/38f4e1edc57f180392db1e361ee88cd0 to your computer and use it in GitHub Desktop.
Save bodrovis/38f4e1edc57f180392db1e361ee88cd0 to your computer and use it in GitHub Desktop.
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
abstract contract AccessControl {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, msg.sender);
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
"no role"
);
}
}
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual {
require(account == msg.sender, "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
//emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
//emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
//emit RoleRevoked(role, account, _msgSender());
}
}
}
import { loadFixture, ethers, expect, time } from "./setup";
import type { Demo } from "../typechain-types";
describe("Demo", function() {
async function deploy() {
const [ superadmin, withdrawer, payer ] = await ethers.getSigners();
const Factory = await ethers.getContractFactory("Demo");
const demo: Demo = await Factory.deploy(withdrawer.address);
await demo.deployed();
return { superadmin, demo, payer, withdrawer }
}
it('works', async function() {
const { superadmin, demo, payer, withdrawer } = await loadFixture(deploy);
console.log(await demo.getRoleAdmin(await demo.WITHDRAWER_ROLE()), await demo.DEFAULT_ADMIN_ROLE());
await demo.connect(withdrawer).grantRole(await demo.PAYER_ROLE(), payer.address);
await demo.connect(withdrawer).withdraw();
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment