From 5804b9d492c7028bad7850052d79561db001e7aa Mon Sep 17 00:00:00 2001 From: Eric Badiere Date: Mon, 11 Dec 2023 19:55:20 -0700 Subject: [PATCH] feat: added OZ Access control example (#539) (#609) * 539 OZ Access control example Signed-off-by: ebadiere * Applied feedback Signed-off-by: ebadiere * Fixed tag. Signed-off-by: ebadiere --------- Signed-off-by: ebadiere --- .../access-control/AccessControlContract.sol | 30 ++++++++ test/OZ/access-control/accessControl.js | 68 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 contracts/oz/access-control/AccessControlContract.sol create mode 100644 test/OZ/access-control/accessControl.js diff --git a/contracts/oz/access-control/AccessControlContract.sol b/contracts/oz/access-control/AccessControlContract.sol new file mode 100644 index 000000000..71d3c6591 --- /dev/null +++ b/contracts/oz/access-control/AccessControlContract.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/access/AccessControl.sol"; + +contract AccessControlContract is AccessControl { + // Define roles + bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); + bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); + + constructor() { + // Assign the deployer (msg.sender) the admin role + _grantRole(ADMIN_ROLE, msg.sender); + } + + // Function that can only be called by users with the admin role + function adminFunction() public view onlyRole(ADMIN_ROLE) returns (string memory) { + return "This function can only be called by administrators"; + } + + // Function that can only be called by users with the manager role + function managerFunction() public view onlyRole(MANAGER_ROLE) returns (string memory) { + return "This function can only be called by managers"; + } + + // Function to grant the manager role to an address + function grantManagerRole(address account) public onlyRole(ADMIN_ROLE) { + _grantRole(MANAGER_ROLE, account); + } +} diff --git a/test/OZ/access-control/accessControl.js b/test/OZ/access-control/accessControl.js new file mode 100644 index 000000000..4ca6b0f6e --- /dev/null +++ b/test/OZ/access-control/accessControl.js @@ -0,0 +1,68 @@ +/*- + * + * Hedera Smart Contracts + * + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +const { expect } = require("chai"); +const { ethers } = require("hardhat"); +const Constants = require('../../constants') + +describe("@OZAccessControlContract", function () { + let admin; + let manager; + let user; + let accessContract; + + const ADMIN_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("ADMIN_ROLE")); + const MANAGER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("MANAGER_ROLE")); + + + // Deploy the contract and set up roles before each test + beforeEach(async function () { + [admin, manager, user] = await ethers.getSigners(); + + const AccessControlContract = await ethers.getContractFactory("AccessControlContract"); + accessContract = await AccessControlContract.deploy(Constants.GAS_LIMIT_1_000_000); + await accessContract.deployed(); + + // Grant the MANAGER_ROLE to the manager address + await accessContract.connect(admin).grantManagerRole(manager.address); + }); + + it("admin should call adminFunction successfully", async function () { + const result = await accessContract.connect(admin).adminFunction(); + expect(result).to.equal("This function can only be called by administrators"); + }); + + it("manager should call managerFunction successfully", async function () { + const result = await accessContract.connect(manager).managerFunction(); + expect(result).to.equal("This function can only be called by managers"); + }); + + it("user should not be able to call adminFunction", async function () { + await expect(accessContract.connect(user).adminFunction()) + .to.be.revertedWithCustomError(accessContract, "AccessControlUnauthorizedAccount") + .withArgs(user.address, ADMIN_ROLE); + }); + + it("user should not be able to call managerFunction", async function () { + await expect(accessContract.connect(user).managerFunction()) + .to.be.revertedWithCustomError(accessContract, "AccessControlUnauthorizedAccount") + .withArgs(user.address, MANAGER_ROLE); + }); +});