expectCall
function expectCall(address callee, bytes calldata data) external;
function expectCall(address callee, bytes calldata data, uint64 count) external;
function expectCall(
address callee,
uint256 value,
bytes calldata data
) external;
function expectCall(
address callee,
uint256 value,
bytes calldata data,
uint64 count
) external;
Description
Expects a call to a specified address callee
, where the call data either strictly or loosely matches data
. The cheatcode can be called in two ways:
- If no
count
parameter is specified, the call will be expected to be made at least the amount of times the cheatcode was called. For the same calldata, you cannot call the cheatcode with nocount
and then pass in acount
parameter. - If
count
is specified, the call will be expected to be made strictlycount
times. For the same calldata, thecount
value cannot be overwritten with another cheatcode call, nor it can be increment by calling the cheatcode without acount
parameter.
count
can also be set to 0 to assert that a call is not made.
When a call is made to callee
the call data is first checked to see if it matches in its entirety with data
. If not, the call data is checked to see if there is a partial match, with the match starting at the first byte of the call data.
Using the second signature we can also check if the call was made with the expected msg.value
.
If the test terminates without the call being made, the test fails.
ℹ️ Internal calls
This cheatcode does not currently work on internal calls. See issue #432.
Examples
Expect that transfer
is called on a token MyToken
one time:
address alice = makeAddr("alice");
emit log_address(alice);
vm.expectCall(
address(token), abi.encodeCall(token.transfer, (alice, 10))
);
token.transfer(alice, 10);
// [PASS]
Expect that transfer
is called on a token MyToken
at least two times:
address alice = makeAddr("alice");
emit log_address(alice);
vm.expectCall(
address(token), abi.encodeCall(token.transfer, (alice, 10))
);
vm.expectCall(
address(token), abi.encodeCall(token.transfer, (alice, 10))
);
token.transfer(alice, 10);
token.transfer(alice, 10);
token.transfer(alice, 10);
// [PASS]
Expect that transfer
is not called on a token MyToken
:
address alice = makeAddr("alice");
emit log_address(alice);
vm.expectCall(
address(token), abi.encodeCall(token.transfer, (alice, 10)), 0
);
token.transferFrom(alice, address(0), 10);
// [PASS]
Expect that transfer
with any calldata is called on a token MyToken
2 times:
address alice = makeAddr("alice");
emit log_address(alice);
vm.expectCall(
address(token), abi.encodeWithSelector(token.transfer.selector), 2
);
token.transfer(alice, 10);
token.transfer(alice, 10);
// [PASS]
Expect that pay
is called on a Contract
with a specific msg.value
and calldata
:
Contract target = new Contract();
vm.expectCall(
address(target),
1,
abi.encodeWithSelector(target.pay.selector, 2)
);
target.pay{value: 1}(2);
// [PASS]
Expect that pay
is called on a Contract
with a specific msg.value
and calldata
3 times:
Contract target = new Contract();
vm.expectCall(
address(target),
1,
abi.encodeWithSelector(target.pay.selector, 2),
3
);
target.pay{value: 1}(2);
target.pay{value: 1}(2);
target.pay{value: 1}(2);
// [PASS]