Hi @wangyuyue,
You could try using AccessControl for your Deny List. I created a proof of concept of what this might look like.
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