Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Exclude from empty code error case where there is no calldata and value #804

Merged
merged 5 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions crates/forge/tests/cli/zk_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,57 @@ contract CallEmptyCode is Test {
.stdout_lossy()
.contains("call may fail or behave unexpectedly due to empty code");
});

// Sending ETH to an EOA doesn't trigger empty code warning
forgetest_async!(test_zk_can_send_eth_to_eoa, |prj, cmd| {
Jrigada marked this conversation as resolved.
Show resolved Hide resolved
foundry_test_utils::util::initialize(prj.root());
prj.add_test(
"SendEthToEOA.t.sol",
r#"
import "forge-std/Test.sol";

contract SendEthToEOA is Test {
function testSendEthToEOA() external {
address eoa = makeAddr("Juan's Account");
vm.deal(address(this), 1 ether);

(bool success,) = eoa.call{value: 1 ether}("");
assertTrue(success, "ETH transfer failed");
}
}
"#,
)
.unwrap();

cmd.args(["test", "--zksync", "--match-test", "testSendEthToEOA"]);
let output = cmd.assert_success().get_output().stdout_lossy();

assert!(!output.contains("call may fail or behave unexpectedly due to empty code"));
});

//Calling an address with Zero value should trigger empty code warning
Jrigada marked this conversation as resolved.
Show resolved Hide resolved
forgetest_async!(test_zk_can_call_empty_code_with_zero_value, |prj, cmd| {
Jrigada marked this conversation as resolved.
Show resolved Hide resolved
foundry_test_utils::util::initialize(prj.root());
prj.add_test(
"CallEmptyCodeWithZeroValue.t.sol",
r#"
import "forge-std/Test.sol";

contract CallEmptyCodeWithZeroValue is Test {
function testCallEmptyCodeWithZeroValue() external {
address eoa = makeAddr("Juan's Account");
vm.deal(address(this), 1 ether);

(bool success,) = eoa.call("");
assertTrue(success, "call failed");
}
}
"#,
)
.unwrap();

cmd.args(["test", "--zksync", "--match-test", "testCallEmptyCodeWithZeroValue"]);
let output = cmd.assert_success().get_output().stdout_lossy();

assert!(output.contains("call may fail or behave unexpectedly due to empty code"));
});
15 changes: 13 additions & 2 deletions crates/zksync/core/src/vm/tracers/cheatcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,22 @@ impl CheatcodeTracer {
}

/// Check if the given address's code is empty
fn has_empty_code<S: ReadStorage>(&self, storage: StoragePtr<S>, target: Address) -> bool {
fn has_empty_code<S: ReadStorage>(
&self,
storage: StoragePtr<S>,
target: Address,
calldata: &[u8],
value: rU256,
) -> bool {
// The following addresses are expected to have empty bytecode
let ignored_known_addresses =
[foundry_evm_abi::HARDHAT_CONSOLE_ADDRESS, self.call_context.tx_caller];

// Skip empty code check for empty calldata with non-zero value (Transfers)
if calldata.is_empty() && !value.is_zero() {
return false;
}

let contract_code = storage.borrow_mut().read_value(&get_code_key(&target.to_h160()));

!ignored_known_addresses.contains(&target) &&
Expand Down Expand Up @@ -277,7 +288,7 @@ impl<S: ReadStorage, H: HistoryMode> DynTracer<S, SimpleMemory<H>> for Cheatcode

// if we get here there was no matching mock call,
// so we check if there's no code at the mocked address
if self.has_empty_code(storage, call_contract) {
if self.has_empty_code(storage, call_contract, &call_input, call_value) {
// issue a more targeted
// error if we already had some mocks there
let had_mocks_message =
Expand Down
Loading