I have a smart contract (built from ERC20Upgradeable & AccessControlUpgradeable) which allows a % split of mints
function setBankMintingShare(uint256 _bankMintingShare) public onlyRole(MINTER_ROLE) validBankMintingShare {
require(_bankMintingShare > 0 && _bankMintingShare < 100, "Bank minting share must be between 1 and 99");
bankMintingShare = _bankMintingShare;
}
In my mint function, I also check to make sure that the _bankMintingShare
is valid before minting because I'm worried that someone might change bankMintingShare
and by pass that check
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
require(bank != address(0), "Bank address must be set");
require(getBankMintingShare() > 0 && getBankMintingShare() < 100, "Bank share must be between 1 and 99");
uint256 bankAmount = amount*getBankMintingShare()/100;
uint256 minterAmount = amount - bankAmount;
_mint(to, bankAmount);
_mint(bank, minterAmount);
}
But now I can't get to 100% test coverage because I can't figure out a way to "force" bankMintingShare into an invalid state to test that branch
I've looked into using smock to mock/fake the bankMintingShare value as the correct invalid state but I cannot for the life of me get it to actually work.
This is what I've come up with so far. It works perfectly if I remove the onlyRole
modifier, otherwise it throws an AccessControl Minter Role required error
const [owner, bank] = await ethers.getSigners();
const myContractFactory = await smock.mock("Coin");
const myContract = await myContractFactory.deploy();
await myContract.setVariable("bankMintingShare", 0);
const myFake = await smock.fake(myContract);
await owner.sendTransaction({
value: utils.parseUnits("10"),
to: myFake.address,
});
await myContract.connect(myFake.wallet).setBank(bank.address);
await expect(
myContract.connect(myFake.wallet).mint(myFake.address, 10000)
).to.be.revertedWith("Bank share must be between 1 and 99");
What I'm stuck on is how to either set the access role to minter OR how to mock/fake the account having the minter role so it doesn't get rejected
My attempt to mock the hasRole function so it returns true didn't work (await myContract.hasRole.returns(true)
), it just seems to take no notice of it
And my attempt to grant an account the MINTER_ROLE (await myContract.grantRole(myContract.MINTER_ROLE(), myFake.address)
) just at best returns the account is missing the default admin role or at worst that VoidSigner cannot sign transactions
At this point I'm pretty much totally stumped, so any thoughts or ideas would go a long way!