How to inherit from AccessControl to create a DenyList

I write a contract which inheritance AccessControl.sol,checkUser() :The first requirement is that the user cannot be on the blacklist,then check if user does have the role he assert.
but when i call this ,the function does not return the correct value
:computer: Environment

openzeppelin --version :2.8.2

:memo:Details

you see,I grant two different roles for each user and add one of the users to the blacklist.
so results display call failed when i check the user who in the blacklist,which is correct:

but when i check another user,the result should have returned true instead of false:
So I wonder what’s wrong with my contract?thank you :blush:
图片
:1234: Code to reproduce

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

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

contract Black is AccessControl,Ownable{

    mapping(address => bool) public blacklist;

    event Blacklisted(address account);
    event Unblacklisted(address account);

    constructor() public {
    _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
}

    function isBlacklist(address _account)
        public
        view
        onlyOwner
        returns (bool)
    {
        return blacklist[_account];
    }

    function checkUser(bytes32 role, address _account) public view  returns (bool){
        require(!isBlacklist(_account), "This user is Blacklisted");
        hasRole(role,_account);
    }

}
1 Like

I think maybe the reason is about:mapping (bytes32 => RoleData) private _roles;??
Should I create struct for each role?
like:
constructor() public {
_roles[…]=RoleData(…,0x00);
}

please help me .I don’t know how to resolve it… :sob:

1 Like

But when I call hasRole(),It works very well…
So what went wrong?

1 Like

Hi @wangyuyue,

You could try using AccessControl for your Deny List. I created a proof of concept of what this might look like.

:warning: The following contract has not been tested nor audited. Any such solution should be appropriately tested and audited

MyContract.sol

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

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

contract MyContract is AccessControl {
    bytes32 public constant DENY_ROLE = keccak256("DENY_ROLE");

    bool public stuff = false;

    constructor() public {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
    }

    function addDenyListed(address account) public {
        grantRole(DENY_ROLE, account);
    }

    function removeDenyListed(address account) public {
        revokeRole(DENY_ROLE, account);
    }

    function renounceRole(bytes32 role, address account)
        public
        virtual
        override
    {
        require(role != DENY_ROLE, "MyContract: cannot renounce deny role");

        super.renounceRole(role, account);
    }

    function priviledgedDoStuff() public {
        require(!(hasRole(DENY_ROLE, msg.sender)), "MyContract: cannot call with deny role");
        stuff = true;
    }
}

Display accounts

$ npx oz accounts
? Pick a network development
Accounts for dev-1593569427827:
Default: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
All:
- 0: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
- 1: 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0

Deploy

$ npx oz deploy
Nothing to compile, all contracts are up to date.
? Choose the kind of deployment regular
? Pick a network development
? Pick a contract to deploy MyContract
✓ Deployed instance of MyContract
0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb

Add account to Deny List

$ npx oz send-tx
? Pick a network development
? Pick an instance MyContract at 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb
? Select which function addDenyListed(account: address)
? account: address: 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
✓ Transaction successful. Transaction hash: 0x75083049b1996f1549138a7843b38afba036f508a0237806d086dea0b95793ed
Events emitted:
 - RoleGranted(0x85e9725df395709c769073d43a0d62fe1592a06e388edf462576b58610263a02, 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0, 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1)

Attempt to call priviledgedDoStuff from account on Deny List

$ npx oz send-tx --from 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
? Pick a network development
? Pick an instance MyContract at 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb
? Select which function priviledgedDoStuff()
✖ Calling: 'priviledgedDoStuff' with no arguments
Error while trying to send transaction to 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb. Error: Returned error: VM Exception while processing transaction: revert MyContract: cannot call with deny role

Get bytes for DENY_ROLE

$ npx oz call
? Pick a network development
? Pick an instance MyContract at 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb
? Select which function DENY_ROLE()
✓ Method 'DENY_ROLE()' returned: 0x85e9725df395709c769073d43a0d62fe1592a06e388edf462576b58610263a02
0x85e9725df395709c769073d43a0d62fe1592a06e388edf462576b58610263a02

Attempt to call renounceRole from account on Deny List

$ npx oz send-tx --from 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
? Pick a network development
? Pick an instance MyContract at 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb
? Select which function renounceRole(role: bytes32, account: address)
? role: bytes32: 0x85e9725df395709c769073d43a0d62fe1592a06e388edf462576b58610263a02
? account: address: 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
✖ Calling: 'renounceRole' with:
- role (bytes32): "0x85e9725df395709c769073d43a0d62fe1592a06e388edf462576b58610263a02"
- account (address): "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0"
Error while trying to send transaction to 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb. Error: Returned error: VM Exception while processing transaction: revert MyContract: cannot renounce deny role

Remove account from Deny List from account with DEFAULT_ADMIN role

$ npx oz send-tx
? Pick a network development
? Pick an instance MyContract at 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb
? Select which function removeDenyListed(account: address)
? account: address: 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
✓ Transaction successful. Transaction hash: 0xab0e3d945a6532dc88aa9885b9c3517e0bf686f3f85cd8c18183a65e4598ddd6
Events emitted:
 - RoleRevoked(0x85e9725df395709c769073d43a0d62fe1592a06e388edf462576b58610263a02, 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0, 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1)

Call priviledgedDoStuff from account without Deny role

$ npx oz send-tx --from 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
? Pick a network development
? Pick an instance MyContract at 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb
? Select which function priviledgedDoStuff()
✓ Transaction successful. Transaction hash: 0x60c106a39df4631830847a86fbee9c9f90c6e6142e8ded2ffcef57df184bc5c1
$ npx oz call
? Pick a network development
? Pick an instance MyContract at 0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb
? Select which function stuff()
✓ Method 'stuff()' returned: true
true
1 Like

Thank you for your advice. I will study harder.
Have a nice weekend :laughing:

1 Like

Thanks. I’m on vacation for a week. :desert_island:

I would suggest playing around with the sample I created to get some ideas for your implementation.

Of course, you have provided a lot of good ideas. I will develop my own plan based on this. Again, I would like to express my huge thanks to you.

1 Like