Skip to content

Commit 708f48f

Browse files
authored
fix(forge): revert on dangling emit (#627)
* revert on dangling emit * better error handling for cheatcodes
1 parent 017dd44 commit 708f48f

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

evm-adapters/src/sputnik/cheatcodes/cheatcode_handler.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,15 @@ impl<'a, 'b, B: Backend, P: PrecompileSet> SputnikExecutor<CheatcodeStackState<'
257257
))]),
258258
)
259259
}
260+
261+
if !self.state().expected_emits.is_empty() {
262+
return (
263+
ExitReason::Revert(ExitRevert::Reverted),
264+
ethers::abi::encode(&[Token::String(
265+
"Expected an emit, but no logs were emitted afterward".to_string(),
266+
)]),
267+
)
268+
}
260269
(s, v)
261270
}
262271
Capture::Trap(_) => {
@@ -668,12 +677,21 @@ impl<'a, 'b, B: Backend, P: PrecompileSet> CheatcodeStackExecutor<'a, 'b, B, P>
668677
outdir.join(format!("{}/{}.json", contract_file, contract_name))
669678
};
670679

671-
let mut file = File::open(path).unwrap();
672680
let mut data = String::new();
673-
file.read_to_string(&mut data).unwrap();
681+
match File::open(path) {
682+
Ok(mut file) => match file.read_to_string(&mut data) {
683+
Ok(_) => {}
684+
Err(e) => return evm_error(&e.to_string()),
685+
},
686+
Err(e) => return evm_error(&e.to_string()),
687+
}
674688

675-
let contract_file: ContractFile = serde_json::from_str(&data).unwrap();
676-
res = ethers::abi::encode(&[Token::Bytes(contract_file.bin.to_vec())]);
689+
match serde_json::from_str::<ContractFile>(&data) {
690+
Ok(contract_file) => {
691+
res = ethers::abi::encode(&[Token::Bytes(contract_file.bin.to_vec())]);
692+
}
693+
Err(e) => return evm_error(&e.to_string()),
694+
}
677695
}
678696
HEVMCalls::Addr(inner) => {
679697
self.add_debug(CheatOp::ADDR);
@@ -711,7 +729,11 @@ impl<'a, 'b, B: Backend, P: PrecompileSet> CheatcodeStackExecutor<'a, 'b, B, P>
711729
// The EVM precompile does not use EIP-155
712730
let sig = wallet.sign_hash(digest.into(), false);
713731

714-
let recovered = sig.recover(digest).unwrap();
732+
let recovered = match sig.recover(digest) {
733+
Ok(rec) => rec,
734+
Err(e) => return evm_error(&e.to_string()),
735+
};
736+
715737
assert_eq!(recovered, wallet.address());
716738

717739
let mut r_bytes = [0u8; 32];
@@ -1557,6 +1579,9 @@ impl<'a, 'b, B: Backend, P: PrecompileSet> Handler for CheatcodeStackExecutor<'a
15571579
.all(|expected| expected.found)
15581580
{
15591581
return evm_error("Log != expected log")
1582+
} else {
1583+
// empty out expected_emits after successfully capturing all of them
1584+
self.state_mut().expected_emits = Vec::new();
15601585
}
15611586

15621587
self.expected_revert(ExpectRevertReturn::Call(res), expected_revert).into_call_inner()
@@ -1770,6 +1795,9 @@ impl<'a, 'b, B: Backend, P: PrecompileSet> Handler for CheatcodeStackExecutor<'a
17701795
.all(|expected| expected.found)
17711796
{
17721797
return revert_return_evm(false, None, || "Log != expected log").into_create_inner()
1798+
} else {
1799+
// empty out expected_emits after successfully capturing all of them
1800+
self.state_mut().expected_emits = Vec::new();
17731801
}
17741802

17751803
self.expected_revert(ExpectRevertReturn::Create(res), expected_revert).into_create_inner()

evm-adapters/testdata/CheatCodes.sol

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,13 @@ contract CheatCodes is DSTest {
364364
emitter.t();
365365
}
366366

367+
function testFailDanglingExpectEmit() public {
368+
ExpectEmit emitter = new ExpectEmit();
369+
// check topic 1, topic 2, and data are the same as the following emitted event
370+
hevm.expectEmit(true,true,false,true);
371+
emit Transfer(address(this), address(1337), 1337);
372+
}
373+
367374
function testExpectEmitMultiple() public {
368375
ExpectEmit emitter = new ExpectEmit();
369376
hevm.expectEmit(true,true,false,true);

0 commit comments

Comments
 (0)