Trey Grainger reported on Telegram:
So I’m running into some incredibly bizarre behavior related to AccessControl in contracts-ethereum-package that I’ve been fighting with for over a day. My contract is modeled after the ERC20PresetMinterPauserUpgradeSafe, which I believe suffers from the same problem (I’ll verify that shortly).
Here’s the issue:
let tok = await MyToken.deployed()
tok.hasRole(tok.PAUSER_ROLE, accounts[1]) //false
tok.grantRole(tok.PAUSER_ROLE, accounts[1]) //success
tok.hasRole(tok.PAUSER_ROLE, accounts[1]) //true
But whenever I call pre.pause(), the fails on the “require(hasRole(tok.PAUSER_ROLE, “…”))” line
function pause() public {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");
_pause();
}
What’s very strange is that if my contract calls hasRole(PAUSER_ROLE, _msgSender()) it successfully returns (true or false), but if it calls require(hasRole(PAUSER_ROLE, _msgSender()) then it throws an exception.
In stepping through the debugger, it initially seems like the _roles mapping is empty whenever I call require(hasRole(…)) in my contract, but is populated with the correctly-assigned roles when I just call hasRole(…))
Has anyone seen this before, or (as a sanity check), has anyone successfully used AccessControl in your upgradeable smart contracts before? I’m assuming the answer to the latter question is a definitive yes, but it’s definitely not working for me and very bizarre, so wondering if anyone else has seen this before or has any insight.