Environment
Truffle / Solidity 6
Details
I’m trying to build a “dao”-like smart contract that implements AccessControl and grants roles to accounts upon other accounts voting on that grant proposal. the idea is that no EOA controls the role granting but the contract does. This collides with security checks in oz’s AccessControl
interface though: when I want a smart contract to control the roles (e.g. by reacting on a positive quorum of other role members to accept a new member to the role), the "msg.sender
must be role admin for this role " requirement doesn’t allow the contract to grant / revoke roles for accounts.
I already tried to make the contract itself an admin for the role but since AccessControl checks against msg.sender
that won’t let us pass since our contract is not the msg.sender . Tried to hack that with a self.delegatecall(abi) approach but think this is leading nowhere.
Any ideas how to achieve that in a “secure” way?
Code to reproduce
(omitted the whole quorum / voting code here)
pragma solidity ^0.6;
import '@openzeppelin/contracts/access/AccessControl.sol';
contract QuorumRoleControl is AccessControl {
bytes32 public constant ROLE_VOTER = keccak256('ROLE_VOTER');
bytes32 public constant ROLE_VOTER_ADMIN = keccak256('ROLE_VOTER_ADMIN');
constructor() public AccessControl() {
_setRoleAdmin(ROLE_VOTER, ROLE_VOTER_ADMIN);
_setupRole(ROLE_VOTER_ADMIN, address(this));
//democracy starts with the first user on earth ;)
_setupRole(ROLE_VOTER, msg.sender);
}
// ... lots of voting code, this is pseudo: ...
function vote(address shouldBecomeRoleMember) {
require(hasRole(ROLE_VOTER,msg.sender));
votes[shouldBecomeRoleMember]++;
}
function settleVoting(address shouldBecomeRoleMember) public {
require(hasRole(ROLE_VOTER, msg.sender)); //unnecessary
//grant / revoke roles, according to the quorum's verdict
if (votes[shouldBecomeRoleMember] > 3)
setupRole(ROLE_VOTER, address(theMemberWeVotedOn));
else
revokeRole(ROLE_VOTER, address(someoneWeAllReallyDislike));
}
}
setupRole / revokeRole will revert with AccessControl: sender must be an admin to revoke
. I can discouragedly use _setupRole
for the grant case but there’s no “hack” for the revoke case.