Last active
November 14, 2022 15:26
-
-
Save bodrovis/38f4e1edc57f180392db1e361ee88cd0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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