@nomiclabs/hardhat-waffle
Version:
Hardhat plugin to test smart contracts with Waffle
89 lines (76 loc) • 2.47 kB
text/typescript
import type { RecordedCall } from "@ethereum-waffle/provider";
import { utils } from "ethers";
/**
* Injects call history into hardhat provider,
* making it possible to use matchers like calledOnContract
*/
class CallHistory {
public recordedCalls: RecordedCall[] = [];
public addUniqueCall(call: RecordedCall) {
if (
this.recordedCalls.find(
(c) => c.address === call.address && c.data === call.data
) === undefined
) {
this.recordedCalls.push(call);
}
}
public clearAll() {
this.recordedCalls = [];
}
}
function toRecordedCall(message: any): RecordedCall {
return {
address: message.to?.buf
? utils.getAddress(utils.hexlify(message.to.buf))
: undefined,
data: message.data ? utils.hexlify(message.data) : "0x",
};
}
function getHardhatVMEventEmitter(hardhatWaffleProvider: any) {
const vm =
hardhatWaffleProvider?._hardhatNetwork.provider?._wrapped._wrapped?._wrapped
?._node?._vmTracer?._vm;
/**
* There were changes related to the location of event emitter introduced
* in Hardhat version 2.11.0.
*/
return vm?.evm?.events ?? vm;
}
let injected = false;
export const injectCallHistory = (hardhatWaffleProvider: any) => {
if (injected) {
return;
}
const callHistory = new CallHistory();
hardhatWaffleProvider.clearCallHistory = () => {
callHistory.clearAll();
};
let beforeMessageListener: (message: any) => void | undefined;
const init =
hardhatWaffleProvider?._hardhatNetwork?.provider?._wrapped?._wrapped
?._wrapped?._init;
if (!init) {
throw new Error("Could not inject call history into hardhat provider");
}
hardhatWaffleProvider._hardhatNetwork.provider._wrapped._wrapped._wrapped._init =
async function () {
await init.apply(this);
if (typeof beforeMessageListener === "function") {
// has to be here because of weird behaviour of init function, which requires us to re-register the handler.
getHardhatVMEventEmitter(hardhatWaffleProvider)?.off?.(
"beforeMessage",
beforeMessageListener
);
}
beforeMessageListener = (message: any) => {
callHistory.addUniqueCall(toRecordedCall(message));
};
hardhatWaffleProvider.callHistory = callHistory.recordedCalls;
getHardhatVMEventEmitter(hardhatWaffleProvider)?.on?.(
"beforeMessage",
beforeMessageListener
);
};
injected = true;
};