Unit test error: “AccessManagedUnauthorized” when minting ERC-20 token in a DAO project

I’m relatively new to Solidity and currently working on building a DAO using the OpenZeppelin contract wizard. I’ve generated ERC-20 token and governor contracts using the wizard to kickstart my project. However, I encountered an issue while setting up my unit tests. Specifically, I’m receiving an error message “AccessManagedUnauthorized” when attempting to mint tokens.
I’m utilizing the Foundry framework for testing. Below is the remainder of my test contract along with the ERC-20 token implementation.
I’ve attempted to dive into the documentation and explore the OpenZeppelin contract code, particularly examining contracts like AccessManaged, but unfortunately, I’m still struggling to grasp the issue. Any guidance or insight on resolving this would be greatly appreciated. Thank you!

Here’s how I’ve set up my test contract:

contract KachalGovTest is Test {
    KachalCoin kcoin;
    TimeLock timelock;

    address public USER = makeAddr("user");
    uint256 public constant INITIAL_SUPPLY = 10 ether;
    function setUp() public {
        vm.startPrank(USER);
        kcoin = new KachalCoin(USER);
        kcoin.mint(USER, INITIAL_SUPPLY);
        kcoin.setAuthority(USER);
        kcoin.delegate(USER);
        timelock = new TimeLock(MIN_DELAY, proposers, executors);
  

test contract:

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

import {Test} from "forge-std/Test.sol";
import {KachalBox} from "../src/KachalBox.sol";
import {KachalCoin} from "../src/KachalCoin.sol";
import {KachalGov} from "../src/KachalGov.sol";
import {TimeLock} from "../src/TimeLock.sol";

contract KachalGovTest is Test {
    KachalBox kbox;
    KachalCoin kcoin;
    KachalGov kgov;
    TimeLock timelock;

    address public USER = makeAddr("user");
    uint256 public constant INITIAL_SUPPLY = 10 ether;
    // arguments for TimeLock
    uint256 public constant MIN_DELAY = 3600; // 1 hour after a vote passes
    address[] proposers;
    address[] executors;

    function setUp() public {
        vm.startPrank(USER);
        kcoin = new KachalCoin(USER);
        kcoin.mint(USER, INITIAL_SUPPLY);
        kcoin.setAuthority(USER);
        kcoin.delegate(USER);
        timelock = new TimeLock(MIN_DELAY, proposers, executors);

        // now we can deploy our gov contract

        kgov = new KachalGov(kcoin, timelock);

        // now we should give some rules
        // the way that time locker has roles, it hashes the names of stuff
        bytes32 proposersRole = timelock.PROPOSER_ROLE();
        // there is a function in timelock name PROPOSER_ROLE, and we are going to alow this
        // proposer role to be just the governer, so only the governor can propose stuff to the timelock
        bytes32 executorRole = timelock.EXECUTOR_ROLE();
        // any body can execute by setting it to zero address
        bytes32 adminRole = timelock.DEFAULT_ADMIN_ROLE();
        // time lock start with some default rolls
        // and we need to grant the governor whole bunch of rolls
        timelock.grantRole(proposersRole, address(kgov));
        // as a grant role function, we grant the proposersRole to the governor so only the governor
        // can actually propose stuff to timelock
        timelock.grantRole(executorRole, address(0));
        // and we need to remove our-selves as the admin of time locker
        timelock.revokeRole(adminRole, address(USER));
        // so the user can no longer be the admin
        vm.stopPrank();

        kbox = new KachalBox();
        kbox.transferOwnership(address(timelock));
    }

    // now we can write a quick test:
    function testCantUpdateBoxWithoutGovernance() public {
        vm.expectRevert();
        kbox.store(1);
    }

    function testWhoIsTheInitialAuthority() public view {
        // kcoin = new KachalCoin(USER);
        assertEq(kcoin.authority(), USER, "The initial Authority should be USER address!");
    }

    function testUSERCanMint() public {
        vm.startPrank(USER);
        kcoin.mint(USER, INITIAL_SUPPLY);
        vm.stopPrank();
        assertEq(kcoin.balanceOf(USER), INITIAL_SUPPLY, "The USER address should have the minted tokens");
    }

    function testMintingPermissions() public {
        vm.startPrank(USER); // Set caller as the governor
        kcoin.mint(USER, 100);
        vm.stopPrank();
        assertEq(kcoin.balanceOf(USER), INITIAL_SUPPLY + 100, "The governor should be able to mint tokens");
    }
}

ERC-20 contract:

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

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {ERC20Pausable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import {AccessManaged} from "@openzeppelin/contracts/access/manager/AccessManaged.sol";
import {ERC20Permit, Nonces} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {ERC20Votes} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";

contract KachalCoin is ERC20, ERC20Burnable, ERC20Pausable, AccessManaged, ERC20Permit, ERC20Votes {
    constructor(address initialAuthority)
        ERC20("KachalCoin", "KCH")
        AccessManaged(initialAuthority)
        ERC20Permit("KachalCoin")
    {}

    function pause() public restricted {
        _pause();
    }

    function unpause() public restricted {
        _unpause();
    }

    function mint(address to, uint256 amount) public restricted {
        _mint(to, amount);
    }

    function clock() public view override returns (uint48) {
        return uint48(block.timestamp);
    }

    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() public pure override returns (string memory) {
        return "mode=timestamp";
    }

    // The following functions are overrides required by Solidity.

    function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Pausable, ERC20Votes) {
        super._update(from, to, value);
    }

    function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
        return super.nonces(owner);
    }
}

here is the error massage:

[FAIL. Reason: setup failed: AccessManagedUnauthorized(0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D)] setUp() (gas: 0)
Traces:
  [2021802] KachalGovTest::setUp()
    ├─ [0] VM::startPrank(user: [0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D])
    │   └─ ← [Return] 
    ├─ [1957628] → new KachalCoin@0x7BD1119CEC127eeCDBa5DCA7d1Bd59986f6d7353
    │   ├─ emit AuthorityUpdated(authority: user: [0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D])
    │   └─ ← [Return] 9428 bytes of code
    ├─ [1900] KachalCoin::mint(user: [0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D], 10000000000000000000 [1e19])
    │   ├─ [0] user::canCall(user: [0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D], KachalCoin: [0x7BD1119CEC127eeCDBa5DCA7d1Bd59986f6d7353], 0x40c10f1900000000000000000000000000000000000000000000000000000000) [staticcall]
    │   │   └─ ← [Stop] 
    │   └─ ← [Revert] AccessManagedUnauthorized(0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D)
    └─ ← [Revert] AccessManagedUnauthorized(0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D)

Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 2.01ms (0.00ns CPU time)

Ran 1 test suite in 1.58s (2.01ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)

Failing tests:
Encountered 1 failing test in test/KachalGovTest.t.sol:KachalGovTest
[FAIL. Reason: setup failed: AccessManagedUnauthorized(0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D)] setUp() (gas: 0)

Encountered a total of 1 failing tests, 0 tests succeeded

I found out that the USER address does not have permission to mint tokens but I’m struggling to figure out what address has the permission to mint tokens. I couldn’t understand how to find the address that has these permissions through testing. I know that I can set Authority through the functions, but still wasn’t able to do so because I thought the address of the test contract had the permission to mint and also transfer Authority but I was wrong.

New contributor

Hessamedean Aghajanlou is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật