Using hardhat and viem, I am trying to test that a Solidity contract reverts with a Custom Error.
Context
The problem is with the first parameter of revertWithCustomError: the contract. I am unable to supply a value that comes from viem there. I am trying to use it like this:
await expect(
contract.write.withdraw([BigInt(0)], {
account: other.account,
})
).to.be.revertedWithCustomError(
contract
"Unauthorized"
);
Attempts
With deployContract
const deployedContract = await hre.viem.deployContract("Inheritance");
With error:
Argument of type '{ read: { heir: (options?: { account?: `0x${string}` | Account | undefined; blockNumber?: bigint | undefined; blockTag?: BlockTag | undefined; } | undefined) => Promise<`0x${string}`>; lastWithdrawalAt: (options?: { ...; } | undefined) => Promise<...>; owner: (options?: { ...; } | undefined) => Promise<...>; }; esti...' is not assignable to parameter of type '{ interface: any; }'.
Property 'interface' is missing in type '{ read: { heir: (options?: { account?: `0x${string}` | Account | undefined; blockNumber?: bigint | undefined; blockTag?: BlockTag | undefined; } | undefined) => Promise<`0x${string}`>; lastWithdrawalAt: (options?: { ...; } | undefined) => Promise<...>; owner: (options?: { ...; } | undefined) => Promise<...>; }; esti...' but required in type '{ interface: any; }'. [2345]
With contractAt
const contract = await hre.viem.getContractAt(
"Inheritance",
deployedContract.address,
);
With error
Argument of type 'GetContractReturnType<[{ inputs: []; stateMutability: "payable"; type: "constructor"; }, { inputs: []; name: "InsufficientBalance"; type: "error"; }, { inputs: []; name: "TooEarlyForInheritance"; type: "error"; }, { inputs: [...]; name: "Unauthorized"; type: "error"; }, ... 7 more ..., { ...; }]>' is not assignable to parameter of type '{ interface: any; }'.
Property 'interface' is missing in type 'GetContractReturnType<[{ inputs: []; stateMutability: "payable"; type: "constructor"; }, { inputs: []; name: "InsufficientBalance"; type: "error"; }, { inputs: []; name: "TooEarlyForInheritance"; type: "error"; }, { inputs: [...]; name: "Unauthorized"; type: "error"; }, ... 7 more ..., { ...; }]>' but required in type '{ interface: any; }'.
Full test code
I stripped unrelated parts to make a minimal example.
import hre from "hardhat";
import { expect } from "chai";
import {
loadFixture,
} from "@nomicfoundation/hardhat-toolbox-viem/network-helpers";
describe("Contract", () => {
async function deployFixture() {
const [
[owner, other],
deployedContract,
publicClient,
] = await Promise.all([
hre.viem.getWalletClients(),
hre.viem.deployContract("Inheritance", [], {
value: BigInt('50'),
}),
hre.viem.getPublicClient(),
]);
return {
owner, other, deployedContract, publicClient,
}
};
describe('Withdraw', () => {
it('Should block the heir', async () => {
const { deployedContract, other } = await loadFixture(deployFixture);
const contract = await hre.viem.getContractAt(
"Inheritance",
deployedContract.address,
);
await expect(
contract.write.withdraw([BigInt(0)], {
account: other.account,
})
).to.be.revertedWithCustomError(
// Tried with both contract and deployedContract
deployedContract,
"Unauthorized"
);
});
});
});