Skip to content

Commit

Permalink
fix(zk): add logs to recorded_logs (#522)
Browse files Browse the repository at this point in the history
* test(zk): recordLogs cheatcode

* fix(zk): add logs to `recorded_logs`

* chore: avoid unnecessary low-level call
  • Loading branch information
Karrq authored Aug 20, 2024
1 parent 98dfb5e commit 1cf88dc
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 1 deletion.
14 changes: 14 additions & 0 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,13 @@ impl Cheatcodes {
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,
}));
}
self.combined_logs.extend(result.logs.clone().into_iter().map(Some));

// for each log in cloned logs call handle_expect_emit
Expand Down Expand Up @@ -1380,6 +1387,13 @@ 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,
}));
}
self.combined_logs.extend(result.logs.clone().into_iter().map(Some));
//for each log in cloned logs call handle_expect_emit
if !self.expected_emits.is_empty() {
Expand Down
8 changes: 8 additions & 0 deletions crates/forge/tests/it/zk/cheats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,11 @@ async fn test_zk_can_mock_modifiers() {

TestConfig::with_filter(runner, filter).evm_spec(SpecId::SHANGHAI).run().await;
}

#[tokio::test(flavor = "multi_thread")]
async fn test_zk_record_logs() {
let runner = TEST_DATA_DEFAULT.runner_zksync();
let filter = Filter::new("RecordLogs", "ZkCheatcodesTest", ".*");

TestConfig::with_filter(runner, filter).evm_spec(SpecId::SHANGHAI).run().await;
}
22 changes: 22 additions & 0 deletions testdata/zk/Cheatcodes.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,26 @@ contract ZkCheatcodesTest is DSTest {
vm.deal(0x4e59b44847b379578588920cA78FbF26c0B4956C, 1 ether);
assertEq(1 ether, address(0x4e59b44847b379578588920cA78FbF26c0B4956C).balance);
}

function testRecordLogsInZkVm() public {
// ensure we are in zkvm
vm.zkVm(true);
vm.recordLogs();
Emitter emitter = new Emitter(); // +7 logs from system contracts
emitter.functionEmit(); // +3 from system contracts

Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 12);
// 0,1: EthToken, 2,3: L1 Messanger, 4: Known Code Storage
assertEq(entries[5].topics.length, 1);
assertEq(entries[5].topics[0], keccak256("EventConstructor(string)"));
assertEq(entries[5].data, abi.encode("constructor"));
// 6: L2 Deployer, 7: EthToken

// 8,9: EthToken
assertEq(entries[10].topics.length, 1);
assertEq(entries[10].topics[0], keccak256("EventFunction(string)"));
assertEq(entries[10].data, abi.encode("function"));
// 11: EthToken
}
}
24 changes: 23 additions & 1 deletion zk-tests/src/Cheatcodes.t.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console2 as console} from "forge-std/Test.sol";
import "forge-std/Test.sol";

contract FixedSlot {
uint8 num; // slot index: 0
Expand Down Expand Up @@ -241,4 +241,26 @@ contract ZkCheatcodesTest is Test {
address(0x4e59b44847b379578588920cA78FbF26c0B4956C).balance
);
}

function testRecordLogsInZkVm() public {
// ensure we are in zkvm
(bool _success, bytes memory _ret) = address(vm).call(abi.encodeWithSignature("zkVm(bool)", true));
vm.recordLogs();
Emitter emitter = new Emitter(); // +7 logs from system contracts
emitter.functionEmit(); // +3 from system contracts

Vm.Log[] memory entries = vm.getRecordedLogs();
assertEq(entries.length, 12);
// 0,1: EthToken, 2,3: L1 Messanger, 4: Known Code Storage
assertEq(entries[5].topics.length, 1);
assertEq(entries[5].topics[0], keccak256("EventConstructor(string)"));
assertEq(entries[5].data, abi.encode("constructor"));
// 6: L2 Deployer, 7: EthToken

// 8,9: EthToken
assertEq(entries[10].topics.length, 1);
assertEq(entries[10].topics[0], keccak256("EventFunction(string)"));
assertEq(entries[10].data, abi.encode("function"));
// 11: EthToken
}
}

0 comments on commit 1cf88dc

Please sign in to comment.