Our migration branch of OpenZeppelin/contracts has tests that pass if run in the standard way, but which fail if you run with coverage enabled.
There are several issue at play here including some tests failing due to the Fusaka gas cap: #7807
But a large number of tests appear to be an underlying issue. Specifically, that the staticcall added by instrumentation resets the the returndata buffer (see EIP-211: "Upon executing any call-like opcode, the buffer is cleared (its size is set to zero)"). However OpenZeppelin leverages RETURNDATASIZE and RETURNDATACOPY, leading to the following pattern when combined with coverage:
__HardhatCoverage.sendHit(0x9fe2d70...);
bool success = LowLevelCall.callNoReturn(target, value, data);
__HardhatCoverage.sendHit(0xfc00d70...); // ← STATICCALL clobbers RETURNDATA here
if (LowLevelCall.returnDataSize() > 0) { // ← always 0 now
LowLevelCall.bubbleRevert();
} else {
revert Errors.FailedCall(); // ← always taken
}
Reproduction Steps
Clone the https://github.com/NomicFoundation/openzeppelin-contracts repo then checkout the chore/update-to-hardhat-3-4 branch:
npm install
npx hardhat test mocha # runs successfully
npx hardhat test mocha --coverage # fails
Our migration branch of OpenZeppelin/contracts has tests that pass if run in the standard way, but which fail if you run with coverage enabled.
There are several issue at play here including some tests failing due to the Fusaka gas cap: #7807
But a large number of tests appear to be an underlying issue. Specifically, that the staticcall added by instrumentation resets the the
returndatabuffer (see EIP-211: "Upon executing any call-like opcode, the buffer is cleared (its size is set to zero)"). However OpenZeppelin leveragesRETURNDATASIZEandRETURNDATACOPY, leading to the following pattern when combined with coverage:Reproduction Steps
Clone the https://github.com/NomicFoundation/openzeppelin-contracts repo then checkout the
chore/update-to-hardhat-3-4branch: