AccessControl Role-Based Control, unable to grant desired role?

Hi everyone, I’m very new to learning Ethereum and employing Smart Contract and I am facing an issue regarding AccessControl that is not able to grant a role to other blocks, despite having an admin role.

From the Docs:
"Each role has an associated admin role, and only accounts that have a role’s admin role can call grantRole and revokeRole "

^From above, how do I go about “calling” said commands to execute into Ganache/Metamask?

Here is the snippet of the Smart Contract using AccessControl:

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;

import "@openzeppelin/contracts/access/AccessControl.sol";

contract VaccinationCertificates is AccessControl {
  // Certificate Authority can issue certificates
  bytes32 public constant CERTIFICATE_AUTHORITY_ROLE = keccak256("CERTIFICATE_AUTHORITY_ROLE");
  // Certificate Authority Admin can issue Certificate Authority roles
  bytes32 public constant CERTIFICATE_AUTHORITY_ADMIN_ROLE = keccak256("CERTIFICATE_AUTHORITY_ADMIN_ROLE");

  mapping(address => bytes32) public certificateAuthorityNames;

  event CertificateAuthorityNameSet(
    address authority,
    bytes32 name
  );

  struct Certificate {
    bytes32 signature;
    address authority;
    uint timestamp;
  }

  mapping(bytes32 => Certificate) public certificates;
  bytes32[] public signatures;

  event CertificateIssued(
    bytes32 signature,
    address authority,
    uint timestamp
  );

  constructor() public {
    // Defining Admin role for Certificate Authority role
    _setRoleAdmin(CERTIFICATE_AUTHORITY_ROLE, CERTIFICATE_AUTHORITY_ADMIN_ROLE);
    
    // Owner is an admin
    _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
  }

  function issueCertificate(bytes32 _signature) public {
    require(hasRole(CERTIFICATE_AUTHORITY_ROLE, msg.sender), "Caller is not a Certificate Authority");
    require(certificates[_signature].timestamp == 0, "Can't overwrite existing certificate");

    signatures.push(_signature);

    certificates[_signature] = Certificate({
      signature: _signature,
      authority: msg.sender,
      timestamp: now
    });

    emit CertificateIssued(_signature, msg.sender, now);
  }

  function setCertificateAuthorityName(address _address, bytes32 _name) public {
    require(hasRole(CERTIFICATE_AUTHORITY_ADMIN_ROLE, msg.sender), "Caller is not a Certificate Authority Admin");
    require(hasRole(CERTIFICATE_AUTHORITY_ROLE, _address), "Given address is not a Certificate Authority");

    certificateAuthorityNames[_address] = _name;

    emit CertificateAuthorityNameSet(_address, _name);
  }

  // TODO: Implement pagination
  function getSignatures() public view returns(bytes32[] memory) {
    return signatures;
  }
}

Deployment to Truffle is via:

const VaccinationCertificates = artifacts.require("VaccinationCertificates");

module.exports = function (deployer) {
  deployer.deploy(VaccinationCertificates);
};

Hence, what am I doing wrong such that the admin role is incapable of granting/revoking the roles for the accounts in the blockchain? Otherwise, how do I go about setting authority for every new block (Account in Metamask) to be granted?

Thanks in advance for the help!

Your roles are organized like this currently:

Where A → B means “A is admin of B”.

In your constructor you assign the default admin role to the deployer (msg.sender). This means the msg.sender is able to grant and revoke the certificate authority admin role. But until you grant that other role to an account, no one is able to grant the certificate authority role.

Consider adding:

_setupRole(CERTIFICATE_AUTHORITY_ADMIN_ROLE, msg.sender);

Sorry for the late reply. I managed to perform the solution to grant the admin role to the first initialized block in the blockchain. Now, when I want to grant the ```CERTIFICATE_AUTHORITY_ROLE" in other blocks in the blockchain on Ganache.

Hence, is the AccessControl to grant role for the other blocks based on a ‘trigger basis’ in the code? How do I go about having the block with the AdminRole to grantRole to other blocks?

Thanks.

How do I get block address 0xbC1 (admin) to grantRole to 0x4d6 such that block 0x4d6 is authorized to performed operations? Is a UI/Button required for the admin to trigger a _setRole for the rest of the blocks?

@GenerallySpeaking I’ve deleted the image since it contained a mnemonic (private key!). Even if it’s for a local Ganache network with no real funds, it’s still preferable that you don’t share it.


I don’t fully understand your question. You need to call the function grantRole from an admin account, with the right arguments. What arguments do you want to use?

Hi, noted on the mnemonic. If I’m using an account that is DEFAULT_ADMIN_ROLE to invoke a grantRole to another account, is this process an internal function? Does that mean if I want an Admin Role to grant Admin privilege to another user, I have to pre-set this configuration? How is this process invoked through a front-end operation?

Sorry if I’m not exactly clear with my intentions. Basically the order of hierarchy exists like this:

At the very beginning of the blockchain, there was a single authority. This authority created authorities for other countries. Later on, each country created separate authorities, that are actually responsible for vaccination (doctors/hospitals etc.). Each authority has a public and a private key that are used to push data into the blockchain.

The protocol of this blockchain allows creating blocks that can revoke the authorities and certificates by authorities of a higher order.

Hence, the CERTIFICATE_AUTHORITY_ADMIN is responsible for creating/granting authorities in the blockchain on Ganache but because each block in the blockchain have unique address and wallet, how is the AccessControl able to acknowledge such dynamic information?

did you find a solution yet