Skip to content

Commit

Permalink
fix(zk): avoid observing log from staticcalls (#547)
Browse files Browse the repository at this point in the history
* fix(zk): avoid observing log from staticcalls

* test(zk): check not obversing staticcall logs

* fix(zk): passthru console.logs (but don't record)

* test(zk): check console.log passthru

* chore: remove unnecessary log statement
  • Loading branch information
Karrq committed Aug 30, 2024
1 parent c8e23ef commit a1155ab
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 15 deletions.
27 changes: 15 additions & 12 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1395,14 +1395,6 @@ impl Cheatcodes {
persisted_factory_deps: Some(&mut self.persisted_factory_deps),
};
if let Ok(result) = foundry_zksync_core::vm::call::<_, DatabaseError>(call, ecx, ccx) {
if let Some(recorded_logs) = &mut self.recorded_logs {
recorded_logs.extend(result.logs.clone().into_iter().map(|log| Vm::Log {
topics: log.data.topics().to_vec(),
data: log.data.data.clone(),
emitter: log.address,
}));
}

// append console logs from zkEVM to the current executor's LogTracer
result.logs.iter().filter_map(decode_console_log).for_each(|decoded_log| {
executor.console_log(
Expand All @@ -1417,10 +1409,21 @@ impl Cheatcodes {
);
});

// for each log in cloned logs call handle_expect_emit
if !self.expected_emits.is_empty() {
for log in result.logs {
expect::handle_expect_emit(self, &log);
// skip log processing for static calls
if !call.is_static {
if let Some(recorded_logs) = &mut self.recorded_logs {
recorded_logs.extend(result.logs.clone().into_iter().map(|log| Vm::Log {
topics: log.data.topics().to_vec(),
data: log.data.data.clone(),
emitter: log.address,
}));
}

// for each log in cloned logs call handle_expect_emit
if !self.expected_emits.is_empty() {
for log in result.logs {
expect::handle_expect_emit(self, &log);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/forge/tests/it/zk/cheats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async fn test_zk_cheat_record_works() {
#[tokio::test(flavor = "multi_thread")]
async fn test_zk_cheat_expect_emit_works() {
let runner = TEST_DATA_DEFAULT.runner_zksync();
let filter = Filter::new("testExpectEmit|testExpectEmitOnCreate", "ZkCheatcodesTest", ".*");
let filter = Filter::new("testExpectEmit", "ZkCheatcodesTest", ".*");

TestConfig::with_filter(runner, filter).evm_spec(SpecId::SHANGHAI).run().await;
}
Expand Down
40 changes: 38 additions & 2 deletions testdata/zk/Cheatcodes.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,19 @@ contract Emitter {
event EventConstructor(string message);
event EventFunction(string message);

string public constant CONSTRUCTOR_MESSAGE = "constructor";
string public constant FUNCTION_MESSAGE = "function";

constructor() {
emit EventConstructor("constructor");
emit EventConstructor(CONSTRUCTOR_MESSAGE);
}

function functionEmit() public {
emit EventFunction("function");
emit EventFunction(FUNCTION_MESSAGE);
}

function emitConsole(string memory message) public view {
console.log(message);
}
}

Expand Down Expand Up @@ -157,6 +164,14 @@ contract ZkCheatcodesTest is DSTest {
new Emitter();
}

function testExpectEmitIgnoresStaticCalls() public {
Emitter emitter = new Emitter();

vm.expectEmit(true, true, true, true);
emit EventFunction(emitter.FUNCTION_MESSAGE());
emitter.functionEmit();
}

function testZkCheatcodesValueFunctionMockReturn() public {
InnerMock inner = new InnerMock();
// Send some funds to so it can pay for the inner call
Expand Down Expand Up @@ -224,6 +239,27 @@ contract ZkCheatcodesTest is DSTest {
assertEq(entries[10].data, abi.encode("function"));
// 11: EthToken
}

function testRecordConsoleLogsLikeEVM() public {
Emitter emitter = new Emitter();
vm.makePersistent(address(emitter));

// ensure we are in zkvm
(bool _success, bytes memory _ret) = address(vm).call(abi.encodeWithSignature("zkVm(bool)", true));

vm.recordLogs();
emitter.emitConsole("zkvm");
Vm.Log[] memory zkvmEntries = vm.getRecordedLogs();

// ensure we are NOT in zkvm
(_success, _ret) = address(vm).call(abi.encodeWithSignature("zkVm(bool)", false));

vm.recordLogs();
emitter.emitConsole("evm");
Vm.Log[] memory evmEntries = vm.getRecordedLogs();

assertEq(zkvmEntries.length, evmEntries.length);
}
}

contract UsesCheatcodes {
Expand Down

0 comments on commit a1155ab

Please sign in to comment.