DAO项目铸造ERC-20代币时遇AccessManagedUnauthorized单元测试错误求助
1. 先搞清楚谁拥有铸币权限
AccessManaged体系里,初始权限一般在合约部署者手里。你可以在测试里加一段代码验证并打印权限地址:
// 测试合约中新增验证逻辑 function test_FindMintPermissionHolder() public { // Foundry测试里,msg.sender默认是合约部署者 address deployer = msg.sender; bytes32 minterRole = token.MINTER_ROLE(); // 方式1:检查部署者是否有铸币权限 bool deployerHasPermission = token.hasRole(minterRole, deployer); assertTrue(deployerHasPermission, "部署者应该拥有铸币权限"); // 方式2:直接打印所有铸币角色持有者 uint256 holderCount = token.getRoleMemberCount(minterRole); for(uint256 i=0; i<holderCount; i++){ console.log("铸币权限持有者[%d]:", i, token.getRoleMember(minterRole, i)); } }
运行forge test -vvv就能在控制台看到权限地址。如果是用OpenZeppelin向导生成的合约,也有可能把铸币权限绑定到了Governor合约,记得一并检查Governor地址的权限。
2. 给测试用户授权或用有权限的地址调用mint
- 方案一:让有权限的地址给测试用户授权铸币角色
function setUp() public { // 部署ERC20和Governor合约的逻辑... address deployer = msg.sender; bytes32 minterRole = token.MINTER_ROLE(); // 用部署者身份给测试用户授权 vm.prank(deployer); token.grantRole(minterRole, USER); } // 此时用USER调用mint就不会报错 function test_MintSuccessWithAuthorizedUser() public { vm.prank(USER); token.mint(USER, 100 ether); assertEq(token.balanceOf(USER), 100 ether); }
- 方案二:直接用有权限的地址(比如部署者或Governor)执行mint
function test_MintSuccessWithDeployer() public { // 切换到部署者身份调用mint vm.prank(msg.sender); token.mint(USER, 100 ether); assertEq(token.balanceOf(USER), 100 ether); }
3. 排查设置Authority失败的问题
如果你尝试自定义Authority但没生效,检查这几点:
- 调用
setAuthority的地址必须拥有DEFAULT_ADMIN_ROLE(默认是部署者) - 自定义的Authority合约必须正确实现
canCall方法,符合AccessManaged的权限校验逻辑 - 测试时必须用
vm.prank切换到有权限的地址再执行设置:
function test_SetCustomAuthoritySuccess() public { MyCustomAuthority customAuthority = new MyCustomAuthority(); // 用部署者身份设置Authority vm.prank(msg.sender); token.setAuthority(address(customAuthority)); // 验证设置是否成功 assertEq(token.authority(), address(customAuthority)); }
4. 用错误日志定位细节
如果还是卡壳,把错误日志里的调用栈信息理清楚,重点关注:
- 触发权限错误的调用地址
- 权限校验对应的函数选择器和目标合约
- 当前角色或Authority的配置状态
内容的提问来源于stack exchange,提问作者Hessamedean Aghajanlou
相关产品推荐
相关产品推荐

